diff --git a/constraint.cpp b/constraint.cpp index 80ec12c..e25bbce 100644 --- a/constraint.cpp +++ b/constraint.cpp @@ -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 *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); diff --git a/drawconstraint.cpp b/drawconstraint.cpp index ac5895e..e71951e 100644 --- a/drawconstraint.cpp +++ b/drawconstraint.cpp @@ -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)); diff --git a/entity.cpp b/entity.cpp index 0af5511..057d27f 100644 --- a/entity.cpp +++ b/entity.cpp @@ -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 *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(); } diff --git a/expr.cpp b/expr.cpp index 1904cb6..dec32df 100644 --- a/expr.cpp +++ b/expr.cpp @@ -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(); diff --git a/expr.h b/expr.h index 1d68e77..faa2a76 100644 --- a/expr.h +++ b/expr.h @@ -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); diff --git a/sketch.h b/sketch.h index 593fed5..858a0a6 100644 --- a/sketch.h +++ b/sketch.h @@ -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;