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]
solver
Jonathan Westhues 2008-04-19 03:09:47 -08:00
parent 0d3217c0df
commit cc03fe40aa
13 changed files with 253 additions and 276 deletions

View File

@ -21,15 +21,15 @@ void Constraint::MenuConstrain(int id) {
c.ptB = gs.point[1]; c.ptB = gs.point[1];
} else if(gs.lineSegments == 1 && gs.n == 1) { } else if(gs.lineSegments == 1 && gs.n == 1) {
c.type = PT_PT_DISTANCE; c.type = PT_PT_DISTANCE;
c.ptA = gs.entity[0].point(16); Entity *e = SS.GetEntity(gs.entity[0]);
c.ptB = gs.entity[0].point(16+3); c.ptA = e->assoc[0];
c.ptB = e->assoc[1];
} else { } else {
Error("Bad selection for distance / diameter constraint."); Error("Bad selection for distance / diameter constraint.");
return; return;
} }
c.disp.offset = Vector::MakeFrom(50, 50, 50); c.disp.offset = Vector::MakeFrom(50, 50, 50);
c.exprA = Expr::FromString("1+3+2")->DeepCopyKeep(); c.exprA = Expr::FromString("1+3+2")->DeepCopyKeep();
FreeAllExprs();
AddConstraint(&c); AddConstraint(&c);
break; break;

View File

