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
parent
d5a8c431da
commit
4bd44bf18a
16
entity.cpp
16
entity.cpp
|
@ -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
111
file.cpp
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
84
sketch.cpp
84
sketch.cpp
|
@ -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();
|
||||||
|
|
||||||
|
|
23
sketch.h
23
sketch.h
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
10
solvespace.h
10
solvespace.h
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue