diff --git a/constraint.cpp b/constraint.cpp index 7d107949..63ef5657 100644 --- a/constraint.cpp +++ b/constraint.cpp @@ -154,13 +154,17 @@ void Constraint::MenuConstrain(int id) { break; case GraphicsWindow::MNU_SYMMETRIC: - if(gs.points == 2 && gs.workplanes == 1 && gs.n == 3) { - c.type = SYMMETRIC; + if(gs.points == 2 && + ((gs.workplanes == 1 && gs.n == 3) || + (gs.n == 2))) + { c.entityA = gs.entity[0]; c.ptA = gs.point[0]; c.ptB = gs.point[1]; - } else if(gs.lineSegments == 1 && gs.workplanes == 1 && gs.n == 2) { - c.type = SYMMETRIC; + } else if(gs.lineSegments == 1 && + ((gs.workplanes == 1 && gs.n == 2) || + (gs.n == 1))) + { int i = SS.GetEntity(gs.entity[0])->IsWorkplane() ? 1 : 0; Entity *line = SS.GetEntity(gs.entity[i]); c.entityA = gs.entity[1-i]; @@ -170,6 +174,26 @@ void Constraint::MenuConstrain(int id) { Error("Bad selection for symmetric constraint."); return; } + if(c.entityA.v == Entity::NO_ENTITY.v) { + if(c.workplane.v == Entity::FREE_IN_3D.v) { + Error("Must be locked in to workplane when constraining " + "symmetric without an explicit symmetry plane."); + return; + } + Vector pa = SS.GetEntity(c.ptA)->PointGetNum(); + Vector pb = SS.GetEntity(c.ptB)->PointGetNum(); + Vector dp = pa.Minus(pb); + Entity *norm = SS.GetEntity(c.workplane)->Normal();; + Vector u = norm->NormalU(), v = norm->NormalV(); + if(fabs(dp.Dot(u)) > fabs(dp.Dot(v))) { + c.type = SYMMETRIC_HORIZ; + } else { + c.type = SYMMETRIC_VERT; + } + } else { + // Symmetry with a symmetry plane specified explicitly. + c.type = SYMMETRIC; + } AddConstraint(&c); break; @@ -567,6 +591,25 @@ void Constraint::Generate(IdList *l) { } break; + case SYMMETRIC_HORIZ: + case SYMMETRIC_VERT: { + Entity *a = SS.GetEntity(ptA); + Entity *b = SS.GetEntity(ptB); + + Expr *au, *av, *bu, *bv; + a->PointGetExprsInWorkplane(workplane, &au, &av); + b->PointGetExprsInWorkplane(workplane, &bu, &bv); + + if(type == SYMMETRIC_HORIZ) { + AddEq(l, av->Minus(bv), 0); + AddEq(l, au->Plus(bu), 0); + } else { + AddEq(l, au->Minus(bu), 0); + AddEq(l, av->Plus(bv), 0); + } + break; + } + case HORIZONTAL: case VERTICAL: { hEntity ha, hb; diff --git a/drawconstraint.cpp b/drawconstraint.cpp index 396049b0..84c3ae7a 100644 --- a/drawconstraint.cpp +++ b/drawconstraint.cpp @@ -307,10 +307,17 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) { break; } - case SYMMETRIC: { + { + Vector n; + case SYMMETRIC: + n = SS.GetEntity(entityA)->Normal()->NormalN(); goto s; + case SYMMETRIC_HORIZ: + n = SS.GetEntity(workplane)->Normal()->NormalU(); goto s; + case SYMMETRIC_VERT: + n = SS.GetEntity(workplane)->Normal()->NormalV(); goto s; +s: Vector a = SS.GetEntity(ptA)->PointGetNum(); Vector b = SS.GetEntity(ptB)->PointGetNum(); - Vector n = SS.GetEntity(entityA)->Normal()->NormalN(); for(int i = 0; i < 2; i++) { Vector tail = (i == 0) ? a : b; Vector d = (i == 0) ? b : a; diff --git a/sketch.h b/sketch.h index 618c3b01..7ae0f48f 100644 --- a/sketch.h +++ b/sketch.h @@ -331,6 +331,8 @@ public: static const int EQUAL_LENGTH_LINES = 50; static const int LENGTH_RATIO = 51; static const int SYMMETRIC = 60; + static const int SYMMETRIC_HORIZ = 61; + static const int SYMMETRIC_VERT = 62; static const int AT_MIDPOINT = 70; static const int HORIZONTAL = 80; static const int VERTICAL = 81;