@ -16,10 +16,11 @@ void Constraint::DrawOrGetDistance(void) {
Vector gu = SS.GW.projUp; Vector gu = SS.GW.projUp;
Vector gn = gr.Cross(gu); Vector gn = gr.Cross(gu);
glxColor(1, 0.3, 1);
switch(type) { switch(type) {
case PT_PT_DISTANCE: { case PT_PT_DISTANCE: {
Vector ap = SS.GetPoint(ptA)->GetCoords(); Vector ap = SS.GetEntity(ptA)->GetPointCoords();
Vector bp = SS.GetPoint(ptB)->GetCoords(); Vector bp = SS.GetEntity(ptB)->GetPointCoords();
Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(disp.offset); Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(disp.offset);

2
dsc.h
View File

@ -91,7 +91,7 @@ public:
T *FindById(H h) { T *FindById(H h) {
T *t = FindByIdNoOops(h); T *t = FindByIdNoOops(h);
if(!t) { 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(); oops();
} }
return t; return t;

View File

@ -1,14 +1,14 @@
#include "solvespace.h" #include "solvespace.h"
char *Entity::DescriptionString(void) { char *Entity::DescriptionString(void) {
Request *r = SS.GetRequest(request()); Request *r = SS.GetRequest(h.request());
return r->DescriptionString(); return r->DescriptionString();
} }
void Entity::Get2dCsysBasisVectors(Vector *u, Vector *v) { void Entity::Get2dCsysBasisVectors(Vector *u, Vector *v) {
double q[4]; double q[4];
for(int i = 0; i < 4; i++) { 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]); 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(); *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) { void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
if(dogd.drawing) { if(dogd.drawing) {
glBegin(GL_LINE_STRIP); glBegin(GL_LINE_STRIP);
@ -46,11 +106,41 @@ double Entity::GetDistance(Point2d mp) {
return dogd.dmin; return dogd.dmin;
} }
void Entity::DrawOrGetDistance(void) { void Entity::DrawOrGetDistance(void) {
glxColor(1, 1, 1);
switch(type) { 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: { case CSYS_2D: {
if(!SS.GW.show2dCsyss) break;
Vector p; Vector p;
p = SS.point.FindById(point(16))->GetCoords(); p = SS.GetEntity(assoc[0])->GetPointCoords();
Vector u, v; Vector u, v;
Get2dCsysBasisVectors(&u, &v); Get2dCsysBasisVectors(&u, &v);
@ -65,28 +155,25 @@ void Entity::DrawOrGetDistance(void) {
Vector mm = p.Minus(us).Minus(vs); Vector mm = p.Minus(us).Minus(vs);
Vector mp = p.Minus(us).Plus (vs); Vector mp = p.Minus(us).Plus (vs);
glxColor(0, 0.4, 0.4);
LineDrawOrGetDistance(pp, pm); LineDrawOrGetDistance(pp, pm);
LineDrawOrGetDistance(pm, mm); LineDrawOrGetDistance(pm, mm);
LineDrawOrGetDistance(mm, mp); LineDrawOrGetDistance(mm, mp);
LineDrawOrGetDistance(mp, pp); LineDrawOrGetDistance(mp, pp);
if(dogd.drawing) { if(dogd.drawing) {
Request *r = SS.request.FindById(this->request());
glPushMatrix(); glPushMatrix();
glxTranslatev(mm); glxTranslatev(mm);
glxOntoCsys(u, v); glxOntoCsys(u, v);
glxWriteText(r->DescriptionString()); glxWriteText(DescriptionString());
glPopMatrix(); glPopMatrix();
} }
break; break;
} }
case DATUM_POINT:
// All display is handled by the generated point.
break;
case LINE_SEGMENT: { case LINE_SEGMENT: {
Vector a = SS.point.FindById(point(16))->GetCoords(); Vector a = SS.GetEntity(assoc[0])->GetPointCoords();
Vector b = SS.point.FindById(point(16+3))->GetCoords(); Vector b = SS.GetEntity(assoc[1])->GetPointCoords();
LineDrawOrGetDistance(a, b); LineDrawOrGetDistance(a, b);
break; break;
} }

1
expr.h
View File

@ -45,7 +45,6 @@ public:
double v; double v;
hParam parh; hParam parh;
Param *parp; Param *parp;
hPoint point;
hEntity entity; hEntity entity;
// For use while parsing // For use while parsing

View File

@ -41,14 +41,6 @@ bool SolveSpace::SaveToFile(char *filename) {
fprintf(fh, "AddEntity\n\n"); 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++) { for(i = 0; i < constraint.n; i++) {
Constraint *c = &(constraint.elem[i]); Constraint *c = &(constraint.elem[i]);
fprintf(fh, "Constraint.h.v=%08x\n", c->h.v); fprintf(fh, "Constraint.h.v=%08x\n", c->h.v);

View File

@ -3,6 +3,8 @@
// A public-domain Hershey vector font ("Simplex"). // A public-domain Hershey vector font ("Simplex").
#include "font.table" #include "font.table"
static bool ColorLocked;
void glxWriteText(char *str) void glxWriteText(char *str)
{ {
double scale = 0.7/SS.GW.scale; double scale = 0.7/SS.GW.scale;
@ -54,3 +56,22 @@ void glxOntoCsys(Vector u, Vector v)
0, 0, 0, 1); 0, 0, 0, 1);
glMultMatrixd(mat); 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);
}
}

View File

@ -138,9 +138,9 @@ void GraphicsWindow::MenuView(int id) {
SS.GW.GroupSelection(); SS.GW.GroupSelection();
Entity *e = NULL; Entity *e = NULL;
if(SS.GW.gs.n == 1 && SS.GW.gs.csyss == 1) { 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) { } 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) { if(e) {
// A quaternion with our original rotation // A quaternion with our original rotation
@ -160,7 +160,7 @@ void GraphicsWindow::MenuView(int id) {
// And also get the offsets. // And also get the offsets.
Vector offset0 = SS.GW.offset; 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. // Animate transition, unless it's a tiny move.
SDWORD dt = (mp < 0.01) ? (-20) : (SDWORD)(100 + 1000*mp); 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]); Selection *s = &(SS.GW.selection[i]);
hRequest r; hRequest r;
r.v = 0; r.v = 0;
if(s->point.v) { if(s->entity.v) {
Point *pt = SS.GetPoint(s->point); r = s->entity.request();
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(r.v) SS.request.Tag(r, 1); if(r.v) SS.request.Tag(r, 1);
} }
@ -299,11 +292,11 @@ c:
} }
} }
void GraphicsWindow::UpdateDraggedHPoint(hPoint hp, double mx, double my) { void GraphicsWindow::UpdateDraggedEntity(hEntity hp, double mx, double my) {
Point *p = SS.point.FindById(hp); Entity *p = SS.GetEntity(hp);
Vector pos = p->GetCoords(); Vector pos = p->GetPointCoords();
UpdateDraggedPoint(&pos, mx, my); UpdateDraggedPoint(&pos, mx, my);
p->ForceTo(pos); p->ForcePointTo(pos);
} }
void GraphicsWindow::UpdateDraggedPoint(Vector *pos, double mx, double my) { 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) { } else if(leftDown) {
// We are left-dragging. This is often used to drag points, or // We are left-dragging. This is often used to drag points, or
// constraint labels. // constraint labels.
if(hover.point.v && !hover.point.isFromReferences()) { if(hover.entity.v &&
SS.GetEntity(hover.entity)->IsPoint() &&
!SS.GetEntity(hover.entity)->IsFromReferences())
{
ClearSelection(); ClearSelection();
UpdateDraggedHPoint(hover.point, x, y); UpdateDraggedEntity(hover.entity, x, y);
} else if(hover.constraint.v && } else if(hover.constraint.v &&
SS.GetConstraint(hover.constraint)->HasLabel()) SS.GetConstraint(hover.constraint)->HasLabel())
{ {
@ -370,7 +366,7 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
} }
} else { } else {
if(pendingOperation == PENDING_OPERATION_DRAGGING_POINT) { if(pendingOperation == PENDING_OPERATION_DRAGGING_POINT) {
UpdateDraggedHPoint(pendingPoint, x, y); UpdateDraggedEntity(pendingPoint, x, y);
} else { } else {
// Do our usual hit testing, for the selection. // Do our usual hit testing, for the selection.
Selection s; Selection s;
@ -384,24 +380,21 @@ void GraphicsWindow::MouseMoved(double x, double y, bool leftDown,
} }
bool GraphicsWindow::Selection::Equals(Selection *b) { bool GraphicsWindow::Selection::Equals(Selection *b) {
if(point.v != b->point.v) return false;
if(entity.v != b->entity.v) return false; if(entity.v != b->entity.v) return false;
if(constraint.v != b->constraint.v) return false; if(constraint.v != b->constraint.v) return false;
return true; return true;
} }
bool GraphicsWindow::Selection::IsEmpty(void) { bool GraphicsWindow::Selection::IsEmpty(void) {
if(point.v) return false;
if(entity.v) return false; if(entity.v) return false;
if(constraint.v) return false; if(constraint.v) return false;
return true; return true;
} }
void GraphicsWindow::Selection::Clear(void) { void GraphicsWindow::Selection::Clear(void) {
point.v = entity.v = constraint.v = 0; entity.v = constraint.v = 0;
} }
void GraphicsWindow::Selection::Draw(void) { void GraphicsWindow::Selection::Draw(void) {
if(point.v) SS.point. FindById(point )->Draw(); if(entity.v) SS.GetEntity (entity )->Draw();
if(entity.v) SS.entity. FindById(entity )->Draw(); if(constraint.v) SS.GetConstraint(constraint)->Draw();
if(constraint.v) SS.constraint.FindById(constraint)->Draw();
} }
void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) { void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) {
@ -410,21 +403,13 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) {
memset(dest, 0, sizeof(*dest)); memset(dest, 0, sizeof(*dest));
// Do the points // Do the entities
for(i = 0; i < SS.entity.n; i++) { for(i = 0; i < SS.entity.n; i++) {
d = SS.entity.elem[i].GetDistance(mp); d = SS.entity.elem[i].GetDistance(mp);
if(d < 10 && d < dmin) { if(d < 10 && d < dmin) {
memset(dest, 0, sizeof(*dest)); memset(dest, 0, sizeof(*dest));
dest->entity = SS.entity.elem[i].h; dest->entity = SS.entity.elem[i].h;
} dmin = d;
}
// 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;
} }
} }
@ -434,6 +419,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) {
if(d < 10 && d < dmin) { if(d < 10 && d < dmin) {
memset(dest, 0, sizeof(*dest)); memset(dest, 0, sizeof(*dest));
dest->constraint = SS.constraint.elem[i].h; dest->constraint = SS.constraint.elem[i].h;
dmin = d;
} }
} }
} }
@ -452,10 +438,6 @@ void GraphicsWindow::GroupSelection(void) {
int i; int i;
for(i = 0; i < MAX_SELECTED; i++) { for(i = 0; i < MAX_SELECTED; i++) {
Selection *s = &(selection[i]); Selection *s = &(selection[i]);
if(s->point.v) {
gs.point[(gs.points)++] = s->point;
(gs.n)++;
}
if(s->entity.v) { if(s->entity.v) {
gs.entity[(gs.entities)++] = s->entity; gs.entity[(gs.entities)++] = s->entity;
(gs.n)++; (gs.n)++;
@ -465,6 +447,9 @@ void GraphicsWindow::GroupSelection(void) {
case Entity::CSYS_2D: (gs.csyss)++; break; case Entity::CSYS_2D: (gs.csyss)++; break;
case Entity::LINE_SEGMENT: (gs.lineSegments)++; 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) { switch(pendingOperation) {
case MNU_DATUM_POINT: case MNU_DATUM_POINT:
hr = AddRequest(Request::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; pendingOperation = 0;
break; break;
case MNU_LINE_SEGMENT: case MNU_LINE_SEGMENT:
hr = AddRequest(Request::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; pendingOperation = PENDING_OPERATION_DRAGGING_POINT;
pendingPoint = hr.entity(0).point(16+3); pendingPoint = hr.entity(2);
pendingDescription = "click to place next point of line"; pendingDescription = "click to place next point of line";
SS.point.FindById(pendingPoint)->ForceTo(v); SS.GetEntity(pendingPoint)->ForcePointTo(v);
break; break;
case PENDING_OPERATION_DRAGGING_POINT: case PENDING_OPERATION_DRAGGING_POINT:
// The MouseMoved event has already dragged it under the cursor.
pendingOperation = 0; pendingOperation = 0;
break; break;
@ -629,15 +615,10 @@ void GraphicsWindow::Paint(int w, int h) {
int i; int i;
// First, draw the entire scene. // First, draw the entire scene.
glColor3f(1, 1, 1); glxUnlockColor();
for(i = 0; i < SS.entity.n; i++) { for(i = 0; i < SS.entity.n; i++) {
SS.entity.elem[i].Draw(); 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++) { for(i = 0; i < SS.constraint.n; i++) {
SS.constraint.elem[i].Draw(); 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 // Then redraw whatever the mouse is hovering over, highlighted. Have
// to disable the depth test, so that we can overdraw. // to disable the depth test, so that we can overdraw.
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
glColor3f(1, 1, 0); glxLockColorTo(1, 1, 0);
hover.Draw(); hover.Draw();
// And finally draw the selection, same mechanism. // And finally draw the selection, same mechanism.
glColor3f(1, 0, 0); glxLockColorTo(1, 0, 0);
for(i = 0; i < MAX_SELECTED; i++) { for(i = 0; i < MAX_SELECTED; i++) {
selection[i].Draw(); selection[i].Draw();
} }

View File

@ -17,15 +17,15 @@ char *Group::DescriptionString(void) {
return ret; return ret;
} }
void Request::AddParam(IdList<Param,hParam> *param, Entity *e, int index) { hParam Request::AddParam(IdList<Param,hParam> *param, hParam hp) {
Param pa; Param pa;
memset(&pa, 0, sizeof(pa)); memset(&pa, 0, sizeof(pa));
pa.h = e->param(index); pa.h = hp;
param->Add(&pa); param->Add(&pa);
return hp;
} }
void Request::Generate(IdList<Entity,hEntity> *entity, void Request::Generate(IdList<Entity,hEntity> *entity,
IdList<Point,hPoint> *point,
IdList<Param,hParam> *param) IdList<Param,hParam> *param)
{ {
int points = 0; int points = 0;
@ -37,46 +37,50 @@ void Request::Generate(IdList<Entity,hEntity> *entity,
Entity e; Entity e;
memset(&e, 0, sizeof(e)); memset(&e, 0, sizeof(e));
e.h = this->entity(0);
bool shown = true;
switch(type) { switch(type) {
case Request::CSYS_2D: case Request::CSYS_2D:
et = Entity::CSYS_2D; points = 1; params = 4; goto c; et = Entity::CSYS_2D; points = 1; params = 4; goto c;
case Request::DATUM_POINT: 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: case Request::LINE_SEGMENT:
et = Entity::LINE_SEGMENT; points = 2; params = 0; goto c; et = Entity::LINE_SEGMENT; points = 2; params = 0; goto c;
c: { c: {
// Common routines, for all the requests that generate a single // Generate the entity that's specific to this request.
// 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);
}
e.type = et; 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; break;
} }
@ -100,72 +104,4 @@ void Param::ForceTo(double v) {
known = true; 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);
}

126
sketch.h
View File

@ -6,11 +6,9 @@ class hGroup;
class hRequest; class hRequest;
class hEntity; class hEntity;
class hParam; class hParam;
class hPoint;
class Entity; class Entity;
class Param; class Param;
class Point;
class hEquation; class hEquation;
class Equation; class Equation;
@ -19,41 +17,32 @@ class Equation;
// some data structure in the sketch. // some data structure in the sketch.
class hGroup { class hGroup {
public: public:
// bits 10: 0 -- group index // bits 15: 0 -- group index
DWORD v; DWORD v;
}; };
class hRequest { class hRequest {
public: public:
// bits 14: 0 -- request index (the high bits may be used as an import ID) // bits 15: 0 -- request index
DWORD v; DWORD v;
inline hEntity entity(int i); inline hEntity entity(int i);
inline hParam param(int i);
}; };
class hEntity { class hEntity {
public: public:
// bits 9: 0 -- entity index // bits 15: 0 -- entity index
// 24:10 -- request index // 31:16 -- request index
DWORD v; DWORD v;
inline hRequest request(void); inline hRequest request(void);
inline hParam param(int i);
inline hPoint point(int i);
}; };
class hParam { class hParam {
public: public:
// bits 6: 0 -- param index // bits 15: 0 -- param index
// 16: 7 -- entity index // 31:16 -- request index
// 31:17 -- request index
DWORD v; 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. // A set of requests. Every request must have an associated group.
@ -94,13 +83,8 @@ public:
NameStr name; NameStr name;
inline hEntity entity(int i) hParam AddParam(IdList<Param,hParam> *param, hParam hp);
{ hEntity r; r.v = ((this->h.v) << 10) | i; return r; } void Generate(IdList<Entity,hEntity> *entity, IdList<Param,hParam> *param);
void AddParam(IdList<Param,hParam> *param, Entity *e, int index);
void Generate(IdList<Entity,hEntity> *entity,
IdList<Point,hPoint> *point,
IdList<Param,hParam> *param);
char *DescriptionString(void); char *DescriptionString(void);
}; };
@ -113,30 +97,46 @@ public:
static const hEntity NO_CSYS; static const hEntity NO_CSYS;
static const int CSYS_2D = 1000; static const int CSYS_2D = 1000;
static const int DATUM_POINT = 1001; static const int POINT_IN_3D = 2000;
static const int LINE_SEGMENT = 1010; static const int POINT_IN_2D = 2001;
static const int LINE_SEGMENT = 3000;
int type; int type;
inline hRequest request(void) bool symbolic;
{ hRequest r; r.v = (this->h.v >> 10); return r; } // The params are usually handles to the symbolic variables, but may
inline hParam param(int i) // also be constants
{ hParam r; r.v = ((this->h.v) << 7) | i; return r; } union {
inline hPoint point(int i) hParam h[16];
{ hPoint r; r.v = ((this->h.v) << 7) | i; return r; } 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); 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 { struct {
bool drawing; bool drawing;
Point2d mp; Point2d mp;
double dmin; double dmin;
} dogd; // state for drawing or getting distance (for hit testing) } dogd;
void LineDrawOrGetDistance(Vector a, Vector b); void LineDrawOrGetDistance(Vector a, Vector b);
void DrawOrGetDistance(void); void DrawOrGetDistance(void);
void Draw(void); void Draw(void);
double GetDistance(Point2d mp); double GetDistance(Point2d mp);
char *DescriptionString(void);
}; };
class Param { class Param {
@ -150,53 +150,17 @@ public:
void ForceTo(double v); 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) 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) inline hRequest hEntity::request(void)
{ hRequest r; r.v = (v >> 10); return r; } { hRequest r; r.v = (v >> 16); 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;
}
inline hRequest hParam::request(void)
{ hRequest r; r.v = (v >> 16); return r; }
class hConstraint { class hConstraint {
@ -223,9 +187,9 @@ public:
// These are the parameters for the constraint. // These are the parameters for the constraint.
Expr *exprA; Expr *exprA;
Expr *exprB; Expr *exprB;
hPoint ptA; hEntity ptA;
hPoint ptB; hEntity ptB;
hPoint ptC; hEntity ptC;
hEntity entityA; hEntity entityA;
hEntity entityB; hEntity entityB;

View File

@ -8,7 +8,6 @@ void SolveSpace::Init(void) {
group.Clear(); group.Clear();
entity.Clear(); entity.Clear();
point.Clear();
param.Clear(); param.Clear();
// Our initial group, that contains the references. // Our initial group, that contains the references.
@ -57,9 +56,8 @@ void SolveSpace::GenerateAll(void) {
param.MoveSelfInto(&prev); param.MoveSelfInto(&prev);
entity.Clear(); entity.Clear();
point.Clear();
for(i = 0; i < request.n; i++) { for(i = 0; i < request.n; i++) {
request.elem[i].Generate(&entity, &point, &param); request.elem[i].Generate(&entity, &param);
} }
for(i = 0; i < param.n; i++) { 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, }, { Request::HREQUEST_REFERENCE_ZX, 0.5, -0.5, -0.5, -0.5, },
}; };
for(int i = 0; i < 3; i++) { for(int i = 0; i < 3; i++) {
hEntity he; hRequest hr = Quat[i].hr;
he = request.FindById(Quat[i].hr)->entity(0);
Entity *e = entity.FindById(he);
// The origin for our coordinate system, always zero // The origin for our coordinate system, always zero
Vector v = Vector::MakeFrom(0, 0, 0); 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. // The quaternion that defines the rotation, from the table.
param.FindById(e->param(0))->ForceTo(Quat[i].a); GetParam(hr.param(0))->ForceTo(Quat[i].a);
param.FindById(e->param(1))->ForceTo(Quat[i].b); GetParam(hr.param(1))->ForceTo(Quat[i].b);
param.FindById(e->param(2))->ForceTo(Quat[i].c); GetParam(hr.param(2))->ForceTo(Quat[i].c);
param.FindById(e->param(3))->ForceTo(Quat[i].d); GetParam(hr.param(3))->ForceTo(Quat[i].d);
} }
} }

View File

@ -61,6 +61,9 @@ void glxVertex3v(Vector u);
void glxWriteText(char *str); void glxWriteText(char *str);
void glxTranslatev(Vector u); void glxTranslatev(Vector u);
void glxOntoCsys(Vector u, Vector v); 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])) #define arraylen(x) (sizeof((x))/sizeof((x)[0]))
@ -83,7 +86,6 @@ public:
// These lists are generated automatically when we solve the sketch. // These lists are generated automatically when we solve the sketch.
IdList<Entity,hEntity> entity; IdList<Entity,hEntity> entity;
IdList<Point,hPoint> point;
IdList<Param,hParam> param; IdList<Param,hParam> param;
inline Constraint *GetConstraint(hConstraint h) inline Constraint *GetConstraint(hConstraint h)
@ -91,7 +93,6 @@ public:
inline Request *GetRequest(hRequest h) { return request.FindById(h); } inline Request *GetRequest(hRequest h) { return request.FindById(h); }
inline Entity *GetEntity (hEntity h) { return entity. FindById(h); } inline Entity *GetEntity (hEntity h) { return entity. FindById(h); }
inline Param *GetParam (hParam h) { return param. FindById(h); } inline Param *GetParam (hParam h) { return param. FindById(h); }
inline Point *GetPoint (hPoint h) { return point. FindById(h); }
hGroup activeGroup; hGroup activeGroup;

7
ui.h
View File

@ -137,7 +137,7 @@ public:
// Operations that must be completed by doing something with the mouse // Operations that must be completed by doing something with the mouse
// are noted here. // are noted here.
static const int PENDING_OPERATION_DRAGGING_POINT = 0x0f000000; static const int PENDING_OPERATION_DRAGGING_POINT = 0x0f000000;
hPoint pendingPoint; hEntity pendingPoint;
int pendingOperation; int pendingOperation;
char *pendingDescription; char *pendingDescription;
hRequest AddRequest(int type); hRequest AddRequest(int type);
@ -146,7 +146,6 @@ public:
// The current selection. // The current selection.
class Selection { class Selection {
public: public:
hPoint point;
hEntity entity; hEntity entity;
hConstraint constraint; hConstraint constraint;
@ -162,7 +161,7 @@ public:
void HitTestMakeSelection(Point2d mp, Selection *dest); void HitTestMakeSelection(Point2d mp, Selection *dest);
void ClearSelection(void); void ClearSelection(void);
struct { struct {
hPoint point[MAX_SELECTED]; hEntity point[MAX_SELECTED];
hEntity entity[MAX_SELECTED]; hEntity entity[MAX_SELECTED];
int points; int points;
int entities; int entities;
@ -182,7 +181,7 @@ public:
static void ToggleAnyDatumShown(int link, DWORD v); static void ToggleAnyDatumShown(int link, DWORD v);
void UpdateDraggedPoint(Vector *pos, double mx, double my); 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. // These are called by the platform-specific code.
void Paint(int w, int h); void Paint(int w, int h);