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;
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);

39
dsc.h
View File

@ -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 T, class H>
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);

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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<Entity,hEntity> *l,
IdList<Group,hGroup> *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<Entity,hEntity> *l,
}
}
void Entity::GeneratePointsAndParams(IdList<Point,hPoint> *lpt,
IdList<Param,hParam> *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<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));
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();
}
}

156
sketch.h
View File

@ -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<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 {
public:
double val;
hParam h;
};
class Point {
public:
hPoint h;
hEntity csys;
void GenerateParams(IdList<Param,hParam> *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<Point,hPoint> *pt,
IdList<Param,hParam> *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

View File

@ -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, &param);
// 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(&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/glu.h>
class Expr;
#include "dsc.h"
#include "ui.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;
}
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;