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.entityA = gs.entity[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 {
Error("Bad selection for at midpoint constraint.");
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) {
IdList<Equation,hEquation> l;
// 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 m = (a.Plus(b)).ScaledBy(Expr::FromConstant(0.5));
ExprVector p = SS.GetEntity(ptA)->PointGetExprs();
AddEq(l, (m.x)->Minus(p.x), 0);
AddEq(l, (m.y)->Minus(p.y), 1);
AddEq(l, (m.z)->Minus(p.z), 2);
if(ptA.v) {
ExprVector p = SS.GetEntity(ptA)->PointGetExprs();
AddEq(l, (m.x)->Minus(p.x), 0);
AddEq(l, (m.y)->Minus(p.y), 1);
AddEq(l, (m.z)->Minus(p.z), 2);
} else {
AddEq(l, PointPlaneDistance(m, entityB), 0);
}
} else {
Entity *ln = SS.GetEntity(entityA);
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 *mv = Expr::FromConstant(0.5)->Times(av->Plus(bv));
Entity *p = SS.GetEntity(ptA);
Expr *pu, *pv;
p->PointGetExprsInWorkplane(workplane, &pu, &pv);
AddEq(l, pu->Minus(mu), 0);
AddEq(l, pv->Minus(mv), 1);
if(ptA.v) {
Entity *p = SS.GetEntity(ptA);
Expr *pu, *pv;
p->PointGetExprsInWorkplane(workplane, &pu, &pv);
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;
@ -411,17 +434,17 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
Expr *mu = Expr::FromConstant(0.5)->Times(au->Plus(bu));
Expr *mv = Expr::FromConstant(0.5)->Times(av->Plus(bv));
ExprVector u, v, o;
Entity *w = SS.GetEntity(workplane);
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);
ExprVector m = PointInThreeSpace(workplane, mu, mv);
AddEq(l, PointPlaneDistance(m, plane->h), 0);
// Construct a vector within the workplane that is normal
// to the symmetry pane's normal (i.e., that lies in the
// plane of symmetry). The line connecting the points is
// perpendicular to that constructed vector.
ExprVector u, v;
Entity *w = SS.GetEntity(workplane);
w->WorkplaneGetBasisExprs(&u, &v);
ExprVector pa = a->PointGetExprs();
ExprVector pb = b->PointGetExprs();
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 offset = (a.Minus(b)).Cross(gn);
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) {
glPushMatrix();
@ -177,7 +180,7 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
(type == AT_MIDPOINT) ? "M" : NULL)));
glPopMatrix();
} 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);
}
} else {

View File

@ -316,6 +316,7 @@ public:
static Expr *PointLineDistance(hEntity workplane, hEntity pt, hEntity ln);
static Expr *PointPlaneDistance(ExprVector p, hEntity plane);
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);
};