2008-04-01 10:48:44 +00:00
|
|
|
#include "solvespace.h"
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
const hEntity EntityBase::FREE_IN_3D = { 0 };
|
|
|
|
const hEntity EntityBase::NO_ENTITY = { 0 };
|
2008-06-06 08:14:37 +00:00
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
bool EntityBase::HasVector(void) {
|
2008-05-09 05:33:23 +00:00
|
|
|
switch(type) {
|
|
|
|
case LINE_SEGMENT:
|
|
|
|
case NORMAL_IN_3D:
|
|
|
|
case NORMAL_IN_2D:
|
2008-05-11 06:09:46 +00:00
|
|
|
case NORMAL_N_COPY:
|
|
|
|
case NORMAL_N_ROT:
|
2008-06-01 08:29:59 +00:00
|
|
|
case NORMAL_N_ROT_AA:
|
2008-05-09 05:33:23 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
ExprVector EntityBase::VectorGetExprs(void) {
|
2008-05-09 05:33:23 +00:00
|
|
|
switch(type) {
|
|
|
|
case LINE_SEGMENT:
|
2009-04-19 05:53:16 +00:00
|
|
|
return (SK.GetEntity(point[0])->PointGetExprs()).Minus(
|
|
|
|
SK.GetEntity(point[1])->PointGetExprs());
|
2008-05-09 05:33:23 +00:00
|
|
|
|
|
|
|
case NORMAL_IN_3D:
|
|
|
|
case NORMAL_IN_2D:
|
2008-05-11 06:09:46 +00:00
|
|
|
case NORMAL_N_COPY:
|
|
|
|
case NORMAL_N_ROT:
|
2008-06-01 08:29:59 +00:00
|
|
|
case NORMAL_N_ROT_AA:
|
2008-05-09 05:33:23 +00:00
|
|
|
return NormalExprsN();
|
|
|
|
|
|
|
|
default: oops();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Vector EntityBase::VectorGetNum(void) {
|
2008-05-11 10:40:37 +00:00
|
|
|
switch(type) {
|
|
|
|
case LINE_SEGMENT:
|
2009-04-19 05:53:16 +00:00
|
|
|
return (SK.GetEntity(point[0])->PointGetNum()).Minus(
|
|
|
|
SK.GetEntity(point[1])->PointGetNum());
|
2008-05-11 10:40:37 +00:00
|
|
|
|
|
|
|
case NORMAL_IN_3D:
|
|
|
|
case NORMAL_IN_2D:
|
|
|
|
case NORMAL_N_COPY:
|
|
|
|
case NORMAL_N_ROT:
|
2008-06-01 08:29:59 +00:00
|
|
|
case NORMAL_N_ROT_AA:
|
2008-05-11 10:40:37 +00:00
|
|
|
return NormalN();
|
|
|
|
|
|
|
|
default: oops();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Vector EntityBase::VectorGetRefPoint(void) {
|
2008-05-09 05:33:23 +00:00
|
|
|
switch(type) {
|
|
|
|
case LINE_SEGMENT:
|
2009-04-19 05:53:16 +00:00
|
|
|
return ((SK.GetEntity(point[0])->PointGetNum()).Plus(
|
|
|
|
SK.GetEntity(point[1])->PointGetNum())).ScaledBy(0.5);
|
2008-05-09 05:33:23 +00:00
|
|
|
|
|
|
|
case NORMAL_IN_3D:
|
|
|
|
case NORMAL_IN_2D:
|
2008-05-11 06:09:46 +00:00
|
|
|
case NORMAL_N_COPY:
|
|
|
|
case NORMAL_N_ROT:
|
2008-06-01 08:29:59 +00:00
|
|
|
case NORMAL_N_ROT_AA:
|
2009-04-19 05:53:16 +00:00
|
|
|
return SK.GetEntity(point[0])->PointGetNum();
|
2008-05-09 05:33:23 +00:00
|
|
|
|
|
|
|
default: oops();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
bool EntityBase::IsCircle(void) {
|
2008-05-16 06:34:06 +00:00
|
|
|
return (type == CIRCLE) || (type == ARC_OF_CIRCLE);
|
2008-05-08 07:30:30 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Expr *EntityBase::CircleGetRadiusExpr(void) {
|
2008-05-12 10:01:44 +00:00
|
|
|
if(type == CIRCLE) {
|
2009-04-19 05:53:16 +00:00
|
|
|
return SK.GetEntity(distance)->DistanceGetExpr();
|
2008-05-12 10:01:44 +00:00
|
|
|
} else if(type == ARC_OF_CIRCLE) {
|
|
|
|
return Constraint::Distance(workplane, point[0], point[1]);
|
|
|
|
} else oops();
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
double EntityBase::CircleGetRadiusNum(void) {
|
2008-05-12 10:01:44 +00:00
|
|
|
if(type == CIRCLE) {
|
2009-04-19 05:53:16 +00:00
|
|
|
return SK.GetEntity(distance)->DistanceGetNum();
|
2008-05-12 10:01:44 +00:00
|
|
|
} else if(type == ARC_OF_CIRCLE) {
|
2009-04-19 05:53:16 +00:00
|
|
|
Vector c = SK.GetEntity(point[0])->PointGetNum();
|
|
|
|
Vector pa = SK.GetEntity(point[1])->PointGetNum();
|
2008-05-12 10:01:44 +00:00
|
|
|
return (pa.Minus(c)).Magnitude();
|
|
|
|
} else oops();
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
void EntityBase::ArcGetAngles(double *thetaa, double *thetab, double *dtheta) {
|
2008-05-12 10:01:44 +00:00
|
|
|
if(type != ARC_OF_CIRCLE) oops();
|
|
|
|
|
|
|
|
Quaternion q = Normal()->NormalGetNum();
|
|
|
|
Vector u = q.RotationU(), v = q.RotationV();
|
|
|
|
|
2009-04-19 05:53:16 +00:00
|
|
|
Vector c = SK.GetEntity(point[0])->PointGetNum();
|
|
|
|
Vector pa = SK.GetEntity(point[1])->PointGetNum();
|
|
|
|
Vector pb = SK.GetEntity(point[2])->PointGetNum();
|
2008-05-12 10:01:44 +00:00
|
|
|
|
|
|
|
Point2d c2 = c.Project2d(u, v);
|
|
|
|
Point2d pa2 = (pa.Project2d(u, v)).Minus(c2);
|
|
|
|
Point2d pb2 = (pb.Project2d(u, v)).Minus(c2);
|
|
|
|
|
|
|
|
*thetaa = atan2(pa2.y, pa2.x);
|
|
|
|
*thetab = atan2(pb2.y, pb2.x);
|
|
|
|
*dtheta = *thetab - *thetaa;
|
2009-01-03 12:27:33 +00:00
|
|
|
// If the endpoints are coincident, call it a full arc, not a zero arc;
|
|
|
|
// useful concept to have when splitting
|
|
|
|
while(*dtheta < 1e-6) *dtheta += 2*PI;
|
2008-05-12 10:01:44 +00:00
|
|
|
while(*dtheta > (2*PI)) *dtheta -= 2*PI;
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
bool EntityBase::IsWorkplane(void) {
|
2008-05-05 11:17:00 +00:00
|
|
|
return (type == WORKPLANE);
|
2008-04-20 11:35:10 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
ExprVector EntityBase::WorkplaneGetOffsetExprs(void) {
|
2009-04-19 05:53:16 +00:00
|
|
|
return SK.GetEntity(point[0])->PointGetExprs();
|
2008-04-23 07:29:19 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Vector EntityBase::WorkplaneGetOffset(void) {
|
2009-04-19 05:53:16 +00:00
|
|
|
return SK.GetEntity(point[0])->PointGetNum();
|
2008-04-21 08:16:38 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
void EntityBase::WorkplaneGetPlaneExprs(ExprVector *n, Expr **dn) {
|
2008-04-27 03:26:27 +00:00
|
|
|
if(type == WORKPLANE) {
|
2008-05-05 11:17:00 +00:00
|
|
|
*n = Normal()->NormalExprsN();
|
2008-04-22 13:14:15 +00:00
|
|
|
|
2009-04-19 05:53:16 +00:00
|
|
|
ExprVector p0 = SK.GetEntity(point[0])->PointGetExprs();
|
2008-04-22 13:14:15 +00:00
|
|
|
// The plane is n dot (p - p0) = 0, or
|
|
|
|
// n dot p - n dot p0 = 0
|
|
|
|
// so dn = n dot p0
|
|
|
|
*dn = p0.Dot(*n);
|
|
|
|
} else {
|
|
|
|
oops();
|
|
|
|
}
|
2008-04-21 08:16:38 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
double EntityBase::DistanceGetNum(void) {
|
2008-05-07 08:19:37 +00:00
|
|
|
if(type == DISTANCE) {
|
2009-04-19 05:53:16 +00:00
|
|
|
return SK.GetParam(param[0])->val;
|
2008-05-11 06:09:46 +00:00
|
|
|
} else if(type == DISTANCE_N_COPY) {
|
2008-05-07 08:19:37 +00:00
|
|
|
return numDistance;
|
|
|
|
} else oops();
|
|
|
|
}
|
2009-04-19 04:28:21 +00:00
|
|
|
Expr *EntityBase::DistanceGetExpr(void) {
|
2008-05-07 08:19:37 +00:00
|
|
|
if(type == DISTANCE) {
|
2008-06-01 08:45:11 +00:00
|
|
|
return Expr::From(param[0]);
|
2008-05-11 06:09:46 +00:00
|
|
|
} else if(type == DISTANCE_N_COPY) {
|
2008-06-01 08:45:11 +00:00
|
|
|
return Expr::From(numDistance);
|
2008-05-07 08:19:37 +00:00
|
|
|
} else oops();
|
|
|
|
}
|
2009-04-19 04:28:21 +00:00
|
|
|
void EntityBase::DistanceForceTo(double v) {
|
2008-05-07 08:19:37 +00:00
|
|
|
if(type == DISTANCE) {
|
2009-04-19 05:53:16 +00:00
|
|
|
(SK.GetParam(param[0]))->val = v;
|
2008-05-11 06:09:46 +00:00
|
|
|
} else if(type == DISTANCE_N_COPY) {
|
2008-05-07 08:19:37 +00:00
|
|
|
// do nothing, it's locked
|
|
|
|
} else oops();
|
|
|
|
}
|
|
|
|
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *EntityBase::Normal(void) {
|
2009-04-19 05:53:16 +00:00
|
|
|
return SK.GetEntity(normal);
|
2008-05-05 11:17:00 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
bool EntityBase::IsPoint(void) {
|
2008-04-19 11:09:47 +00:00
|
|
|
switch(type) {
|
|
|
|
case POINT_IN_3D:
|
|
|
|
case POINT_IN_2D:
|
2008-05-11 10:40:37 +00:00
|
|
|
case POINT_N_COPY:
|
2008-05-11 06:09:46 +00:00
|
|
|
case POINT_N_TRANS:
|
|
|
|
case POINT_N_ROT_TRANS:
|
2008-06-01 08:29:59 +00:00
|
|
|
case POINT_N_ROT_AA:
|
2008-05-11 06:09:46 +00:00
|
|
|
return true;
|
2008-04-19 11:09:47 +00:00
|
|
|
|
2008-05-11 06:09:46 +00:00
|
|
|
default:
|
|
|
|
return false;
|
2008-05-05 06:18:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
bool EntityBase::IsNormal(void) {
|
2008-05-05 06:18:01 +00:00
|
|
|
switch(type) {
|
|
|
|
case NORMAL_IN_3D:
|
|
|
|
case NORMAL_IN_2D:
|
2008-05-11 06:09:46 +00:00
|
|
|
case NORMAL_N_COPY:
|
|
|
|
case NORMAL_N_ROT:
|
2008-06-01 08:29:59 +00:00
|
|
|
case NORMAL_N_ROT_AA:
|
2008-05-11 06:09:46 +00:00
|
|
|
return true;
|
2008-05-05 06:18:01 +00:00
|
|
|
|
|
|
|
default: return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Quaternion EntityBase::NormalGetNum(void) {
|
2008-05-05 06:18:01 +00:00
|
|
|
Quaternion q;
|
|
|
|
switch(type) {
|
|
|
|
case NORMAL_IN_3D:
|
2008-06-02 03:37:58 +00:00
|
|
|
q = Quaternion::From(param[0], param[1], param[2], param[3]);
|
2008-05-05 06:18:01 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NORMAL_IN_2D: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *wrkpl = SK.GetEntity(workplane);
|
|
|
|
EntityBase *norm = SK.GetEntity(wrkpl->normal);
|
2008-05-05 06:18:01 +00:00
|
|
|
q = norm->NormalGetNum();
|
|
|
|
break;
|
|
|
|
}
|
2008-05-11 06:09:46 +00:00
|
|
|
case NORMAL_N_COPY:
|
2008-05-05 06:18:01 +00:00
|
|
|
q = numNormal;
|
|
|
|
break;
|
|
|
|
|
2008-05-11 06:09:46 +00:00
|
|
|
case NORMAL_N_ROT:
|
2008-06-02 03:37:58 +00:00
|
|
|
q = Quaternion::From(param[0], param[1], param[2], param[3]);
|
2008-05-11 06:09:46 +00:00
|
|
|
q = q.Times(numNormal);
|
|
|
|
break;
|
|
|
|
|
2008-06-01 08:29:59 +00:00
|
|
|
case NORMAL_N_ROT_AA: {
|
2008-06-21 22:49:57 +00:00
|
|
|
q = GetAxisAngleQuaternion(0);
|
2008-06-01 08:29:59 +00:00
|
|
|
q = q.Times(numNormal);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-05-05 06:18:01 +00:00
|
|
|
default: oops();
|
|
|
|
}
|
|
|
|
return q;
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
void EntityBase::NormalForceTo(Quaternion q) {
|
2008-05-05 06:18:01 +00:00
|
|
|
switch(type) {
|
|
|
|
case NORMAL_IN_3D:
|
2009-04-19 05:53:16 +00:00
|
|
|
SK.GetParam(param[0])->val = q.w;
|
|
|
|
SK.GetParam(param[1])->val = q.vx;
|
|
|
|
SK.GetParam(param[2])->val = q.vy;
|
|
|
|
SK.GetParam(param[3])->val = q.vz;
|
2008-05-05 06:18:01 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NORMAL_IN_2D:
|
2008-05-11 06:09:46 +00:00
|
|
|
case NORMAL_N_COPY:
|
2008-05-05 06:18:01 +00:00
|
|
|
// There's absolutely nothing to do; these are locked.
|
|
|
|
break;
|
2008-05-29 10:10:12 +00:00
|
|
|
case NORMAL_N_ROT: {
|
|
|
|
Quaternion qp = q.Times(numNormal.Inverse());
|
|
|
|
|
2009-04-19 05:53:16 +00:00
|
|
|
SK.GetParam(param[0])->val = qp.w;
|
|
|
|
SK.GetParam(param[1])->val = qp.vx;
|
|
|
|
SK.GetParam(param[2])->val = qp.vy;
|
|
|
|
SK.GetParam(param[3])->val = qp.vz;
|
2008-05-11 06:09:46 +00:00
|
|
|
break;
|
2008-05-29 10:10:12 +00:00
|
|
|
}
|
2008-05-11 06:09:46 +00:00
|
|
|
|
2008-06-01 08:29:59 +00:00
|
|
|
case NORMAL_N_ROT_AA:
|
|
|
|
// Not sure if I'll bother implementing this one
|
|
|
|
break;
|
|
|
|
|
2008-05-05 06:18:01 +00:00
|
|
|
default: oops();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Vector EntityBase::NormalU(void) {
|
2008-05-05 11:17:00 +00:00
|
|
|
return NormalGetNum().RotationU();
|
|
|
|
}
|
2009-04-19 04:28:21 +00:00
|
|
|
Vector EntityBase::NormalV(void) {
|
2008-05-05 11:17:00 +00:00
|
|
|
return NormalGetNum().RotationV();
|
|
|
|
}
|
2009-04-19 04:28:21 +00:00
|
|
|
Vector EntityBase::NormalN(void) {
|
2008-05-05 11:17:00 +00:00
|
|
|
return NormalGetNum().RotationN();
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
ExprVector EntityBase::NormalExprsU(void) {
|
2008-05-05 11:17:00 +00:00
|
|
|
return NormalGetExprs().RotationU();
|
|
|
|
}
|
2009-04-19 04:28:21 +00:00
|
|
|
ExprVector EntityBase::NormalExprsV(void) {
|
2008-05-05 11:17:00 +00:00
|
|
|
return NormalGetExprs().RotationV();
|
|
|
|
}
|
2009-04-19 04:28:21 +00:00
|
|
|
ExprVector EntityBase::NormalExprsN(void) {
|
2008-05-05 11:17:00 +00:00
|
|
|
return NormalGetExprs().RotationN();
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
ExprQuaternion EntityBase::NormalGetExprs(void) {
|
2008-05-05 06:18:01 +00:00
|
|
|
ExprQuaternion q;
|
|
|
|
switch(type) {
|
|
|
|
case NORMAL_IN_3D:
|
2008-06-01 08:57:16 +00:00
|
|
|
q = ExprQuaternion::From(param[0], param[1], param[2], param[3]);
|
2008-05-05 06:18:01 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case NORMAL_IN_2D: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *wrkpl = SK.GetEntity(workplane);
|
|
|
|
EntityBase *norm = SK.GetEntity(wrkpl->normal);
|
2008-05-05 06:18:01 +00:00
|
|
|
q = norm->NormalGetExprs();
|
|
|
|
break;
|
|
|
|
}
|
2008-05-11 06:09:46 +00:00
|
|
|
case NORMAL_N_COPY:
|
2008-06-01 08:45:11 +00:00
|
|
|
q = ExprQuaternion::From(numNormal);
|
2008-05-05 06:18:01 +00:00
|
|
|
break;
|
|
|
|
|
2008-05-11 06:09:46 +00:00
|
|
|
case NORMAL_N_ROT: {
|
2008-06-01 08:45:11 +00:00
|
|
|
ExprQuaternion orig = ExprQuaternion::From(numNormal);
|
2008-06-01 08:57:16 +00:00
|
|
|
q = ExprQuaternion::From(param[0], param[1], param[2], param[3]);
|
2008-05-11 06:09:46 +00:00
|
|
|
|
|
|
|
q = q.Times(orig);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-06-01 08:29:59 +00:00
|
|
|
case NORMAL_N_ROT_AA: {
|
2008-06-01 08:45:11 +00:00
|
|
|
ExprQuaternion orig = ExprQuaternion::From(numNormal);
|
2008-06-21 22:49:57 +00:00
|
|
|
q = GetAxisAngleQuaternionExprs(0);
|
2008-06-01 08:29:59 +00:00
|
|
|
q = q.Times(orig);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-05-05 06:18:01 +00:00
|
|
|
default: oops();
|
2008-04-22 13:14:15 +00:00
|
|
|
}
|
2008-05-05 06:18:01 +00:00
|
|
|
return q;
|
2008-04-22 13:14:15 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
void EntityBase::PointForceTo(Vector p) {
|
2008-04-19 11:09:47 +00:00
|
|
|
switch(type) {
|
|
|
|
case POINT_IN_3D:
|
2009-04-19 05:53:16 +00:00
|
|
|
SK.GetParam(param[0])->val = p.x;
|
|
|
|
SK.GetParam(param[1])->val = p.y;
|
|
|
|
SK.GetParam(param[2])->val = p.z;
|
2008-04-19 11:09:47 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case POINT_IN_2D: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *c = SK.GetEntity(workplane);
|
2008-05-05 11:17:00 +00:00
|
|
|
p = p.Minus(c->WorkplaneGetOffset());
|
2009-04-19 05:53:16 +00:00
|
|
|
SK.GetParam(param[0])->val = p.Dot(c->Normal()->NormalU());
|
|
|
|
SK.GetParam(param[1])->val = p.Dot(c->Normal()->NormalV());
|
2008-04-19 11:09:47 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-04-27 09:03:01 +00:00
|
|
|
|
2008-05-11 06:09:46 +00:00
|
|
|
case POINT_N_TRANS: {
|
2008-05-27 06:36:59 +00:00
|
|
|
if(timesApplied == 0) break;
|
2008-05-17 08:02:39 +00:00
|
|
|
Vector trans = (p.Minus(numPoint)).ScaledBy(1.0/timesApplied);
|
2009-04-19 05:53:16 +00:00
|
|
|
SK.GetParam(param[0])->val = trans.x;
|
|
|
|
SK.GetParam(param[1])->val = trans.y;
|
|
|
|
SK.GetParam(param[2])->val = trans.z;
|
2008-04-27 09:03:01 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-05-11 06:09:46 +00:00
|
|
|
case POINT_N_ROT_TRANS: {
|
|
|
|
// Force only the translation; leave the rotation unchanged. But
|
|
|
|
// remember that we're working with respect to the rotated
|
|
|
|
// point.
|
|
|
|
Vector trans = p.Minus(PointGetQuaternion().Rotate(numPoint));
|
2009-04-19 05:53:16 +00:00
|
|
|
SK.GetParam(param[0])->val = trans.x;
|
|
|
|
SK.GetParam(param[1])->val = trans.y;
|
|
|
|
SK.GetParam(param[2])->val = trans.z;
|
2008-05-11 06:09:46 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-06-01 08:29:59 +00:00
|
|
|
case POINT_N_ROT_AA: {
|
|
|
|
// Force only the angle; the axis and center of rotation stay
|
2008-06-01 08:45:11 +00:00
|
|
|
Vector offset = Vector::From(param[0], param[1], param[2]);
|
|
|
|
Vector normal = Vector::From(param[4], param[5], param[6]);
|
2008-06-01 08:29:59 +00:00
|
|
|
Vector u = normal.Normal(0), v = normal.Normal(1);
|
|
|
|
Vector po = p.Minus(offset), numo = numPoint.Minus(offset);
|
|
|
|
double thetap = atan2(v.Dot(po), u.Dot(po));
|
|
|
|
double thetan = atan2(v.Dot(numo), u.Dot(numo));
|
|
|
|
double thetaf = (thetap - thetan);
|
2009-04-19 05:53:16 +00:00
|
|
|
double thetai = (SK.GetParam(param[3])->val)*timesApplied*2;
|
2008-06-01 08:29:59 +00:00
|
|
|
double dtheta = thetaf - thetai;
|
|
|
|
// Take the smallest possible change in the actual step angle,
|
|
|
|
// in order to avoid jumps when you cross from +pi to -pi
|
|
|
|
while(dtheta < -PI) dtheta += 2*PI;
|
|
|
|
while(dtheta > PI) dtheta -= 2*PI;
|
2009-04-19 05:53:16 +00:00
|
|
|
SK.GetParam(param[3])->val = (thetai + dtheta)/(timesApplied*2);
|
2008-06-01 08:29:59 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-05-11 10:40:37 +00:00
|
|
|
case POINT_N_COPY:
|
|
|
|
// Nothing to do; it's a static copy
|
|
|
|
break;
|
|
|
|
|
2008-04-19 11:09:47 +00:00
|
|
|
default: oops();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Vector EntityBase::PointGetNum(void) {
|
2008-04-19 11:09:47 +00:00
|
|
|
Vector p;
|
|
|
|
switch(type) {
|
|
|
|
case POINT_IN_3D:
|
2008-06-02 03:37:58 +00:00
|
|
|
p = Vector::From(param[0], param[1], param[2]);
|
2008-04-19 11:09:47 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case POINT_IN_2D: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *c = SK.GetEntity(workplane);
|
2008-05-05 11:17:00 +00:00
|
|
|
Vector u = c->Normal()->NormalU();
|
|
|
|
Vector v = c->Normal()->NormalV();
|
2009-04-19 05:53:16 +00:00
|
|
|
p = u.ScaledBy(SK.GetParam(param[0])->val);
|
|
|
|
p = p.Plus(v.ScaledBy(SK.GetParam(param[1])->val));
|
2008-05-05 11:17:00 +00:00
|
|
|
p = p.Plus(c->WorkplaneGetOffset());
|
2008-04-19 11:09:47 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-04-27 09:03:01 +00:00
|
|
|
|
2008-05-11 06:09:46 +00:00
|
|
|
case POINT_N_TRANS: {
|
2008-06-02 03:37:58 +00:00
|
|
|
Vector trans = Vector::From(param[0], param[1], param[2]);
|
|
|
|
p = numPoint.Plus(trans.ScaledBy(timesApplied));
|
2008-04-27 09:03:01 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-05-11 06:09:46 +00:00
|
|
|
|
|
|
|
case POINT_N_ROT_TRANS: {
|
2008-06-02 03:37:58 +00:00
|
|
|
Vector offset = Vector::From(param[0], param[1], param[2]);
|
2008-05-11 06:09:46 +00:00
|
|
|
Quaternion q = PointGetQuaternion();
|
|
|
|
p = q.Rotate(numPoint);
|
|
|
|
p = p.Plus(offset);
|
|
|
|
break;
|
|
|
|
}
|
2008-05-11 10:40:37 +00:00
|
|
|
|
2008-06-01 08:29:59 +00:00
|
|
|
case POINT_N_ROT_AA: {
|
2008-06-02 03:37:58 +00:00
|
|
|
Vector offset = Vector::From(param[0], param[1], param[2]);
|
2008-06-01 08:29:59 +00:00
|
|
|
Quaternion q = PointGetQuaternion();
|
|
|
|
p = numPoint.Minus(offset);
|
|
|
|
p = q.Rotate(p);
|
|
|
|
p = p.Plus(offset);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-05-11 10:40:37 +00:00
|
|
|
case POINT_N_COPY:
|
|
|
|
p = numPoint;
|
|
|
|
break;
|
|
|
|
|
2008-04-19 11:09:47 +00:00
|
|
|
default: oops();
|
|
|
|
}
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
ExprVector EntityBase::PointGetExprs(void) {
|
2008-04-22 13:14:15 +00:00
|
|
|
ExprVector r;
|
2008-04-20 11:35:10 +00:00
|
|
|
switch(type) {
|
|
|
|
case POINT_IN_3D:
|
2008-06-02 03:37:58 +00:00
|
|
|
r = ExprVector::From(param[0], param[1], param[2]);
|
2008-04-20 11:35:10 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case POINT_IN_2D: {
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *c = SK.GetEntity(workplane);
|
2008-05-05 11:17:00 +00:00
|
|
|
ExprVector u = c->Normal()->NormalExprsU();
|
|
|
|
ExprVector v = c->Normal()->NormalExprsV();
|
|
|
|
r = c->WorkplaneGetOffsetExprs();
|
2008-06-01 08:45:11 +00:00
|
|
|
r = r.Plus(u.ScaledBy(Expr::From(param[0])));
|
|
|
|
r = r.Plus(v.ScaledBy(Expr::From(param[1])));
|
2008-04-20 11:35:10 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-05-11 06:09:46 +00:00
|
|
|
case POINT_N_TRANS: {
|
2008-06-01 08:57:16 +00:00
|
|
|
ExprVector orig = ExprVector::From(numPoint);
|
|
|
|
ExprVector trans = ExprVector::From(param[0], param[1], param[2]);
|
2008-06-01 08:45:11 +00:00
|
|
|
r = orig.Plus(trans.ScaledBy(Expr::From(timesApplied)));
|
2008-04-27 09:03:01 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-05-11 06:09:46 +00:00
|
|
|
case POINT_N_ROT_TRANS: {
|
2008-06-01 08:45:11 +00:00
|
|
|
ExprVector orig = ExprVector::From(numPoint);
|
2008-06-01 08:57:16 +00:00
|
|
|
ExprVector trans = ExprVector::From(param[0], param[1], param[2]);
|
|
|
|
ExprQuaternion q =
|
|
|
|
ExprQuaternion::From(param[3], param[4], param[5], param[6]);
|
2008-05-11 06:09:46 +00:00
|
|
|
orig = q.Rotate(orig);
|
|
|
|
r = orig.Plus(trans);
|
|
|
|
break;
|
|
|
|
}
|
2008-06-01 08:29:59 +00:00
|
|
|
case POINT_N_ROT_AA: {
|
2008-06-01 08:45:11 +00:00
|
|
|
ExprVector orig = ExprVector::From(numPoint);
|
|
|
|
ExprVector trans = ExprVector::From(param[0], param[1], param[2]);
|
2008-06-21 22:49:57 +00:00
|
|
|
ExprQuaternion q = GetAxisAngleQuaternionExprs(3);
|
2008-06-01 08:29:59 +00:00
|
|
|
orig = orig.Minus(trans);
|
|
|
|
orig = q.Rotate(orig);
|
|
|
|
r = orig.Plus(trans);
|
|
|
|
break;
|
|
|
|
}
|
2008-05-11 10:40:37 +00:00
|
|
|
case POINT_N_COPY:
|
2008-06-01 08:45:11 +00:00
|
|
|
r = ExprVector::From(numPoint);
|
2008-05-11 10:40:37 +00:00
|
|
|
break;
|
|
|
|
|
2008-04-20 11:35:10 +00:00
|
|
|
default: oops();
|
|
|
|
}
|
2008-04-22 13:14:15 +00:00
|
|
|
return r;
|
2008-04-20 11:35:10 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
void EntityBase::PointGetExprsInWorkplane(hEntity wrkpl, Expr **u, Expr **v) {
|
2008-04-27 05:00:12 +00:00
|
|
|
if(type == POINT_IN_2D && workplane.v == wrkpl.v) {
|
|
|
|
// They want our coordinates in the form that we've written them,
|
|
|
|
// very nice.
|
2008-06-01 08:45:11 +00:00
|
|
|
*u = Expr::From(param[0]);
|
|
|
|
*v = Expr::From(param[1]);
|
2008-04-27 05:00:12 +00:00
|
|
|
} else {
|
|
|
|
// Get the offset and basis vectors for this weird exotic csys.
|
2009-04-20 07:30:09 +00:00
|
|
|
EntityBase *w = SK.GetEntity(wrkpl);
|
2008-04-27 05:00:12 +00:00
|
|
|
ExprVector wp = w->WorkplaneGetOffsetExprs();
|
2008-05-05 11:17:00 +00:00
|
|
|
ExprVector wu = w->Normal()->NormalExprsU();
|
|
|
|
ExprVector wv = w->Normal()->NormalExprsV();
|
2008-04-27 05:00:12 +00:00
|
|
|
|
|
|
|
// Get our coordinates in three-space, and project them into that
|
|
|
|
// coordinate system.
|
|
|
|
ExprVector ev = PointGetExprs();
|
|
|
|
ev = ev.Minus(wp);
|
|
|
|
*u = ev.Dot(wu);
|
|
|
|
*v = ev.Dot(wv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
void EntityBase::PointForceQuaternionTo(Quaternion q) {
|
2008-05-11 06:09:46 +00:00
|
|
|
if(type != POINT_N_ROT_TRANS) oops();
|
|
|
|
|
2009-04-19 05:53:16 +00:00
|
|
|
SK.GetParam(param[3])->val = q.w;
|
|
|
|
SK.GetParam(param[4])->val = q.vx;
|
|
|
|
SK.GetParam(param[5])->val = q.vy;
|
|
|
|
SK.GetParam(param[6])->val = q.vz;
|
2008-05-11 06:09:46 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Quaternion EntityBase::GetAxisAngleQuaternion(int param0) {
|
2008-06-21 22:49:57 +00:00
|
|
|
Quaternion q;
|
2009-04-19 05:53:16 +00:00
|
|
|
double theta = timesApplied*SK.GetParam(param[param0+0])->val;
|
2008-06-21 22:49:57 +00:00
|
|
|
double s = sin(theta), c = cos(theta);
|
|
|
|
q.w = c;
|
2009-04-19 05:53:16 +00:00
|
|
|
q.vx = s*SK.GetParam(param[param0+1])->val;
|
|
|
|
q.vy = s*SK.GetParam(param[param0+2])->val;
|
|
|
|
q.vz = s*SK.GetParam(param[param0+3])->val;
|
2008-06-21 22:49:57 +00:00
|
|
|
return q;
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
ExprQuaternion EntityBase::GetAxisAngleQuaternionExprs(int param0) {
|
2008-06-21 22:49:57 +00:00
|
|
|
ExprQuaternion q;
|
|
|
|
|
|
|
|
Expr *theta = Expr::From(timesApplied)->Times(
|
|
|
|
Expr::From(param[param0+0]));
|
|
|
|
Expr *c = theta->Cos(), *s = theta->Sin();
|
|
|
|
q.w = c;
|
|
|
|
q.vx = s->Times(Expr::From(param[param0+1]));
|
|
|
|
q.vy = s->Times(Expr::From(param[param0+2]));
|
|
|
|
q.vz = s->Times(Expr::From(param[param0+3]));
|
|
|
|
return q;
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Quaternion EntityBase::PointGetQuaternion(void) {
|
2008-05-11 06:09:46 +00:00
|
|
|
Quaternion q;
|
2008-06-01 08:29:59 +00:00
|
|
|
|
|
|
|
if(type == POINT_N_ROT_AA) {
|
2008-06-21 22:49:57 +00:00
|
|
|
q = GetAxisAngleQuaternion(3);
|
2008-06-01 08:29:59 +00:00
|
|
|
} else if(type == POINT_N_ROT_TRANS) {
|
2008-06-02 03:37:58 +00:00
|
|
|
q = Quaternion::From(param[3], param[4], param[5], param[6]);
|
2008-06-01 08:29:59 +00:00
|
|
|
} else oops();
|
|
|
|
|
2008-05-11 06:09:46 +00:00
|
|
|
return q;
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
bool EntityBase::IsFace(void) {
|
2008-06-02 03:31:37 +00:00
|
|
|
switch(type) {
|
|
|
|
case FACE_NORMAL_PT:
|
|
|
|
case FACE_XPROD:
|
|
|
|
case FACE_N_ROT_TRANS:
|
2008-06-21 22:49:57 +00:00
|
|
|
case FACE_N_TRANS:
|
|
|
|
case FACE_N_ROT_AA:
|
2008-06-02 03:31:37 +00:00
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
ExprVector EntityBase::FaceGetNormalExprs(void) {
|
2008-06-02 03:31:37 +00:00
|
|
|
ExprVector r;
|
|
|
|
if(type == FACE_NORMAL_PT) {
|
2008-06-06 08:46:55 +00:00
|
|
|
Vector v = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
|
|
|
r = ExprVector::From(v.WithMagnitude(1));
|
2008-06-02 03:31:37 +00:00
|
|
|
} else if(type == FACE_XPROD) {
|
|
|
|
ExprVector vc = ExprVector::From(param[0], param[1], param[2]);
|
2008-06-13 04:41:27 +00:00
|
|
|
ExprVector vn =
|
|
|
|
ExprVector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
2008-06-02 03:31:37 +00:00
|
|
|
r = vc.Cross(vn);
|
2008-06-06 08:46:55 +00:00
|
|
|
r = r.WithMagnitude(Expr::From(1.0));
|
2008-06-02 03:31:37 +00:00
|
|
|
} else if(type == FACE_N_ROT_TRANS) {
|
2008-06-06 08:46:55 +00:00
|
|
|
// 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.
|
2008-06-02 03:31:37 +00:00
|
|
|
r = ExprVector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
|
|
|
ExprQuaternion q =
|
|
|
|
ExprQuaternion::From(param[3], param[4], param[5], param[6]);
|
|
|
|
r = q.Rotate(r);
|
2008-06-21 22:49:57 +00:00
|
|
|
} else if(type == FACE_N_TRANS) {
|
|
|
|
r = ExprVector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
|
|
|
} else if(type == FACE_N_ROT_AA) {
|
|
|
|
r = ExprVector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
|
|
|
ExprQuaternion q = GetAxisAngleQuaternionExprs(3);
|
|
|
|
r = q.Rotate(r);
|
2008-06-02 03:31:37 +00:00
|
|
|
} else oops();
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Vector EntityBase::FaceGetNormalNum(void) {
|
2008-06-02 03:31:37 +00:00
|
|
|
Vector r;
|
|
|
|
if(type == FACE_NORMAL_PT) {
|
|
|
|
r = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
|
|
|
} else if(type == FACE_XPROD) {
|
|
|
|
Vector vc = Vector::From(param[0], param[1], param[2]);
|
2008-06-13 04:41:27 +00:00
|
|
|
Vector vn = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
|
|
|
r = vc.Cross(vn);
|
2008-06-02 03:31:37 +00:00
|
|
|
} else if(type == FACE_N_ROT_TRANS) {
|
|
|
|
// The numerical normal vector gets the rotation
|
|
|
|
r = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
|
|
|
Quaternion q = Quaternion::From(param[3], param[4], param[5], param[6]);
|
|
|
|
r = q.Rotate(r);
|
2008-06-21 22:49:57 +00:00
|
|
|
} else if(type == FACE_N_TRANS) {
|
|
|
|
r = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
|
|
|
} else if(type == FACE_N_ROT_AA) {
|
|
|
|
r = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz);
|
|
|
|
Quaternion q = GetAxisAngleQuaternion(3);
|
|
|
|
r = q.Rotate(r);
|
2008-06-02 03:31:37 +00:00
|
|
|
} else oops();
|
2008-06-06 08:46:55 +00:00
|
|
|
return r.WithMagnitude(1);
|
2008-06-02 03:31:37 +00:00
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
ExprVector EntityBase::FaceGetPointExprs(void) {
|
2008-06-02 03:31:37 +00:00
|
|
|
ExprVector r;
|
|
|
|
if(type == FACE_NORMAL_PT) {
|
2009-04-19 05:53:16 +00:00
|
|
|
r = SK.GetEntity(point[0])->PointGetExprs();
|
2008-06-02 03:31:37 +00:00
|
|
|
} else if(type == FACE_XPROD) {
|
|
|
|
r = ExprVector::From(numPoint);
|
|
|
|
} else if(type == FACE_N_ROT_TRANS) {
|
|
|
|
// The numerical point gets the rotation and translation.
|
|
|
|
ExprVector trans = ExprVector::From(param[0], param[1], param[2]);
|
|
|
|
ExprQuaternion q =
|
|
|
|
ExprQuaternion::From(param[3], param[4], param[5], param[6]);
|
|
|
|
r = ExprVector::From(numPoint);
|
|
|
|
r = q.Rotate(r);
|
|
|
|
r = r.Plus(trans);
|
2008-06-21 22:49:57 +00:00
|
|
|
} else if(type == FACE_N_TRANS) {
|
|
|
|
ExprVector trans = ExprVector::From(param[0], param[1], param[2]);
|
|
|
|
r = ExprVector::From(numPoint);
|
|
|
|
r = r.Plus(trans.ScaledBy(Expr::From(timesApplied)));
|
|
|
|
} else if(type == FACE_N_ROT_AA) {
|
|
|
|
ExprVector trans = ExprVector::From(param[0], param[1], param[2]);
|
|
|
|
ExprQuaternion q = GetAxisAngleQuaternionExprs(3);
|
|
|
|
r = ExprVector::From(numPoint);
|
|
|
|
r = r.Minus(trans);
|
|
|
|
r = q.Rotate(r);
|
|
|
|
r = r.Plus(trans);
|
2008-06-02 03:31:37 +00:00
|
|
|
} else oops();
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
Vector EntityBase::FaceGetPointNum(void) {
|
2008-06-06 08:46:55 +00:00
|
|
|
Vector r;
|
|
|
|
if(type == FACE_NORMAL_PT) {
|
2009-04-19 05:53:16 +00:00
|
|
|
r = SK.GetEntity(point[0])->PointGetNum();
|
2008-06-06 08:46:55 +00:00
|
|
|
} 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);
|
2008-06-21 22:49:57 +00:00
|
|
|
} else if(type == FACE_N_TRANS) {
|
|
|
|
Vector trans = Vector::From(param[0], param[1], param[2]);
|
|
|
|
r = numPoint.Plus(trans.ScaledBy(timesApplied));
|
|
|
|
} else if(type == FACE_N_ROT_AA) {
|
|
|
|
Vector trans = Vector::From(param[0], param[1], param[2]);
|
|
|
|
Quaternion q = GetAxisAngleQuaternion(3);
|
|
|
|
r = numPoint.Minus(trans);
|
|
|
|
r = q.Rotate(r);
|
|
|
|
r = r.Plus(trans);
|
2008-06-06 08:46:55 +00:00
|
|
|
} else oops();
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
void EntityBase::AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index) {
|
2008-05-08 07:30:30 +00:00
|
|
|
Equation eq;
|
|
|
|
eq.e = expr;
|
|
|
|
eq.h = h.equation(index);
|
|
|
|
l->Add(&eq);
|
|
|
|
}
|
|
|
|
|
2009-04-19 04:28:21 +00:00
|
|
|
void EntityBase::GenerateEquations(IdList<Equation,hEquation> *l) {
|
2008-05-08 07:30:30 +00:00
|
|
|
switch(type) {
|
|
|
|
case NORMAL_IN_3D: {
|
|
|
|
ExprQuaternion q = NormalGetExprs();
|
2008-06-01 08:45:11 +00:00
|
|
|
AddEq(l, (q.Magnitude())->Minus(Expr::From(1)), 0);
|
2008-05-08 07:30:30 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-05-12 10:01:44 +00:00
|
|
|
case ARC_OF_CIRCLE: {
|
|
|
|
// If this is a copied entity, with its point already fixed
|
|
|
|
// with respect to each other, then we don't want to generate
|
|
|
|
// the distance constraint!
|
2009-07-07 08:21:59 +00:00
|
|
|
if(SK.GetEntity(point[0])->type != POINT_IN_2D) break;
|
|
|
|
|
|
|
|
// If the two endpoints of the arc are constrained coincident
|
|
|
|
// (to make a complete circle), then our distance constraint
|
|
|
|
// would be redundant and therefore overconstrain things.
|
2009-08-21 04:58:28 +00:00
|
|
|
int i;
|
|
|
|
for(i = 0; i < SK.constraint.n; i++) {
|
|
|
|
ConstraintBase *c = &(SK.constraint.elem[i]);
|
2009-07-07 08:21:59 +00:00
|
|
|
if(c->group.v != group.v) continue;
|
|
|
|
if(c->type != Constraint::POINTS_COINCIDENT) continue;
|
|
|
|
|
|
|
|
if((c->ptA.v == point[1].v && c->ptB.v == point[2].v) ||
|
|
|
|
(c->ptA.v == point[2].v && c->ptB.v == point[1].v))
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2008-05-12 10:01:44 +00:00
|
|
|
}
|
2009-08-21 04:58:28 +00:00
|
|
|
if(i < SK.constraint.n) break;
|
2009-07-07 08:21:59 +00:00
|
|
|
|
|
|
|
Expr *ra = Constraint::Distance(workplane, point[0], point[1]);
|
|
|
|
Expr *rb = Constraint::Distance(workplane, point[0], point[2]);
|
|
|
|
AddEq(l, ra->Minus(rb), 0);
|
2008-05-12 10:01:44 +00:00
|
|
|
break;
|
|
|
|
}
|
2008-05-08 07:30:30 +00:00
|
|
|
default:;
|
|
|
|
// Most entities do not generate equations.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|