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]
solver
Jonathan Westhues 2008-04-09 00:39:01 -08:00
parent a7fa89c2cc
commit 9c2a8a08dc
9 changed files with 261 additions and 200 deletions

View File

@ -176,7 +176,7 @@ void TextWindow::ShowGroupList(void) {
int i; int i;
for(i = 0; i < SS.group.elems; 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]) { if(g->name.str[0]) {
Printf(" %s", g->name.str); Printf(" %s", g->name.str);
} else { } else {
@ -192,7 +192,7 @@ void TextWindow::ShowRequestList(void) {
int i; int i;
for(i = 0; i < SS.request.elems; 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]) { if(r->name.str[0]) {
Printf(" %s", r->name.str); Printf(" %s", r->name.str);

39
dsc.h
View File

@ -2,13 +2,14 @@
#ifndef __DSC_H #ifndef __DSC_H
#define __DSC_H #define __DSC_H
typedef unsigned __int64 QWORD;
typedef unsigned long DWORD; typedef unsigned long DWORD;
typedef unsigned char BYTE; typedef unsigned char BYTE;
class Vector { class Vector {
public: public:
double x, y, z; double x, y, z;
static Vector MakeFrom(double x, double y, double z);
Vector Plus(Vector b); Vector Plus(Vector b);
Vector Minus(Vector b); Vector Minus(Vector b);
@ -20,6 +21,11 @@ public:
double Magnitude(void); double Magnitude(void);
Vector ScaledBy(double v); 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); void glVertex3v(Vector u);
@ -33,8 +39,7 @@ template <class T, class H>
class IdList { class IdList {
public: public:
typedef struct { typedef struct {
T v; T t;
H h;
int tag; int tag;
} Elem; } Elem;
@ -42,36 +47,28 @@ public:
int elems; int elems;
int elemsAllocated; int elemsAllocated;
H AddAndAssignId(T *v) { H AddAndAssignId(T *t) {
H ht;
ht.v = 0;
return AddAndAssignId(v, ht);
}
H AddAndAssignId(T *v, H ht) {
int i; int i;
QWORD id = 0; DWORD id = 0;
for(i = 0; i < elems; i++) { for(i = 0; i < elems; i++) {
id = max(id, (elem[i].h.v & 0xfff)); id = max(id, elem[i].t.h.v);
} }
H h; t->h.v = (id + 1);
h.v = (id + 1) | ht.v; Add(t);
AddById(v, h);
return h; return t->h;
} }
void AddById(T *v, H h) { void Add(T *t) {
if(elems >= elemsAllocated) { if(elems >= elemsAllocated) {
elemsAllocated = (elemsAllocated + 32)*2; elemsAllocated = (elemsAllocated + 32)*2;
elem = (Elem *)realloc(elem, elemsAllocated*sizeof(elem[0])); elem = (Elem *)realloc(elem, elemsAllocated*sizeof(elem[0]));
if(!elem) oops(); if(!elem) oops();
} }
elem[elems].v = *v; elem[elems].t = *t;
elem[elems].h = h;
elem[elems].tag = 0; elem[elems].tag = 0;
elems++; elems++;
} }
@ -79,8 +76,8 @@ public:
T *FindById(H h) { T *FindById(H h) {
int i; int i;
for(i = 0; i < elems; i++) { for(i = 0; i < elems; i++) {
if(elem[i].h.v == h.v) { if(elem[i].t.h.v == h.v) {
return &(elem[i].v); return &(elem[i].t);
} }
} }
dbp("failed to look up item %16lx, searched %d items", h.v); dbp("failed to look up item %16lx, searched %d items", h.v);

View File

@ -1,32 +1,35 @@
#include "solvespace.h" #include "solvespace.h"
void Entity::Draw(void) { void Entity::Draw(void) {
int i; switch(type) {
for(i = 0; i < 3; i++) { case CSYS_2D: {
Vector p, u, v; Vector p;
double a, b, c, d;
if(i == 0) { SS.point.FindById(point(16))->GetInto(&p);
p.x = 0; p.y = 0; p.z = 1; a = SS.param.FindById(param(0))->val;
} else if(i == 1) { b = SS.param.FindById(param(1))->val;
p.x = 0; p.y = 1; p.z = 0; c = SS.param.FindById(param(2))->val;
} else { d = SS.param.FindById(param(3))->val;
p.x = 1; p.y = 0; p.z = 0;
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;
} }
default:
u = p.Normal(0); oops();
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();
} }
} }

View File

@ -148,7 +148,9 @@ void GraphicsWindow::Paint(int w, int h) {
glClearDepth(1.0); glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Entity e; int i;
e.Draw(); for(i = 0; i < SS.entity.elems; i++) {
SS.entity.elem[i].t.Draw();
}
} }

View File

@ -1,25 +1,83 @@
#include "solvespace.h" #include "solvespace.h"
const hEntity Entity::NONE = { 0 }; const hEntity Entity::NO_CSYS = { 0 };
const hGroup Group::HGROUP_REFERENCES = { 1 }; const hGroup Group::HGROUP_REFERENCES = { 1 };
const hRequest Request::HREQUEST_REFERENCE_XY = { 1 }; const hRequest Request::HREQUEST_REFERENCE_XY = { 1 };
const hRequest Request::HREQUEST_REFERENCE_YZ = { 2 }; const hRequest Request::HREQUEST_REFERENCE_YZ = { 2 };
const hRequest Request::HREQUEST_REFERENCE_ZX = { 3 }; const hRequest Request::HREQUEST_REFERENCE_ZX = { 3 };
void Request::GenerateEntities(IdList<Entity,hEntity> *l, void Request::AddParam(Entity *e, int index) {
IdList<Group,hGroup> *gl) 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; Entity e;
memset(&e, 0, sizeof(e)); memset(&e, 0, sizeof(e));
e.h = this->entity(0);
Group *g = gl->FindById(group);
e.csys = csys = g->csys;
switch(type) { switch(type) {
case TWO_D_CSYS: case Request::CSYS_2D:
e.type = Entity::TWO_D_CSYS; type = Entity::CSYS_2D; points = 1; params = 4; goto c;
l->AddById(&e, h.entity(group, 0)); 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; break;
default: default:
@ -27,47 +85,16 @@ void Request::GenerateEntities(IdList<Entity,hEntity> *l,
} }
} }
void Entity::GeneratePointsAndParams(IdList<Point,hPoint> *lpt, void Point::GetInto(Vector *v) {
IdList<Param,hParam> *lpa)
{
int ptc, pac;
switch(type) { switch(type) {
case TWO_D_CSYS: ptc = 1; pac = 4; break; case IN_FREE_SPACE:
v->x = SS.param.FindById(param(0))->val;
default: v->y = SS.param.FindById(param(1))->val;
oops(); v->z = SS.param.FindById(param(2))->val;
}
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<Param,hParam> *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));
break; break;
default: default:
oops(); oops();
} }
} }

156
sketch.h
View File

@ -3,74 +3,44 @@
#define __SKETCH_H #define __SKETCH_H
class hEntity; class hEntity;
class Entity;
class hPoint; class hPoint;
class hRequest; class hRequest;
class hParam; class hParam;
class hGroup; 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 { class hGroup {
public: public:
// bits 11: 0 -- group index // bits 10: 0 -- group index
QWORD v; DWORD v;
}; };
class hRequest { class hRequest {
public: public:
// bits 11: 0 -- request index // bits 10: 0 -- request index
QWORD v; DWORD v;
};
hEntity entity(hGroup g, int i); class hEntity {
public:
// bits 10: 0 -- entity index
// 21:11 -- request index
DWORD v;
}; };
class hParam { class hParam {
public: public:
// bits 7: 0 -- param index // bits 7: 0 -- param index
// 10: 8 -- type (0 for 3d point, 7 for from entity) // 18: 8 -- entity index
// 15:11 -- point index, or zero if from entity // 29:19 -- request index
// 31:16 -- entity index DWORD v;
// 43:32 -- request index
// 55:44 -- group index
QWORD v;
inline hGroup group(void) { hGroup r; r.v = (v >> 44); return r; }
}; };
class hPoint { class hPoint {
// bits 7: 0 -- point index
// 18: 8 -- entity index
// 29:19 -- request index
public: public:
// bits 2: 0 -- type (0 for 3d point) DWORD v;
// 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;
}
}; };
// A set of requests. Every request must have an associated group. A group // A set of requests. Every request must have an associated group. A group
@ -81,7 +51,9 @@ class Group {
public: public:
static const hGroup HGROUP_REFERENCES; 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; NameStr name;
}; };
@ -89,11 +61,13 @@ public:
// line, or a // line, or a
class Request { class Request {
public: public:
// Some predefined requests, that are present in every sketch.
static const hRequest HREQUEST_REFERENCE_XY; static const hRequest HREQUEST_REFERENCE_XY;
static const hRequest HREQUEST_REFERENCE_YZ; static const hRequest HREQUEST_REFERENCE_YZ;
static const hRequest HREQUEST_REFERENCE_ZX; 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; static const int LINE_SEGMENT = 1;
int type; int type;
@ -101,51 +75,71 @@ public:
hRequest h; hRequest h;
hGroup group; hGroup group;
hEntity csys;
NameStr name; NameStr name;
void GenerateEntities(IdList<Entity,hEntity> *l, IdList<Group,hGroup> *gl); inline hEntity entity(int i)
}; { hEntity r; r.v = ((this->h.v) << 11) | i; return r; }
class Param { void AddParam(Entity *e, int index);
public: void Generate(void);
double val;
hParam h;
};
class Point {
public:
hPoint h;
hEntity csys;
void GenerateParams(IdList<Param,hParam> *l);
}; };
class Entity { class Entity {
public: 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; static const int LINE_SEGMENT = 101;
int type; int type;
hEntity h; 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 Draw(void);
void GeneratePointsAndParams(IdList<Point,hPoint> *pt,
IdList<Param,hParam> *pa);
}; };
// Must be defined later, once hEntity has been defined. class Param {
inline hEntity hRequest::entity(hGroup g, int i) { public:
hEntity r; hParam h;
r.v = (g.v << 28) | (v << 16) | i; double val;
return r; 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 #endif

View File

@ -19,11 +19,12 @@ void SolveSpace::Init(void) {
// Our initial group, that contains the references. // Our initial group, that contains the references.
Group g; Group g;
memset(&g, 0, sizeof(g)); memset(&g, 0, sizeof(g));
g.csys = Entity::NONE; g.csys = Entity::NO_CSYS;
g.name.strcpy("__references"); 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(""); g.name.strcpy("");
group.AddAndAssignId(&g); group.AddAndAssignId(&g);
@ -32,20 +33,24 @@ void SolveSpace::Init(void) {
// planes; these are our references, present in every sketch. // planes; these are our references, present in every sketch.
Request r; Request r;
memset(&r, 0, sizeof(r)); memset(&r, 0, sizeof(r));
r.type = Request::TWO_D_CSYS; r.type = Request::CSYS_2D;
r.group = Group::HGROUP_REFERENCES; r.group = Group::HGROUP_REFERENCES;
r.name.strcpy("__xy_plane"); 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"); 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"); r.name.strcpy("__zx_plane");
request.AddById(&r, Request::HREQUEST_REFERENCE_ZX); r.h = Request::HREQUEST_REFERENCE_ZX;
request.Add(&r);
TW.ShowGroupList(); TW.ShowGroupList();
TW.ShowRequestList(); TW.ShowRequestList();
TW.ClearScreen();
Solve(); Solve();
} }
@ -54,21 +59,31 @@ void SolveSpace::Solve(void) {
entity.Clear(); entity.Clear();
for(i = 0; i < request.elems; i++) { for(i = 0; i < request.elems; i++) {
request.elem[i].v.GenerateEntities(&entity, &group); request.elem[i].t.Generate();
} }
point.Clear(); // Force the values of the paramters that define the three reference
param.Clear(); // coordinate systems.
for(i = 0; i < entity.elems; i++) { static const struct {
entity.elem[i].v.GeneratePointsAndParams(&point, &param); 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(&param);
}
TW.Printf("entities=%d", entity.elems);
TW.Printf("points=%d", point.elems);
TW.Printf("params=%d", param.elems);
} }

View File

@ -21,6 +21,7 @@ void dbp(char *str, ...);
#include <gl/gl.h> #include <gl/gl.h>
#include <gl/glu.h> #include <gl/glu.h>
class Expr;
#include "dsc.h" #include "dsc.h"
#include "ui.h" #include "ui.h"
#include "sketch.h" #include "sketch.h"

View File

@ -23,6 +23,28 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
mat[15] = a44; 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 Vector::Plus(Vector b) {
Vector r; Vector r;