Initial work on the assembly (`import') feature. I can import a

part, including all of its entities and the triangle mesh. These
are transformed by a rotation and translation, and appear in the
sketch; the transformation may be set with constraints.

[git-p4: depot-paths = "//depot/solvespace/": change = 1756]
solver
Jonathan Westhues 2008-05-29 02:10:12 -08:00
parent d5a8c431da
commit 4bd44bf18a
7 changed files with 233 additions and 31 deletions

View File

@ -240,8 +240,15 @@ void Entity::NormalForceTo(Quaternion q) {
// There's absolutely nothing to do; these are locked. // There's absolutely nothing to do; these are locked.
break; break;
case NORMAL_N_ROT: case NORMAL_N_ROT: {
Quaternion qp = q.Times(numNormal.Inverse());
SS.GetParam(param[0])->val = qp.w;
SS.GetParam(param[1])->val = qp.vx;
SS.GetParam(param[2])->val = qp.vy;
SS.GetParam(param[3])->val = qp.vz;
break; break;
}
default: oops(); default: oops();
} }
@ -852,4 +859,11 @@ void Entity::GenerateEquations(IdList<Equation,hEquation> *l) {
} }
} }
void Entity::CalculateNumerical(void) {
if(IsPoint()) actPoint = PointGetNum();
if(IsNormal()) actNormal = NormalGetNum();
if(type == DISTANCE || type == DISTANCE_N_COPY) {
actDistance = DistanceGetNum();
}
}

111
file.cpp
View File

@ -1,5 +1,7 @@
#include "solvespace.h" #include "solvespace.h"
#define VERSION_STRING "±²³SolveSpaceREVa"
void SolveSpace::NewFile(void) { void SolveSpace::NewFile(void) {
constraint.Clear(); constraint.Clear();
request.Clear(); request.Clear();
@ -54,7 +56,6 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
{ 'g', "Group.name", 'N', &(SS.sv.g.name) }, { 'g', "Group.name", 'N', &(SS.sv.g.name) },
{ 'g', "Group.activeWorkplane.v", 'x', &(SS.sv.g.activeWorkplane.v) }, { 'g', "Group.activeWorkplane.v", 'x', &(SS.sv.g.activeWorkplane.v) },
{ 'g', "Group.opA.v", 'x', &(SS.sv.g.opA.v) }, { 'g', "Group.opA.v", 'x', &(SS.sv.g.opA.v) },
{ 'g', "Group.opB.v", 'x', &(SS.sv.g.opB.v) },
{ 'g', "Group.exprA", 'E', &(SS.sv.g.exprA) }, { 'g', "Group.exprA", 'E', &(SS.sv.g.exprA) },
{ 'g', "Group.subtype", 'd', &(SS.sv.g.subtype) }, { 'g', "Group.subtype", 'd', &(SS.sv.g.subtype) },
{ 'g', "Group.meshCombine", 'd', &(SS.sv.g.meshCombine) }, { 'g', "Group.meshCombine", 'd', &(SS.sv.g.meshCombine) },
@ -70,6 +71,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
{ 'g', "Group.wrkpl.negateV", 'b', &(SS.sv.g.wrkpl.negateV) }, { 'g', "Group.wrkpl.negateV", 'b', &(SS.sv.g.wrkpl.negateV) },
{ 'g', "Group.visible", 'b', &(SS.sv.g.visible) }, { 'g', "Group.visible", 'b', &(SS.sv.g.visible) },
{ 'g', "Group.remap", 'M', &(SS.sv.g.remap) }, { 'g', "Group.remap", 'M', &(SS.sv.g.remap) },
{ 'g', "Group.impFile", 'P', &(SS.sv.g.impFile) },
{ 'p', "Param.h.v.", 'x', &(SS.sv.p.h.v) }, { 'p', "Param.h.v.", 'x', &(SS.sv.p.h.v) },
{ 'p', "Param.val", 'f', &(SS.sv.p.val) }, { 'p', "Param.val", 'f', &(SS.sv.p.val) },
@ -107,6 +109,15 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
{ 'e', "Entity.numNormal.vy", 'f', &(SS.sv.e.numNormal.vy) }, { 'e', "Entity.numNormal.vy", 'f', &(SS.sv.e.numNormal.vy) },
{ 'e', "Entity.numNormal.vz", 'f', &(SS.sv.e.numNormal.vz) }, { 'e', "Entity.numNormal.vz", 'f', &(SS.sv.e.numNormal.vz) },
{ 'e', "Entity.numDistance", 'f', &(SS.sv.e.numDistance) }, { 'e', "Entity.numDistance", 'f', &(SS.sv.e.numDistance) },
{ 'e', "Entity.actPoint.x", 'f', &(SS.sv.e.actPoint.x) },
{ 'e', "Entity.actPoint.y", 'f', &(SS.sv.e.actPoint.y) },
{ 'e', "Entity.actPoint.z", 'f', &(SS.sv.e.actPoint.z) },
{ 'e', "Entity.actNormal.w", 'f', &(SS.sv.e.actNormal.w) },
{ 'e', "Entity.actNormal.vx", 'f', &(SS.sv.e.actNormal.vx) },
{ 'e', "Entity.actNormal.vy", 'f', &(SS.sv.e.actNormal.vy) },
{ 'e', "Entity.actNormal.vz", 'f', &(SS.sv.e.actNormal.vz) },
{ 'e', "Entity.actDistance", 'f', &(SS.sv.e.actDistance) },
{ 'c', "Constraint.h.v", 'x', &(SS.sv.c.h.v) }, { 'c', "Constraint.h.v", 'x', &(SS.sv.c.h.v) },
{ 'c', "Constraint.type", 'd', &(SS.sv.c.type) }, { 'c', "Constraint.type", 'd', &(SS.sv.c.type) },
@ -131,14 +142,22 @@ void SolveSpace::SaveUsingTable(int type) {
int i; int i;
for(i = 0; SAVED[i].type != 0; i++) { for(i = 0; SAVED[i].type != 0; i++) {
if(SAVED[i].type != type) continue; if(SAVED[i].type != type) continue;
fprintf(fh, "%s=", SAVED[i].desc);
int fmt = SAVED[i].fmt;
void *p = SAVED[i].ptr; void *p = SAVED[i].ptr;
switch(SAVED[i].fmt) { // Any items that aren't specified are assumed to be zero
if(fmt == 'd' && *((int *)p) == 0) continue;
if(fmt == 'x' && *((DWORD *)p) == 0) continue;
if(fmt == 'f' && *((double *)p) == 0.0) continue;
fprintf(fh, "%s=", SAVED[i].desc);
switch(fmt) {
case 'd': fprintf(fh, "%d", *((int *)p)); break; case 'd': fprintf(fh, "%d", *((int *)p)); break;
case 'b': fprintf(fh, "%d", *((bool *)p) ? 1 : 0); break; case 'b': fprintf(fh, "%d", *((bool *)p) ? 1 : 0); break;
case 'x': fprintf(fh, "%08x", *((DWORD *)p)); break; case 'x': fprintf(fh, "%08x", *((DWORD *)p)); break;
case 'f': fprintf(fh, "%.20f", *((double *)p)); break; case 'f': fprintf(fh, "%.20f", *((double *)p)); break;
case 'N': fprintf(fh, "%s", ((NameStr *)p)->str); break; case 'N': fprintf(fh, "%s", ((NameStr *)p)->str); break;
case 'P': fprintf(fh, "%s", (char *)p); break;
case 'E': fprintf(fh, "%s", (*((Expr **)p))->Print()); break; case 'E': fprintf(fh, "%s", (*((Expr **)p))->Print()); break;
case 'M': { case 'M': {
@ -167,7 +186,7 @@ bool SolveSpace::SaveToFile(char *filename) {
return false; return false;
} }
fprintf(fh, "ñ÷åò±²³´SolveSpaceREVa\n\n\n"); fprintf(fh, "%s\n\n\n", VERSION_STRING);
int i; int i;
for(i = 0; i < group.n; i++) { for(i = 0; i < group.n; i++) {
@ -189,6 +208,7 @@ bool SolveSpace::SaveToFile(char *filename) {
} }
for(i = 0; i < entity.n; i++) { for(i = 0; i < entity.n; i++) {
(entity.elem[i]).CalculateNumerical();
sv.e = entity.elem[i]; sv.e = entity.elem[i];
SaveUsingTable('e'); SaveUsingTable('e');
fprintf(fh, "AddEntity\n\n"); fprintf(fh, "AddEntity\n\n");
@ -200,6 +220,14 @@ bool SolveSpace::SaveToFile(char *filename) {
fprintf(fh, "AddConstraint\n\n"); fprintf(fh, "AddConstraint\n\n");
} }
SMesh *m = &(group.elem[group.n-1].mesh);
for(i = 0; i < m->l.n; i++) {
STriangle *tr = &(m->l.elem[i]);
fprintf(fh, "Triangle "
"%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n",
CO(tr->a), CO(tr->b), CO(tr->c));
}
fclose(fh); fclose(fh);
return true; return true;
@ -223,6 +251,10 @@ void SolveSpace::LoadUsingTable(char *key, char *val) {
*((Expr **)p) = e->DeepCopyKeep(); *((Expr **)p) = e->DeepCopyKeep();
break; break;
case 'P':
if(strlen(val)+1 < MAX_PATH) strcpy((char *)p, val);
break;
case 'M': { case 'M': {
IdList<EntityMap,EntityId> *m = IdList<EntityMap,EntityId> *m =
(IdList<EntityMap,EntityId> *)p; (IdList<EntityMap,EntityId> *)p;
@ -264,9 +296,9 @@ bool SolveSpace::LoadFromFile(char *filename) {
constraint.Clear(); constraint.Clear();
request.Clear(); request.Clear();
group.Clear(); group.Clear();
entity.Clear(); entity.Clear();
param.Clear(); param.Clear();
memset(&sv, 0, sizeof(sv));
char line[1024]; char line[1024];
while(fgets(line, sizeof(line), fh)) { while(fgets(line, sizeof(line), fh)) {
@ -296,8 +328,10 @@ bool SolveSpace::LoadFromFile(char *filename) {
} else if(strcmp(line, "AddConstraint")==0) { } else if(strcmp(line, "AddConstraint")==0) {
SS.constraint.Add(&(sv.c)); SS.constraint.Add(&(sv.c));
memset(&(sv.c), 0, sizeof(sv.c)); memset(&(sv.c), 0, sizeof(sv.c));
} else if(strcmp(line, "ñ÷åò±²³´SolveSpaceREVa")==0) { } else if(strcmp(line, VERSION_STRING)==0) {
// do nothing, version string // do nothing, version string
} else if(memcmp(line, "Triangle", 8)==0) {
// likewise ignore the triangles; we generate those
} else { } else {
oops(); oops();
} }
@ -308,3 +342,68 @@ bool SolveSpace::LoadFromFile(char *filename) {
return true; return true;
} }
bool SolveSpace::LoadEntitiesFromFile(char *file, EntityList *le, SMesh *m) {
fh = fopen(file, "r");
if(!fh) return false;
le->Clear();
memset(&sv, 0, sizeof(sv));
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;
LoadUsingTable(key, val);
} else if(strcmp(line, "AddGroup")==0) {
} else if(strcmp(line, "AddParam")==0) {
} else if(strcmp(line, "AddEntity")==0) {
le->Add(&(sv.e));
memset(&(sv.e), 0, sizeof(sv.e));
} else if(strcmp(line, "AddRequest")==0) {
} else if(strcmp(line, "AddConstraint")==0) {
} else if(strcmp(line, VERSION_STRING)==0) {
} else if(memcmp(line, "Triangle", 8)==0) {
STriangle tr; ZERO(&tr);
if(sscanf(line, "Triangle %lf %lf %lf %lf %lf %lf %lf %lf %lf",
&(tr.a.x), &(tr.a.y), &(tr.a.z),
&(tr.b.x), &(tr.b.y), &(tr.b.z),
&(tr.c.x), &(tr.c.y), &(tr.c.z)) != 9)
{
oops();
}
m->AddTriangle(&tr);
} else {
oops();
}
}
fclose(fh);
return true;
}
void SolveSpace::ReloadAllImported(void) {
int i;
for(i = 0; i < group.n; i++) {
Group *g = &(group.elem[i]);
if(g->type != Group::IMPORTED) continue;
g->impEntity.Clear();
g->impMesh.Clear();
if(!LoadEntitiesFromFile(g->impFile, &(g->impEntity), &(g->impMesh))) {
oops();
}
}
}

View File

@ -24,6 +24,11 @@ void Group::MenuGroup(int id) {
memset(&g, 0, sizeof(g)); memset(&g, 0, sizeof(g));
g.visible = true; g.visible = true;
if(id >= RECENT_IMPORT && id < (RECENT_IMPORT + MAX_RECENT)) {
strcpy(g.impFile, RecentFile[id-RECENT_IMPORT]);
id = GraphicsWindow::MNU_GROUP_IMPORT;
}
SS.GW.GroupSelection(); SS.GW.GroupSelection();
#define gs (SS.GW.gs) #define gs (SS.GW.gs)
@ -95,10 +100,23 @@ void Group::MenuGroup(int id) {
g.name.strcpy("translate"); g.name.strcpy("translate");
break; break;
case GraphicsWindow::MNU_GROUP_IMPORT: {
g.type = IMPORTED;
g.opA = SS.GW.activeGroup;
if(strlen(g.impFile) == 0) {
if(!GetOpenFile(g.impFile, SLVS_EXT, SLVS_PATTERN)) return;
}
g.name.strcpy("import");
break;
}
default: oops(); default: oops();
} }
SS.group.AddAndAssignId(&g); SS.group.AddAndAssignId(&g);
if(g.type == IMPORTED) {
SS.ReloadAllImported();
}
SS.GenerateAll(SS.GW.solving == GraphicsWindow::SOLVE_ALWAYS); SS.GenerateAll(SS.GW.solving == GraphicsWindow::SOLVE_ALWAYS);
SS.GW.activeGroup = g.h; SS.GW.activeGroup = g.h;
if(g.type == DRAWING_WORKPLANE) { if(g.type == DRAWING_WORKPLANE) {
@ -191,14 +209,15 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
Entity *e = &(entity->elem[i]); Entity *e = &(entity->elem[i]);
if(e->group.v != opA.v) continue; if(e->group.v != opA.v) continue;
e->CalculateNumerical();
hEntity he = e->h; e = NULL; hEntity he = e->h; e = NULL;
// As soon as I call CopyEntity, e may become invalid! That // As soon as I call CopyEntity, e may become invalid! That
// adds entities, which may cause a realloc. // adds entities, which may cause a realloc.
CopyEntity(he, ai, CopyEntity(SS.GetEntity(he), ai,
h.param(0), h.param(1), h.param(2), h.param(0), h.param(1), h.param(2),
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
true); true);
CopyEntity(he, af, CopyEntity(SS.GetEntity(he), af,
h.param(0), h.param(1), h.param(2), h.param(0), h.param(1), h.param(2),
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
true); true);
@ -218,7 +237,8 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
Entity *e = &(entity->elem[i]); Entity *e = &(entity->elem[i]);
if(e->group.v != opA.v) continue; if(e->group.v != opA.v) continue;
CopyEntity(e->h, a*2 - (subtype == ONE_SIDED ? 0 : (n-1)), e->CalculateNumerical();
CopyEntity(e, a*2 - (subtype == ONE_SIDED ? 0 : (n-1)),
h.param(0), h.param(1), h.param(2), h.param(0), h.param(1), h.param(2),
NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM, NO_PARAM,
true); true);
@ -241,7 +261,29 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
Entity *e = &(entity->elem[i]); Entity *e = &(entity->elem[i]);
if(e->group.v != opA.v) continue; if(e->group.v != opA.v) continue;
CopyEntity(e->h, 0, e->CalculateNumerical();
CopyEntity(e, 0,
h.param(0), h.param(1), h.param(2),
h.param(3), h.param(4), h.param(5), h.param(6),
false);
}
break;
case IMPORTED:
// The translation vector
AddParam(param, h.param(0), gp.x);
AddParam(param, h.param(1), gp.y);
AddParam(param, h.param(2), gp.z);
// The rotation quaternion
AddParam(param, h.param(3), 1);
AddParam(param, h.param(4), 0);
AddParam(param, h.param(5), 0);
AddParam(param, h.param(6), 0);
for(i = 0; i < impEntity.n; i++) {
Entity *ie = &(impEntity.elem[i]);
CopyEntity(ie, 0,
h.param(0), h.param(1), h.param(2), h.param(0), h.param(1), h.param(2),
h.param(3), h.param(4), h.param(5), h.param(6), h.param(3), h.param(4), h.param(5), h.param(6),
false); false);
@ -254,7 +296,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
void Group::GenerateEquations(IdList<Equation,hEquation> *l) { void Group::GenerateEquations(IdList<Equation,hEquation> *l) {
Equation eq; Equation eq;
if(type == ROTATE) { if(type == ROTATE || type == IMPORTED) {
// Normalize the quaternion // Normalize the quaternion
ExprQuaternion q = { ExprQuaternion q = {
Expr::FromParam(h.param(3)), Expr::FromParam(h.param(3)),
@ -266,6 +308,8 @@ void Group::GenerateEquations(IdList<Equation,hEquation> *l) {
l->Add(&eq); l->Add(&eq);
} else if(type == EXTRUDE) { } else if(type == EXTRUDE) {
if(wrkpl.entityB.v != Entity::FREE_IN_3D.v) { if(wrkpl.entityB.v != Entity::FREE_IN_3D.v) {
// The extrusion path is locked along a line, normal to the
// specified workplane.
Entity *w = SS.GetEntity(wrkpl.entityB); Entity *w = SS.GetEntity(wrkpl.entityB);
ExprVector u = w->Normal()->NormalExprsU(); ExprVector u = w->Normal()->NormalExprsU();
ExprVector v = w->Normal()->NormalExprsV(); ExprVector v = w->Normal()->NormalExprsV();
@ -315,12 +359,10 @@ void Group::MakeExtrusionLines(hEntity in, int ai, int af) {
SS.entity.Add(&en); SS.entity.Add(&en);
} }
void Group::CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz, void Group::CopyEntity(Entity *ep, int a, hParam dx, hParam dy, hParam dz,
hParam qw, hParam qvx, hParam qvy, hParam qvz, hParam qw, hParam qvx, hParam qvy, hParam qvz,
bool transOnly) bool transOnly)
{ {
Entity *ep = SS.GetEntity(in);
Entity en; Entity en;
memset(&en, 0, sizeof(en)); memset(&en, 0, sizeof(en));
en.type = ep->type; en.type = ep->type;
@ -378,7 +420,7 @@ void Group::CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz,
en.param[5] = qvy; en.param[5] = qvy;
en.param[6] = qvz; en.param[6] = qvz;
} }
en.numPoint = ep->PointGetNum(); en.numPoint = ep->actPoint;
en.timesApplied = a; en.timesApplied = a;
break; break;
@ -395,7 +437,7 @@ void Group::CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz,
en.param[2] = qvy; en.param[2] = qvy;
en.param[3] = qvz; en.param[3] = qvz;
} }
en.numNormal = ep->NormalGetNum(); en.numNormal = ep->actNormal;
en.point[0] = Remap(ep->point[0], a); en.point[0] = Remap(ep->point[0], a);
en.timesApplied = a; en.timesApplied = a;
break; break;
@ -403,7 +445,7 @@ void Group::CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz,
case Entity::DISTANCE_N_COPY: case Entity::DISTANCE_N_COPY:
case Entity::DISTANCE: case Entity::DISTANCE:
en.type = Entity::DISTANCE_N_COPY; en.type = Entity::DISTANCE_N_COPY;
en.numDistance = ep->DistanceGetNum(); en.numDistance = ep->actDistance;
break; break;
default: default:
@ -512,6 +554,26 @@ void Group::MakePolygons(void) {
outm.AddTriangle(bbot, btop, atop); outm.AddTriangle(bbot, btop, atop);
} }
} }
} else if(type == IMPORTED) {
// Triangles are just copied over, with the appropriate transformation
// applied.
Vector offset = {
SS.GetParam(h.param(0))->val,
SS.GetParam(h.param(1))->val,
SS.GetParam(h.param(2))->val };
Quaternion q = {
SS.GetParam(h.param(3))->val,
SS.GetParam(h.param(4))->val,
SS.GetParam(h.param(5))->val,
SS.GetParam(h.param(6))->val };
for(int i = 0; i < impMesh.l.n; i++) {
STriangle st = impMesh.l.elem[i];
st.a = q.Rotate(st.a).Plus(offset);
st.b = q.Rotate(st.b).Plus(offset);
st.c = q.Rotate(st.c).Plus(offset);
outm.AddTriangle(&st);
}
} }
edges.Clear(); edges.Clear();

View File

@ -87,7 +87,6 @@ public:
int type; int type;
hGroup opA; hGroup opA;
hGroup opB;
bool visible; bool visible;
hEntity activeWorkplane; hEntity activeWorkplane;
Expr *exprA; Expr *exprA;
@ -127,7 +126,15 @@ public:
static const int COMBINE_AS_DIFFERENCE = 1; static const int COMBINE_AS_DIFFERENCE = 1;
int meshCombine; int meshCombine;
IdList<EntityMap,EntityId> remap;
char impFile[MAX_PATH];
SMesh impMesh;
EntityList impEntity;
NameStr name; NameStr name;
char *DescriptionString(void); char *DescriptionString(void);
static void AddParam(IdList<Param,hParam> *param, hParam hp, double v); static void AddParam(IdList<Param,hParam> *param, hParam hp, double v);
@ -136,10 +143,9 @@ public:
// entities may have come from multiple requests, it's necessary to // entities may have come from multiple requests, it's necessary to
// remap the entity ID so that it's still unique. We do this with a // remap the entity ID so that it's still unique. We do this with a
// mapping list. // mapping list.
IdList<EntityMap,EntityId> remap;
hEntity Remap(hEntity in, int copyNumber); hEntity Remap(hEntity in, int copyNumber);
void MakeExtrusionLines(hEntity in, int ai, int af); void MakeExtrusionLines(hEntity in, int ai, int af);
void CopyEntity(hEntity in, int a, hParam dx, hParam dy, hParam dz, void CopyEntity(Entity *ep, int a, hParam dx, hParam dy, hParam dz,
hParam qw, hParam qvx, hParam qvy, hParam qvz, hParam qw, hParam qvx, hParam qvy, hParam qvz,
bool transOnly); bool transOnly);
@ -235,11 +241,18 @@ public:
// and directions. // and directions.
hParam param[7]; hParam param[7];
// Transformed points/normals/distances have their numerical value. // Transformed points/normals/distances have their numerical base
Vector numPoint; Vector numPoint;
Quaternion numNormal; Quaternion numNormal;
double numDistance; double numDistance;
// All points/normals/distances have their numerical value; this is
// a convenience, to simplify the import/assembly code, so that the
// part is entirely described by the entities.
Vector actPoint;
Quaternion actNormal;
double actDistance;
hGroup group; hGroup group;
hEntity workplane; // or Entity::FREE_IN_3D hEntity workplane; // or Entity::FREE_IN_3D
@ -316,6 +329,8 @@ public:
void AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index); void AddEq(IdList<Equation,hEquation> *l, Expr *expr, int index);
void GenerateEquations(IdList<Equation,hEquation> *l); void GenerateEquations(IdList<Equation,hEquation> *l);
void CalculateNumerical(void);
char *DescriptionString(void); char *DescriptionString(void);
}; };

View File

@ -3,9 +3,10 @@
SolveSpace SS; SolveSpace SS;
void SolveSpace::Init(char *cmdLine) { void SolveSpace::Init(char *cmdLine) {
if(strlen(cmdLine) == 0) {
NewFile(); NewFile();
} else { AfterNewFile();
if(strlen(cmdLine) != 0) {
if(LoadFromFile(cmdLine)) { if(LoadFromFile(cmdLine)) {
strcpy(saveFile, cmdLine); strcpy(saveFile, cmdLine);
} else { } else {
@ -17,6 +18,7 @@ void SolveSpace::Init(char *cmdLine) {
} }
void SolveSpace::AfterNewFile(void) { void SolveSpace::AfterNewFile(void) {
ReloadAllImported();
GenerateAll(false, 0, INT_MAX); GenerateAll(false, 0, INT_MAX);
TW.Init(); TW.Init();
@ -78,7 +80,6 @@ bool SolveSpace::EntityExists(hEntity he) {
bool SolveSpace::PruneGroups(hGroup hg) { bool SolveSpace::PruneGroups(hGroup hg) {
Group *g = GetGroup(hg); Group *g = GetGroup(hg);
if(GroupsInOrder(g->opA, hg) && if(GroupsInOrder(g->opA, hg) &&
GroupsInOrder(g->opB, hg) &&
EntityExists(g->wrkpl.origin) && EntityExists(g->wrkpl.origin) &&
EntityExists(g->wrkpl.entityB) && EntityExists(g->wrkpl.entityB) &&
EntityExists(g->wrkpl.entityC)) EntityExists(g->wrkpl.entityC))
@ -334,9 +335,6 @@ void SolveSpace::AddToRecentList(char *file) {
} }
void SolveSpace::MenuFile(int id) { void SolveSpace::MenuFile(int id) {
char *slvsPattern =
"SolveSpace Models (*.slvs)\0*.slvs\0All Files (*)\0*\0\0";
char *slvsExt = "slvs";
if(id >= RECENT_OPEN && id < (RECENT_OPEN+MAX_RECENT)) { if(id >= RECENT_OPEN && id < (RECENT_OPEN+MAX_RECENT)) {
char newFile[MAX_PATH]; char newFile[MAX_PATH];
@ -362,7 +360,7 @@ void SolveSpace::MenuFile(int id) {
case GraphicsWindow::MNU_OPEN: { case GraphicsWindow::MNU_OPEN: {
char newFile[MAX_PATH] = ""; char newFile[MAX_PATH] = "";
if(GetOpenFile(newFile, slvsExt, slvsPattern)) { if(GetOpenFile(newFile, SLVS_EXT, SLVS_PATTERN)) {
if(SS.LoadFromFile(newFile)) { if(SS.LoadFromFile(newFile)) {
strcpy(SS.saveFile, newFile); strcpy(SS.saveFile, newFile);
AddToRecentList(newFile); AddToRecentList(newFile);
@ -380,7 +378,7 @@ void SolveSpace::MenuFile(int id) {
char newFile[MAX_PATH]; char newFile[MAX_PATH];
strcpy(newFile, SS.saveFile); strcpy(newFile, SS.saveFile);
if(id == GraphicsWindow::MNU_SAVE_AS || strlen(newFile)==0) { if(id == GraphicsWindow::MNU_SAVE_AS || strlen(newFile)==0) {
if(!GetSaveFile(newFile, slvsExt, slvsPattern)) break; if(!GetSaveFile(newFile, SLVS_EXT, SLVS_PATTERN)) break;
} }
if(SS.SaveToFile(newFile)) { if(SS.SaveToFile(newFile)) {

View File

@ -41,6 +41,7 @@ class Expr;
class ExprVector; class ExprVector;
class ExprQuaternion; class ExprQuaternion;
// From the platform-specific code. // From the platform-specific code.
#define MAX_RECENT 8 #define MAX_RECENT 8
#define RECENT_OPEN (0xf000) #define RECENT_OPEN (0xf000)
@ -49,6 +50,8 @@ extern char RecentFile[MAX_RECENT][MAX_PATH];
void RefreshRecentMenus(void); void RefreshRecentMenus(void);
int SaveFileYesNoCancel(void); int SaveFileYesNoCancel(void);
#define SLVS_PATTERN "SolveSpace Models (*.slvs)\0*.slvs\0All Files (*)\0*\0\0"
#define SLVS_EXT "slvs"
BOOL GetSaveFile(char *file, char *defExtension, char *selPattern); BOOL GetSaveFile(char *file, char *defExtension, char *selPattern);
BOOL GetOpenFile(char *file, char *defExtension, char *selPattern); BOOL GetOpenFile(char *file, char *defExtension, char *selPattern);
@ -81,6 +84,11 @@ void vl(void); // debug function to validate
#include "dsc.h" #include "dsc.h"
#include "polygon.h" #include "polygon.h"
class Entity;
class hEntity;
typedef IdList<Entity,hEntity> EntityList;
#include "sketch.h" #include "sketch.h"
#include "ui.h" #include "ui.h"
#include "expr.h" #include "expr.h"
@ -234,6 +242,8 @@ public:
void NewFile(void); void NewFile(void);
bool SaveToFile(char *filename); bool SaveToFile(char *filename);
bool LoadFromFile(char *filename); bool LoadFromFile(char *filename);
bool LoadEntitiesFromFile(char *filename, EntityList *le, SMesh *m);
void ReloadAllImported(void);
struct { struct {
int requests; int requests;

View File

@ -407,6 +407,10 @@ void TextWindow::ShowGroupInfo(void) {
g->DescriptionString(), g->DescriptionString(),
g->h.v, &TextWindow::ScreenChangeGroupName, s); g->h.v, &TextWindow::ScreenChangeGroupName, s);
if(g->type == Group::IMPORTED) {
Printf(true, "%FtIMPORT %E '%s'", g->impFile);
}
if(g->type == Group::EXTRUDE) { if(g->type == Group::EXTRUDE) {
s = "EXTRUDE"; s = "EXTRUDE";
} else if(g->type == Group::TRANSLATE) { } else if(g->type == Group::TRANSLATE) {