Add symmetric about line constraint. This applies only when locked

in a workplane, since it would otherwise be ambiguous.

[git-p4: depot-paths = "//depot/solvespace/": change = 1817]
solver
Jonathan Westhues 2008-07-01 22:59:49 -08:00
parent 8a70efed05
commit 48c5018613
5 changed files with 79 additions and 5 deletions

View File

@ -22,6 +22,7 @@ char *Constraint::DescriptionString(void) {
case SYMMETRIC: s = "symmetric"; break; case SYMMETRIC: s = "symmetric"; break;
case SYMMETRIC_HORIZ: s = "symmetric-h"; break; case SYMMETRIC_HORIZ: s = "symmetric-h"; break;
case SYMMETRIC_VERT: s = "symmetric-v"; break; case SYMMETRIC_VERT: s = "symmetric-v"; break;
case SYMMETRIC_LINE: s = "symmetric-line"; break;
case AT_MIDPOINT: s = "at-midpoint"; break; case AT_MIDPOINT: s = "at-midpoint"; break;
case HORIZONTAL: s = "horizontal"; break; case HORIZONTAL: s = "horizontal"; break;
case VERTICAL: s = "vertical"; break; case VERTICAL: s = "vertical"; break;
@ -70,7 +71,7 @@ void Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) {
void Constraint::MenuConstrain(int id) { void Constraint::MenuConstrain(int id) {
Constraint c; Constraint c;
memset(&c, 0, sizeof(c)); ZERO(&c);
c.group = SS.GW.activeGroup; c.group = SS.GW.activeGroup;
c.workplane = SS.GW.ActiveWorkplane(); c.workplane = SS.GW.ActiveWorkplane();
@ -235,11 +236,37 @@ void Constraint::MenuConstrain(int id) {
c.entityA = gs.entity[1-i]; c.entityA = gs.entity[1-i];
c.ptA = line->point[0]; c.ptA = line->point[0];
c.ptB = line->point[1]; c.ptB = line->point[1];
} else if(SS.GW.LockedInWorkplane()
&& gs.lineSegments == 2 && gs.n == 2)
{
Entity *l0 = SS.GetEntity(gs.entity[0]),
*l1 = SS.GetEntity(gs.entity[1]);
if((l1->group.v != SS.GW.activeGroup.v) ||
(l1->construction && !(l0->construction)))
{
SWAP(Entity *, l0, l1);
}
c.ptA = l1->point[0];
c.ptB = l1->point[1];
c.entityA = l0->h;
c.type = SYMMETRIC_LINE;
} else if(SS.GW.LockedInWorkplane()
&& gs.lineSegments == 1 && gs.points == 2 && gs.n == 3)
{
c.ptA = gs.point[0];
c.ptB = gs.point[1];
c.entityA = gs.entity[0];
c.type = SYMMETRIC_LINE;
} else { } else {
Error("Bad selection for symmetric constraint."); Error("Bad selection for symmetric constraint.");
return; return;
} }
if(c.entityA.v == Entity::NO_ENTITY.v) { if(c.type != 0) {
// Already done, symmetry about a line segment in a workplane
} else if(c.entityA.v == Entity::NO_ENTITY.v) {
// Horizontal / vertical symmetry, implicit symmetry plane
// normal to the workplane
if(c.workplane.v == Entity::FREE_IN_3D.v) { if(c.workplane.v == Entity::FREE_IN_3D.v) {
Error("Must be locked in to workplane when constraining " Error("Must be locked in to workplane when constraining "
"symmetric without an explicit symmetry plane."); "symmetric without an explicit symmetry plane.");
@ -832,6 +859,39 @@ void Constraint::GenerateReal(IdList<Equation,hEquation> *l) {
break; break;
} }
case SYMMETRIC_LINE: {
Entity *pa = SS.GetEntity(ptA);
Entity *pb = SS.GetEntity(ptB);
Expr *pau, *pav, *pbu, *pbv;
pa->PointGetExprsInWorkplane(workplane, &pau, &pav);
pb->PointGetExprsInWorkplane(workplane, &pbu, &pbv);
Entity *ln = SS.GetEntity(entityA);
Entity *la = SS.GetEntity(ln->point[0]);
Entity *lb = SS.GetEntity(ln->point[1]);
Expr *lau, *lav, *lbu, *lbv;
la->PointGetExprsInWorkplane(workplane, &lau, &lav);
lb->PointGetExprsInWorkplane(workplane, &lbu, &lbv);
Expr *dpu = pbu->Minus(pau), *dpv = pbv->Minus(pav);
Expr *dlu = lbu->Minus(lau), *dlv = lbv->Minus(lav);
// The line through the points is perpendicular to the line
// of symmetry.
AddEq(l, (dlu->Times(dpu))->Plus(dlv->Times(dpv)), 0);
// And the signed distances of the points to the line are
// equal in magnitude and opposite in sign, so sum to zero
Expr *dista = (dlv->Times(lau->Minus(pau)))->Minus(
(dlu->Times(lav->Minus(pav))));
Expr *distb = (dlv->Times(lau->Minus(pbu)))->Minus(
(dlu->Times(lav->Minus(pbv))));
AddEq(l, dista->Plus(distb), 1);
break;
}
case HORIZONTAL: case HORIZONTAL:
case VERTICAL: { case VERTICAL: {
hEntity ha, hb; hEntity ha, hb;

View File

@ -491,9 +491,21 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
n = SS.GetEntity(workplane)->Normal()->NormalU(); goto s; n = SS.GetEntity(workplane)->Normal()->NormalU(); goto s;
case SYMMETRIC_VERT: case SYMMETRIC_VERT:
n = SS.GetEntity(workplane)->Normal()->NormalV(); goto s; n = SS.GetEntity(workplane)->Normal()->NormalV(); goto s;
case SYMMETRIC_LINE: {
Entity *ln = SS.GetEntity(entityA);
Vector la = SS.GetEntity(ln->point[0])->PointGetNum(),
lb = SS.GetEntity(ln->point[1])->PointGetNum();
la = la.ProjectInto(workplane);
lb = lb.ProjectInto(workplane);
n = lb.Minus(la);
Vector nw = SS.GetEntity(workplane)->Normal()->NormalN();
n = n.RotatedAbout(nw, PI/2);
goto s;
}
s: s:
Vector a = SS.GetEntity(ptA)->PointGetNum(); Vector a = SS.GetEntity(ptA)->PointGetNum();
Vector b = SS.GetEntity(ptB)->PointGetNum(); Vector b = SS.GetEntity(ptB)->PointGetNum();
for(int i = 0; i < 2; i++) { for(int i = 0; i < 2; i++) {
Vector tail = (i == 0) ? a : b; Vector tail = (i == 0) ? a : b;
Vector d = (i == 0) ? b : a; Vector d = (i == 0) ? b : a;

View File

@ -447,6 +447,7 @@ public:
static const int SYMMETRIC = 60; static const int SYMMETRIC = 60;
static const int SYMMETRIC_HORIZ = 61; static const int SYMMETRIC_HORIZ = 61;
static const int SYMMETRIC_VERT = 62; static const int SYMMETRIC_VERT = 62;
static const int SYMMETRIC_LINE = 63;
static const int AT_MIDPOINT = 70; static const int AT_MIDPOINT = 70;
static const int HORIZONTAL = 80; static const int HORIZONTAL = 80;
static const int VERTICAL = 81; static const int VERTICAL = 81;

View File

@ -463,10 +463,11 @@ void TextWindow::ShowGroupInfo(void) {
if(c->group.v == shown->group.v) { if(c->group.v == shown->group.v) {
char *s = c->DescriptionString(); char *s = c->DescriptionString();
Printf(false, "%Bp %Fl%Ll%D%f%h%s%E", Printf(false, "%Bp %Fl%Ll%D%f%h%s%E %s",
(a & 1) ? 'd' : 'a', (a & 1) ? 'd' : 'a',
c->h.v, (&TextWindow::ScreenSelectConstraint), c->h.v, (&TextWindow::ScreenSelectConstraint),
(&TextWindow::ScreenHoverConstraint), s); (&TextWindow::ScreenHoverConstraint), s,
c->reference ? "(ref)" : "");
a++; a++;
} }
} }

View File

@ -8,7 +8,7 @@ auto-generate circles and faces when lathing
copy the section geometry to other end when sweeping copy the section geometry to other end when sweeping
cylindrical faces cylindrical faces
draw explicit edges draw explicit edges
symmetric about line segment perpendicular constraint
long term long term