From 9c2a8a08dc358ea1a4e797555cb2d22770b8ec20 Mon Sep 17 00:00:00 2001 From: Jonathan Westhues Date: Wed, 9 Apr 2008 00:39:01 -0800 Subject: [PATCH] Drastic changes to the handle structure; that's now just 32 bits, and I am assuming that many more operations will require lookups in the IdList<>. Add code to represent and draw a 2d coordinate system. The origin is described by a point, and the orientation by a quaternion. So now it does the same thing before, and draws the reference planes, but with a lot more lines of code. [git-p4: depot-paths = "//depot/solvespace/": change = 1658] --- cmdline.cpp | 4 +- dsc.h | 39 ++++++------ entity.cpp | 53 ++++++++-------- graphicswin.cpp | 6 +- sketch.cpp | 123 +++++++++++++++++++++++--------------- sketch.h | 156 +++++++++++++++++++++++------------------------- solvespace.cpp | 57 +++++++++++------- solvespace.h | 1 + util.cpp | 22 +++++++ 9 files changed, 261 insertions(+), 200 deletions(-) diff --git a/cmdline.cpp b/cmdline.cpp index 4df9a81..026db5b 100644 --- a/cmdline.cpp +++ b/cmdline.cpp @@ -176,7 +176,7 @@ void TextWindow::ShowGroupList(void) { int i; for(i = 0; i < SS.group.elems; i++) { - Group *g = &(SS.group.elem[i].v); + Group *g = &(SS.group.elem[i].t); if(g->name.str[0]) { Printf(" %s", g->name.str); } else { @@ -192,7 +192,7 @@ void TextWindow::ShowRequestList(void) { int i; for(i = 0; i < SS.request.elems; i++) { - Request *r = &(SS.request.elem[i].v); + Request *r = &(SS.request.elem[i].t); if(r->name.str[0]) { Printf(" %s", r->name.str); diff --git a/dsc.h b/dsc.h index 24e9be8..b9fb180 100644 --- a/dsc.h +++ b/dsc.h @@ -2,13 +2,14 @@ #ifndef __DSC_H #define __DSC_H -typedef unsigned __int64 QWORD; typedef unsigned long DWORD; typedef unsigned char BYTE; class Vector { public: double x, y, z; + + static Vector MakeFrom(double x, double y, double z); Vector Plus(Vector b); Vector Minus(Vector b); @@ -20,6 +21,11 @@ public: double Magnitude(void); Vector ScaledBy(double v); + // Call a rotation matrix [ u' v' n' ]'; this returns the first and + // second rows, where that matrix is generated by the given quaternion + // a + bi + cj + dk + static Vector RotationU(double a, double b, double c, double d); + static Vector RotationV(double a, double b, double c, double d); }; void glVertex3v(Vector u); @@ -33,8 +39,7 @@ template class IdList { public: typedef struct { - T v; - H h; + T t; int tag; } Elem; @@ -42,36 +47,28 @@ public: int elems; int elemsAllocated; - H AddAndAssignId(T *v) { - H ht; - ht.v = 0; - return AddAndAssignId(v, ht); - } - - H AddAndAssignId(T *v, H ht) { + H AddAndAssignId(T *t) { int i; - QWORD id = 0; + DWORD id = 0; for(i = 0; i < elems; i++) { - id = max(id, (elem[i].h.v & 0xfff)); + id = max(id, elem[i].t.h.v); } - H h; - h.v = (id + 1) | ht.v; - AddById(v, h); + t->h.v = (id + 1); + Add(t); - return h; + return t->h; } - void AddById(T *v, H h) { + void Add(T *t) { if(elems >= elemsAllocated) { elemsAllocated = (elemsAllocated + 32)*2; elem = (Elem *)realloc(elem, elemsAllocated*sizeof(elem[0])); if(!elem) oops(); } - elem[elems].v = *v; - elem[elems].h = h; + elem[elems].t = *t; elem[elems].tag = 0; elems++; } @@ -79,8 +76,8 @@ public: T *FindById(H h) { int i; for(i = 0; i < elems; i++) { - if(elem[i].h.v == h.v) { - return &(elem[i].v); + if(elem[i].t.h.v == h.v) { + return &(elem[i].t); } } dbp("failed to look up item %16lx, searched %d items", h.v); diff --git a/entity.cpp b/entity.cpp index 8e4e6fe..4d6a118 100644 --- a/entity.cpp +++ b/entity.cpp @@ -1,32 +1,35 @@ #include "solvespace.h" void Entity::Draw(void) { - int i; - for(i = 0; i < 3; i++) { - Vector p, u, v; + switch(type) { + case CSYS_2D: { + Vector p; + double a, b, c, d; - if(i == 0) { - p.x = 0; p.y = 0; p.z = 1; - } else if(i == 1) { - p.x = 0; p.y = 1; p.z = 0; - } else { - p.x = 1; p.y = 0; p.z = 0; + SS.point.FindById(point(16))->GetInto(&p); + a = SS.param.FindById(param(0))->val; + b = SS.param.FindById(param(1))->val; + c = SS.param.FindById(param(2))->val; + d = SS.param.FindById(param(3))->val; + + Vector u = Vector::RotationU(a, b, c, d); + Vector v = Vector::RotationV(a, b, c, d); + + double s = (min(SS.GW.width, SS.GW.height))*0.4; + + u = u.ScaledBy(s); + v = v.ScaledBy(s); + + Vector r; + glBegin(GL_LINE_LOOP); + r = p; r = r.Minus(v); r = r.Minus(u); glVertex3v(r); + r = p; r = r.Plus(v); r = r.Minus(u); glVertex3v(r); + r = p; r = r.Plus(v); r = r.Plus(u); glVertex3v(r); + r = p; r = r.Minus(v); r = r.Plus(u); glVertex3v(r); + glEnd(); + break; } - - u = p.Normal(0); - v = p.Normal(1); - - double s = (min(SS.GW.width, SS.GW.height))*0.4; - - u = u.ScaledBy(s); - v = v.ScaledBy(s); - - Vector r; - glBegin(GL_LINE_LOOP); - r = p; r = r.Minus(v); r = r.Minus(u); glVertex3v(r); - r = p; r = r.Plus(v); r = r.Minus(u); glVertex3v(r); - r = p; r = r.Plus(v); r = r.Plus(u); glVertex3v(r); - r = p; r = r.Minus(v); r = r.Plus(u); glVertex3v(r); - glEnd(); + default: + oops(); } } diff --git a/graphicswin.cpp b/graphicswin.cpp index 8154b2d..cd754b9 100644 --- a/graphicswin.cpp +++ b/graphicswin.cpp @@ -148,7 +148,9 @@ void GraphicsWindow::Paint(int w, int h) { glClearDepth(1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - Entity e; - e.Draw(); + int i; + for(i = 0; i < SS.entity.elems; i++) { + SS.entity.elem[i].t.Draw(); + } } diff --git a/sketch.cpp b/sketch.cpp index ae142fc..2270fd8 100644 --- a/sketch.cpp +++ b/sketch.cpp @@ -1,25 +1,83 @@ #include "solvespace.h" -const hEntity Entity::NONE = { 0 }; +const hEntity Entity::NO_CSYS = { 0 }; const hGroup Group::HGROUP_REFERENCES = { 1 }; const hRequest Request::HREQUEST_REFERENCE_XY = { 1 }; const hRequest Request::HREQUEST_REFERENCE_YZ = { 2 }; const hRequest Request::HREQUEST_REFERENCE_ZX = { 3 }; -void Request::GenerateEntities(IdList *l, - IdList *gl) -{ +void Request::AddParam(Entity *e, int index) { + Param pa; + memset(&pa, 0, sizeof(pa)); + pa.h = e->param(index); + SS.param.Add(&pa); +} + +void Request::Generate(void) { + int points = 0; + int params = 0; + int type = 0; + int i; + + Group *g = SS.group.FindById(group); + Entity e; memset(&e, 0, sizeof(e)); - - Group *g = gl->FindById(group); - e.csys = csys = g->csys; + e.h = this->entity(0); switch(type) { - case TWO_D_CSYS: - e.type = Entity::TWO_D_CSYS; - l->AddById(&e, h.entity(group, 0)); + case Request::CSYS_2D: + type = Entity::CSYS_2D; points = 1; params = 4; goto c; + case Request::LINE_SEGMENT: + type = 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(&e, i); + } + for(i = 0; i < points; i++) { + Point pt; + memset(&pt, 0, sizeof(pt)); + pt.h = e.point(16 + 3*i); + if(g->csys.v == Entity::NO_CSYS.v) { + pt.type = Point::IN_FREE_SPACE; + // params for x y z + AddParam(&e, 16 + 3*i + 0); + AddParam(&e, 16 + 3*i + 1); + AddParam(&e, 16 + 3*i + 2); + } else { + pt.type = Point::IN_2D_CSYS; + pt.csys = g->csys; + // params for u v + AddParam(&e, 16 + 3*i + 0); + AddParam(&e, 16 + 3*i + 1); + } + SS.point.Add(&pt); + } + + e.type = type; + SS.entity.Add(&e); + break; + } + + default: + oops(); + } +} + +void Param::ForceTo(double v) { + val = v; + known = true; +} + +void Point::ForceTo(Vector v) { + switch(type) { + case IN_FREE_SPACE: + SS.param.FindById(param(0))->ForceTo(v.x); + SS.param.FindById(param(1))->ForceTo(v.y); + SS.param.FindById(param(2))->ForceTo(v.z); break; default: @@ -27,47 +85,16 @@ void Request::GenerateEntities(IdList *l, } } -void Entity::GeneratePointsAndParams(IdList *lpt, - IdList *lpa) -{ - int ptc, pac; - +void Point::GetInto(Vector *v) { switch(type) { - case TWO_D_CSYS: ptc = 1; pac = 4; break; - - default: - oops(); - } - - Point pt; - memset(&pt, 0, sizeof(pt)); - - pt.csys = csys; - - Param pa; - memset(&pa, 0, sizeof(pa)); - int i; - for(i = 0; i < ptc; i++) { - lpt->AddById(&pt, h.point3(i)); - } - for(i = 0; i < pac; i++) { - lpa->AddById(&pa, h.param(i)); - } -} - -void Point::GenerateParams(IdList *l) { - Param pa; - memset(&pa, 0, sizeof(pa)); - - switch(h.v & 7) { - case 0: - // A point in 3-space; three parameters x, y, z. - l->AddById(&pa, h.param(0)); - l->AddById(&pa, h.param(1)); - l->AddById(&pa, h.param(2)); + case IN_FREE_SPACE: + v->x = SS.param.FindById(param(0))->val; + v->y = SS.param.FindById(param(1))->val; + v->z = SS.param.FindById(param(2))->val; break; - + default: oops(); } } + diff --git a/sketch.h b/sketch.h index 569915c..e16a55a 100644 --- a/sketch.h +++ b/sketch.h @@ -3,74 +3,44 @@ #define __SKETCH_H class hEntity; -class Entity; class hPoint; class hRequest; class hParam; class hGroup; +class Entity; + +// 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 11: 0 -- group index - QWORD v; + // bits 10: 0 -- group index + DWORD v; }; - class hRequest { public: - // bits 11: 0 -- request index - QWORD v; - - hEntity entity(hGroup g, int i); + // bits 10: 0 -- request index + DWORD v; +}; +class hEntity { +public: + // bits 10: 0 -- entity index + // 21:11 -- request index + DWORD v; }; - class hParam { public: // bits 7: 0 -- param index - // 10: 8 -- type (0 for 3d point, 7 for from entity) - // 15:11 -- point index, or zero if from entity - // 31:16 -- entity index - // 43:32 -- request index - // 55:44 -- group index - QWORD v; - - inline hGroup group(void) { hGroup r; r.v = (v >> 44); return r; } + // 18: 8 -- entity index + // 29:19 -- request index + DWORD v; }; - class hPoint { + // bits 7: 0 -- point index + // 18: 8 -- entity index + // 29:19 -- request index public: - // bits 2: 0 -- type (0 for 3d point) - // 7: 3 -- point index - // 23: 8 -- entity index - // 35:24 -- request index - // 47:36 -- group index - QWORD v; - - inline hParam param(int i) { - hParam r; - r.v = (v << 8) | i; - return r; - } -}; - -class hEntity { -public: - // bits 15: 0 -- entity index - // 27:16 -- request index - // 39:17 -- group index - QWORD v; - - inline hGroup group(void) - { hGroup r; r.v = (v >> 28); return r; } - inline hRequest request(void) - { hRequest r; r.v = (v >> 16) & 0xfff; return r; } - inline hPoint point3(int i) - { hPoint r; r.v = (v << 8) | (i << 3) | 0; return r; } - - inline hParam param(int i) { - hParam r; - r.v = (((v << 8) | 7) << 8) | i; - return r; - } + DWORD v; }; // A set of requests. Every request must have an associated group. A group @@ -81,7 +51,9 @@ class Group { public: static const hGroup HGROUP_REFERENCES; - hEntity csys; + hGroup h; + + hEntity csys; // or Entity::NO_CSYS, if it's not locked in a 2d csys NameStr name; }; @@ -89,11 +61,13 @@ public: // line, or a 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; - static const int TWO_D_CSYS = 0; + // Types of requests + static const int CSYS_2D = 0; static const int LINE_SEGMENT = 1; int type; @@ -101,51 +75,71 @@ public: hRequest h; hGroup group; - hEntity csys; NameStr name; - void GenerateEntities(IdList *l, IdList *gl); -}; + inline hEntity entity(int i) + { hEntity r; r.v = ((this->h.v) << 11) | i; return r; } -class Param { -public: - double val; - - hParam h; -}; - -class Point { -public: - hPoint h; - - hEntity csys; - - void GenerateParams(IdList *l); + void AddParam(Entity *e, int index); + void Generate(void); }; class Entity { public: - static const hEntity NONE; + static const hEntity NO_CSYS; - static const int TWO_D_CSYS = 100; + static const int CSYS_2D = 100; static const int LINE_SEGMENT = 101; int type; hEntity h; - hEntity csys; + + Expr *expr[16]; + + inline hParam param(int i) + { hParam r; r.v = ((this->h.v) << 8) | i; return r; } + inline hPoint point(int i) + { hPoint r; r.v = ((this->h.v) << 8) | i; return r; } void Draw(void); - void GeneratePointsAndParams(IdList *pt, - IdList *pa); }; -// Must be defined later, once hEntity has been defined. -inline hEntity hRequest::entity(hGroup g, int i) { - hEntity r; - r.v = (g.v << 28) | (v << 16) | i; - return r; -} +class Param { +public: + hParam h; + double val; + bool known; + void ForceTo(double v); +}; + +class Point { +public: + // 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 + static const int BY_EXPR = 2; // three Expr *, could be anything + + hEntity csys; + + inline hEntity entity(void) + { hEntity r; r.v = (h.v >> 8); 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. + Expr *x(void); + Expr *y(void); + Expr *z(void); + + void ForceTo(Vector v); + void GetInto(Vector *v); +}; #endif diff --git a/solvespace.cpp b/solvespace.cpp index c8cc5b7..014b734 100644 --- a/solvespace.cpp +++ b/solvespace.cpp @@ -19,11 +19,12 @@ void SolveSpace::Init(void) { // Our initial group, that contains the references. Group g; memset(&g, 0, sizeof(g)); - g.csys = Entity::NONE; + g.csys = Entity::NO_CSYS; g.name.strcpy("__references"); - group.AddById(&g, Group::HGROUP_REFERENCES); + g.h = Group::HGROUP_REFERENCES; + group.Add(&g); - g.csys = Entity::NONE; + g.csys = Entity::NO_CSYS; g.name.strcpy(""); group.AddAndAssignId(&g); @@ -32,20 +33,24 @@ void SolveSpace::Init(void) { // planes; these are our references, present in every sketch. Request r; memset(&r, 0, sizeof(r)); - r.type = Request::TWO_D_CSYS; + r.type = Request::CSYS_2D; r.group = Group::HGROUP_REFERENCES; r.name.strcpy("__xy_plane"); - request.AddById(&r, Request::HREQUEST_REFERENCE_XY); + r.h = Request::HREQUEST_REFERENCE_XY; + request.Add(&r); + r.name.strcpy("__yz_plane"); - request.AddById(&r, Request::HREQUEST_REFERENCE_YZ); + r.h = Request::HREQUEST_REFERENCE_YZ; + request.Add(&r); + r.name.strcpy("__zx_plane"); - request.AddById(&r, Request::HREQUEST_REFERENCE_ZX); + r.h = Request::HREQUEST_REFERENCE_ZX; + request.Add(&r); TW.ShowGroupList(); TW.ShowRequestList(); - TW.ClearScreen(); Solve(); } @@ -54,21 +59,31 @@ void SolveSpace::Solve(void) { entity.Clear(); for(i = 0; i < request.elems; i++) { - request.elem[i].v.GenerateEntities(&entity, &group); + request.elem[i].t.Generate(); } - point.Clear(); - param.Clear(); - for(i = 0; i < entity.elems; i++) { - entity.elem[i].v.GeneratePointsAndParams(&point, ¶m); + // Force the values of the paramters that define the three reference + // coordinate systems. + static const struct { + hRequest hr; + double a, b, c, d; + } Quat[] = { + { Request::HREQUEST_REFERENCE_XY, 1, 0, 0, 0, }, + { Request::HREQUEST_REFERENCE_YZ, 0.5, 0.5, 0.5, 0.5, }, + { Request::HREQUEST_REFERENCE_ZX, 0.5, -0.5, -0.5, -0.5, }, + }; + for(i = 0; i < 3; i++) { + hEntity he; + he = request.FindById(Quat[i].hr)->entity(0); + Entity *e = entity.FindById(he); + // The origin for our coordinate system, always zero + Vector v = Vector::MakeFrom(0, 0, 0); + point.FindById(e->point(16))->ForceTo(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); } - for(i = 0; i < point.elems; i++) { - point.elem[i].v.GenerateParams(¶m); - } - - TW.Printf("entities=%d", entity.elems); - TW.Printf("points=%d", point.elems); - TW.Printf("params=%d", param.elems); - } diff --git a/solvespace.h b/solvespace.h index d75d079..95199bd 100644 --- a/solvespace.h +++ b/solvespace.h @@ -21,6 +21,7 @@ void dbp(char *str, ...); #include #include +class Expr; #include "dsc.h" #include "ui.h" #include "sketch.h" diff --git a/util.cpp b/util.cpp index 4542d16..81d72a9 100644 --- a/util.cpp +++ b/util.cpp @@ -23,6 +23,28 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14, mat[15] = a44; } +Vector Vector::MakeFrom(double x, double y, double z) { + Vector v; + v.x = x; v.y = y; v.z = z; + return v; +} + +Vector Vector::RotationU(double a, double b, double c, double d) { + Vector v; + v.x = a*a + b*b - c*c - d*d; + v.y = 2*b*c - 2*a*d; + v.z = 2*a*c + 2*b*d; + return v; +} + +Vector Vector::RotationV(double a, double b, double c, double d) { + Vector v; + v.x = 2*a*d + 2*b*c; + v.y = a*a - b*b + c*c - d*d; + v.z = 2*c*d - 2*a*b; + return v; +} + Vector Vector::Plus(Vector b) { Vector r;