Don't keep a dimension or group's user-entered numerical value as
an Expr *, since that complicates multiple units and also memory management. Now it's just a double. [git-p4: depot-paths = "//depot/solvespace/": change = 1791]solver
parent
1674443ab2
commit
28e3f0abab
|
@ -115,7 +115,7 @@ void Constraint::MenuConstrain(int id) {
|
|||
c.disp.offset = Vector::From(0, 0, 0);
|
||||
}
|
||||
|
||||
c.exprA = Expr::From("0")->DeepCopyKeep();
|
||||
c.valA = 0;
|
||||
c.ModifyToSatisfy();
|
||||
AddConstraint(&c);
|
||||
break;
|
||||
|
@ -175,7 +175,7 @@ void Constraint::MenuConstrain(int id) {
|
|||
return;
|
||||
}
|
||||
|
||||
c.exprA = Expr::From("0")->DeepCopyKeep();
|
||||
c.valA = 0;
|
||||
c.ModifyToSatisfy();
|
||||
AddConstraint(&c);
|
||||
break;
|
||||
|
@ -327,7 +327,7 @@ void Constraint::MenuConstrain(int id) {
|
|||
c.type = ANGLE;
|
||||
c.entityA = gs.vector[0];
|
||||
c.entityB = gs.vector[1];
|
||||
c.exprA = Expr::From(0.0)->DeepCopyKeep();
|
||||
c.valA = 0;
|
||||
c.otherAngle = true;
|
||||
} else {
|
||||
Error("Bad selection for angle constraint.");
|
||||
|
@ -352,7 +352,7 @@ void Constraint::MenuConstrain(int id) {
|
|||
case GraphicsWindow::MNU_COMMENT:
|
||||
c.type = COMMENT;
|
||||
c.comment.strcpy("NEW COMMENT -- DOUBLE-CLICK TO EDIT");
|
||||
c.disp.offset = SS.GW.offset;
|
||||
c.disp.offset = SS.GW.offset.ScaledBy(-1);
|
||||
AddConstraint(&c);
|
||||
break;
|
||||
|
||||
|
@ -485,9 +485,7 @@ void Constraint::ModifyToSatisfy(void) {
|
|||
b = b.ProjectVectorInto(workplane);
|
||||
}
|
||||
double c = (a.Dot(b))/(a.Magnitude() * b.Magnitude());
|
||||
double theta = acos(c)*180/PI;
|
||||
Expr::FreeKeep(&exprA);
|
||||
exprA = Expr::From(theta)->DeepCopyKeep();
|
||||
valA = acos(c)*180/PI;
|
||||
} else {
|
||||
// We'll fix these ones up by looking at their symbolic equation;
|
||||
// that means no extra work.
|
||||
|
@ -499,11 +497,8 @@ void Constraint::ModifyToSatisfy(void) {
|
|||
if(l.n != 1) oops();
|
||||
|
||||
// These equations are written in the form f(...) - d = 0, where
|
||||
// d is the value of the exprA.
|
||||
double v = (l.elem[0].e)->Eval();
|
||||
double nd = exprA->Eval() + v;
|
||||
Expr::FreeKeep(&exprA);
|
||||
exprA = Expr::From(nd)->DeepCopyKeep();
|
||||
// d is the value of the valA.
|
||||
valA += (l.elem[0].e)->Eval();
|
||||
|
||||
l.Clear();
|
||||
}
|
||||
|
@ -522,8 +517,7 @@ void Constraint::Generate(IdList<Equation,hEquation> *l) {
|
|||
}
|
||||
}
|
||||
void Constraint::GenerateReal(IdList<Equation,hEquation> *l) {
|
||||
Expr *exA = NULL;
|
||||
if(exprA) exA = exprA->DeepCopy();
|
||||
Expr *exA = Expr::From(valA);
|
||||
|
||||
switch(type) {
|
||||
case PT_PT_DISTANCE:
|
||||
|
@ -546,7 +540,7 @@ void Constraint::GenerateReal(IdList<Equation,hEquation> *l) {
|
|||
Entity *f = SS.GetEntity(entityA);
|
||||
ExprVector p0 = f->FaceGetPointExprs();
|
||||
ExprVector n = f->FaceGetNormalExprs();
|
||||
AddEq(l, (pt.Minus(p0)).Dot(n)->Minus(exprA), 0);
|
||||
AddEq(l, (pt.Minus(p0)).Dot(n)->Minus(exA), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
7
draw.cpp
7
draw.cpp
|
@ -556,8 +556,8 @@ void GraphicsWindow::MouseLeftDoubleClick(double mx, double my) {
|
|||
Vector p3 = c->GetLabelPos();
|
||||
Point2d p2 = ProjectPoint(p3);
|
||||
char *s = (c->type == Constraint::COMMENT) ? c->comment.str :
|
||||
c->exprA->Print();
|
||||
ShowGraphicsEditControl((int)p2.x, (int)p2.y, s);
|
||||
ToString(c->valA);
|
||||
ShowGraphicsEditControl((int)p2.x, (int)p2.y-4, s);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -575,8 +575,7 @@ void GraphicsWindow::EditControlDone(char *s) {
|
|||
if(e) {
|
||||
SS.UndoRemember();
|
||||
|
||||
Expr::FreeKeep(&(c->exprA));
|
||||
c->exprA = e->DeepCopyKeep();
|
||||
c->valA = e->Eval();
|
||||
|
||||
SS.MarkGroupDirty(c->group);
|
||||
SS.GenerateAll();
|
||||
|
|
|
@ -44,14 +44,14 @@ double Constraint::EllipticalInterpolation(double rx, double ry, double theta) {
|
|||
char *Constraint::Label(void) {
|
||||
static char Ret[1024];
|
||||
if(type == ANGLE) {
|
||||
sprintf(Ret, "%.2f", exprA->Eval());
|
||||
sprintf(Ret, "%.2f", valA);
|
||||
} else if(type == LENGTH_RATIO) {
|
||||
sprintf(Ret, "%.3f:1", exprA->Eval());
|
||||
sprintf(Ret, "%.3f:1", valA);
|
||||
} else if(type == COMMENT) {
|
||||
strcpy(Ret, comment.str);
|
||||
} else {
|
||||
// exprA has units of distance
|
||||
strcpy(Ret, SS.GW.ToString(exprA->Eval()));
|
||||
// valA has units of distance
|
||||
strcpy(Ret, SS.GW.ToString(valA));
|
||||
}
|
||||
if(reference) {
|
||||
strcat(Ret, " REF");
|
||||
|
|
22
expr.cpp
22
expr.cpp
|
@ -268,28 +268,6 @@ Expr *Expr::DeepCopy(void) {
|
|||
return n;
|
||||
}
|
||||
|
||||
Expr *Expr::DeepCopyKeep(void) {
|
||||
Expr *n = (Expr *)MemAlloc(sizeof(Expr));
|
||||
*n = *this;
|
||||
n->marker = 0xbad2feed;
|
||||
n->a = n->b = NULL;
|
||||
int c = n->Children();
|
||||
if(c > 0) n->a = a->DeepCopyKeep();
|
||||
if(c > 1) n->b = b->DeepCopyKeep();
|
||||
return n;
|
||||
}
|
||||
|
||||
void Expr::FreeKeep(Expr **e) {
|
||||
if(!(*e)) oops();
|
||||
|
||||
int c = (*e)->Children();
|
||||
if(c > 0) FreeKeep(&((*e)->a));
|
||||
if(c > 1) FreeKeep(&((*e)->b));
|
||||
if((*e)->marker != 0xbad2feed) oops();
|
||||
MemFree(*e);
|
||||
*e = NULL;
|
||||
}
|
||||
|
||||
Expr *Expr::DeepCopyWithParamsAsPointers(IdList<Param,hParam> *firstTry,
|
||||
IdList<Param,hParam> *thenTry)
|
||||
{
|
||||
|
|
8
expr.h
8
expr.h
|
@ -84,17 +84,13 @@ public:
|
|||
char *Print(void);
|
||||
void PrintW(void); // worker
|
||||
|
||||
// Make a copy of an expression that won't get blown away when we
|
||||
// do a FreeAllExprs(), or free it later.
|
||||
Expr *DeepCopyKeep(void);
|
||||
static void FreeKeep(Expr **f);
|
||||
// or a copy that will
|
||||
Expr *DeepCopy(void);
|
||||
// number of child nodes: 0 (e.g. constant), 1 (sqrt), or 2 (+)
|
||||
int Children(void);
|
||||
// total number of nodes in the tree
|
||||
int Nodes(void);
|
||||
|
||||
// Make a simple copy
|
||||
Expr *DeepCopy(void);
|
||||
// Make a copy, with the parameters (usually referenced by hParam)
|
||||
// resolved to pointers to the actual value. This speeds things up
|
||||
// considerably.
|
||||
|
|
17
file.cpp
17
file.cpp
|
@ -65,7 +65,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
|
|||
{ 'g', "Group.name", 'N', &(SS.sv.g.name) },
|
||||
{ 'g', "Group.activeWorkplane.v", 'x', &(SS.sv.g.activeWorkplane.v) },
|
||||
{ 'g', "Group.opA.v", 'x', &(SS.sv.g.opA.v) },
|
||||
{ 'g', "Group.exprA", 'E', &(SS.sv.g.exprA) },
|
||||
{ 'g', "Group.valA", 'f', &(SS.sv.g.valA) },
|
||||
{ 'g', "Group.color", 'x', &(SS.sv.g.color) },
|
||||
{ 'g', "Group.subtype", 'd', &(SS.sv.g.subtype) },
|
||||
{ 'g', "Group.skipFirst", 'b', &(SS.sv.g.skipFirst) },
|
||||
|
@ -118,7 +118,7 @@ const SolveSpace::SaveTable SolveSpace::SAVED[] = {
|
|||
{ 'c', "Constraint.type", 'd', &(SS.sv.c.type) },
|
||||
{ 'c', "Constraint.group.v", 'x', &(SS.sv.c.group.v) },
|
||||
{ 'c', "Constraint.workplane.v", 'x', &(SS.sv.c.workplane.v) },
|
||||
{ 'c', "Constraint.exprA", 'E', &(SS.sv.c.exprA) },
|
||||
{ 'c', "Constraint.valA", 'f', &(SS.sv.c.valA) },
|
||||
{ '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) },
|
||||
|
@ -154,7 +154,6 @@ void SolveSpace::SaveUsingTable(int type) {
|
|||
case 'f': fprintf(fh, "%.20f", *((double *)p)); 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 'M': {
|
||||
int j;
|
||||
|
@ -223,9 +222,6 @@ bool SolveSpace::SaveToFile(char *filename) {
|
|||
SMesh *m = &(group.elem[group.n-1].mesh);
|
||||
for(i = 0; i < m->l.n; i++) {
|
||||
STriangle *tr = &(m->l.elem[i]);
|
||||
/*
|
||||
double mag = tr->Normal().Magnitude();
|
||||
dbp("triangle: mag=%.5f", mag); */
|
||||
fprintf(fh, "Triangle %08x %08x "
|
||||
"%.20f %.20f %.20f %.20f %.20f %.20f %.20f %.20f %.20f\n",
|
||||
tr->meta.face, tr->meta.color,
|
||||
|
@ -248,12 +244,6 @@ void SolveSpace::LoadUsingTable(char *key, char *val) {
|
|||
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::From(val);
|
||||
if(!e) e = Expr::From(0.0);
|
||||
*((Expr **)p) = e->DeepCopyKeep();
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
if(strlen(val)+1 < MAX_PATH) strcpy((char *)p, val);
|
||||
|
@ -371,7 +361,6 @@ bool SolveSpace::LoadEntitiesFromFile(char *file, EntityList *le, SMesh *m) {
|
|||
} else if(strcmp(line, "AddGroup")==0) {
|
||||
// Don't leak memory; these get allocated whether we want them
|
||||
// or not.
|
||||
if(sv.g.exprA) Expr::FreeKeep(&(sv.g.exprA));
|
||||
sv.g.remap.Clear();
|
||||
} else if(strcmp(line, "AddParam")==0) {
|
||||
|
||||
|
@ -381,7 +370,7 @@ bool SolveSpace::LoadEntitiesFromFile(char *file, EntityList *le, SMesh *m) {
|
|||
} else if(strcmp(line, "AddRequest")==0) {
|
||||
|
||||
} else if(strcmp(line, "AddConstraint")==0) {
|
||||
if(sv.c.exprA) Expr::FreeKeep(&(sv.c.exprA));
|
||||
|
||||
} else if(strcmp(line, VERSION_STRING)==0) {
|
||||
|
||||
} else if(memcmp(line, "Triangle", 8)==0) {
|
||||
|
|
|
@ -115,7 +115,7 @@ void Group::MenuGroup(int id) {
|
|||
}
|
||||
g.type = ROTATE;
|
||||
g.opA = SS.GW.activeGroup;
|
||||
g.exprA = Expr::From(3)->DeepCopyKeep();
|
||||
g.valA = 3;
|
||||
g.subtype = ONE_SIDED;
|
||||
g.name.strcpy("rotate");
|
||||
SS.GW.ClearSelection();
|
||||
|
@ -125,7 +125,7 @@ void Group::MenuGroup(int id) {
|
|||
case GraphicsWindow::MNU_GROUP_TRANS:
|
||||
g.type = TRANSLATE;
|
||||
g.opA = SS.GW.activeGroup;
|
||||
g.exprA = Expr::From(3)->DeepCopyKeep();
|
||||
g.valA = 3;
|
||||
g.subtype = ONE_SIDED;
|
||||
g.predef.entityB = SS.GW.ActiveWorkplane();
|
||||
g.activeWorkplane = SS.GW.ActiveWorkplane();
|
||||
|
@ -293,7 +293,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
AddParam(param, h.param(1), gp.y);
|
||||
AddParam(param, h.param(2), gp.z);
|
||||
|
||||
int n = (int)(exprA->Eval()), a0 = 0;
|
||||
int n = (int)valA, a0 = 0;
|
||||
if(subtype == ONE_SIDED && skipFirst) {
|
||||
a0++; n++;
|
||||
}
|
||||
|
@ -325,7 +325,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
|
|||
AddParam(param, h.param(5), gn.y);
|
||||
AddParam(param, h.param(6), gn.z);
|
||||
|
||||
int n = (int)(exprA->Eval()), a0 = 0;
|
||||
int n = (int)valA, a0 = 0;
|
||||
if(subtype == ONE_SIDED && skipFirst) {
|
||||
a0++; n++;
|
||||
}
|
||||
|
|
4
sketch.h
4
sketch.h
|
@ -91,7 +91,7 @@ public:
|
|||
bool visible;
|
||||
bool clean;
|
||||
hEntity activeWorkplane;
|
||||
Expr *exprA;
|
||||
double valA;
|
||||
DWORD color;
|
||||
|
||||
static const int SOLVED_OKAY = 0;
|
||||
|
@ -442,7 +442,7 @@ public:
|
|||
hEntity workplane;
|
||||
|
||||
// These are the parameters for the constraint.
|
||||
Expr *exprA;
|
||||
double valA;
|
||||
hEntity ptA;
|
||||
hEntity ptB;
|
||||
hEntity ptC;
|
||||
|
|
|
@ -640,7 +640,9 @@ void TextWindow::ScreenChangeExprA(int link, DWORD v) {
|
|||
// There's an extra line for the skipFirst parameter in one-sided groups.
|
||||
int r = (g->subtype == Group::ONE_SIDED) ? 15 : 13;
|
||||
|
||||
ShowTextEditControl(r, 9, g->exprA->Print());
|
||||
char str[1024];
|
||||
sprintf(str, "%d", (int)g->valA);
|
||||
ShowTextEditControl(r, 9, str);
|
||||
SS.TW.edit.meaning = EDIT_TIMES_REPEATED;
|
||||
SS.TW.edit.group.v = v;
|
||||
}
|
||||
|
@ -724,7 +726,7 @@ void TextWindow::ShowGroupInfo(void) {
|
|||
space = true;
|
||||
}
|
||||
|
||||
int times = (int)(g->exprA->Eval());
|
||||
int times = (int)(g->valA);
|
||||
Printf(space, "%Ft%s%E %d time%s %Fl%Ll%D%f[change]%E",
|
||||
s2, times, times == 1 ? "" : "s",
|
||||
g->h.v, &TextWindow::ScreenChangeExprA);
|
||||
|
@ -916,8 +918,7 @@ void TextWindow::EditControlDone(char *s) {
|
|||
SS.UndoRemember();
|
||||
|
||||
Group *g = SS.GetGroup(edit.group);
|
||||
Expr::FreeKeep(&(g->exprA));
|
||||
g->exprA = e->DeepCopyKeep();
|
||||
g->valA = e->Eval();
|
||||
|
||||
SS.MarkGroupDirty(g->h);
|
||||
SS.later.generateAll = true;
|
||||
|
|
12
undoredo.cpp
12
undoredo.cpp
|
@ -45,7 +45,6 @@ void SolveSpace::PushFromCurrentOnto(UndoStack *uk) {
|
|||
// And then clean up all the stuff that needs to be a deep copy,
|
||||
// and zero out all the dynamic stuff that will get regenerated.
|
||||
dest.clean = false;
|
||||
if(src->exprA) dest.exprA = src->exprA->DeepCopyKeep();
|
||||
ZERO(&(dest.solved));
|
||||
ZERO(&(dest.poly));
|
||||
ZERO(&(dest.polyError));
|
||||
|
@ -65,7 +64,6 @@ void SolveSpace::PushFromCurrentOnto(UndoStack *uk) {
|
|||
for(i = 0; i < constraint.n; i++) {
|
||||
Constraint *src = &(constraint.elem[i]);
|
||||
Constraint dest = *src;
|
||||
if(src->exprA) dest.exprA = src->exprA->DeepCopyKeep();
|
||||
ZERO(&(dest.dogd));
|
||||
ut->constraint.Add(&dest);
|
||||
}
|
||||
|
@ -88,7 +86,6 @@ void SolveSpace::PopOntoCurrentFrom(UndoStack *uk) {
|
|||
// Free everything in the main copy of the program before replacing it
|
||||
for(i = 0; i < group.n; i++) {
|
||||
Group *g = &(group.elem[i]);
|
||||
if(g->exprA) Expr::FreeKeep(&(g->exprA));
|
||||
g->poly.Clear();
|
||||
g->mesh.Clear();
|
||||
g->meshError.interferesAt.Clear();
|
||||
|
@ -96,10 +93,6 @@ void SolveSpace::PopOntoCurrentFrom(UndoStack *uk) {
|
|||
g->impMesh.Clear();
|
||||
g->impEntity.Clear();
|
||||
}
|
||||
for(i = 0; i < constraint.n; i++) {
|
||||
Constraint *c = &(constraint.elem[i]);
|
||||
if(c->exprA) Expr::FreeKeep(&(c->exprA));
|
||||
}
|
||||
group.Clear();
|
||||
request.Clear();
|
||||
constraint.Clear();
|
||||
|
@ -138,15 +131,10 @@ void SolveSpace::UndoClearState(UndoState *ut) {
|
|||
for(i = 0; i < ut->group.n; i++) {
|
||||
Group *g = &(ut->group.elem[i]);
|
||||
|
||||
if(g->exprA) Expr::FreeKeep(&(g->exprA));
|
||||
g->remap.Clear();
|
||||
}
|
||||
ut->group.Clear();
|
||||
ut->request.Clear();
|
||||
for(i = 0; i < ut->constraint.n; i++) {
|
||||
Constraint *c = &(ut->constraint.elem[i]);
|
||||
if(c->exprA) Expr::FreeKeep(&(c->exprA));
|
||||
}
|
||||
ut->constraint.Clear();
|
||||
ut->param.Clear();
|
||||
ZERO(ut);
|
||||
|
|
Loading…
Reference in New Issue