From b293c0ef41b8ee27b2a79c1e840cc1d1fdeb644a Mon Sep 17 00:00:00 2001 From: Jonathan Westhues Date: Sat, 18 Apr 2009 20:28:21 -0800 Subject: [PATCH] Split the Entity and Constraint classes into Xxx and XxxBase, with the fundamental geometric stuff in XxxBase. Next I hope to make the constraint solver use only the XxxBase types. [git-p4: depot-paths = "//depot/solvespace/": change = 1941] --- constraint.cpp | 2 - constrainteq.cpp | 28 ++++++---- drawentity.cpp | 10 ++++ entity.cpp | 100 +++++++++++++++------------------- sketch.h | 139 +++++++++++++++++++++++++---------------------- 5 files changed, 146 insertions(+), 133 deletions(-) diff --git a/constraint.cpp b/constraint.cpp index 2fb8836..bc12ff1 100644 --- a/constraint.cpp +++ b/constraint.cpp @@ -1,7 +1,5 @@ #include "solvespace.h" -const hConstraint Constraint::NO_CONSTRAINT = { 0 }; - char *Constraint::DescriptionString(void) { static char ret[1024]; diff --git a/constrainteq.cpp b/constrainteq.cpp index f03277f..74b3be5 100644 --- a/constrainteq.cpp +++ b/constrainteq.cpp @@ -1,6 +1,8 @@ #include "solvespace.h" -Expr *Constraint::VectorsParallel(int eq, ExprVector a, ExprVector b) { +const hConstraint ConstraintBase::NO_CONSTRAINT = { 0 }; + +Expr *ConstraintBase::VectorsParallel(int eq, ExprVector a, ExprVector b) { ExprVector r = a.Cross(b); // Hairy ball theorem screws me here. There's no clean solution that I // know, so let's pivot on the initial numerical guess. Our caller @@ -29,7 +31,8 @@ Expr *Constraint::VectorsParallel(int eq, ExprVector a, ExprVector b) { oops(); } -Expr *Constraint::PointLineDistance(hEntity wrkpl, hEntity hpt, hEntity hln) { +Expr *ConstraintBase::PointLineDistance(hEntity wrkpl, hEntity hpt, hEntity hln) +{ Entity *ln = SS.GetEntity(hln); Entity *a = SS.GetEntity(ln->point[0]); Entity *b = SS.GetEntity(ln->point[1]); @@ -65,14 +68,14 @@ Expr *Constraint::PointLineDistance(hEntity wrkpl, hEntity hpt, hEntity hln) { } } -Expr *Constraint::PointPlaneDistance(ExprVector p, hEntity hpl) { +Expr *ConstraintBase::PointPlaneDistance(ExprVector p, hEntity hpl) { ExprVector n; Expr *d; SS.GetEntity(hpl)->WorkplaneGetPlaneExprs(&n, &d); return (p.Dot(n))->Minus(d); } -Expr *Constraint::Distance(hEntity wrkpl, hEntity hpa, hEntity hpb) { +Expr *ConstraintBase::Distance(hEntity wrkpl, hEntity hpa, hEntity hpb) { Entity *pa = SS.GetEntity(hpa); Entity *pb = SS.GetEntity(hpb); if(!(pa->IsPoint() && pb->IsPoint())) oops(); @@ -103,7 +106,9 @@ Expr *Constraint::Distance(hEntity wrkpl, hEntity hpa, hEntity hpb) { // Return the cosine of the angle between two vectors. If a workplane is // specified, then it's the cosine of their projections into that workplane. //----------------------------------------------------------------------------- -Expr *Constraint::DirectionCosine(hEntity wrkpl, ExprVector ae, ExprVector be) { +Expr *ConstraintBase::DirectionCosine(hEntity wrkpl, + ExprVector ae, ExprVector be) +{ if(wrkpl.v == Entity::FREE_IN_3D.v) { Expr *mags = (ae.Magnitude())->Times(be.Magnitude()); return (ae.Dot(be))->Div(mags); @@ -122,7 +127,9 @@ Expr *Constraint::DirectionCosine(hEntity wrkpl, ExprVector ae, ExprVector be) { } } -ExprVector Constraint::PointInThreeSpace(hEntity workplane, Expr *u, Expr *v) { +ExprVector ConstraintBase::PointInThreeSpace(hEntity workplane, + Expr *u, Expr *v) +{ Entity *w = SS.GetEntity(workplane); ExprVector ub = w->Normal()->NormalExprsU(); @@ -132,7 +139,7 @@ ExprVector Constraint::PointInThreeSpace(hEntity workplane, Expr *u, Expr *v) { return (ub.ScaledBy(u)).Plus(vb.ScaledBy(v)).Plus(ob); } -void Constraint::ModifyToSatisfy(void) { +void ConstraintBase::ModifyToSatisfy(void) { if(type == ANGLE) { Vector a = SS.GetEntity(entityA)->VectorGetNum(); Vector b = SS.GetEntity(entityB)->VectorGetNum(); @@ -161,19 +168,20 @@ void Constraint::ModifyToSatisfy(void) { } } -void Constraint::AddEq(IdList *l, Expr *expr, int index) { +void ConstraintBase::AddEq(IdList *l, Expr *expr, int index) +{ Equation eq; eq.e = expr; eq.h = h.equation(index); l->Add(&eq); } -void Constraint::Generate(IdList *l) { +void ConstraintBase::Generate(IdList *l) { if(!reference) { GenerateReal(l); } } -void Constraint::GenerateReal(IdList *l) { +void ConstraintBase::GenerateReal(IdList *l) { Expr *exA = Expr::From(valA); switch(type) { diff --git a/drawentity.cpp b/drawentity.cpp index b643d4d..a6d38f5 100644 --- a/drawentity.cpp +++ b/drawentity.cpp @@ -1,5 +1,15 @@ #include "solvespace.h" +char *Entity::DescriptionString(void) { + if(h.isFromRequest()) { + Request *r = SS.GetRequest(h.request()); + return r->DescriptionString(); + } else { + Group *g = SS.GetGroup(h.group()); + return g->DescriptionString(); + } +} + void Entity::LineDrawOrGetDistance(Vector a, Vector b) { if(dogd.drawing) { // Draw lines from active group in front of those from previous diff --git a/entity.cpp b/entity.cpp index 182cf19..9301eb8 100644 --- a/entity.cpp +++ b/entity.cpp @@ -1,19 +1,9 @@ #include "solvespace.h" -const hEntity Entity::FREE_IN_3D = { 0 }; -const hEntity Entity::NO_ENTITY = { 0 }; +const hEntity EntityBase::FREE_IN_3D = { 0 }; +const hEntity EntityBase::NO_ENTITY = { 0 }; -char *Entity::DescriptionString(void) { - if(h.isFromRequest()) { - Request *r = SS.GetRequest(h.request()); - return r->DescriptionString(); - } else { - Group *g = SS.GetGroup(h.group()); - return g->DescriptionString(); - } -} - -bool Entity::HasVector(void) { +bool EntityBase::HasVector(void) { switch(type) { case LINE_SEGMENT: case NORMAL_IN_3D: @@ -28,7 +18,7 @@ bool Entity::HasVector(void) { } } -ExprVector Entity::VectorGetExprs(void) { +ExprVector EntityBase::VectorGetExprs(void) { switch(type) { case LINE_SEGMENT: return (SS.GetEntity(point[0])->PointGetExprs()).Minus( @@ -45,7 +35,7 @@ ExprVector Entity::VectorGetExprs(void) { } } -Vector Entity::VectorGetNum(void) { +Vector EntityBase::VectorGetNum(void) { switch(type) { case LINE_SEGMENT: return (SS.GetEntity(point[0])->PointGetNum()).Minus( @@ -62,7 +52,7 @@ Vector Entity::VectorGetNum(void) { } } -Vector Entity::VectorGetRefPoint(void) { +Vector EntityBase::VectorGetRefPoint(void) { switch(type) { case LINE_SEGMENT: return ((SS.GetEntity(point[0])->PointGetNum()).Plus( @@ -79,11 +69,11 @@ Vector Entity::VectorGetRefPoint(void) { } } -bool Entity::IsCircle(void) { +bool EntityBase::IsCircle(void) { return (type == CIRCLE) || (type == ARC_OF_CIRCLE); } -Expr *Entity::CircleGetRadiusExpr(void) { +Expr *EntityBase::CircleGetRadiusExpr(void) { if(type == CIRCLE) { return SS.GetEntity(distance)->DistanceGetExpr(); } else if(type == ARC_OF_CIRCLE) { @@ -91,7 +81,7 @@ Expr *Entity::CircleGetRadiusExpr(void) { } else oops(); } -double Entity::CircleGetRadiusNum(void) { +double EntityBase::CircleGetRadiusNum(void) { if(type == CIRCLE) { return SS.GetEntity(distance)->DistanceGetNum(); } else if(type == ARC_OF_CIRCLE) { @@ -101,7 +91,7 @@ double Entity::CircleGetRadiusNum(void) { } else oops(); } -void Entity::ArcGetAngles(double *thetaa, double *thetab, double *dtheta) { +void EntityBase::ArcGetAngles(double *thetaa, double *thetab, double *dtheta) { if(type != ARC_OF_CIRCLE) oops(); Quaternion q = Normal()->NormalGetNum(); @@ -124,19 +114,19 @@ void Entity::ArcGetAngles(double *thetaa, double *thetab, double *dtheta) { while(*dtheta > (2*PI)) *dtheta -= 2*PI; } -bool Entity::IsWorkplane(void) { +bool EntityBase::IsWorkplane(void) { return (type == WORKPLANE); } -ExprVector Entity::WorkplaneGetOffsetExprs(void) { +ExprVector EntityBase::WorkplaneGetOffsetExprs(void) { return SS.GetEntity(point[0])->PointGetExprs(); } -Vector Entity::WorkplaneGetOffset(void) { +Vector EntityBase::WorkplaneGetOffset(void) { return SS.GetEntity(point[0])->PointGetNum(); } -void Entity::WorkplaneGetPlaneExprs(ExprVector *n, Expr **dn) { +void EntityBase::WorkplaneGetPlaneExprs(ExprVector *n, Expr **dn) { if(type == WORKPLANE) { *n = Normal()->NormalExprsN(); @@ -150,21 +140,21 @@ void Entity::WorkplaneGetPlaneExprs(ExprVector *n, Expr **dn) { } } -double Entity::DistanceGetNum(void) { +double EntityBase::DistanceGetNum(void) { if(type == DISTANCE) { return SS.GetParam(param[0])->val; } else if(type == DISTANCE_N_COPY) { return numDistance; } else oops(); } -Expr *Entity::DistanceGetExpr(void) { +Expr *EntityBase::DistanceGetExpr(void) { if(type == DISTANCE) { return Expr::From(param[0]); } else if(type == DISTANCE_N_COPY) { return Expr::From(numDistance); } else oops(); } -void Entity::DistanceForceTo(double v) { +void EntityBase::DistanceForceTo(double v) { if(type == DISTANCE) { (SS.GetParam(param[0]))->val = v; } else if(type == DISTANCE_N_COPY) { @@ -172,11 +162,11 @@ void Entity::DistanceForceTo(double v) { } else oops(); } -Entity *Entity::Normal(void) { +Entity *EntityBase::Normal(void) { return SS.GetEntity(normal); } -bool Entity::IsPoint(void) { +bool EntityBase::IsPoint(void) { switch(type) { case POINT_IN_3D: case POINT_IN_2D: @@ -191,7 +181,7 @@ bool Entity::IsPoint(void) { } } -bool Entity::IsNormal(void) { +bool EntityBase::IsNormal(void) { switch(type) { case NORMAL_IN_3D: case NORMAL_IN_2D: @@ -204,7 +194,7 @@ bool Entity::IsNormal(void) { } } -Quaternion Entity::NormalGetNum(void) { +Quaternion EntityBase::NormalGetNum(void) { Quaternion q; switch(type) { case NORMAL_IN_3D: @@ -237,7 +227,7 @@ Quaternion Entity::NormalGetNum(void) { return q; } -void Entity::NormalForceTo(Quaternion q) { +void EntityBase::NormalForceTo(Quaternion q) { switch(type) { case NORMAL_IN_3D: SS.GetParam(param[0])->val = q.w; @@ -268,27 +258,27 @@ void Entity::NormalForceTo(Quaternion q) { } } -Vector Entity::NormalU(void) { +Vector EntityBase::NormalU(void) { return NormalGetNum().RotationU(); } -Vector Entity::NormalV(void) { +Vector EntityBase::NormalV(void) { return NormalGetNum().RotationV(); } -Vector Entity::NormalN(void) { +Vector EntityBase::NormalN(void) { return NormalGetNum().RotationN(); } -ExprVector Entity::NormalExprsU(void) { +ExprVector EntityBase::NormalExprsU(void) { return NormalGetExprs().RotationU(); } -ExprVector Entity::NormalExprsV(void) { +ExprVector EntityBase::NormalExprsV(void) { return NormalGetExprs().RotationV(); } -ExprVector Entity::NormalExprsN(void) { +ExprVector EntityBase::NormalExprsN(void) { return NormalGetExprs().RotationN(); } -ExprQuaternion Entity::NormalGetExprs(void) { +ExprQuaternion EntityBase::NormalGetExprs(void) { ExprQuaternion q; switch(type) { case NORMAL_IN_3D: @@ -325,11 +315,11 @@ ExprQuaternion Entity::NormalGetExprs(void) { return q; } -bool Entity::PointIsFromReferences(void) { +bool EntityBase::PointIsFromReferences(void) { return h.request().IsFromReferences(); } -void Entity::PointForceTo(Vector p) { +void EntityBase::PointForceTo(Vector p) { switch(type) { case POINT_IN_3D: SS.GetParam(param[0])->val = p.x; @@ -392,7 +382,7 @@ void Entity::PointForceTo(Vector p) { } } -Vector Entity::PointGetNum(void) { +Vector EntityBase::PointGetNum(void) { Vector p; switch(type) { case POINT_IN_3D: @@ -441,7 +431,7 @@ Vector Entity::PointGetNum(void) { return p; } -ExprVector Entity::PointGetExprs(void) { +ExprVector EntityBase::PointGetExprs(void) { ExprVector r; switch(type) { case POINT_IN_3D: @@ -490,7 +480,7 @@ ExprVector Entity::PointGetExprs(void) { return r; } -void Entity::PointGetExprsInWorkplane(hEntity wrkpl, Expr **u, Expr **v) { +void EntityBase::PointGetExprsInWorkplane(hEntity wrkpl, Expr **u, Expr **v) { if(type == POINT_IN_2D && workplane.v == wrkpl.v) { // They want our coordinates in the form that we've written them, // very nice. @@ -512,7 +502,7 @@ void Entity::PointGetExprsInWorkplane(hEntity wrkpl, Expr **u, Expr **v) { } } -void Entity::PointForceQuaternionTo(Quaternion q) { +void EntityBase::PointForceQuaternionTo(Quaternion q) { if(type != POINT_N_ROT_TRANS) oops(); SS.GetParam(param[3])->val = q.w; @@ -521,7 +511,7 @@ void Entity::PointForceQuaternionTo(Quaternion q) { SS.GetParam(param[6])->val = q.vz; } -Quaternion Entity::GetAxisAngleQuaternion(int param0) { +Quaternion EntityBase::GetAxisAngleQuaternion(int param0) { Quaternion q; double theta = timesApplied*SS.GetParam(param[param0+0])->val; double s = sin(theta), c = cos(theta); @@ -532,7 +522,7 @@ Quaternion Entity::GetAxisAngleQuaternion(int param0) { return q; } -ExprQuaternion Entity::GetAxisAngleQuaternionExprs(int param0) { +ExprQuaternion EntityBase::GetAxisAngleQuaternionExprs(int param0) { ExprQuaternion q; Expr *theta = Expr::From(timesApplied)->Times( @@ -545,7 +535,7 @@ ExprQuaternion Entity::GetAxisAngleQuaternionExprs(int param0) { return q; } -Quaternion Entity::PointGetQuaternion(void) { +Quaternion EntityBase::PointGetQuaternion(void) { Quaternion q; if(type == POINT_N_ROT_AA) { @@ -557,7 +547,7 @@ Quaternion Entity::PointGetQuaternion(void) { return q; } -bool Entity::IsFace(void) { +bool EntityBase::IsFace(void) { switch(type) { case FACE_NORMAL_PT: case FACE_XPROD: @@ -570,7 +560,7 @@ bool Entity::IsFace(void) { } } -ExprVector Entity::FaceGetNormalExprs(void) { +ExprVector EntityBase::FaceGetNormalExprs(void) { ExprVector r; if(type == FACE_NORMAL_PT) { Vector v = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz); @@ -599,7 +589,7 @@ ExprVector Entity::FaceGetNormalExprs(void) { return r; } -Vector Entity::FaceGetNormalNum(void) { +Vector EntityBase::FaceGetNormalNum(void) { Vector r; if(type == FACE_NORMAL_PT) { r = Vector::From(numNormal.vx, numNormal.vy, numNormal.vz); @@ -622,7 +612,7 @@ Vector Entity::FaceGetNormalNum(void) { return r.WithMagnitude(1); } -ExprVector Entity::FaceGetPointExprs(void) { +ExprVector EntityBase::FaceGetPointExprs(void) { ExprVector r; if(type == FACE_NORMAL_PT) { r = SS.GetEntity(point[0])->PointGetExprs(); @@ -651,7 +641,7 @@ ExprVector Entity::FaceGetPointExprs(void) { return r; } -Vector Entity::FaceGetPointNum(void) { +Vector EntityBase::FaceGetPointNum(void) { Vector r; if(type == FACE_NORMAL_PT) { r = SS.GetEntity(point[0])->PointGetNum(); @@ -676,14 +666,14 @@ Vector Entity::FaceGetPointNum(void) { return r; } -void Entity::AddEq(IdList *l, Expr *expr, int index) { +void EntityBase::AddEq(IdList *l, Expr *expr, int index) { Equation eq; eq.e = expr; eq.h = h.equation(index); l->Add(&eq); } -void Entity::GenerateEquations(IdList *l) { +void EntityBase::GenerateEquations(IdList *l) { switch(type) { case NORMAL_IN_3D: { ExprQuaternion q = NormalGetExprs(); diff --git a/sketch.h b/sketch.h index 15d3a85..18d782c 100644 --- a/sketch.h +++ b/sketch.h @@ -249,7 +249,7 @@ public: char *DescriptionString(void); }; -class Entity { +class EntityBase { public: int tag; hEntity h; @@ -289,6 +289,9 @@ public: int type; + hGroup group; + hEntity workplane; // or Entity::FREE_IN_3D + // When it comes time to draw an entity, we look here to get the // defining variables. hEntity point[4]; @@ -303,23 +306,6 @@ public: Quaternion numNormal; double numDistance; - // An imported entity that was hidden in the source file ends up hidden - // here too. - bool forceHidden; - - // All points/normals/distances have their numerical value; this is - // a convenience, to simplify the import/assembly code, so that the - // part is entirely described by the entities. - Vector actPoint; - Quaternion actNormal; - double actDistance; - // and the shown state also gets saved here, for later import - bool actVisible; - - hGroup group; - hEntity workplane; // or Entity::FREE_IN_3D - - bool construction; NameStr str; NameStr font; @@ -329,7 +315,6 @@ public: Quaternion GetAxisAngleQuaternion(int param0); ExprQuaternion GetAxisAngleQuaternionExprs(int param0); - bool IsVisible(void); bool IsCircle(void); Expr *CircleGetRadiusExpr(void); @@ -383,6 +368,27 @@ public: ExprVector NormalExprsV(void); ExprVector NormalExprsN(void); + void AddEq(IdList *l, Expr *expr, int index); + void GenerateEquations(IdList *l); +}; + +class Entity : public EntityBase { +public: + // An imported entity that was hidden in the source file ends up hidden + // here too. + bool forceHidden; + + // All points/normals/distances have their numerical value; this is + // a convenience, to simplify the import/assembly code, so that the + // part is entirely described by the entities. + Vector actPoint; + Quaternion actNormal; + double actDistance; + // and the shown state also gets saved here, for later import + bool actVisible; + + bool construction; + // Routines to draw and hit-test the representation of the entity // on-screen. struct { @@ -394,6 +400,8 @@ public: void LineDrawOrGetDistance(Vector a, Vector b); void DrawOrGetDistance(void); + bool IsVisible(void); + void GenerateBezierCurves(SBezierList *sbl); void GenerateEdges(SEdgeList *el, bool includingConstruction=false); @@ -402,9 +410,6 @@ public: double GetDistance(Point2d mp); Vector GetReferencePos(void); - void AddEq(IdList *l, Expr *expr, int index); - void GenerateEquations(IdList *l); - void CalculateNumerical(bool forExport); char *DescriptionString(void); @@ -433,8 +438,11 @@ public: inline hEquation equation(int i); }; -class Constraint { +class ConstraintBase { public: + int tag; + hConstraint h; + static const hConstraint NO_CONSTRAINT; static const int POINTS_COINCIDENT = 20; @@ -470,9 +478,6 @@ public: static const int COMMENT = 1000; - int tag; - hConstraint h; - int type; hGroup group; @@ -488,46 +493,8 @@ public: hEntity entityD; bool other; - bool reference; // a ref dimension, that generates no eqs - - NameStr comment; // since comments are represented as constraints - - // These define how the constraint is drawn on-screen. - struct { - Vector offset; - } disp; - - char *DescriptionString(void); - - static void AddConstraint(Constraint *c, bool rememberForUndo); - static void AddConstraint(Constraint *c); - static void MenuConstrain(int id); - - static void DeleteAllConstraintsFor(int type, hEntity entityA, hEntity ptA); - - struct { - bool drawing; - Point2d mp; - double dmin; - Vector refp; - } dogd; // state for drawing or getting distance (for hit testing) - void LineDrawOrGetDistance(Vector a, Vector b); - void DrawOrGetDistance(Vector *labelPos); - double EllipticalInterpolation(double rx, double ry, double theta); - char *Label(void); - void DoArcForAngle(Vector a0, Vector da, Vector b0, Vector db, - Vector offset, Vector *ref); - void DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu); - void DoProjectedPoint(Vector *p); - void DoEqualLenTicks(Vector a, Vector b, Vector gn); - void DoEqualRadiusTicks(hEntity he); - - double GetDistance(Point2d mp); - Vector GetLabelPos(void); - Vector GetReferencePos(void); - void Draw(void); - - bool HasLabel(void); + bool reference; // a ref dimension, that generates no eqs + NameStr comment; // since comments are represented as constraints void Generate(IdList *l); void GenerateReal(IdList *l); @@ -540,6 +507,46 @@ public: 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); +}; + +class Constraint : public ConstraintBase { +public: + // These define how the constraint is drawn on-screen. + struct { + Vector offset; + } disp; + + // State for drawing or getting distance (for hit testing). + struct { + bool drawing; + Point2d mp; + double dmin; + Vector refp; + } dogd; + + double GetDistance(Point2d mp); + Vector GetLabelPos(void); + Vector GetReferencePos(void); + void Draw(void); + + void LineDrawOrGetDistance(Vector a, Vector b); + void DrawOrGetDistance(Vector *labelPos); + double EllipticalInterpolation(double rx, double ry, double theta); + char *Label(void); + void DoArcForAngle(Vector a0, Vector da, Vector b0, Vector db, + Vector offset, Vector *ref); + void DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu); + void DoProjectedPoint(Vector *p); + void DoEqualLenTicks(Vector a, Vector b, Vector gn); + void DoEqualRadiusTicks(hEntity he); + + bool HasLabel(void); + char *DescriptionString(void); + + static void AddConstraint(Constraint *c, bool rememberForUndo); + static void AddConstraint(Constraint *c); + static void MenuConstrain(int id); + static void DeleteAllConstraintsFor(int type, hEntity entityA, hEntity ptA); static void ConstrainCoincident(hEntity ptA, hEntity ptB); static void Constrain(int type, hEntity ptA, hEntity ptB, hEntity entityA);