diff --git a/constraint.cpp b/constraint.cpp index 131446f..2812c1f 100644 --- a/constraint.cpp +++ b/constraint.cpp @@ -10,6 +10,7 @@ char *Constraint::DescriptionString(void) { case PT_LINE_DISTANCE: s = "pt-line-distance"; break; case PT_PLANE_DISTANCE: s = "pt-plane-distance"; break; case PT_FACE_DISTANCE: s = "pt-face-distance"; break; + case PROJ_PT_DISTANCE: s = "proj-pt-pt-distance"; break; case PT_IN_PLANE: s = "pt-in-plane"; break; case PT_ON_LINE: s = "pt-on-line"; break; case PT_ON_FACE: s = "pt-on-face"; break; @@ -122,6 +123,11 @@ void Constraint::MenuConstrain(int id) { Entity *e = SK.GetEntity(gs.entity[0]); c.ptA = e->point[0]; c.ptB = e->point[1]; + } else if(gs.vectors == 1 && gs.points == 2 && gs.n == 3) { + c.type = PROJ_PT_DISTANCE; + c.ptA = gs.point[0]; + c.ptB = gs.point[1]; + c.entityA = gs.vector[0]; } else if(gs.workplanes == 1 && gs.points == 1 && gs.n == 2) { c.type = PT_PLANE_DISTANCE; c.ptA = gs.point[0]; @@ -138,17 +144,19 @@ void Constraint::MenuConstrain(int id) { c.type = DIAMETER; c.entityA = gs.entity[0]; } else { - Error("Bad selection for distance / diameter constraint. This " - "constraint can apply to:\n\n" - " * two points (distance between points)\n" - " * a line segment (length)\n" - " * a workplane and a point (minimum distance)\n" - " * a line segment and a point (minimum distance)\n" - " * a plane face and a point (minimum distance)\n" - " * a circle or an arc (diameter)\n"); + Error( +"Bad selection for distance / diameter constraint. This " +"constraint can apply to:\n\n" +" * two points (distance between points)\n" +" * a line segment (length)\n" +" * two points and a line segment or normal (projected distance)\n" +" * a workplane and a point (minimum distance)\n" +" * a line segment and a point (minimum distance)\n" +" * a plane face and a point (minimum distance)\n" +" * a circle or an arc (diameter)\n"); return; } - if(c.type == PT_PT_DISTANCE) { + if(c.type == PT_PT_DISTANCE || c.type == PROJ_PT_DISTANCE) { Vector n = SS.GW.projRight.Cross(SS.GW.projUp); Vector a = SK.GetEntity(c.ptA)->PointGetNum(); Vector b = SK.GetEntity(c.ptB)->PointGetNum(); diff --git a/constrainteq.cpp b/constrainteq.cpp index fa6c3cc..e6e256a 100644 --- a/constrainteq.cpp +++ b/constrainteq.cpp @@ -189,6 +189,18 @@ void ConstraintBase::GenerateReal(IdList *l) { AddEq(l, Distance(workplane, ptA, ptB)->Minus(exA), 0); break; + case PROJ_PT_DISTANCE: { + ExprVector pA = SK.GetEntity(ptA)->PointGetExprs(), + pB = SK.GetEntity(ptB)->PointGetExprs(), + dp = pB.Minus(pA); + + ExprVector pp = SK.GetEntity(entityA)->VectorGetExprs(); + pp = pp.WithMagnitude(Expr::From(1.0)); + + AddEq(l, (dp.Dot(pp))->Minus(exA), 0); + break; + } + case PT_LINE_DISTANCE: AddEq(l, PointLineDistance(workplane, ptA, entityA)->Minus(exA), 0); diff --git a/drawconstraint.cpp b/drawconstraint.cpp index 5486a21..fb0f18a 100644 --- a/drawconstraint.cpp +++ b/drawconstraint.cpp @@ -6,6 +6,7 @@ bool Constraint::HasLabel(void) { case PT_PLANE_DISTANCE: case PT_FACE_DISTANCE: case PT_PT_DISTANCE: + case PROJ_PT_DISTANCE: case DIAMETER: case LENGTH_RATIO: case ANGLE: @@ -137,12 +138,16 @@ void Constraint::DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu) { } } -void Constraint::DoProjectedPoint(Vector *r) { - Vector p = r->ProjectInto(workplane); +void Constraint::StippledLine(Vector a, Vector b) { glLineStipple(4, 0x5555); glEnable(GL_LINE_STIPPLE); - LineDrawOrGetDistance(p, *r); + LineDrawOrGetDistance(a, b); glDisable(GL_LINE_STIPPLE); +} + +void Constraint::DoProjectedPoint(Vector *r) { + Vector p = r->ProjectInto(workplane); + StippledLine(p, *r); *r = p; } @@ -421,6 +426,25 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) { break; } + case PROJ_PT_DISTANCE: { + Vector ap = SK.GetEntity(ptA)->PointGetNum(), + bp = SK.GetEntity(ptB)->PointGetNum(), + dp = (bp.Minus(ap)), + pp = SK.GetEntity(entityA)->VectorGetNum(); + + Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(disp.offset); + + pp = pp.WithMagnitude(1); + double d = dp.Dot(pp); + Vector bpp = ap.Plus(pp.ScaledBy(d)); + StippledLine(ap, bpp); + StippledLine(bp, bpp); + + DoLineWithArrows(ref, ap, bpp, false); + DoLabel(ref, labelPos, gr, gu); + break; + } + case PT_FACE_DISTANCE: case PT_PLANE_DISTANCE: { Vector pt = SK.GetEntity(ptA)->PointGetNum(); diff --git a/exposed/DOC.txt b/exposed/DOC.txt index 4ba2547..23873ae 100644 --- a/exposed/DOC.txt +++ b/exposed/DOC.txt @@ -264,7 +264,13 @@ the wrkpl member are marked with no star. SLVS_C_PT_PT_DISTANCE* - The distance between points ptA and ptB is equal to valA. + The distance between points ptA and ptB is equal to valA. This is an + unsigned distance, so valA must always be positive. + +SLVS_C_PROJ_PT_DISTANCE + + The distance between points ptA and ptB, as projected along the line + or normal entityA, is equal to valA. This is a signed distance. SLVS_C_POINTS_COINCIDENT* diff --git a/exposed/lib.cpp b/exposed/lib.cpp index 560cf87..44ac914 100644 --- a/exposed/lib.cpp +++ b/exposed/lib.cpp @@ -164,6 +164,7 @@ case SLVS_C_PERPENDICULAR: t = Constraint::PERPENDICULAR; break; case SLVS_C_ARC_LINE_TANGENT: t = Constraint::ARC_LINE_TANGENT; break; case SLVS_C_CUBIC_LINE_TANGENT: t = Constraint::CUBIC_LINE_TANGENT; break; case SLVS_C_EQUAL_RADIUS: t = Constraint::EQUAL_RADIUS; break; +case SLVS_C_PROJ_PT_DISTANCE: t = Constraint::PROJ_PT_DISTANCE; break; default: dbp("bad constraint type %d", sc->type); return; } diff --git a/exposed/slvs.h b/exposed/slvs.h index bd7fdfa..5c09004 100644 --- a/exposed/slvs.h +++ b/exposed/slvs.h @@ -98,6 +98,7 @@ typedef struct { #define SLVS_C_ARC_LINE_TANGENT 100027 #define SLVS_C_CUBIC_LINE_TANGENT 100028 #define SLVS_C_EQUAL_RADIUS 100029 +#define SLVS_C_PROJ_PT_DISTANCE 100030 typedef struct { Slvs_hConstraint h; diff --git a/mouse.cpp b/mouse.cpp index dd5b54b..5a3c29e 100644 --- a/mouse.cpp +++ b/mouse.cpp @@ -1154,6 +1154,7 @@ void GraphicsWindow::EditControlDone(char *s) { SS.UndoRemember(); switch(c->type) { + case Constraint::PROJ_PT_DISTANCE: case Constraint::PT_LINE_DISTANCE: case Constraint::PT_FACE_DISTANCE: case Constraint::PT_PLANE_DISTANCE: { diff --git a/sketch.h b/sketch.h index b532d31..c02de88 100644 --- a/sketch.h +++ b/sketch.h @@ -518,6 +518,7 @@ public: static const int PT_PLANE_DISTANCE = 31; static const int PT_LINE_DISTANCE = 32; static const int PT_FACE_DISTANCE = 33; + static const int PROJ_PT_DISTANCE = 34; static const int PT_IN_PLANE = 41; static const int PT_ON_LINE = 42; static const int PT_ON_FACE = 43; @@ -609,6 +610,7 @@ public: void DoLineWithArrows(Vector ref, Vector a, Vector b, bool onlyOneExt); int DoLineTrimmedAgainstBox(Vector ref, Vector a, Vector b); void DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu); + void StippledLine(Vector a, Vector b); void DoProjectedPoint(Vector *p); void DoEqualLenTicks(Vector a, Vector b, Vector gn); void DoEqualRadiusTicks(hEntity he); diff --git a/wishlist.txt b/wishlist.txt index e9944af..5a95c00 100644 --- a/wishlist.txt +++ b/wishlist.txt @@ -1,6 +1,6 @@ replace show/hide links with icons? lock point where dragged constraint -projected and signed distance constraints +remove toolbar icons for sketch in 3d, add View -> Align to Workplane rounding, as a special group associative entities from solid model, as a special group