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];
} 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;

View File

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

2
dsc.h
View File

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

View File

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

1
expr.h
View File

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

View File

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

View File

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

View File

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

View File

@ -17,15 +17,15 @@ char *Group::DescriptionString(void) {
return ret;
}
void Request::AddParam(IdList<Param,hParam> *param, Entity *e, int index) {
hParam Request::AddParam(IdList<Param,hParam> *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,hEntity> *entity,
IdList<Point,hPoint> *point,
IdList<Param,hParam> *param)
{
int points = 0;
@ -37,46 +37,50 @@ void Request::Generate(IdList<Entity,hEntity> *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);
}

126
sketch.h
View File

@ -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,hParam> *param, Entity *e, int index);
void Generate(IdList<Entity,hEntity> *entity,
IdList<Point,hPoint> *point,
IdList<Param,hParam> *param);
hParam AddParam(IdList<Param,hParam> *param, hParam hp);
void Generate(IdList<Entity,hEntity> *entity, IdList<Param,hParam> *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;

View File

@ -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, &param);
request.elem[i].Generate(&entity, &param);
}
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);
}
}

View File

@ -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,hEntity> entity;
IdList<Point,hPoint> point;
IdList<Param,hParam> 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;

7
ui.h
View File

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