diff --git a/Makefile b/Makefile index 494e58f..237bab7 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ DEFINES = /D_WIN32_WINNT=0x500 /DISOLATION_AWARE_ENABLED /D_WIN32_IE=0x500 /DWIN32_LEAN_AND_MEAN /DWIN32 CFLAGS = /W3 /nologo -I..\common\win32 /O2 /D_DEBUG /D_CRT_SECURE_NO_WARNINGS /Zi /I. /EHs -HEADERS = ..\common\win32\freeze.h ui.h solvespace.h dsc.h sketch.h expr.h +HEADERS = ..\common\win32\freeze.h ui.h solvespace.h dsc.h sketch.h expr.h polygon.h OBJDIR = obj @@ -27,7 +27,7 @@ LIBS = user32.lib gdi32.lib comctl32.lib advapi32.lib opengl32.lib glu32.lib all: $(OBJDIR)/solvespace.exe @cp $(OBJDIR)/solvespace.exe . - solvespace + solvespace t.slvs clean: rm -f obj/* diff --git a/file.cpp b/file.cpp index c5f17af..ab8e63c 100644 --- a/file.cpp +++ b/file.cpp @@ -1,61 +1,149 @@ #include "solvespace.h" +void SolveSpace::NewFile(void) { + constraint.Clear(); + request.Clear(); + group.Clear(); + + entity.Clear(); + param.Clear(); + + // Our initial group, that contains the references. + Group g; + memset(&g, 0, sizeof(g)); + g.name.strcpy("#references"); + g.h = Group::HGROUP_REFERENCES; + group.Add(&g); + + // And an empty group, for the first stuff the user draws. + g.name.strcpy(""); + group.AddAndAssignId(&g); + + + // Let's create three two-d coordinate systems, for the coordinate + // planes; these are our references, present in every sketch. + Request r; + memset(&r, 0, sizeof(r)); + r.type = Request::CSYS_2D; + r.group = Group::HGROUP_REFERENCES; + r.csys = Entity::NO_CSYS; + + r.name.strcpy("#XY-csys"); + r.h = Request::HREQUEST_REFERENCE_XY; + request.Add(&r); + + r.name.strcpy("#YZ-csys"); + r.h = Request::HREQUEST_REFERENCE_YZ; + request.Add(&r); + + r.name.strcpy("#ZX-csys"); + r.h = Request::HREQUEST_REFERENCE_ZX; + request.Add(&r); +} + + +const SolveSpace::SaveTable SolveSpace::SAVED[] = { + { 'g', "Group.h.v", 'x', &(SS.sv.g.h.v) }, + { 'g', "Group.type", 'd', &(SS.sv.g.type) }, + { 'g', "Group.name", 'N', &(SS.sv.g.name) }, + { 'g', "Group.solveOrder", 'd', &(SS.sv.g.solveOrder) }, + { 'g', "Group.visible", 'b', &(SS.sv.g.visible) }, + + { 'p', "Param.h.v.", 'x', &(SS.sv.p.h.v) }, + { 'p', "Param.val", 'f', &(SS.sv.p.val) }, + + { 'r', "Request.h.v", 'x', &(SS.sv.r.h.v) }, + { 'r', "Request.type", 'd', &(SS.sv.r.type) }, + { 'r', "Request.csys.v", 'x', &(SS.sv.r.csys.v) }, + { 'r', "Request.group.v", 'x', &(SS.sv.r.group.v) }, + { 'r', "Request.name", 'N', &(SS.sv.r.name) }, + { 'r', "Request.construction", 'b', &(SS.sv.r.construction) }, + + { 'e', "Entity.h.v", 'x', &(SS.sv.e.h.v) }, + { 'e', "Entity.type", 'd', &(SS.sv.e.type) }, + { 'e', "Entity.param.h[0].v", 'x', &(SS.sv.e.param.h[0].v) }, + { 'e', "Entity.param.h[1].v", 'x', &(SS.sv.e.param.h[1].v) }, + { 'e', "Entity.param.h[2].v", 'x', &(SS.sv.e.param.h[2].v) }, + { 'e', "Entity.param.h[3].v", 'x', &(SS.sv.e.param.h[3].v) }, + { 'e', "Entity.assoc[0].v", 'x', &(SS.sv.e.assoc[0].v) }, + { 'e', "Entity.assoc[1].v", 'x', &(SS.sv.e.assoc[1].v) }, + { 'e', "Entity.assoc[2].v", 'x', &(SS.sv.e.assoc[2].v) }, + { 'e', "Entity.assoc[3].v", 'x', &(SS.sv.e.assoc[3].v) }, + { 'e', "Entity.csys.v", 'x', &(SS.sv.e.csys.v) }, + + { 'c', "Constraint.h.v", 'x', &(SS.sv.c.h.v) }, + { 'c', "Constraint.type", 'd', &(SS.sv.c.type) }, + { 'c', "Constraint.group.v", 'x', &(SS.sv.c.group.v) }, + { 'c', "Constraint.exprA", 'E', &(SS.sv.c.exprA) }, + { 'c', "Constraint.exprB", 'E', &(SS.sv.c.exprB) }, + { 'c', "Constraint.ptA.v", 'x', &(SS.sv.c.ptA.v) }, + { 'c', "Constraint.ptB.v", 'x', &(SS.sv.c.ptB.v) }, + { 'c', "Constraint.ptC.v", 'x', &(SS.sv.c.ptC.v) }, + { 'c', "Constraint.entityA.v", 'x', &(SS.sv.c.entityA.v) }, + { 'c', "Constraint.entityB.v", 'x', &(SS.sv.c.entityB.v) }, + { 'c', "Constraint.disp.offset.x", 'f', &(SS.sv.c.disp.offset.x)}, + { 'c', "Constraint.disp.offset.y", 'f', &(SS.sv.c.disp.offset.y)}, + { 'c', "Constraint.disp.offset.z", 'f', &(SS.sv.c.disp.offset.z)}, + + { 0, NULL, NULL, NULL }, +}; + +void SolveSpace::SaveUsingTable(int type) { + int i; + for(i = 0; SAVED[i].type != 0; i++) { + if(SAVED[i].type != type) continue; + fprintf(fh, "%s=", SAVED[i].desc); + void *p = SAVED[i].ptr; + switch(SAVED[i].fmt) { + case 'd': fprintf(fh, "%d", *((int *)p)); break; + case 'b': fprintf(fh, "%d", *((bool *)p) ? 1 : 0); break; + case 'x': fprintf(fh, "%08x", *((DWORD *)p)); break; + case 'f': fprintf(fh, "%.20f", *((double *)p)); break; + case 'N': fprintf(fh, "%s", ((NameStr *)p)->str); break; + case 'E': fprintf(fh, "%s", (*((Expr **)p))->Print()); break; + default: oops(); + } + fprintf(fh, "\n"); + } +} + bool SolveSpace::SaveToFile(char *filename) { fh = fopen(filename, "w"); if(!fh) { - Error("Couldn't write to file '%s'", fh); + Error("Couldn't write to file '%s'", filename); return false; } - fprintf(fh, "!!SolveSpaceREVa\n\n\n"); + 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); + sv.g = group.elem[i]; + SaveUsingTable('g'); 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); + sv.p = param.elem[i]; + SaveUsingTable('p'); 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); + sv.r = request.elem[i]; + SaveUsingTable('r'); 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); + sv.e = entity.elem[i]; + SaveUsingTable('e'); fprintf(fh, "AddEntity\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); + sv.c = constraint.elem[i]; + SaveUsingTable('c'); fprintf(fh, "AddConstraint\n\n"); } @@ -67,10 +155,73 @@ bool SolveSpace::SaveToFile(char *filename) { bool SolveSpace::LoadFromFile(char *filename) { fh = fopen(filename, "r"); if(!fh) { - Error("Couldn't read from file '%s'", fh); + Error("Couldn't read from file '%s'", filename); return false; } + constraint.Clear(); + request.Clear(); + group.Clear(); + + entity.Clear(); + param.Clear(); + + char line[1024]; + while(fgets(line, sizeof(line), fh)) { + char *s = strchr(line, '\n'); + if(s) *s = '\0'; + + if(*line == '\0') continue; + + char *e = strchr(line, '='); + if(e) { + *e = '\0'; + char *key = line, *val = e+1; + int i; + for(i = 0; SAVED[i].type != 0; i++) { + if(strcmp(SAVED[i].desc, key)==0) { + void *p = SAVED[i].ptr; + switch(SAVED[i].fmt) { + case 'd': *((int *)p) = atoi(val); break; + case 'b': *((bool *)p) = (atoi(val) != 0); break; + case 'x': sscanf(val, "%x", (DWORD *)p); break; + case 'f': *((double *)p) = atof(val); break; + case 'N': ((NameStr *)p)->strcpy(val); break; + case 'E': + Expr *e; + e = Expr::FromString(val); + if(!e) e = Expr::FromConstant(0); + *((Expr **)p) = e->DeepCopyKeep(); + break; + + default: oops(); + } + break; + } + } + if(SAVED[i].type == 0) oops(); + + } else if(strcmp(line, "AddGroup")==0) { + SS.group.Add(&(sv.g)); + } else if(strcmp(line, "AddParam")==0) { + // params are regenerated, but we want to preload the values + // for initial guesses + SS.param.Add(&(sv.p)); + } else if(strcmp(line, "AddEntity")==0) { + // entities are regenerated + } else if(strcmp(line, "AddRequest")==0) { + SS.request.Add(&(sv.r)); + } else if(strcmp(line, "AddConstraint")==0) { + SS.constraint.Add(&(sv.c)); + } else if(strcmp(line, "ñ÷åò±²³´SolveSpaceREVa")==0) { + // do nothing, version string + } else { + oops(); + } + } + + fclose(fh); + return true; } diff --git a/polygon.h b/polygon.h index 95ea594..c135572 100644 --- a/polygon.h +++ b/polygon.h @@ -2,20 +2,39 @@ #ifndef __POLYGON_H #define __POLYGON_H -class SPolyhedron { +template +class SList { public: + T *elem; + int n; + int elemsAllocated; }; -class SPolygon { -public: -}; - -class SContour { +class SEdge { public: + Vector a, b; }; class SEdgeList { +public: + SList l; + +}; + +class SContour { +public: + SList l; +}; + +class SPolygon { +public: + SList l; +}; + +class SPolyhedron { + SList l; public: }; #endif + diff --git a/sketch.h b/sketch.h index baa6da6..a745397 100644 --- a/sketch.h +++ b/sketch.h @@ -55,6 +55,11 @@ public: int tag; hGroup h; + static const int DRAWING_GROUP = 5000; + static const int STEP_AND_REPEAT_TRANSLATING = 5010; + static const int STEP_AND_REPEAT_ROTATING = 5020; + int type; + int solveOrder; bool solved; diff --git a/solvespace.cpp b/solvespace.cpp index 6f42821..0cb4822 100644 --- a/solvespace.cpp +++ b/solvespace.cpp @@ -2,45 +2,12 @@ SolveSpace SS; -void SolveSpace::Init(void) { - constraint.Clear(); - request.Clear(); - group.Clear(); - - entity.Clear(); - param.Clear(); - - // Our initial group, that contains the references. - Group g; - memset(&g, 0, sizeof(g)); - g.name.strcpy("#references"); - g.h = Group::HGROUP_REFERENCES; - group.Add(&g); - - // And an empty group, for the first stuff the user draws. - g.name.strcpy(""); - group.AddAndAssignId(&g); - - - // Let's create three two-d coordinate systems, for the coordinate - // planes; these are our references, present in every sketch. - Request r; - memset(&r, 0, sizeof(r)); - r.type = Request::CSYS_2D; - r.group = Group::HGROUP_REFERENCES; - r.csys = Entity::NO_CSYS; - - r.name.strcpy("#XY-csys"); - r.h = Request::HREQUEST_REFERENCE_XY; - request.Add(&r); - - r.name.strcpy("#YZ-csys"); - r.h = Request::HREQUEST_REFERENCE_YZ; - request.Add(&r); - - r.name.strcpy("#ZX-csys"); - r.h = Request::HREQUEST_REFERENCE_ZX; - request.Add(&r); +void SolveSpace::Init(char *cmdLine) { + if(strlen(cmdLine) == 0) { + NewFile(); + } else { + LoadFromFile(cmdLine); + } TW.Init(); GW.Init(); @@ -69,6 +36,7 @@ void SolveSpace::GenerateAll(void) { prev.Clear(); ForceReferences(); + InvalidateGraphics(); } void SolveSpace::ForceReferences(void) { @@ -186,10 +154,15 @@ void SolveSpace::Solve(void) { void SolveSpace::MenuFile(int id) { switch(id) { case GraphicsWindow::MNU_NEW: + SS.NewFile(); + SS.GenerateAll(); + break; + case GraphicsWindow::MNU_OPEN: + break; case GraphicsWindow::MNU_SAVE: - SS.SaveToFile("t.slv"); + SS.SaveToFile("t.slvs"); break; case GraphicsWindow::MNU_SAVE_AS: diff --git a/solvespace.h b/solvespace.h index 4eb8985..410ffbd 100644 --- a/solvespace.h +++ b/solvespace.h @@ -154,13 +154,31 @@ public: void GenerateAll(void); void ForceReferences(void); - void Init(void); + void Init(char *cmdLine); bool SolveGroup(hGroup hg); bool SolveWorker(int order); void Solve(void); + char saveFile[MAX_PATH]; + bool unsaved; + typedef struct { + char type; + char *desc; + char fmt; + void *ptr; + } SaveTable; + static const SaveTable SAVED[]; + void SaveUsingTable(int type); + struct { + Group g; + Request r; + Entity e; + Param p; + Constraint c; + } sv; static void MenuFile(int id); + void NewFile(void); bool SaveToFile(char *filename); bool LoadFromFile(char *filename); diff --git a/win32/w32main.cpp b/win32/w32main.cpp index ec754b0..2d2544e 100644 --- a/win32/w32main.cpp +++ b/win32/w32main.cpp @@ -720,7 +720,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, FreeAllExprs(); // Call in to the platform-independent code, and let them do their init - SS.Init(); + SS.Init(lpCmdLine); ShowWindow(TextWnd, SW_SHOWNOACTIVATE); ShowWindow(GraphicsWnd, SW_SHOW);