#ifndef __SKETCH_H #define __SKETCH_H class hGroup; class hRequest; class hEntity; class hParam; class Entity; class Param; class hConstraint; class hEquation; class Equation; // All of the hWhatever handles are a 32-bit ID, that is used to represent // some data structure in the sketch. class hGroup { public: // bits 15: 0 -- group index DWORD v; inline hEntity entity(int i); inline hParam param(int i); inline hEquation equation(int i); }; class hRequest { public: // bits 15: 0 -- request index DWORD v; inline hEntity entity(int i); inline hParam param(int i); inline bool IsFromReferences(void); }; class hEntity { public: // bits 15: 0 -- entity index // 31:16 -- request index DWORD v; inline bool isFromRequest(void); inline hRequest request(void); inline hGroup group(void); inline hEquation equation(int i); }; class hParam { public: // bits 15: 0 -- param index // 31:16 -- request index DWORD v; inline hRequest request(void); }; class EntityId { public: DWORD v; // entity ID, starting from 0 }; class EntityMap { public: int tag; EntityId h; hEntity input; int copyNumber; // (input, copyNumber) gets mapped to ((Request)xxx).entity(h.v) }; // A set of requests. Every request must have an associated group. class Group { public: static const hGroup HGROUP_REFERENCES; int tag; hGroup h; static const int DRAWING_3D = 5000; static const int DRAWING_WORKPLANE = 5001; static const int EXTRUDE = 5010; static const int ROTATE = 5020; static const int TRANSLATE = 5030; int type; hGroup opA; hGroup opB; bool visible; hEntity activeWorkplane; Expr *exprA; static const int SOLVED_OKAY = 0; static const int DIDNT_CONVERGE = 10; static const int SINGULAR_JACOBIAN = 11; struct { int how; SList remove; } solved; static const int WORKPLANE_BY_POINT_ORTHO = 6000; static const int WORKPLANE_BY_LINE_SEGMENTS = 6001; static const int ONE_SIDED = 7000; static const int TWO_SIDED = 7001; int subtype; struct { Quaternion q; hEntity origin; hEntity entityB; hEntity entityC; bool swapUV; bool negateU; bool negateV; } wrkpl; SPolygon poly; struct { SEdge notClosedAt; bool yes; } polyError; SMesh mesh; static const int COMBINE_AS_UNION = 0; static const int COMBINE_AS_DIFFERENCE = 1; int meshCombine; NameStr name; char *DescriptionString(void); static void AddParam(IdList *param, hParam hp, double v); void Generate(IdList *entity, IdList *param); // When a request generates entities from entities, and the source // entities may have come from multiple requests, it's necessary to // remap the entity ID so that it's still unique. We do this with a // mapping list. IdList remap; hEntity Remap(hEntity in, int copyNumber); void MakeExtrusionLines(hEntity in, int ai, int af); void CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz, hParam qw, hParam qvx, hParam qvy, hParam qvz, bool transOnly); void GenerateEquations(IdList *l); SMesh *PreviousGroupMesh(void); void MakePolygons(void); void Draw(void); SPolygon GetPolygon(void); static void MenuGroup(int id); }; // A user request for some primitive or derived operation; for example a // line, or a step and repeat. class Request { public: // Some predefined requests, that are present in every sketch. static const hRequest HREQUEST_REFERENCE_XY; static const hRequest HREQUEST_REFERENCE_YZ; static const hRequest HREQUEST_REFERENCE_ZX; int tag; hRequest h; // Types of requests static const int WORKPLANE = 100; static const int DATUM_POINT = 101; static const int LINE_SEGMENT = 200; static const int CUBIC = 300; static const int CIRCLE = 400; static const int ARC_OF_CIRCLE = 500; int type; hEntity workplane; // or Entity::FREE_IN_3D hGroup group; NameStr name; bool construction; static hParam AddParam(IdList *param, hParam hp); void Generate(IdList *entity, IdList *param); char *DescriptionString(void); }; class Entity { public: int tag; hEntity h; static const hEntity FREE_IN_3D; static const hEntity NO_ENTITY; static const int POINT_IN_3D = 2000; static const int POINT_IN_2D = 2001; static const int POINT_N_TRANS = 2010; static const int POINT_N_ROT_TRANS = 2011; static const int POINT_N_COPY = 2012; static const int NORMAL_IN_3D = 3000; static const int NORMAL_IN_2D = 3001; // This is a normal that lies in a plane; so if the defining workplane // has basis vectors uw, vw, nw, then // n = (cos theta)*uw + (sin theta)*vw // u = (sin theta)*uw - (cos theta)*vw // v = nw static const int NORMAL_IN_PLANE = 3002; static const int NORMAL_N_COPY = 3010; static const int NORMAL_N_ROT = 3011; static const int DISTANCE = 4000; static const int DISTANCE_N_COPY = 4001; static const int WORKPLANE = 10000; static const int LINE_SEGMENT = 11000; static const int CUBIC = 12000; static const int CIRCLE = 13000; static const int ARC_OF_CIRCLE = 14000; int type; // When it comes time to draw an entity, we look here to get the // defining variables. hEntity point[4]; hEntity normal; hEntity distance; // The only types that have their own params are points, normals, // and directions. hParam param[7]; // Transformed points/normals/distances have their numerical value. Vector numPoint; Quaternion numNormal; double numDistance; hGroup group; hEntity workplane; // or Entity::FREE_IN_3D bool construction; // For entities that are derived by a transformation, the number of // times to apply the transformation. int timesApplied; bool IsCircle(void); Expr *CircleGetRadiusExpr(void); double CircleGetRadiusNum(void); void ArcGetAngles(double *thetaa, double *thetab, double *dtheta); bool HasVector(void); ExprVector VectorGetExprs(void); Vector VectorGetNum(void); Vector VectorGetRefPoint(void); // For distances double DistanceGetNum(void); Expr *DistanceGetExpr(void); void DistanceForceTo(double v); bool IsWorkplane(void); // The plane is points P such that P dot (xn, yn, zn) - d = 0 void WorkplaneGetPlaneExprs(ExprVector *n, Expr **d); ExprVector WorkplaneGetOffsetExprs(void); Vector WorkplaneGetOffset(void); Entity *Normal(void); bool IsPoint(void); // Applies for any of the point types Vector PointGetNum(void); ExprVector PointGetExprs(void); void PointGetExprsInWorkplane(hEntity wrkpl, Expr **u, Expr **v); void PointForceTo(Vector v); bool PointIsFromReferences(void); // These apply only the POINT_N_ROT_TRANS, which has an assoc rotation Quaternion PointGetQuaternion(void); void PointForceQuaternionTo(Quaternion q); bool IsNormal(void); // Applies for any of the normal types Quaternion NormalGetNum(void); ExprQuaternion NormalGetExprs(void); void NormalForceTo(Quaternion q); Vector NormalU(void); Vector NormalV(void); Vector NormalN(void); ExprVector NormalExprsU(void); ExprVector NormalExprsV(void); ExprVector NormalExprsN(void); // Routines to draw and hit-test the representation of the entity // on-screen. struct { bool drawing; Point2d mp; double dmin; SEdgeList *edges; Vector refp; } dogd; // state for drawing or getting distance (for hit testing) void LineDrawOrGetDistance(Vector a, Vector b); void LineDrawOrGetDistanceOrEdge(Vector a, Vector b); void DrawOrGetDistance(int order); void Draw(int order); double GetDistance(Point2d mp); void GenerateEdges(SEdgeList *el); Vector GetReferencePos(void); void AddEq(IdList *l, Expr *expr, int index); void GenerateEquations(IdList *l); char *DescriptionString(void); }; class Param { public: int tag; hParam h; double val; bool known; bool assumed; // Used only in the solver hParam substd; static const hParam NO_PARAM; }; class hConstraint { public: DWORD v; inline hEquation equation(int i); }; class Constraint { public: static const hConstraint NO_CONSTRAINT; 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 EQUAL_LENGTH_LINES = 50; static const int LENGTH_RATIO = 51; static const int SYMMETRIC = 60; static const int SYMMETRIC_HORIZ = 61; static const int SYMMETRIC_VERT = 62; static const int AT_MIDPOINT = 70; static const int HORIZONTAL = 80; static const int VERTICAL = 81; static const int DIAMETER = 90; static const int PT_ON_CIRCLE = 100; static const int SAME_ORIENTATION = 110; static const int ANGLE = 120; static const int PARALLEL = 121; static const int EQUAL_RADIUS = 130; int tag; hConstraint h; int type; hGroup group; hEntity workplane; // These are the parameters for the constraint. Expr *exprA; Expr *exprB; hEntity ptA; hEntity ptB; hEntity ptC; hEntity entityA; hEntity entityB; bool otherAngle; // These define how the constraint is drawn on-screen. struct { Vector offset; } disp; char *DescriptionString(void); static void AddConstraint(Constraint *c); static void MenuConstrain(int id); 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); void DoLabel(Vector ref, Vector *labelPos, Vector gr, Vector gu); void DoProjectedPoint(Vector *p); double GetDistance(Point2d mp); Vector GetLabelPos(void); Vector GetReferencePos(void); void Draw(void); bool HasLabel(void); void Generate(IdList *l); // Some helpers when generating symbolic constraint equations void ModifyToSatisfy(void); void AddEq(IdList *l, Expr *expr, int index); static Expr *Distance(hEntity workplane, hEntity pa, hEntity pb); static Expr *PointLineDistance(hEntity workplane, hEntity pt, hEntity ln); 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); static void ConstrainCoincident(hEntity ptA, hEntity ptB); static void Constrain(int type, hEntity ptA, hEntity ptB, hEntity entityA); }; class hEquation { public: DWORD v; }; class Equation { public: int tag; hEquation h; Expr *e; }; inline hEntity hGroup::entity(int i) { hEntity r; r.v = 0x80000000 | (v << 16) | i; return r; } inline hParam hGroup::param(int i) { hParam r; r.v = 0x80000000 | (v << 16) | i; return r; } inline hEquation hGroup::equation(int i) { hEquation r; r.v = (v << 16) | 0x80000000 | i; return r; } inline bool hRequest::IsFromReferences(void) { if(v == Request::HREQUEST_REFERENCE_XY.v) return true; if(v == Request::HREQUEST_REFERENCE_YZ.v) return true; if(v == Request::HREQUEST_REFERENCE_ZX.v) return true; return false; } inline hEntity hRequest::entity(int i) { hEntity r; r.v = (v << 16) | i; return r; } inline hParam hRequest::param(int i) { hParam r; r.v = (v << 16) | i; return r; } inline bool hEntity::isFromRequest(void) { if(v & 0x80000000) return false; else return true; } inline hRequest hEntity::request(void) { hRequest r; r.v = (v >> 16); return r; } inline hGroup hEntity::group(void) { hGroup r; r.v = (v >> 16) & 0x3fff; return r; } inline hEquation hEntity::equation(int i) { if(i != 0) oops(); hEquation r; r.v = v | 0x40000000; return r; } inline hRequest hParam::request(void) { hRequest r; r.v = (v >> 16); return r; } inline hEquation hConstraint::equation(int i) { hEquation r; r.v = (v << 16) | i; return r; } #endif