ExprVector EntityBase::FaceGetPointExprs(void) { ExprVector r; if(type == FACE_NORMAL_PT) { r = SK.GetEntity(point[0])->PointGetExprs(); } 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); } 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); } else oops(); return r; }
ExprVector EntityBase::FaceGetNormalExprs(void) { ExprVector r; if(type == FACE_NORMAL_PT) { 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(numNormal.vx, numNormal.vy, numNormal.vz); 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 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]); r = q.Rotate(r); } 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); } else oops(); return r; }
void Group::GenerateEquations(IdList<Equation,hEquation> *l) { Equation eq; ZERO(&eq); if(type == IMPORTED) { // Normalize the quaternion ExprQuaternion q = { Expr::From(h.param(3)), Expr::From(h.param(4)), Expr::From(h.param(5)), Expr::From(h.param(6)) }; AddEq(l, (q.Magnitude())->Minus(Expr::From(1)), 0); } else if(type == ROTATE) { // The axis and center of rotation are specified numerically #define EC(x) (Expr::From(x)) #define EP(x) (Expr::From(h.param(x))) ExprVector orig = SK.GetEntity(predef.origin)->PointGetExprs(); AddEq(l, (orig.x)->Minus(EP(0)), 0); AddEq(l, (orig.y)->Minus(EP(1)), 1); AddEq(l, (orig.z)->Minus(EP(2)), 2); // param 3 is the angle, which is free Vector axis = SK.GetEntity(predef.entityB)->VectorGetNum(); axis = axis.WithMagnitude(1); AddEq(l, (EC(axis.x))->Minus(EP(4)), 3); AddEq(l, (EC(axis.y))->Minus(EP(5)), 4); AddEq(l, (EC(axis.z))->Minus(EP(6)), 5); #undef EC #undef EP } else if(type == EXTRUDE) { if(predef.entityB.v != Entity::FREE_IN_3D.v) { // The extrusion path is locked along a line, normal to the // specified workplane. Entity *w = SK.GetEntity(predef.entityB); ExprVector u = w->Normal()->NormalExprsU(); ExprVector v = w->Normal()->NormalExprsV(); ExprVector extruden = { Expr::From(h.param(0)), Expr::From(h.param(1)), Expr::From(h.param(2)) }; AddEq(l, u.Dot(extruden), 0); AddEq(l, v.Dot(extruden), 1); } } else if(type == TRANSLATE) { if(predef.entityB.v != Entity::FREE_IN_3D.v) { Entity *w = SK.GetEntity(predef.entityB); ExprVector n = w->Normal()->NormalExprsN(); ExprVector trans; trans = ExprVector::From(h.param(0), h.param(1), h.param(2)); // The translation vector is parallel to the workplane AddEq(l, trans.Dot(n), 0); } } }
ExprVector EntityBase::PointGetExprs(void) { ExprVector r; switch(type) { case POINT_IN_3D: r = ExprVector::From(param[0], param[1], param[2]); break; case POINT_IN_2D: { EntityBase *c = SK.GetEntity(workplane); ExprVector u = c->Normal()->NormalExprsU(); ExprVector v = c->Normal()->NormalExprsV(); r = c->WorkplaneGetOffsetExprs(); r = r.Plus(u.ScaledBy(Expr::From(param[0]))); r = r.Plus(v.ScaledBy(Expr::From(param[1]))); break; } case POINT_N_TRANS: { ExprVector orig = ExprVector::From(numPoint); ExprVector trans = ExprVector::From(param[0], param[1], param[2]); r = orig.Plus(trans.ScaledBy(Expr::From(timesApplied))); break; } case POINT_N_ROT_TRANS: { ExprVector orig = ExprVector::From(numPoint); ExprVector trans = ExprVector::From(param[0], param[1], param[2]); ExprQuaternion q = ExprQuaternion::From(param[3], param[4], param[5], param[6]); orig = q.Rotate(orig); r = orig.Plus(trans); break; } case POINT_N_ROT_AA: { ExprVector orig = ExprVector::From(numPoint); ExprVector trans = ExprVector::From(param[0], param[1], param[2]); ExprQuaternion q = GetAxisAngleQuaternionExprs(3); orig = orig.Minus(trans); orig = q.Rotate(orig); r = orig.Plus(trans); break; } case POINT_N_COPY: r = ExprVector::From(numPoint); break; default: oops(); } return r; }
void EntityBase::GenerateEquations(IdList<Equation,hEquation> *l) { switch(type) { case NORMAL_IN_3D: { ExprQuaternion q = NormalGetExprs(); AddEq(l, (q.Magnitude())->Minus(Expr::From(1)), 0); break; } 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! 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. int i; for(i = 0; i < SK.constraint.n; i++) { ConstraintBase *c = &(SK.constraint.elem[i]); 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; } } if(i < SK.constraint.n) break; Expr *ra = Constraint::Distance(workplane, point[0], point[1]); Expr *rb = Constraint::Distance(workplane, point[0], point[2]); AddEq(l, ra->Minus(rb), 0); break; } default:; // Most entities do not generate equations. } }
ExprQuaternion EntityBase::NormalGetExprs(void) { ExprQuaternion q; switch(type) { case NORMAL_IN_3D: q = ExprQuaternion::From(param[0], param[1], param[2], param[3]); break; case NORMAL_IN_2D: { EntityBase *wrkpl = SK.GetEntity(workplane); EntityBase *norm = SK.GetEntity(wrkpl->normal); q = norm->NormalGetExprs(); break; } case NORMAL_N_COPY: q = ExprQuaternion::From(numNormal); break; case NORMAL_N_ROT: { ExprQuaternion orig = ExprQuaternion::From(numNormal); q = ExprQuaternion::From(param[0], param[1], param[2], param[3]); q = q.Times(orig); break; } case NORMAL_N_ROT_AA: { ExprQuaternion orig = ExprQuaternion::From(numNormal); q = GetAxisAngleQuaternionExprs(0); q = q.Times(orig); break; } default: oops(); } return q; }