Add point-face distance constraints.

[git-p4: depot-paths = "//depot/solvespace/": change = 1778]
solver
Jonathan Westhues 2008-06-06 00:46:55 -08:00
parent 8a0809e6a0
commit ccbda13a03
6 changed files with 65 additions and 15 deletions

View File

@ -11,6 +11,7 @@ char *Constraint::DescriptionString(void) {
case PT_PT_DISTANCE: s = "pt-pt-distance"; break;
case PT_LINE_DISTANCE: s = "pt-line-distance"; break;
case PT_PLANE_DISTANCE: s = "pt-plane-distance"; break;
case PT_FACE_DISTANCE: s = "pt-face-distance"; break;
case PT_IN_PLANE: s = "pt-in-plane"; break;
case PT_ON_LINE: s = "pt-on-line"; break;
case PT_ON_FACE: s = "pt-on-face"; break;
@ -92,6 +93,10 @@ void Constraint::MenuConstrain(int id) {
c.type = PT_LINE_DISTANCE;
c.ptA = gs.point[0];
c.entityA = gs.entity[0];
} else if(gs.faces == 1 && gs.points == 1 && gs.n == 2) {
c.type = PT_FACE_DISTANCE;
c.ptA = gs.point[0];
c.entityA = gs.face[0];
} else if(gs.circlesOrArcs == 1 && gs.n == 1) {
c.type = DIAMETER;
c.entityA = gs.entity[0];
@ -494,6 +499,15 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
break;
}
case PT_FACE_DISTANCE: {
ExprVector pt = SS.GetEntity(ptA)->PointGetExprs();
Entity *f = SS.GetEntity(entityA);
ExprVector p0 = f->FaceGetPointExprs();
ExprVector n = f->FaceGetNormalExprs();
AddEq(l, (pt.Minus(p0)).Dot(n)->Minus(exprA), 0);
break;
}
case EQUAL_LENGTH_LINES: {
Entity *a = SS.GetEntity(entityA);
Entity *b = SS.GetEntity(entityB);

View File

@ -4,6 +4,7 @@ bool Constraint::HasLabel(void) {
switch(type) {
case PT_LINE_DISTANCE:
case PT_PLANE_DISTANCE:
case PT_FACE_DISTANCE:
case PT_PT_DISTANCE:
case DIAMETER:
case LENGTH_RATIO:
@ -112,11 +113,19 @@ void Constraint::DrawOrGetDistance(Vector *labelPos) {
break;
}
case PT_FACE_DISTANCE:
case PT_PLANE_DISTANCE: {
Vector pt = SS.GetEntity(ptA)->PointGetNum();
Entity *plane = SS.GetEntity(entityA);
Vector n = plane->Normal()->NormalN();
Vector p = plane->WorkplaneGetOffset();
Entity *enta = SS.GetEntity(entityA);
Vector n, p;
if(type == PT_PLANE_DISTANCE) {
n = enta->Normal()->NormalN();
p = enta->WorkplaneGetOffset();
} else {
n = enta->FaceGetNormalNum();
p = enta->FaceGetPointNum();
}
double d = (p.Minus(pt)).Dot(n);
Vector closest = pt.Plus(n.WithMagnitude(d));

View File

@ -570,13 +570,17 @@ bool Entity::IsFace(void) {
ExprVector Entity::FaceGetNormalExprs(void) {
ExprVector r;
if(type == FACE_NORMAL_PT) {
r = ExprVector::From(numNormal.vx, numNormal.vy, numNormal.vz);
Vector v = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz);
r = ExprVector::From(v.WithMagnitude(1));
} else if(type == FACE_XPROD) {
ExprVector vc = ExprVector::From(param[0], param[1], param[2]);
ExprVector vn = ExprVector::From(numVector);
r = vc.Cross(vn);
r = r.WithMagnitude(Expr::From(1.0));
} else if(type == FACE_N_ROT_TRANS) {
// The numerical normal vector gets the rotation
// The numerical normal vector gets the rotation; the numerical
// normal has magnitude one, and the rotation doesn't change that,
// so there's no need to fix it up.
r = ExprVector::From(numNormal.vx, numNormal.vy, numNormal.vz);
ExprQuaternion q =
ExprQuaternion::From(param[3], param[4], param[5], param[6]);
@ -598,7 +602,7 @@ Vector Entity::FaceGetNormalNum(void) {
Quaternion q = Quaternion::From(param[3], param[4], param[5], param[6]);
r = q.Rotate(r);
} else oops();
return r;
return r.WithMagnitude(1);
}
ExprVector Entity::FaceGetPointExprs(void) {
@ -619,6 +623,22 @@ ExprVector Entity::FaceGetPointExprs(void) {
return r;
}
Vector Entity::FaceGetPointNum(void) {
Vector r;
if(type == FACE_NORMAL_PT) {
r = SS.GetEntity(point[0])->PointGetNum();
} else if(type == FACE_XPROD) {
r = numPoint;
} else if(type == FACE_N_ROT_TRANS) {
// The numerical point gets the rotation and translation.
Vector trans = Vector::From(param[0], param[1], param[2]);
Quaternion q = Quaternion::From(param[3], param[4], param[5], param[6]);
r = q.Rotate(numPoint);
r = r.Plus(trans);
} else oops();
return r;
}
void Entity::AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index) {
Equation eq;
eq.e = expr;
@ -656,10 +676,9 @@ void Entity::CalculateNumerical(void) {
actDistance = DistanceGetNum();
}
if(IsFace()) {
ExprVector p = FaceGetPointExprs();
ExprVector n = FaceGetNormalExprs();
numPoint = Vector::From( p.x->Eval(), p.y->Eval(), p.z->Eval());
numNormal = Quaternion::From(0, n.x->Eval(), n.y->Eval(), n.z->Eval());
numPoint = FaceGetPointNum();
Vector n = FaceGetNormalNum();
numNormal = Quaternion::From(0, n.x, n.y, n.z);
}
visible = IsVisible();
}

View File

@ -69,6 +69,11 @@ ExprVector ExprVector::ScaledBy(Expr *s) {
return r;
}
ExprVector ExprVector::WithMagnitude(Expr *s) {
Expr *m = Magnitude();
return ScaledBy(s->Div(m));
}
Expr *ExprVector::Magnitude(void) {
Expr *r;
r = x->Square();

1
expr.h
View File

@ -134,6 +134,7 @@ public:
Expr *Dot(ExprVector b);
ExprVector Cross(ExprVector b);
ExprVector ScaledBy(Expr *s);
ExprVector WithMagnitude(Expr *s);
Expr *Magnitude(void);
Vector Eval(void);

View File

@ -318,6 +318,7 @@ public:
ExprVector FaceGetNormalExprs(void);
Vector FaceGetNormalNum(void);
ExprVector FaceGetPointExprs(void);
Vector FaceGetPointNum(void);
bool IsPoint(void);
// Applies for any of the point types
@ -399,11 +400,12 @@ public:
static const int USER_EQUATION = 10;
static const int POINTS_COINCIDENT = 20;
static const int PT_PT_DISTANCE = 30;
static const int PT_LINE_DISTANCE = 31;
static const int PT_PLANE_DISTANCE = 32;
static const int PT_IN_PLANE = 40;
static const int PT_ON_LINE = 41;
static const int PT_ON_FACE = 42;
static const int PT_PLANE_DISTANCE = 31;
static const int PT_LINE_DISTANCE = 32;
static const int PT_FACE_DISTANCE = 33;
static const int PT_IN_PLANE = 41;
static const int PT_ON_LINE = 42;
static const int PT_ON_FACE = 43;
static const int EQUAL_LENGTH_LINES = 50;
static const int LENGTH_RATIO = 51;
static const int SYMMETRIC = 60;