From cc03fe40aab436ba2f06aa6e9a7610a1d62bd7c2 Mon Sep 17 00:00:00 2001 From: Jonathan Westhues Date: Sat, 19 Apr 2008 03:09:47 -0800 Subject: [PATCH] Big structural change; eliminate the Point type in SolveSpace. The points are now entities like any others; so a line segment request will generate three entities, the line segment and its endpoints. I think that's cleaner. When I do step and repeats (and imports, and other similar), I'll need a consistent way to assign those entity ids. That assignment must not change if the sketch is edited. I don't have a clean way to do that; best thought right now is to keep a record of what maps have been used previously, and not pick a new map as long as it's possible to use one that was used previously. This all means that more crap gets pushed in to the Entity structure, so that they can keep track of what solver variables define them. Still seems better, though. I'm closer to ready to start solving. [git-p4: depot-paths = "//depot/solvespace/": change = 1673] --- constraint.cpp | 6 +- drawconstraint.cpp | 5 +- dsc.h | 2 +- entity.cpp | 109 +++++++++++++++++++++++++++++++---- expr.h | 1 - file.cpp | 8 --- glhelper.cpp | 21 +++++++ graphicswin.cpp | 83 +++++++++++---------------- sketch.cpp | 138 ++++++++++++--------------------------------- sketch.h | 126 +++++++++++++++-------------------------- solvespace.cpp | 18 +++--- solvespace.h | 5 +- ui.h | 7 +-- 13 files changed, 253 insertions(+), 276 deletions(-) diff --git a/constraint.cpp b/constraint.cpp index 1baf71a2..de198980 100644 --- a/constraint.cpp +++ b/constraint.cpp @@ -21,15 +21,15 @@ void Constraint::MenuConstrain(int id) { c.ptB = gs.point[1]; } else if(gs.lineSegments == 1 && gs.n == 1) { c.type = PT_PT_DISTANCE; - c.ptA = gs.entity[0].point(16); - c.ptB = gs.entity[0].point(16+3); + Entity *e = SS.GetEntity(gs.entity[0]); + c.ptA = e->assoc[0]; + c.ptB = e->assoc[1]; } else { Error("Bad selection for distance / diameter constraint."); return; } c.disp.offset = Vector::MakeFrom(50, 50, 50); c.exprA = Expr::FromString("1+3+2")->DeepCopyKeep(); - FreeAllExprs(); AddConstraint(&c); break; diff --git a/drawconstraint.cpp b/drawconstraint.cpp index d9f4c556..a82b8947 100644 --- a/drawconstraint.cpp +++ b/drawconstraint.cpp @@ -16,10 +16,11 @@ void Constraint::DrawOrGetDistance(void) { Vector gu = SS.GW.projUp; Vector gn = gr.Cross(gu); + glxColor(1, 0.3, 1); switch(type) { case PT_PT_DISTANCE: { - Vector ap = SS.GetPoint(ptA)->GetCoords(); - Vector bp = SS.GetPoint(ptB)->GetCoords(); + Vector ap = SS.GetEntity(ptA)->GetPointCoords(); + Vector bp = SS.GetEntity(ptB)->GetPointCoords(); Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(disp.offset); diff --git a/dsc.h b/dsc.h index 77512996..46b856fe 100644 --- a/dsc.h +++ b/dsc.h @@ -91,7 +91,7 @@ public: T *FindById(H h) { T *t = FindByIdNoOops(h); if(!t) { - dbp("failed to look up item %16lx, searched %d items", h.v, n); + dbp("failed to look up item %08x, searched %d items", h.v, n); oops(); } return t; diff --git a/entity.cpp b/entity.cpp index ade16e89..aacd3e16 100644 --- a/entity.cpp +++ b/entity.cpp @@ -1,14 +1,14 @@ #include "solvespace.h" char *Entity::DescriptionString(void) { - Request *r = SS.GetRequest(request()); + Request *r = SS.GetRequest(h.request()); return r->DescriptionString(); } void Entity::Get2dCsysBasisVectors(Vector *u, Vector *v) { double q[4]; for(int i = 0; i < 4; i++) { - q[i] = SS.param.FindById(param(i))->val; + q[i] = SS.GetParam(param.h[i])->val; } Quaternion quat = Quaternion::MakeFrom(q[0], q[1], q[2], q[3]); @@ -16,6 +16,66 @@ void Entity::Get2dCsysBasisVectors(Vector *u, Vector *v) { *v = quat.RotationV(); } +bool Entity::IsPoint(void) { + switch(type) { + case POINT_IN_3D: + case POINT_IN_2D: + return true; + default: + return false; + } +} + +bool Entity::IsFromReferences(void) { + hRequest hr = h.request(); + if(hr.v == Request::HREQUEST_REFERENCE_XY.v) return true; + if(hr.v == Request::HREQUEST_REFERENCE_YZ.v) return true; + if(hr.v == Request::HREQUEST_REFERENCE_ZX.v) return true; + return false; +} + +void Entity::ForcePointTo(Vector p) { + switch(type) { + case POINT_IN_3D: + SS.GetParam(param.h[0])->ForceTo(p.x); + SS.GetParam(param.h[1])->ForceTo(p.y); + SS.GetParam(param.h[2])->ForceTo(p.z); + break; + + case POINT_IN_2D: { + Entity *c = SS.GetEntity(csys); + Vector u, v; + c->Get2dCsysBasisVectors(&u, &v); + SS.GetParam(param.h[0])->ForceTo(p.Dot(u)); + SS.GetParam(param.h[1])->ForceTo(p.Dot(v)); + break; + } + default: oops(); + } +} + +Vector Entity::GetPointCoords(void) { + Vector p; + switch(type) { + case POINT_IN_3D: + p.x = SS.GetParam(param.h[0])->val; + p.y = SS.GetParam(param.h[1])->val; + p.z = SS.GetParam(param.h[2])->val; + break; + + case POINT_IN_2D: { + Entity *c = SS.GetEntity(csys); + Vector u, v; + c->Get2dCsysBasisVectors(&u, &v); + p = u.ScaledBy(SS.GetParam(param.h[0])->val); + p = p.Plus(v.ScaledBy(SS.GetParam(param.h[1])->val)); + break; + } + default: oops(); + } + return p; +} + void Entity::LineDrawOrGetDistance(Vector a, Vector b) { if(dogd.drawing) { glBegin(GL_LINE_STRIP); @@ -46,11 +106,41 @@ double Entity::GetDistance(Point2d mp) { return dogd.dmin; } -void Entity::DrawOrGetDistance(void) { +void Entity::DrawOrGetDistance(void) { + glxColor(1, 1, 1); + switch(type) { + case POINT_IN_3D: + case POINT_IN_2D: { + Entity *isfor = SS.GetEntity(h.request().entity(0)); + if(!SS.GW.show2dCsyss && isfor->type == Entity::CSYS_2D) break; + + Vector v = GetPointCoords(); + + if(dogd.drawing) { + double s = 4; + Vector r = SS.GW.projRight.ScaledBy(s/SS.GW.scale); + Vector d = SS.GW.projUp.ScaledBy(s/SS.GW.scale); + + glxColor(0, 0.8, 0); + glBegin(GL_QUADS); + glxVertex3v(v.Plus (r).Plus (d)); + glxVertex3v(v.Plus (r).Minus(d)); + glxVertex3v(v.Minus(r).Minus(d)); + glxVertex3v(v.Minus(r).Plus (d)); + glEnd(); + } else { + Point2d pp = SS.GW.ProjectPoint(v); + dogd.dmin = pp.DistanceTo(dogd.mp) - 8; + } + break; + } + case CSYS_2D: { + if(!SS.GW.show2dCsyss) break; + Vector p; - p = SS.point.FindById(point(16))->GetCoords(); + p = SS.GetEntity(assoc[0])->GetPointCoords(); Vector u, v; Get2dCsysBasisVectors(&u, &v); @@ -65,28 +155,25 @@ void Entity::DrawOrGetDistance(void) { Vector mm = p.Minus(us).Minus(vs); Vector mp = p.Minus(us).Plus (vs); + glxColor(0, 0.4, 0.4); LineDrawOrGetDistance(pp, pm); LineDrawOrGetDistance(pm, mm); LineDrawOrGetDistance(mm, mp); LineDrawOrGetDistance(mp, pp); if(dogd.drawing) { - Request *r = SS.request.FindById(this->request()); glPushMatrix(); glxTranslatev(mm); glxOntoCsys(u, v); - glxWriteText(r->DescriptionString()); + glxWriteText(DescriptionString()); glPopMatrix(); } break; } - case DATUM_POINT: - // All display is handled by the generated point. - break; case LINE_SEGMENT: { - Vector a = SS.point.FindById(point(16))->GetCoords(); - Vector b = SS.point.FindById(point(16+3))->GetCoords(); + Vector a = SS.GetEntity(assoc[0])->GetPointCoords(); + Vector b = SS.GetEntity(assoc[1])->GetPointCoords(); LineDrawOrGetDistance(a, b); break; } diff --git a/expr.h b/expr.h index d512caef..24bafea6 100644 --- a/expr.h +++ b/expr.h @@ -45,7 +45,6 @@ public: double v; hParam parh; Param *parp; - hPoint point; hEntity entity; // For use while parsing diff --git a/file.cpp b/file.cpp index d09dbdc2..c5f17af9 100644 --- a/file.cpp +++ b/file.cpp @@ -41,14 +41,6 @@ bool SolveSpace::SaveToFile(char *filename) { fprintf(fh, "AddEntity\n\n"); } - for(i = 0; i < point.n; i++) { - Point *p = &(point.elem[i]); - fprintf(fh, "Point.h.v=%08x\n", p->h.v); - fprintf(fh, "Point.type=%d\n", p->type); - fprintf(fh, "Point.csys.v=%08x\n", p->csys.v); - fprintf(fh, "AddPoint\n\n"); - } - for(i = 0; i < constraint.n; i++) { Constraint *c = &(constraint.elem[i]); fprintf(fh, "Constraint.h.v=%08x\n", c->h.v); diff --git a/glhelper.cpp b/glhelper.cpp index 1b77e53f..0f60b036 100644 --- a/glhelper.cpp +++ b/glhelper.cpp @@ -3,6 +3,8 @@ // A public-domain Hershey vector font ("Simplex"). #include "font.table" +static bool ColorLocked; + void glxWriteText(char *str) { double scale = 0.7/SS.GW.scale; @@ -54,3 +56,22 @@ void glxOntoCsys(Vector u, Vector v) 0, 0, 0, 1); glMultMatrixd(mat); } + +void glxLockColorTo(double r, double g, double b) +{ + ColorLocked = false; + glxColor(r, g, b); + ColorLocked = true; +} + +void glxUnlockColor(void) +{ + ColorLocked = false; +} + +void glxColor(double r, double g, double b) +{ + if(!ColorLocked) { + glColor3f((GLfloat)r, (GLfloat)g, (GLfloat)b); + } +} diff --git a/graphicswin.cpp b/graphicswin.cpp index 1ea72938..48b2a01c 100644 --- a/graphicswin.cpp +++ b/graphicswin.cpp @@ -138,9 +138,9 @@ void GraphicsWindow::MenuView(int id) { SS.GW.GroupSelection(); Entity *e = NULL; if(SS.GW.gs.n == 1 && SS.GW.gs.csyss == 1) { - e = SS.entity.FindById(SS.GW.gs.entity[0]); + e = SS.GetEntity(SS.GW.gs.entity[0]); } else if(SS.GW.activeCsys.v != Entity::NO_CSYS.v) { - e = SS.entity.FindById(SS.GW.activeCsys); + e = SS.GetEntity(SS.GW.activeCsys); } if(e) { // A quaternion with our original rotation @@ -160,7 +160,7 @@ void GraphicsWindow::MenuView(int id) { // And also get the offsets. Vector offset0 = SS.GW.offset; - Vector offsetf = SS.point.FindById(e->point(16))->GetCoords(); + Vector offsetf = SS.GetEntity(e->assoc[0])->GetPointCoords(); // Animate transition, unless it's a tiny move. SDWORD dt = (mp < 0.01) ? (-20) : (SDWORD)(100 + 1000*mp); @@ -241,15 +241,8 @@ void GraphicsWindow::MenuEdit(int id) { Selection *s = &(SS.GW.selection[i]); hRequest r; r.v = 0; - if(s->point.v) { - Point *pt = SS.GetPoint(s->point); - Entity *e = SS.GetEntity(pt->entity()); - if(e->type == Entity::DATUM_POINT) { - r = e->request(); - } - } else if(s->entity.v) { - Entity *e = SS.GetEntity(s->entity); - r = e->request(); + if(s->entity.v) { + r = s->entity.request(); } if(r.v) SS.request.Tag(r, 1); } @@ -299,11 +292,11 @@ c: } } -void GraphicsWindow::UpdateDraggedHPoint(hPoint hp, double mx, double my) { - Point *p = SS.point.FindById(hp); - Vector pos = p->GetCoords(); +void GraphicsWindow::UpdateDraggedEntity(hEntity hp, double mx, double my) { + Entity *p = SS.GetEntity(hp); + Vector pos = p->GetPointCoords(); UpdateDraggedPoint(&pos, mx, my); - p->ForceTo(pos); + p->ForcePointTo(pos); } void GraphicsWindow::UpdateDraggedPoint(Vector *pos, double mx, double my) { @@ -358,9 +351,12 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown, } else if(leftDown) { // We are left-dragging. This is often used to drag points, or // constraint labels. - if(hover.point.v && !hover.point.isFromReferences()) { + if(hover.entity.v && + SS.GetEntity(hover.entity)->IsPoint() && + !SS.GetEntity(hover.entity)->IsFromReferences()) + { ClearSelection(); - UpdateDraggedHPoint(hover.point, x, y); + UpdateDraggedEntity(hover.entity, x, y); } else if(hover.constraint.v && SS.GetConstraint(hover.constraint)->HasLabel()) { @@ -370,7 +366,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown, } } else { if(pendingOperation == PENDING_OPERATION_DRAGGING_POINT) { - UpdateDraggedHPoint(pendingPoint, x, y); + UpdateDraggedEntity(pendingPoint, x, y); } else { // Do our usual hit testing, for the selection. Selection s; @@ -384,24 +380,21 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown, } bool GraphicsWindow::Selection::Equals(Selection *b) { - if(point.v != b->point.v) return false; if(entity.v != b->entity.v) return false; if(constraint.v != b->constraint.v) return false; return true; } bool GraphicsWindow::Selection::IsEmpty(void) { - if(point.v) return false; if(entity.v) return false; if(constraint.v) return false; return true; } void GraphicsWindow::Selection::Clear(void) { - point.v = entity.v = constraint.v = 0; + entity.v = constraint.v = 0; } void GraphicsWindow::Selection::Draw(void) { - if(point.v) SS.point. FindById(point )->Draw(); - if(entity.v) SS.entity. FindById(entity )->Draw(); - if(constraint.v) SS.constraint.FindById(constraint)->Draw(); + if(entity.v) SS.GetEntity (entity )->Draw(); + if(constraint.v) SS.GetConstraint(constraint)->Draw(); } void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) { @@ -410,21 +403,13 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) { memset(dest, 0, sizeof(*dest)); - // Do the points + // Do the entities for(i = 0; i < SS.entity.n; i++) { d = SS.entity.elem[i].GetDistance(mp); if(d < 10 && d < dmin) { memset(dest, 0, sizeof(*dest)); dest->entity = SS.entity.elem[i].h; - } - } - - // Entities - for(i = 0; i < SS.point.n; i++) { - d = SS.point.elem[i].GetDistance(mp); - if(d < 10 && d < dmin) { - memset(dest, 0, sizeof(*dest)); - dest->point = SS.point.elem[i].h; + dmin = d; } } @@ -434,6 +419,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) { if(d < 10 && d < dmin) { memset(dest, 0, sizeof(*dest)); dest->constraint = SS.constraint.elem[i].h; + dmin = d; } } } @@ -452,10 +438,6 @@ void GraphicsWindow::GroupSelection(void) { int i; for(i = 0; i < MAX_SELECTED; i++) { Selection *s = &(selection[i]); - if(s->point.v) { - gs.point[(gs.points)++] = s->point; - (gs.n)++; - } if(s->entity.v) { gs.entity[(gs.entities)++] = s->entity; (gs.n)++; @@ -465,6 +447,9 @@ void GraphicsWindow::GroupSelection(void) { case Entity::CSYS_2D: (gs.csyss)++; break; case Entity::LINE_SEGMENT: (gs.lineSegments)++; break; } + if(e->IsPoint()) { + gs.point[(gs.points)++] = s->entity; + } } } } @@ -503,20 +488,21 @@ void GraphicsWindow::MouseLeftDown(double mx, double my) { switch(pendingOperation) { case MNU_DATUM_POINT: hr = AddRequest(Request::DATUM_POINT); - SS.point.FindById(hr.entity(0).point(16))->ForceTo(v); + SS.GetEntity(hr.entity(0))->ForcePointTo(v); pendingOperation = 0; break; case MNU_LINE_SEGMENT: hr = AddRequest(Request::LINE_SEGMENT); - SS.point.FindById(hr.entity(0).point(16))->ForceTo(v); + SS.GetEntity(hr.entity(1))->ForcePointTo(v); pendingOperation = PENDING_OPERATION_DRAGGING_POINT; - pendingPoint = hr.entity(0).point(16+3); + pendingPoint = hr.entity(2); pendingDescription = "click to place next point of line"; - SS.point.FindById(pendingPoint)->ForceTo(v); + SS.GetEntity(pendingPoint)->ForcePointTo(v); break; case PENDING_OPERATION_DRAGGING_POINT: + // The MouseMoved event has already dragged it under the cursor. pendingOperation = 0; break; @@ -629,15 +615,10 @@ void GraphicsWindow::Paint(int w, int h) { int i; // First, draw the entire scene. - glColor3f(1, 1, 1); + glxUnlockColor(); for(i = 0; i < SS.entity.n; i++) { SS.entity.elem[i].Draw(); } - glColor3f(0, 0.8f, 0); - for(i = 0; i < SS.point.n; i++) { - SS.point.elem[i].Draw(); - } - glColor3f(1.0f, 0, 1.0f); for(i = 0; i < SS.constraint.n; i++) { SS.constraint.elem[i].Draw(); } @@ -645,11 +626,11 @@ void GraphicsWindow::Paint(int w, int h) { // Then redraw whatever the mouse is hovering over, highlighted. Have // to disable the depth test, so that we can overdraw. glDisable(GL_DEPTH_TEST); - glColor3f(1, 1, 0); + glxLockColorTo(1, 1, 0); hover.Draw(); // And finally draw the selection, same mechanism. - glColor3f(1, 0, 0); + glxLockColorTo(1, 0, 0); for(i = 0; i < MAX_SELECTED; i++) { selection[i].Draw(); } diff --git a/sketch.cpp b/sketch.cpp index e8ab248c..07ea0f4c 100644 --- a/sketch.cpp +++ b/sketch.cpp @@ -17,15 +17,15 @@ char *Group::DescriptionString(void) { return ret; } -void Request::AddParam(IdList *param, Entity *e, int index) { +hParam Request::AddParam(IdList *param, hParam hp) { Param pa; memset(&pa, 0, sizeof(pa)); - pa.h = e->param(index); + pa.h = hp; param->Add(&pa); + return hp; } void Request::Generate(IdList *entity, - IdList *point, IdList *param) { int points = 0; @@ -37,46 +37,50 @@ void Request::Generate(IdList *entity, Entity e; memset(&e, 0, sizeof(e)); - e.h = this->entity(0); - - bool shown = true; switch(type) { case Request::CSYS_2D: et = Entity::CSYS_2D; points = 1; params = 4; goto c; case Request::DATUM_POINT: - et = Entity::DATUM_POINT; points = 1; params = 0; goto c; + et = 0; points = 1; params = 0; goto c; case Request::LINE_SEGMENT: et = Entity::LINE_SEGMENT; points = 2; params = 0; goto c; c: { - // Common routines, for all the requests that generate a single - // entity that's defined by a simple combination of pts and params. - for(i = 0; i < params; i++) { - AddParam(param, &e, i); - } - for(i = 0; i < points; i++) { - Point pt; - memset(&pt, 0, sizeof(pt)); - pt.csys = csys; - pt.h = e.point(16 + 3*i); - if(csys.v == Entity::NO_CSYS.v) { - pt.type = Point::IN_FREE_SPACE; - // params for x y z - AddParam(param, &e, 16 + 3*i + 0); - AddParam(param, &e, 16 + 3*i + 1); - AddParam(param, &e, 16 + 3*i + 2); - } else { - pt.type = Point::IN_2D_CSYS; - // params for u v - AddParam(param, &e, 16 + 3*i + 0); - AddParam(param, &e, 16 + 3*i + 1); - } - point->Add(&pt); - } - + // Generate the entity that's specific to this request. e.type = et; - entity->Add(&e); + e.h = h.entity(0); + + // And generate entities for the points + for(i = 0; i < points; i++) { + Entity p; + memset(&p, 0, sizeof(p)); + p.csys = csys; + // points start from entity 1, except for datum point case + p.h = h.entity(i+(et ? 1 : 0)); + p.symbolic = true; + if(csys.v == Entity::NO_CSYS.v) { + p.type = Entity::POINT_IN_3D; + // params for x y z + p.param.h[0] = AddParam(param, h.param(16 + 3*i + 0)); + p.param.h[1] = AddParam(param, h.param(16 + 3*i + 1)); + p.param.h[2] = AddParam(param, h.param(16 + 3*i + 2)); + } else { + p.type = Entity::POINT_IN_2D; + // params for u v + p.param.h[0] = AddParam(param, h.param(16 + 3*i + 0)); + p.param.h[1] = AddParam(param, h.param(16 + 3*i + 1)); + } + entity->Add(&p); + e.assoc[i] = p.h; + } + // And generate any params not associated with the point that + // we happen to need. + for(i = 0; i < params; i++) { + e.param.h[i] = AddParam(param, h.param(i)); + } + + if(et) entity->Add(&e); break; } @@ -100,72 +104,4 @@ void Param::ForceTo(double v) { known = true; } -void Point::ForceTo(Vector p) { - switch(type) { - case IN_FREE_SPACE: - SS.GetParam(param(0))->ForceTo(p.x); - SS.GetParam(param(1))->ForceTo(p.y); - SS.GetParam(param(2))->ForceTo(p.z); - break; - - case IN_2D_CSYS: { - Entity *c = SS.GetEntity(csys); - Vector u, v; - c->Get2dCsysBasisVectors(&u, &v); - SS.GetParam(param(0))->ForceTo(p.Dot(u)); - SS.GetParam(param(1))->ForceTo(p.Dot(v)); - break; - } - - default: - oops(); - } -} - -Vector Point::GetCoords(void) { - Vector p; - switch(type) { - case IN_FREE_SPACE: - p.x = SS.GetParam(param(0))->val; - p.y = SS.GetParam(param(1))->val; - p.z = SS.GetParam(param(2))->val; - break; - - case IN_2D_CSYS: { - Entity *c = SS.GetEntity(csys); - Vector u, v; - c->Get2dCsysBasisVectors(&u, &v); - p = u.ScaledBy(SS.GetParam(param(0))->val); - p = p.Plus(v.ScaledBy(SS.GetParam(param(1))->val)); - break; - } - - default: - oops(); - } - - return p; -} - -void Point::Draw(void) { - Vector v = GetCoords(); - - double s = 4; - Vector r = SS.GW.projRight.ScaledBy(4/SS.GW.scale); - Vector d = SS.GW.projUp.ScaledBy(4/SS.GW.scale); - - glBegin(GL_QUADS); - glxVertex3v(v.Plus (r).Plus (d)); - glxVertex3v(v.Plus (r).Minus(d)); - glxVertex3v(v.Minus(r).Minus(d)); - glxVertex3v(v.Minus(r).Plus (d)); - glEnd(); -} - -double Point::GetDistance(Point2d mp) { - Vector v = GetCoords(); - Point2d pp = SS.GW.ProjectPoint(v); - - return pp.DistanceTo(mp); -} diff --git a/sketch.h b/sketch.h index 58678728..a0a005e6 100644 --- a/sketch.h +++ b/sketch.h @@ -6,11 +6,9 @@ class hGroup; class hRequest; class hEntity; class hParam; -class hPoint; class Entity; class Param; -class Point; class hEquation; class Equation; @@ -19,41 +17,32 @@ class Equation; // some data structure in the sketch. class hGroup { public: - // bits 10: 0 -- group index + // bits 15: 0 -- group index DWORD v; }; class hRequest { public: - // bits 14: 0 -- request index (the high bits may be used as an import ID) + // bits 15: 0 -- request index DWORD v; inline hEntity entity(int i); + inline hParam param(int i); }; class hEntity { public: - // bits 9: 0 -- entity index - // 24:10 -- request index + // bits 15: 0 -- entity index + // 31:16 -- request index DWORD v; inline hRequest request(void); - inline hParam param(int i); - inline hPoint point(int i); }; class hParam { public: - // bits 6: 0 -- param index - // 16: 7 -- entity index - // 31:17 -- request index + // bits 15: 0 -- param index + // 31:16 -- request index DWORD v; -}; -class hPoint { - // bits 6: 0 -- point index - // 16: 7 -- entity index - // 31:17 -- request index -public: - DWORD v; - inline bool isFromReferences(void); + inline hRequest request(void); }; // A set of requests. Every request must have an associated group. @@ -94,13 +83,8 @@ public: NameStr name; - inline hEntity entity(int i) - { hEntity r; r.v = ((this->h.v) << 10) | i; return r; } - - void AddParam(IdList *param, Entity *e, int index); - void Generate(IdList *entity, - IdList *point, - IdList *param); + hParam AddParam(IdList *param, hParam hp); + void Generate(IdList *entity, IdList *param); char *DescriptionString(void); }; @@ -113,30 +97,46 @@ public: static const hEntity NO_CSYS; static const int CSYS_2D = 1000; - static const int DATUM_POINT = 1001; - static const int LINE_SEGMENT = 1010; + static const int POINT_IN_3D = 2000; + static const int POINT_IN_2D = 2001; + static const int LINE_SEGMENT = 3000; int type; - inline hRequest request(void) - { hRequest r; r.v = (this->h.v >> 10); return r; } - inline hParam param(int i) - { hParam r; r.v = ((this->h.v) << 7) | i; return r; } - inline hPoint point(int i) - { hPoint r; r.v = ((this->h.v) << 7) | i; return r; } + bool symbolic; + // The params are usually handles to the symbolic variables, but may + // also be constants + union { + hParam h[16]; + double v[16]; + } param; + // Associated entities, e.g. the endpoints for a line segment + hEntity assoc[16]; - char *DescriptionString(void); + hEntity csys; // or Entity::NO_CSYS + // Applies only for a CSYS_2D type void Get2dCsysBasisVectors(Vector *u, Vector *v); + bool IsPoint(void); + // Applies for any of the point types + void GetPointExprs(Expr **x, Expr **y, Expr **z); + Vector GetPointCoords(void); + void ForcePointTo(Vector v); + bool IsFromReferences(void); + + // Routines to draw and hit-test the representation of the entity + // on-screen. struct { bool drawing; Point2d mp; double dmin; - } dogd; // state for drawing or getting distance (for hit testing) + } dogd; void LineDrawOrGetDistance(Vector a, Vector b); void DrawOrGetDistance(void); void Draw(void); double GetDistance(Point2d mp); + + char *DescriptionString(void); }; class Param { @@ -150,53 +150,17 @@ public: void ForceTo(double v); }; -class Point { -public: - int tag; - // The point ID is equal to the initial param ID. - hPoint h; - - int type; - static const int IN_FREE_SPACE = 0; // three params, x y z - static const int IN_2D_CSYS = 1; // two params, u v, plus csys - - hEntity csys; - - inline hEntity entity(void) - { hEntity r; r.v = (h.v >> 7); return r; } - inline hParam param(int i) - { hParam r; r.v = h.v + i; return r; } - - // The point, in base coordinates. This may be a single parameter, or - // it may be a more complex expression if our point is locked in a - // 2d csys. - void GetExprs(Expr **x, Expr **y, Expr **z); - Vector GetCoords(void); - - void ForceTo(Vector v); - - void Draw(void); - double GetDistance(Point2d mp); -}; inline hEntity hRequest::entity(int i) - { hEntity r; r.v = (v << 10) | i; return r; } + { 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 hRequest hEntity::request(void) - { hRequest r; r.v = (v >> 10); return r; } -inline hParam hEntity::param(int i) - { hParam r; r.v = (v << 7) | i; return r; } -inline hPoint hEntity::point(int i) - { hPoint r; r.v = (v << 7) | i; return r; } - -inline bool hPoint::isFromReferences(void) { - DWORD d = v >> 17; - if(d == Request::HREQUEST_REFERENCE_XY.v) return true; - if(d == Request::HREQUEST_REFERENCE_YZ.v) return true; - if(d == Request::HREQUEST_REFERENCE_ZX.v) return true; - return false; -} + { hRequest r; r.v = (v >> 16); return r; } +inline hRequest hParam::request(void) + { hRequest r; r.v = (v >> 16); return r; } class hConstraint { @@ -223,9 +187,9 @@ public: // These are the parameters for the constraint. Expr *exprA; Expr *exprB; - hPoint ptA; - hPoint ptB; - hPoint ptC; + hEntity ptA; + hEntity ptB; + hEntity ptC; hEntity entityA; hEntity entityB; diff --git a/solvespace.cpp b/solvespace.cpp index c392450c..8c29b75f 100644 --- a/solvespace.cpp +++ b/solvespace.cpp @@ -8,7 +8,6 @@ void SolveSpace::Init(void) { group.Clear(); entity.Clear(); - point.Clear(); param.Clear(); // Our initial group, that contains the references. @@ -57,9 +56,8 @@ void SolveSpace::GenerateAll(void) { param.MoveSelfInto(&prev); entity.Clear(); - point.Clear(); for(i = 0; i < request.n; i++) { - request.elem[i].Generate(&entity, &point, ¶m); + request.elem[i].Generate(&entity, ¶m); } for(i = 0; i < param.n; i++) { @@ -84,17 +82,15 @@ void SolveSpace::ForceReferences(void) { { Request::HREQUEST_REFERENCE_ZX, 0.5, -0.5, -0.5, -0.5, }, }; for(int i = 0; i < 3; i++) { - hEntity he; - he = request.FindById(Quat[i].hr)->entity(0); - Entity *e = entity.FindById(he); + hRequest hr = Quat[i].hr; // The origin for our coordinate system, always zero Vector v = Vector::MakeFrom(0, 0, 0); - point.FindById(e->point(16))->ForceTo(v); + GetEntity(hr.entity(1))->ForcePointTo(v); // The quaternion that defines the rotation, from the table. - param.FindById(e->param(0))->ForceTo(Quat[i].a); - param.FindById(e->param(1))->ForceTo(Quat[i].b); - param.FindById(e->param(2))->ForceTo(Quat[i].c); - param.FindById(e->param(3))->ForceTo(Quat[i].d); + GetParam(hr.param(0))->ForceTo(Quat[i].a); + GetParam(hr.param(1))->ForceTo(Quat[i].b); + GetParam(hr.param(2))->ForceTo(Quat[i].c); + GetParam(hr.param(3))->ForceTo(Quat[i].d); } } diff --git a/solvespace.h b/solvespace.h index d1a31a61..4f416f19 100644 --- a/solvespace.h +++ b/solvespace.h @@ -61,6 +61,9 @@ void glxVertex3v(Vector u); void glxWriteText(char *str); void glxTranslatev(Vector u); void glxOntoCsys(Vector u, Vector v); +void glxLockColorTo(double r, double g, double b); +void glxUnlockColor(void); +void glxColor(double r, double g, double b); #define arraylen(x) (sizeof((x))/sizeof((x)[0])) @@ -83,7 +86,6 @@ public: // These lists are generated automatically when we solve the sketch. IdList entity; - IdList point; IdList param; inline Constraint *GetConstraint(hConstraint h) @@ -91,7 +93,6 @@ public: inline Request *GetRequest(hRequest h) { return request.FindById(h); } inline Entity *GetEntity (hEntity h) { return entity. FindById(h); } inline Param *GetParam (hParam h) { return param. FindById(h); } - inline Point *GetPoint (hPoint h) { return point. FindById(h); } hGroup activeGroup; diff --git a/ui.h b/ui.h index fc6d34d4..53d37f6f 100644 --- a/ui.h +++ b/ui.h @@ -137,7 +137,7 @@ public: // Operations that must be completed by doing something with the mouse // are noted here. static const int PENDING_OPERATION_DRAGGING_POINT = 0x0f000000; - hPoint pendingPoint; + hEntity pendingPoint; int pendingOperation; char *pendingDescription; hRequest AddRequest(int type); @@ -146,7 +146,6 @@ public: // The current selection. class Selection { public: - hPoint point; hEntity entity; hConstraint constraint; @@ -162,7 +161,7 @@ public: void HitTestMakeSelection(Point2d mp, Selection *dest); void ClearSelection(void); struct { - hPoint point[MAX_SELECTED]; + hEntity point[MAX_SELECTED]; hEntity entity[MAX_SELECTED]; int points; int entities; @@ -182,7 +181,7 @@ public: static void ToggleAnyDatumShown(int link, DWORD v); void UpdateDraggedPoint(Vector *pos, double mx, double my); - void UpdateDraggedHPoint(hPoint hp, double mx, double my); + void UpdateDraggedEntity(hEntity hp, double mx, double my); // These are called by the platform-specific code. void Paint(int w, int h);