Rename some stuff in the IdList again. Rough in the file save
stuff, though no file load stuff, and perhaps this can all be made to work from a table somehow. Move the quaternion stuff into its own class, and add a fancy animated view when you orient onto a csys. [git-p4: depot-paths = "//depot/solvespace/": change = 1672]solver
parent
c097fea4f3
commit
0d3217c0df
1
Makefile
1
Makefile
|
@ -19,6 +19,7 @@ SSOBJS = $(OBJDIR)\solvespace.obj \
|
|||
$(OBJDIR)\expr.obj \
|
||||
$(OBJDIR)\constraint.obj \
|
||||
$(OBJDIR)\drawconstraint.obj \
|
||||
$(OBJDIR)\file.obj \
|
||||
|
||||
|
||||
LIBS = user32.lib gdi32.lib comctl32.lib advapi32.lib opengl32.lib glu32.lib
|
||||
|
|
54
dsc.h
54
dsc.h
|
@ -5,6 +5,28 @@
|
|||
typedef unsigned long DWORD;
|
||||
typedef unsigned char BYTE;
|
||||
|
||||
class Vector;
|
||||
|
||||
class Quaternion {
|
||||
public:
|
||||
// a + bi + cj + dk
|
||||
double a, b, c, d;
|
||||
|
||||
static Quaternion MakeFrom(double a, double b, double c, double d);
|
||||
static Quaternion MakeFrom(Vector u, Vector v);
|
||||
|
||||
Quaternion Plus(Quaternion y);
|
||||
Quaternion Minus(Quaternion y);
|
||||
Quaternion ScaledBy(double s);
|
||||
double Magnitude(void);
|
||||
Quaternion WithMagnitude(double s);
|
||||
|
||||
// Call a rotation matrix [ u' v' n' ]'; this returns the first and
|
||||
// second rows, where that matrix is generated by this quaternion
|
||||
Vector RotationU(void);
|
||||
Vector RotationV(void);
|
||||
};
|
||||
|
||||
class Vector {
|
||||
public:
|
||||
double x, y, z;
|
||||
|
@ -21,12 +43,6 @@ public:
|
|||
double Magnitude(void);
|
||||
Vector WithMagnitude(double s);
|
||||
Vector ScaledBy(double s);
|
||||
|
||||
// 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);
|
||||
};
|
||||
|
||||
class Point2d {
|
||||
|
@ -44,14 +60,14 @@ template <class T, class H>
|
|||
class IdList {
|
||||
public:
|
||||
T *elem;
|
||||
int elems;
|
||||
int n;
|
||||
int elemsAllocated;
|
||||
|
||||
H AddAndAssignId(T *t) {
|
||||
int i;
|
||||
DWORD id = 0;
|
||||
|
||||
for(i = 0; i < elems; i++) {
|
||||
for(i = 0; i < n; i++) {
|
||||
id = max(id, elem[i].h.v);
|
||||
}
|
||||
|
||||
|
@ -62,20 +78,20 @@ public:
|
|||
}
|
||||
|
||||
void Add(T *t) {
|
||||
if(elems >= elemsAllocated) {
|
||||
if(n >= elemsAllocated) {
|
||||
elemsAllocated = (elemsAllocated + 32)*2;
|
||||
elem = (T *)MemRealloc(elem, elemsAllocated*sizeof(elem[0]));
|
||||
if(!elem) oops();
|
||||
}
|
||||
|
||||
elem[elems] = *t;
|
||||
elems++;
|
||||
elem[n] = *t;
|
||||
n++;
|
||||
}
|
||||
|
||||
T *FindById(H h) {
|
||||
T *t = FindByIdNoOops(h);
|
||||
if(!t) {
|
||||
dbp("failed to look up item %16lx, searched %d items", h.v, elems);
|
||||
dbp("failed to look up item %16lx, searched %d items", h.v, n);
|
||||
oops();
|
||||
}
|
||||
return t;
|
||||
|
@ -83,7 +99,7 @@ public:
|
|||
|
||||
T *FindByIdNoOops(H h) {
|
||||
int i;
|
||||
for(i = 0; i < elems; i++) {
|
||||
for(i = 0; i < n; i++) {
|
||||
if(elem[i].h.v == h.v) {
|
||||
return &(elem[i]);
|
||||
}
|
||||
|
@ -93,14 +109,14 @@ public:
|
|||
|
||||
void ClearTags(void) {
|
||||
int i;
|
||||
for(i = 0; i < elems; i++) {
|
||||
for(i = 0; i < n; i++) {
|
||||
elem[i].tag = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Tag(H h, int tag) {
|
||||
int i;
|
||||
for(i = 0; i < elems; i++) {
|
||||
for(i = 0; i < n; i++) {
|
||||
if(elem[i].h.v == h.v) {
|
||||
elem[i].tag = tag;
|
||||
}
|
||||
|
@ -110,7 +126,7 @@ public:
|
|||
void RemoveTagged(void) {
|
||||
int src, dest;
|
||||
dest = 0;
|
||||
for(src = 0; src < elems; src++) {
|
||||
for(src = 0; src < n; src++) {
|
||||
if(elem[src].tag) {
|
||||
// this item should be deleted
|
||||
} else {
|
||||
|
@ -120,18 +136,18 @@ public:
|
|||
dest++;
|
||||
}
|
||||
}
|
||||
elems = dest;
|
||||
n = dest;
|
||||
// and elemsAllocated is untouched, because we didn't resize
|
||||
}
|
||||
|
||||
void MoveSelfInto(IdList<T,H> *l) {
|
||||
memcpy(l, this, sizeof(*this));
|
||||
elemsAllocated = elems = 0;
|
||||
elemsAllocated = n = 0;
|
||||
elem = NULL;
|
||||
}
|
||||
|
||||
void Clear(void) {
|
||||
elemsAllocated = elems = 0;
|
||||
elemsAllocated = n = 0;
|
||||
if(elem) free(elem);
|
||||
elem = NULL;
|
||||
}
|
||||
|
|
|
@ -10,9 +10,10 @@ void Entity::Get2dCsysBasisVectors(Vector *u, Vector *v) {
|
|||
for(int i = 0; i < 4; i++) {
|
||||
q[i] = SS.param.FindById(param(i))->val;
|
||||
}
|
||||
Quaternion quat = Quaternion::MakeFrom(q[0], q[1], q[2], q[3]);
|
||||
|
||||
*u = Vector::RotationU(q[0], q[1], q[2], q[3]);
|
||||
*v = Vector::RotationV(q[0], q[1], q[2], q[3]);
|
||||
*u = quat.RotationU();
|
||||
*v = quat.RotationV();
|
||||
}
|
||||
|
||||
void Entity::LineDrawOrGetDistance(Vector a, Vector b) {
|
||||
|
|
3
expr.cpp
3
expr.cpp
|
@ -130,6 +130,8 @@ void Expr::App(char *s, ...) {
|
|||
vsprintf(StringBuffer+strlen(StringBuffer), s, f);
|
||||
}
|
||||
char *Expr::Print(void) {
|
||||
if(!this) return "0";
|
||||
|
||||
StringBuffer[0] = '\0';
|
||||
PrintW();
|
||||
return StringBuffer;
|
||||
|
@ -356,6 +358,7 @@ void Expr::Lex(char *in) {
|
|||
|
||||
Expr *Expr::FromString(char *in) {
|
||||
UnparsedCnt = 0;
|
||||
UnparsedP = 0;
|
||||
OperandsP = 0;
|
||||
OperatorsP = 0;
|
||||
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
#include "solvespace.h"
|
||||
|
||||
bool SolveSpace::SaveToFile(char *filename) {
|
||||
fh = fopen(filename, "w");
|
||||
if(!fh) {
|
||||
Error("Couldn't write to file '%s'", fh);
|
||||
return false;
|
||||
}
|
||||
|
||||
fprintf(fh, "!!SolveSpaceREVa\n\n\n");
|
||||
|
||||
int i;
|
||||
for(i = 0; i < group.n; i++) {
|
||||
Group *g = &(group.elem[i]);
|
||||
fprintf(fh, "Group.h.v=%08x\n", g->h.v);
|
||||
fprintf(fh, "Group.name=%s\n", g->name.str);
|
||||
fprintf(fh, "AddGroup\n\n");
|
||||
}
|
||||
|
||||
for(i = 0; i < param.n; i++) {
|
||||
Param *p = &(param.elem[i]);
|
||||
fprintf(fh, "Param.h.v=%08x\n", p->h.v);
|
||||
fprintf(fh, "Param.val=%.20f\n", p->val);
|
||||
fprintf(fh, "AddParam\n\n");
|
||||
}
|
||||
|
||||
for(i = 0; i < request.n; i++) {
|
||||
Request *r = &(request.elem[i]);
|
||||
fprintf(fh, "Request.h.v=%08x\n", r->h.v);
|
||||
fprintf(fh, "Request.type=%d\n", r->type);
|
||||
fprintf(fh, "Request.csys.v=%08x\n", r->csys.v);
|
||||
fprintf(fh, "Request.group.v=%08x\n", r->group.v);
|
||||
fprintf(fh, "Request.name=%s\n", r->name.str);
|
||||
fprintf(fh, "AddRequest\n\n");
|
||||
}
|
||||
|
||||
for(i = 0; i < entity.n; i++) {
|
||||
Entity *e = &(entity.elem[i]);
|
||||
fprintf(fh, "Entity.h.v=%08x\n", e->h.v);
|
||||
fprintf(fh, "Entity.type=%d\n", e->type);
|
||||
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);
|
||||
fprintf(fh, "Constraint.type=%d\n", c->type);
|
||||
fprintf(fh, "Constraint.group.v=%08x\n", c->group);
|
||||
fprintf(fh, "Constraint.exprA=%s\n", c->exprA->Print());
|
||||
fprintf(fh, "Constraint.exprB=%s\n", c->exprB->Print());
|
||||
fprintf(fh, "Constraint.ptA.v=%08x\n", c->ptA.v);
|
||||
fprintf(fh, "Constraint.ptB.v=%08x\n", c->ptB.v);
|
||||
fprintf(fh, "Constraint.ptC.v=%08x\n", c->ptC.v);
|
||||
fprintf(fh, "Constraint.entityA.v=%08x\n", c->entityA.v);
|
||||
fprintf(fh, "Constraint.entityB.v=%08x\n", c->entityB.v);
|
||||
fprintf(fh, "Constraint.disp.offset.x=%.20f\n", c->disp.offset.x);
|
||||
fprintf(fh, "Constraint.disp.offset.y=%.20f\n", c->disp.offset.y);
|
||||
fprintf(fh, "Constraint.disp.offset.z=%.20f\n", c->disp.offset.z);
|
||||
fprintf(fh, "AddConstraint\n\n");
|
||||
}
|
||||
|
||||
fclose(fh);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SolveSpace::LoadFromFile(char *filename) {
|
||||
fh = fopen(filename, "r");
|
||||
if(!fh) {
|
||||
Error("Couldn't read from file '%s'", fh);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -6,15 +6,17 @@
|
|||
#define mEdit (&GraphicsWindow::MenuEdit)
|
||||
#define mReq (&GraphicsWindow::MenuRequest)
|
||||
#define mCon (&Constraint::MenuConstrain)
|
||||
#define mFile (&SolveSpace::MenuFile)
|
||||
#define S 0x100
|
||||
#define C 0x200
|
||||
const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
||||
{ 0, "&File", 0, NULL },
|
||||
{ 1, "&New\tCtrl+N", 0, NULL },
|
||||
{ 1, "&Open...\tCtrl+O", 0, NULL },
|
||||
{ 1, "&Save\tCtrl+S", 0, NULL },
|
||||
{ 1, "Save &As...", 0, NULL },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "E&xit", 0, NULL },
|
||||
{ 1, "&New\tCtrl+N", MNU_NEW, 'N'|C, mFile },
|
||||
{ 1, "&Open...\tCtrl+O", MNU_OPEN, 'O'|C, mFile },
|
||||
{ 1, "&Save\tCtrl+S", MNU_SAVE, 'S'|C, mFile },
|
||||
{ 1, "Save &As...", MNU_SAVE_AS, 0, mFile },
|
||||
{ 1, NULL, 0, 0, NULL },
|
||||
{ 1, "E&xit", MNU_EXIT, 0, mFile },
|
||||
|
||||
{ 0, "&Edit", 0, NULL },
|
||||
{ 1, "&Undo\tCtrl+Z", 0, NULL },
|
||||
|
@ -37,7 +39,7 @@ const GraphicsWindow::MenuEntry GraphicsWindow::menu[] = {
|
|||
|
||||
{ 0, "&Request", 0, NULL },
|
||||
{ 1, "Dra&w in 2d Coordinate System\tW", MNU_SEL_CSYS, 'W', mReq },
|
||||
{ 1, "Draw Anywhere in 3d\tF", MNU_NO_CSYS, 'Q', mReq },
|
||||
{ 1, "Draw Anywhere in 3d\tQ", MNU_NO_CSYS, 'Q', mReq },
|
||||
{ 1, NULL, 0, NULL },
|
||||
{ 1, "Datum &Point\tP", MNU_DATUM_POINT, 'P', mReq },
|
||||
{ 1, "Datum A&xis\tX", 0, 'X', mReq },
|
||||
|
@ -132,18 +134,63 @@ void GraphicsWindow::MenuView(int id) {
|
|||
CheckMenuById(MNU_LOCK_VIEW, SS.GW.viewLocked);
|
||||
break;
|
||||
|
||||
case MNU_ORIENT_ONTO:
|
||||
case MNU_ORIENT_ONTO: {
|
||||
SS.GW.GroupSelection();
|
||||
Entity *e = NULL;
|
||||
if(SS.GW.gs.n == 1 && SS.GW.gs.csyss == 1) {
|
||||
Entity *e = SS.entity.FindById(SS.GW.gs.entity[0]);
|
||||
e->Get2dCsysBasisVectors( &(SS.GW.projRight), &(SS.GW.projUp));
|
||||
SS.GW.offset = SS.point.FindById(e->point(16))->GetCoords();
|
||||
e = SS.entity.FindById(SS.GW.gs.entity[0]);
|
||||
} else if(SS.GW.activeCsys.v != Entity::NO_CSYS.v) {
|
||||
e = SS.entity.FindById(SS.GW.activeCsys);
|
||||
}
|
||||
if(e) {
|
||||
// A quaternion with our original rotation
|
||||
Quaternion quat0 = Quaternion::MakeFrom(
|
||||
SS.GW.projRight, SS.GW.projUp);
|
||||
// And with our final rotation
|
||||
Vector pr, pu;
|
||||
e->Get2dCsysBasisVectors(&pr, &pu);
|
||||
Quaternion quatf = Quaternion::MakeFrom(pr, pu);
|
||||
// Make sure we take the shorter of the two possible paths.
|
||||
double mp = (quatf.Minus(quat0)).Magnitude();
|
||||
double mm = (quatf.Plus(quat0)).Magnitude();
|
||||
if(mp > mm) {
|
||||
quatf = quatf.ScaledBy(-1);
|
||||
mp = mm;
|
||||
}
|
||||
|
||||
// And also get the offsets.
|
||||
Vector offset0 = SS.GW.offset;
|
||||
Vector offsetf = SS.point.FindById(e->point(16))->GetCoords();
|
||||
|
||||
// Animate transition, unless it's a tiny move.
|
||||
SDWORD dt = (mp < 0.01) ? (-20) : (SDWORD)(100 + 1000*mp);
|
||||
SDWORD tn, t0 = GetMilliseconds();
|
||||
double s = 0;
|
||||
do {
|
||||
SS.GW.offset =
|
||||
(offset0.ScaledBy(1 - s)).Plus(offsetf.ScaledBy(s));
|
||||
Quaternion quat =
|
||||
(quat0.ScaledBy(1 - s)).Plus(quatf.ScaledBy(s));
|
||||
quat = quat.WithMagnitude(1);
|
||||
SS.GW.projRight = quat.RotationU();
|
||||
SS.GW.projUp = quat.RotationV();
|
||||
PaintGraphics();
|
||||
|
||||
tn = GetMilliseconds();
|
||||
s = (tn - t0)/((double)dt);
|
||||
} while((tn - t0) < dt);
|
||||
SS.GW.projRight = pr;
|
||||
SS.GW.projUp = pu;
|
||||
SS.GW.offset = offsetf;
|
||||
|
||||
SS.GW.hover.Clear();
|
||||
SS.GW.ClearSelection();
|
||||
InvalidateGraphics();
|
||||
} else {
|
||||
Error("Select plane or coordinate system before orienting.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: oops();
|
||||
}
|
||||
|
@ -156,12 +203,12 @@ void GraphicsWindow::EnsureValidActives(void) {
|
|||
Group *g = SS.group.FindByIdNoOops(activeGroup);
|
||||
if((!g) || (g->h.v == Group::HGROUP_REFERENCES.v)) {
|
||||
int i;
|
||||
for(i = 0; i < SS.group.elems; i++) {
|
||||
for(i = 0; i < SS.group.n; i++) {
|
||||
if(SS.group.elem[i].h.v != Group::HGROUP_REFERENCES.v) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i >= SS.group.elems) oops();
|
||||
if(i >= SS.group.n) oops();
|
||||
activeGroup = SS.group.elem[i].h;
|
||||
change = true;
|
||||
}
|
||||
|
@ -174,6 +221,8 @@ void GraphicsWindow::EnsureValidActives(void) {
|
|||
change = true;
|
||||
}
|
||||
if(change) SS.TW.Show();
|
||||
|
||||
EnableMenuById(MNU_NO_CSYS, (activeCsys.v != Entity::NO_CSYS.v));
|
||||
}
|
||||
|
||||
void GraphicsWindow::MenuEdit(int id) {
|
||||
|
@ -362,7 +411,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) {
|
|||
memset(dest, 0, sizeof(*dest));
|
||||
|
||||
// Do the points
|
||||
for(i = 0; i < SS.entity.elems; i++) {
|
||||
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));
|
||||
|
@ -371,7 +420,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) {
|
|||
}
|
||||
|
||||
// Entities
|
||||
for(i = 0; i < SS.point.elems; i++) {
|
||||
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));
|
||||
|
@ -380,7 +429,7 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp, Selection *dest) {
|
|||
}
|
||||
|
||||
// Constraints
|
||||
for(i = 0; i < SS.constraint.elems; i++) {
|
||||
for(i = 0; i < SS.constraint.n; i++) {
|
||||
d = SS.constraint.elem[i].GetDistance(mp);
|
||||
if(d < 10 && d < dmin) {
|
||||
memset(dest, 0, sizeof(*dest));
|
||||
|
@ -581,15 +630,15 @@ void GraphicsWindow::Paint(int w, int h) {
|
|||
|
||||
// First, draw the entire scene.
|
||||
glColor3f(1, 1, 1);
|
||||
for(i = 0; i < SS.entity.elems; i++) {
|
||||
for(i = 0; i < SS.entity.n; i++) {
|
||||
SS.entity.elem[i].Draw();
|
||||
}
|
||||
glColor3f(0, 0.8f, 0);
|
||||
for(i = 0; i < SS.point.elems; i++) {
|
||||
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.elems; i++) {
|
||||
for(i = 0; i < SS.constraint.n; i++) {
|
||||
SS.constraint.elem[i].Draw();
|
||||
}
|
||||
|
||||
|
|
17
sketch.h
17
sketch.h
|
@ -82,9 +82,9 @@ public:
|
|||
hRequest h;
|
||||
|
||||
// Types of requests
|
||||
static const int CSYS_2D = 10;
|
||||
static const int DATUM_POINT = 11;
|
||||
static const int LINE_SEGMENT = 20;
|
||||
static const int CSYS_2D = 100;
|
||||
static const int DATUM_POINT = 101;
|
||||
static const int LINE_SEGMENT = 200;
|
||||
|
||||
int type;
|
||||
|
||||
|
@ -107,6 +107,9 @@ public:
|
|||
|
||||
class Entity {
|
||||
public:
|
||||
int tag;
|
||||
hEntity h;
|
||||
|
||||
static const hEntity NO_CSYS;
|
||||
|
||||
static const int CSYS_2D = 1000;
|
||||
|
@ -114,11 +117,6 @@ public:
|
|||
static const int LINE_SEGMENT = 1010;
|
||||
int type;
|
||||
|
||||
int tag;
|
||||
hEntity h;
|
||||
|
||||
Expr *expr[16];
|
||||
|
||||
inline hRequest request(void)
|
||||
{ hRequest r; r.v = (this->h.v >> 10); return r; }
|
||||
inline hParam param(int i)
|
||||
|
@ -161,7 +159,6 @@ public:
|
|||
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;
|
||||
|
||||
|
@ -234,9 +231,7 @@ public:
|
|||
|
||||
// These define how the constraint is drawn on-screen.
|
||||
struct {
|
||||
hEntity csys;
|
||||
Vector offset;
|
||||
Vector u, v;
|
||||
} disp;
|
||||
|
||||
static hConstraint AddConstraint(Constraint *c);
|
||||
|
|
|
@ -58,11 +58,11 @@ void SolveSpace::GenerateAll(void) {
|
|||
|
||||
entity.Clear();
|
||||
point.Clear();
|
||||
for(i = 0; i < request.elems; i++) {
|
||||
for(i = 0; i < request.n; i++) {
|
||||
request.elem[i].Generate(&entity, &point, ¶m);
|
||||
}
|
||||
|
||||
for(i = 0; i < param.elems; i++) {
|
||||
for(i = 0; i < param.n; i++) {
|
||||
Param *p = prev.FindByIdNoOops(param.elem[i].h);
|
||||
if(p) {
|
||||
param.elem[i].val = p->val;
|
||||
|
@ -80,8 +80,8 @@ void SolveSpace::ForceReferences(void) {
|
|||
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, },
|
||||
{ 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(int i = 0; i < 3; i++) {
|
||||
hEntity he;
|
||||
|
@ -101,3 +101,21 @@ void SolveSpace::ForceReferences(void) {
|
|||
void SolveSpace::Solve(void) {
|
||||
}
|
||||
|
||||
void SolveSpace::MenuFile(int id) {
|
||||
switch(id) {
|
||||
case GraphicsWindow::MNU_NEW:
|
||||
case GraphicsWindow::MNU_OPEN:
|
||||
|
||||
case GraphicsWindow::MNU_SAVE:
|
||||
SS.SaveToFile("t.slv");
|
||||
break;
|
||||
|
||||
case GraphicsWindow::MNU_SAVE_AS:
|
||||
break;
|
||||
|
||||
case GraphicsWindow::MNU_EXIT:
|
||||
break;
|
||||
|
||||
default: oops();
|
||||
}
|
||||
}
|
||||
|
|
19
solvespace.h
19
solvespace.h
|
@ -14,6 +14,8 @@
|
|||
|
||||
#define isforname(c) (isalnum(c) || (c) == '_' || (c) == '-' || (c) == '#')
|
||||
|
||||
typedef signed long SDWORD;
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
@ -26,12 +28,21 @@
|
|||
class Expr;
|
||||
|
||||
// From the platform-specific code.
|
||||
int SaveFileYesNoCancel(void);
|
||||
BOOL GetSaveFile(char *file, char *defExtension, char *selPattern);
|
||||
BOOL GetOpenFile(char *file, char *defExtension, char *selPattern);
|
||||
|
||||
void CheckMenuById(int id, BOOL checked);
|
||||
void EnableMenuById(int id, BOOL checked);
|
||||
|
||||
void InvalidateGraphics(void);
|
||||
void InvalidateText(void);
|
||||
SDWORD GetMilliseconds(void);
|
||||
void PaintGraphics(void);
|
||||
|
||||
void dbp(char *str, ...);
|
||||
void Error(char *str, ...);
|
||||
|
||||
Expr *AllocExpr(void);
|
||||
void FreeAllExprs(void);
|
||||
void *MemRealloc(void *p, int n);
|
||||
|
@ -82,13 +93,19 @@ public:
|
|||
inline Param *GetParam (hParam h) { return param. FindById(h); }
|
||||
inline Point *GetPoint (hPoint h) { return point. FindById(h); }
|
||||
|
||||
hGroup activeGroup;
|
||||
hGroup activeGroup;
|
||||
|
||||
FILE *fh;
|
||||
|
||||
void GenerateAll(void);
|
||||
void ForceReferences(void);
|
||||
|
||||
void Init(void);
|
||||
void Solve(void);
|
||||
|
||||
static void MenuFile(int id);
|
||||
bool SaveToFile(char *filename);
|
||||
bool LoadFromFile(char *filename);
|
||||
};
|
||||
|
||||
extern SolveSpace SS;
|
||||
|
|
|
@ -254,10 +254,10 @@ void TextWindow::ShowHeader(void) {
|
|||
void TextWindow::ShowAllGroups(void) {
|
||||
Printf("%C8[[all groups in sketch follow]]%E");
|
||||
int i;
|
||||
for(i = 0; i <= SS.group.elems; i++) {
|
||||
for(i = 0; i <= SS.group.n; i++) {
|
||||
DWORD v;
|
||||
char *s;
|
||||
if(i == SS.group.elems) {
|
||||
if(i == SS.group.n) {
|
||||
s = "all requests from all groups";
|
||||
v = 0;
|
||||
} else {
|
||||
|
@ -293,7 +293,7 @@ void TextWindow::ShowRequestsInGroup(void) {
|
|||
}
|
||||
|
||||
int i;
|
||||
for(i = 0; i < SS.request.elems; i++) {
|
||||
for(i = 0; i < SS.request.n; i++) {
|
||||
Request *r = &(SS.request.elem[i]);
|
||||
|
||||
if(r->group.v == shown->group.v || shown->group.v == 0) {
|
||||
|
|
8
ui.h
8
ui.h
|
@ -74,8 +74,14 @@ public:
|
|||
|
||||
// This table describes the top-level menus in the graphics winodw.
|
||||
typedef enum {
|
||||
// File
|
||||
MNU_NEW = 100,
|
||||
MNU_OPEN,
|
||||
MNU_SAVE,
|
||||
MNU_SAVE_AS,
|
||||
MNU_EXIT,
|
||||
// View
|
||||
MNU_ZOOM_IN = 100,
|
||||
MNU_ZOOM_IN,
|
||||
MNU_ZOOM_OUT,
|
||||
MNU_ZOOM_TO_FIT,
|
||||
MNU_ORIENT_ONTO,
|
||||
|
|
88
util.cpp
88
util.cpp
|
@ -23,27 +23,85 @@ void MakeMatrix(double *mat, double a11, double a12, double a13, double a14,
|
|||
mat[15] = a44;
|
||||
}
|
||||
|
||||
Quaternion Quaternion::MakeFrom(double a, double b, double c, double d) {
|
||||
Quaternion q;
|
||||
q.a = a;
|
||||
q.b = b;
|
||||
q.c = c;
|
||||
q.d = d;
|
||||
return q;
|
||||
}
|
||||
|
||||
Quaternion Quaternion::MakeFrom(Vector u, Vector v)
|
||||
{
|
||||
Vector n = u.Cross(v);
|
||||
|
||||
Quaternion q;
|
||||
q.a = 0.5*sqrt(1 + u.x + v.y + n.z);
|
||||
q.b = (1/(4*(q.a)))*(v.z - n.y);
|
||||
q.c = (1/(4*(q.a)))*(n.x - u.z);
|
||||
q.d = (1/(4*(q.a)))*(u.y - v.x);
|
||||
return q;
|
||||
}
|
||||
|
||||
Quaternion Quaternion::Plus(Quaternion y) {
|
||||
Quaternion q;
|
||||
q.a = a + y.a;
|
||||
q.b = b + y.b;
|
||||
q.c = c + y.c;
|
||||
q.d = d + y.d;
|
||||
return q;
|
||||
}
|
||||
|
||||
Quaternion Quaternion::Minus(Quaternion y) {
|
||||
Quaternion q;
|
||||
q.a = a - y.a;
|
||||
q.b = b - y.b;
|
||||
q.c = c - y.c;
|
||||
q.d = d - y.d;
|
||||
return q;
|
||||
}
|
||||
|
||||
Quaternion Quaternion::ScaledBy(double s) {
|
||||
Quaternion q;
|
||||
q.a = a*s;
|
||||
q.b = b*s;
|
||||
q.c = c*s;
|
||||
q.d = d*s;
|
||||
return q;
|
||||
}
|
||||
|
||||
double Quaternion::Magnitude(void) {
|
||||
return sqrt(a*a + b*b + c*c + d*d);
|
||||
}
|
||||
|
||||
Quaternion Quaternion::WithMagnitude(double s) {
|
||||
return ScaledBy(s/Magnitude());
|
||||
}
|
||||
|
||||
Vector Quaternion::RotationU(void) {
|
||||
Vector v;
|
||||
v.x = a*a + b*b - c*c - d*d;
|
||||
v.y = 2*a*d + 2*b*c;
|
||||
v.z = 2*b*d - 2*a*c;
|
||||
return v;
|
||||
}
|
||||
|
||||
Vector Quaternion::RotationV(void) {
|
||||
Vector v;
|
||||
v.x = 2*b*c - 2*a*d;
|
||||
v.y = a*a - b*b + c*c - d*d;
|
||||
v.z = 2*a*b + 2*c*d;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <commdlg.h>
|
||||
#include <gl/gl.h>
|
||||
#include <gl/glu.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -349,6 +350,32 @@ void InvalidateGraphics(void)
|
|||
{
|
||||
InvalidateRect(GraphicsWnd, NULL, FALSE);
|
||||
}
|
||||
static void PaintGraphicsWithHdc(HDC hdc)
|
||||
{
|
||||
HGLRC hgrc = CreateGlContext(hdc);
|
||||
|
||||
RECT r;
|
||||
GetClientRect(GraphicsWnd, &r);
|
||||
int w = r.right - r.left;
|
||||
int h = r.bottom - r.top;
|
||||
|
||||
SS.GW.Paint(w, h);
|
||||
|
||||
SwapBuffers(hdc);
|
||||
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(hgrc);
|
||||
}
|
||||
void PaintGraphics(void)
|
||||
{
|
||||
HDC hdc = GetDC(GraphicsWnd);
|
||||
PaintGraphicsWithHdc(hdc);
|
||||
}
|
||||
SDWORD GetMilliseconds(void)
|
||||
{
|
||||
return (SDWORD)GetTickCount();
|
||||
}
|
||||
|
||||
void InvalidateText(void)
|
||||
{
|
||||
InvalidateRect(TextWnd, NULL, FALSE);
|
||||
|
@ -370,19 +397,7 @@ LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||
PAINTSTRUCT ps;
|
||||
HDC hdc = BeginPaint(hwnd, &ps);
|
||||
|
||||
HGLRC hgrc = CreateGlContext(hdc);
|
||||
|
||||
RECT r;
|
||||
GetClientRect(GraphicsWnd, &r);
|
||||
int w = r.right - r.left;
|
||||
int h = r.bottom - r.top;
|
||||
|
||||
SS.GW.Paint(w, h);
|
||||
|
||||
SwapBuffers(hdc);
|
||||
|
||||
wglMakeCurrent(NULL, NULL);
|
||||
wglDeleteContext(hgrc);
|
||||
PaintGraphicsWithHdc(hdc);
|
||||
|
||||
EndPaint(hwnd, &ps);
|
||||
break;
|
||||
|
@ -446,6 +461,58 @@ LRESULT CALLBACK GraphicsWndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
|||
return 1;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Common dialog routines, to open or save a file.
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL GetOpenFile(char *file, char *defExtension, char *selPattern)
|
||||
{
|
||||
OPENFILENAME ofn;
|
||||
|
||||
memset(&ofn, 0, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hInstance = Instance;
|
||||
ofn.hwndOwner = GraphicsWnd;
|
||||
ofn.lpstrFilter = selPattern;
|
||||
ofn.lpstrDefExt = defExtension;
|
||||
ofn.lpstrFile = file;
|
||||
ofn.nMaxFile = MAX_PATH;
|
||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
||||
|
||||
EnableWindow(GraphicsWnd, FALSE);
|
||||
BOOL r = GetOpenFileName(&ofn);
|
||||
EnableWindow(GraphicsWnd, TRUE);
|
||||
SetForegroundWindow(GraphicsWnd);
|
||||
return r;
|
||||
}
|
||||
BOOL GetSaveFile(char *file, char *defExtension, char *selPattern)
|
||||
{
|
||||
OPENFILENAME ofn;
|
||||
|
||||
memset(&ofn, 0, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hInstance = Instance;
|
||||
ofn.hwndOwner = GraphicsWnd;
|
||||
ofn.lpstrFilter = selPattern;
|
||||
ofn.lpstrDefExt = defExtension;
|
||||
ofn.lpstrFile = file;
|
||||
ofn.nMaxFile = MAX_PATH;
|
||||
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
|
||||
|
||||
EnableWindow(GraphicsWnd, FALSE);
|
||||
BOOL r = GetSaveFileName(&ofn);
|
||||
EnableWindow(GraphicsWnd, TRUE);
|
||||
SetForegroundWindow(GraphicsWnd);
|
||||
return r;
|
||||
}
|
||||
int SaveFileYesNoCancel(void)
|
||||
{
|
||||
return MessageBox(GraphicsWnd,
|
||||
"The program has changed since it was last saved.\r\n\r\n"
|
||||
"Do you want to save the changes?", "SolveSpace",
|
||||
MB_YESNOCANCEL | MB_ICONWARNING);
|
||||
}
|
||||
|
||||
|
||||
static void MenuById(int id, BOOL yes, BOOL check)
|
||||
{
|
||||
int i;
|
||||
|
|
Loading…
Reference in New Issue