diff --git a/constraint.cpp b/constraint.cpp index f5b7abe3..39d5ce9d 100644 --- a/constraint.cpp +++ b/constraint.cpp @@ -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 *l) { } } void Constraint::GenerateReal(IdList *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 *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; } diff --git a/draw.cpp b/draw.cpp index 5910ac5a..0a70b75b 100644 --- a/draw.cpp +++ b/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(); diff --git a/drawconstraint.cpp b/drawconstraint.cpp index 85ac15d3..5289d6b1 100644 --- a/drawconstraint.cpp +++ b/drawconstraint.cpp @@ -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"); diff --git a/expr.cpp b/expr.cpp index dec32dfb..86a4cd96 100644 --- a/expr.cpp +++ b/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 *firstTry, IdList *thenTry) { diff --git a/expr.h b/expr.h index faa2a767..d555d573 100644 --- a/expr.h +++ b/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. diff --git a/file.cpp b/file.cpp index ff8e73b4..ccd62049 100644 --- a/file.cpp +++ b/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) { diff --git a/group.cpp b/group.cpp index 78fd1d4f..b1d979ab 100644 --- a/group.cpp +++ b/group.cpp @@ -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, 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, 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++; } diff --git a/sketch.h b/sketch.h index d427b621..3738912f 100644 --- a/sketch.h +++ b/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; diff --git a/textwin.cpp b/textwin.cpp index 6cc3bd50..67876ad0 100644 --- a/textwin.cpp +++ b/textwin.cpp @@ -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; diff --git a/undoredo.cpp b/undoredo.cpp index b2cec660..b23011b1 100644 --- a/undoredo.cpp +++ b/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);