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
parent
8a70efed05
commit
48c5018613
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
1
sketch.h
1
sketch.h
|
@ -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;
|
||||||
|
|
|
@ -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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue