Make at-midpoint constraint also work to constrain midpoint of a

line segment on a plane. And simplify that code a bit, and improve
display.

[git-p4: depot-paths = "//depot/solvespace/": change = 1702]
solver
Jonathan Westhues 2008-04-30 22:53:50 -08:00
parent b7e8b99f37
commit 658b7df50f
3 changed files with 43 additions and 16 deletions

View File

@ -96,6 +96,11 @@ void Constraint::MenuConstrain(int id) {
c.type = AT_MIDPOINT; c.type = AT_MIDPOINT;
c.entityA = gs.entity[0]; c.entityA = gs.entity[0];
c.ptA = gs.point[0]; c.ptA = gs.point[0];
} else if(gs.lineSegments == 1 && gs.planes == 1 && gs.n == 2) {
c.type = AT_MIDPOINT;
int i = SS.GetEntity(gs.entity[0])->HasPlane() ? 1 : 0;
c.entityA = gs.entity[i];
c.entityB = gs.entity[1-i];
} else { } else {
Error("Bad selection for at midpoint constraint."); Error("Bad selection for at midpoint constraint.");
return; return;
@ -265,6 +270,15 @@ Expr *Constraint::Distance(hEntity wrkpl, hEntity hpa, hEntity hpb) {
} }
} }
ExprVector Constraint::PointInThreeSpace(hEntity workplane, Expr *u, Expr *v) {
ExprVector ub, vb, ob;
Entity *w = SS.GetEntity(workplane);
w->WorkplaneGetBasisExprs(&ub, &vb);
ob = w->WorkplaneGetOffsetExprs();
return (ub.ScaledBy(u)).Plus(vb.ScaledBy(v)).Plus(ob);
}
void Constraint::ModifyToSatisfy(void) { void Constraint::ModifyToSatisfy(void) {
IdList<Equation,hEquation> l; IdList<Equation,hEquation> l;
// An uninit IdList could lead us to free some random address, bad. // An uninit IdList could lead us to free some random address, bad.
@ -357,10 +371,14 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
ExprVector b = SS.GetEntity(ln->point[1])->PointGetExprs(); ExprVector b = SS.GetEntity(ln->point[1])->PointGetExprs();
ExprVector m = (a.Plus(b)).ScaledBy(Expr::FromConstant(0.5)); ExprVector m = (a.Plus(b)).ScaledBy(Expr::FromConstant(0.5));
ExprVector p = SS.GetEntity(ptA)->PointGetExprs(); if(ptA.v) {
AddEq(l, (m.x)->Minus(p.x), 0); ExprVector p = SS.GetEntity(ptA)->PointGetExprs();
AddEq(l, (m.y)->Minus(p.y), 1); AddEq(l, (m.x)->Minus(p.x), 0);
AddEq(l, (m.z)->Minus(p.z), 2); AddEq(l, (m.y)->Minus(p.y), 1);
AddEq(l, (m.z)->Minus(p.z), 2);
} else {
AddEq(l, PointPlaneDistance(m, entityB), 0);
}
} else { } else {
Entity *ln = SS.GetEntity(entityA); Entity *ln = SS.GetEntity(entityA);
Entity *a = SS.GetEntity(ln->point[0]); Entity *a = SS.GetEntity(ln->point[0]);
@ -372,11 +390,16 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
Expr *mu = Expr::FromConstant(0.5)->Times(au->Plus(bu)); Expr *mu = Expr::FromConstant(0.5)->Times(au->Plus(bu));
Expr *mv = Expr::FromConstant(0.5)->Times(av->Plus(bv)); Expr *mv = Expr::FromConstant(0.5)->Times(av->Plus(bv));
Entity *p = SS.GetEntity(ptA); if(ptA.v) {
Expr *pu, *pv; Entity *p = SS.GetEntity(ptA);
p->PointGetExprsInWorkplane(workplane, &pu, &pv); Expr *pu, *pv;
AddEq(l, pu->Minus(mu), 0); p->PointGetExprsInWorkplane(workplane, &pu, &pv);
AddEq(l, pv->Minus(mv), 1); AddEq(l, pu->Minus(mu), 0);
AddEq(l, pv->Minus(mv), 1);
} else {
ExprVector m = PointInThreeSpace(workplane, mu, mv);
AddEq(l, PointPlaneDistance(m, entityB), 0);
}
} }
break; break;
@ -411,17 +434,17 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
Expr *mu = Expr::FromConstant(0.5)->Times(au->Plus(bu)); Expr *mu = Expr::FromConstant(0.5)->Times(au->Plus(bu));
Expr *mv = Expr::FromConstant(0.5)->Times(av->Plus(bv)); Expr *mv = Expr::FromConstant(0.5)->Times(av->Plus(bv));
ExprVector u, v, o; ExprVector m = PointInThreeSpace(workplane, mu, mv);
Entity *w = SS.GetEntity(workplane); AddEq(l, PointPlaneDistance(m, plane->h), 0);
w->WorkplaneGetBasisExprs(&u, &v);
o = w->WorkplaneGetOffsetExprs();
ExprVector m = (u.ScaledBy(mu)).Plus(v.ScaledBy(mv)).Plus(o);
AddEq(l, PointPlaneDistance(m ,plane->h), 0);
// Construct a vector within the workplane that is normal // Construct a vector within the workplane that is normal
// to the symmetry pane's normal (i.e., that lies in the // to the symmetry pane's normal (i.e., that lies in the
// plane of symmetry). The line connecting the points is // plane of symmetry). The line connecting the points is
// perpendicular to that constructed vector. // perpendicular to that constructed vector.
ExprVector u, v;
Entity *w = SS.GetEntity(workplane);
w->WorkplaneGetBasisExprs(&u, &v);
ExprVector pa = a->PointGetExprs(); ExprVector pa = a->PointGetExprs();
ExprVector pb = b->PointGetExprs(); ExprVector pb = b->PointGetExprs();
ExprVector n; ExprVector n;

View File

@ -166,6 +166,9 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
Vector m = (a.ScaledBy(0.5)).Plus(b.ScaledBy(0.5)); Vector m = (a.ScaledBy(0.5)).Plus(b.ScaledBy(0.5));
Vector offset = (a.Minus(b)).Cross(gn); Vector offset = (a.Minus(b)).Cross(gn);
offset = offset.WithMagnitude(13/SS.GW.scale); offset = offset.WithMagnitude(13/SS.GW.scale);
// Draw midpoint constraint on other side of line, so that
// a line can be midpoint and horizontal at same time.
if(type == AT_MIDPOINT) offset = offset.ScaledBy(-1);
if(dogd.drawing) { if(dogd.drawing) {
glPushMatrix(); glPushMatrix();
@ -177,7 +180,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
(type == AT_MIDPOINT) ? "M" : NULL))); (type == AT_MIDPOINT) ? "M" : NULL)));
glPopMatrix(); glPopMatrix();
} else { } else {
Point2d ref = SS.GW.ProjectPoint(m); Point2d ref = SS.GW.ProjectPoint(m.Plus(offset));
dogd.dmin = min(dogd.dmin, ref.DistanceTo(dogd.mp)-10); dogd.dmin = min(dogd.dmin, ref.DistanceTo(dogd.mp)-10);
} }
} else { } else {

View File

@ -316,6 +316,7 @@ public:
static Expr *PointLineDistance(hEntity workplane, hEntity pt, hEntity ln); static Expr *PointLineDistance(hEntity workplane, hEntity pt, hEntity ln);
static Expr *PointPlaneDistance(ExprVector p, hEntity plane); static Expr *PointPlaneDistance(ExprVector p, hEntity plane);
static Expr *VectorsParallel(int eq, ExprVector a, ExprVector b); static Expr *VectorsParallel(int eq, ExprVector a, ExprVector b);
static ExprVector PointInThreeSpace(hEntity workplane, Expr *u, Expr *v);
static void ConstrainCoincident(hEntity ptA, hEntity ptB); static void ConstrainCoincident(hEntity ptA, hEntity ptB);
}; };