Convert many loops to range-for or std algorithms. NFC.

Also add comments about indexing and when we don't use range-for.
This commit is contained in:
Ryan Pavlik 2018-01-03 19:42:38 -06:00 committed by whitequark
parent 97c8cb7d71
commit 86f20cc7e5
16 changed files with 256 additions and 286 deletions

View File

@ -12,13 +12,8 @@ SBsp2 *SBsp2::Alloc() { return (SBsp2 *)AllocTemporary(sizeof(SBsp2)); }
SBsp3 *SBsp3::Alloc() { return (SBsp3 *)AllocTemporary(sizeof(SBsp3)); } SBsp3 *SBsp3::Alloc() { return (SBsp3 *)AllocTemporary(sizeof(SBsp3)); }
SBsp3 *SBsp3::FromMesh(const SMesh *m) { SBsp3 *SBsp3::FromMesh(const SMesh *m) {
SBsp3 *bsp3 = NULL;
int i;
SMesh mc = {}; SMesh mc = {};
for(i = 0; i < m->l.n; i++) { for(auto const &elt : m->l) { mc.AddTriangle(&elt); }
mc.AddTriangle(&(m->l.elem[i]));
}
srand(0); // Let's be deterministic, at least! srand(0); // Let's be deterministic, at least!
int n = mc.l.n; int n = mc.l.n;
@ -28,10 +23,8 @@ SBsp3 *SBsp3::FromMesh(const SMesh *m) {
swap(mc.l.elem[k], mc.l.elem[n]); swap(mc.l.elem[k], mc.l.elem[n]);
} }
for(i = 0; i < mc.l.n; i++) { SBsp3 *bsp3 = NULL;
bsp3 = InsertOrCreate(bsp3, &(mc.l.elem[i]), NULL); for(auto &elt : mc.l) { bsp3 = InsertOrCreate(bsp3, &elt, NULL); }
}
mc.Clear(); mc.Clear();
return bsp3; return bsp3;
} }

View File

@ -59,8 +59,8 @@ std::string Constraint::DescriptionString() const {
void Constraint::DeleteAllConstraintsFor(Constraint::Type type, hEntity entityA, hEntity ptA) void Constraint::DeleteAllConstraintsFor(Constraint::Type type, hEntity entityA, hEntity ptA)
{ {
SK.constraint.ClearTags(); SK.constraint.ClearTags();
for(int i = 0; i < SK.constraint.n; i++) { for(auto &constraint : SK.constraint) {
ConstraintBase *ct = &(SK.constraint.elem[i]); ConstraintBase *ct = &constraint;
if(ct->type != type) continue; if(ct->type != type) continue;
if(ct->entityA != entityA) continue; if(ct->entityA != entityA) continue;

View File

@ -434,10 +434,7 @@ public:
} }
void ClearTags() { void ClearTags() {
int i; for(auto &elt : *this) { elt.tag = 0; }
for(i = 0; i < n; i++) {
elem[i].tag = 0;
}
} }
void Tag(H h, int tag) { void Tag(H h, int tag) {

View File

@ -922,19 +922,16 @@ void EntityBase::GenerateEquations(IdList<Equation,hEquation> *l) const {
// If the two endpoints of the arc are constrained coincident // If the two endpoints of the arc are constrained coincident
// (to make a complete circle), then our distance constraint // (to make a complete circle), then our distance constraint
// would be redundant and therefore overconstrain things. // would be redundant and therefore overconstrain things.
int i; auto it = std::find_if(SK.constraint.begin(), SK.constraint.end(),
for(i = 0; i < SK.constraint.n; i++) { [&](ConstraintBase const &con) {
ConstraintBase *c = &(SK.constraint.elem[i]); return (con.group == group) &&
if(c->group != group) continue; (con.type == Constraint::Type::POINTS_COINCIDENT) &&
if(c->type != Constraint::Type::POINTS_COINCIDENT) continue; ((con.ptA == point[1] && con.ptB == point[2]) ||
(con.ptA == point[2] && con.ptB == point[1]));
if((c->ptA == point[1] && c->ptB == point[2]) || });
(c->ptA == point[2] && c->ptB == point[1])) if(it != SK.constraint.end()) {
{ break;
break;
}
} }
if(i < SK.constraint.n) break;
Expr *ra = Constraint::Distance(workplane, point[0], point[1]); Expr *ra = Constraint::Distance(workplane, point[0], point[1]);
Expr *rb = Constraint::Distance(workplane, point[0], point[2]); Expr *rb = Constraint::Distance(workplane, point[0], point[2]);

View File

@ -96,9 +96,8 @@ void SolveSpaceUI::ExportSectionTo(const Platform::Path &filename) {
bl.CullIdenticalBeziers(/*both=*/true); bl.CullIdenticalBeziers(/*both=*/true);
// Collect lines and beziers with custom style & export. // Collect lines and beziers with custom style & export.
int i; for(auto &ent : SK.entity) {
for(i = 0; i < SK.entity.n; i++) { Entity *e = &ent;
Entity *e = &(SK.entity.elem[i]);
if (!e->IsVisible()) continue; if (!e->IsVisible()) continue;
if (e->style.v < Style::FIRST_CUSTOM) continue; if (e->style.v < Style::FIRST_CUSTOM) continue;
if (!Style::Exportable(e->style.v)) continue; if (!Style::Exportable(e->style.v)) continue;
@ -186,7 +185,6 @@ public:
}; };
void SolveSpaceUI::ExportViewOrWireframeTo(const Platform::Path &filename, bool exportWireframe) { void SolveSpaceUI::ExportViewOrWireframeTo(const Platform::Path &filename, bool exportWireframe) {
int i;
SEdgeList edges = {}; SEdgeList edges = {};
SBezierList beziers = {}; SBezierList beziers = {};
@ -206,8 +204,8 @@ void SolveSpaceUI::ExportViewOrWireframeTo(const Platform::Path &filename, bool
sm = NULL; sm = NULL;
} }
for(i = 0; i < SK.entity.n; i++) { for(auto &entity : SK.entity) {
Entity *e = &(SK.entity.elem[i]); Entity *e = &entity;
if(!e->IsVisible()) continue; if(!e->IsVisible()) continue;
if(e->construction) continue; if(e->construction) continue;

View File

@ -1027,8 +1027,9 @@ void SvgFileWriter::StartFile() {
double sw = max(ptMax.x - ptMin.x, ptMax.y - ptMin.y) / 1000; double sw = max(ptMax.x - ptMin.x, ptMax.y - ptMin.y) / 1000;
fprintf(f, "stroke-width:%f;\r\n", sw); fprintf(f, "stroke-width:%f;\r\n", sw);
fprintf(f, "}\r\n"); fprintf(f, "}\r\n");
for(int i = 0; i < SK.style.n; i++) { for(auto &style : SK.style) {
Style *s = &SK.style.elem[i]; Style *s = &style;
RgbaColor strokeRgb = Style::Color(s->h, /*forExport=*/true); RgbaColor strokeRgb = Style::Color(s->h, /*forExport=*/true);
StipplePattern pattern = Style::PatternType(s->h); StipplePattern pattern = Style::PatternType(s->h);
double stippleScale = Style::StippleScaleMm(s->h); double stippleScale = Style::StippleScaleMm(s->h);

View File

@ -20,8 +20,8 @@ void SolveSpaceUI::ClearExisting() {
UndoClearStack(&redo); UndoClearStack(&redo);
UndoClearStack(&undo); UndoClearStack(&undo);
for(int i = 0; i < SK.groupOrder.n; i++) { for(hGroup hg : SK.groupOrder) {
Group *g = SK.GetGroup(SK.groupOrder.elem[i]); Group *g = SK.GetGroup(hg);
g->Clear(); g->Clear();
} }
@ -301,39 +301,39 @@ bool SolveSpaceUI::SaveToFile(const Platform::Path &filename) {
fprintf(fh, "%s\n\n\n", VERSION_STRING); fprintf(fh, "%s\n\n\n", VERSION_STRING);
int i, j; int i, j;
for(i = 0; i < SK.group.n; i++) { for(auto &g : SK.group) {
sv.g = SK.group.elem[i]; sv.g = g;
SaveUsingTable(filename, 'g'); SaveUsingTable(filename, 'g');
fprintf(fh, "AddGroup\n\n"); fprintf(fh, "AddGroup\n\n");
} }
for(i = 0; i < SK.param.n; i++) { for(auto &p : SK.param) {
sv.p = SK.param.elem[i]; sv.p = p;
SaveUsingTable(filename, 'p'); SaveUsingTable(filename, 'p');
fprintf(fh, "AddParam\n\n"); fprintf(fh, "AddParam\n\n");
} }
for(i = 0; i < SK.request.n; i++) { for(auto &r : SK.request) {
sv.r = SK.request.elem[i]; sv.r = r;
SaveUsingTable(filename, 'r'); SaveUsingTable(filename, 'r');
fprintf(fh, "AddRequest\n\n"); fprintf(fh, "AddRequest\n\n");
} }
for(i = 0; i < SK.entity.n; i++) { for(auto &e : SK.entity) {
(SK.entity.elem[i]).CalculateNumerical(/*forExport=*/true); e.CalculateNumerical(/*forExport=*/true);
sv.e = SK.entity.elem[i]; sv.e = e;
SaveUsingTable(filename, 'e'); SaveUsingTable(filename, 'e');
fprintf(fh, "AddEntity\n\n"); fprintf(fh, "AddEntity\n\n");
} }
for(i = 0; i < SK.constraint.n; i++) { for(auto &c : SK.constraint) {
sv.c = SK.constraint.elem[i]; sv.c = c;
SaveUsingTable(filename, 'c'); SaveUsingTable(filename, 'c');
fprintf(fh, "AddConstraint\n\n"); fprintf(fh, "AddConstraint\n\n");
} }
for(i = 0; i < SK.style.n; i++) { for(auto &s : SK.style) {
sv.s = SK.style.elem[i]; sv.s = s;
if(sv.s.h.v >= Style::FIRST_CUSTOM) { if(sv.s.h.v >= Style::FIRST_CUSTOM) {
SaveUsingTable(filename, 's'); SaveUsingTable(filename, 's');
fprintf(fh, "AddStyle\n\n"); fprintf(fh, "AddStyle\n\n");

View File

@ -14,10 +14,9 @@ void SolveSpaceUI::MarkGroupDirtyByEntity(hEntity he) {
} }
void SolveSpaceUI::MarkGroupDirty(hGroup hg, bool onlyThis) { void SolveSpaceUI::MarkGroupDirty(hGroup hg, bool onlyThis) {
int i;
bool go = false; bool go = false;
for(i = 0; i < SK.groupOrder.n; i++) { for(auto const &gh : SK.groupOrder) {
Group *g = SK.GetGroup(SK.groupOrder.elem[i]); Group *g = SK.GetGroup(gh);
if(g->h == hg) { if(g->h == hg) {
go = true; go = true;
} }
@ -31,23 +30,20 @@ void SolveSpaceUI::MarkGroupDirty(hGroup hg, bool onlyThis) {
} }
bool SolveSpaceUI::PruneOrphans() { bool SolveSpaceUI::PruneOrphans() {
int i;
for(i = 0; i < SK.request.n; i++) {
Request *r = &(SK.request.elem[i]);
if(GroupExists(r->group)) continue;
auto r = std::find_if(SK.request.begin(), SK.request.end(),
[&](Request &r) { return !GroupExists(r.group); });
if(r != SK.request.end()) {
(deleted.requests)++; (deleted.requests)++;
SK.request.RemoveById(r->h); SK.request.RemoveById(r->h);
return true; return true;
} }
for(i = 0; i < SK.constraint.n; i++) { auto c = std::find_if(SK.constraint.begin(), SK.constraint.end(),
Constraint *c = &(SK.constraint.elem[i]); [&](Constraint &c) { return !GroupExists(c.group); });
if(GroupExists(c->group)) continue; if(c != SK.constraint.end()) {
(deleted.constraints)++; (deleted.constraints)++;
(deleted.nonTrivialConstraints)++; (deleted.nonTrivialConstraints)++;
SK.constraint.RemoveById(c->h); SK.constraint.RemoveById(c->h);
return true; return true;
} }
@ -91,44 +87,38 @@ bool SolveSpaceUI::PruneGroups(hGroup hg) {
} }
bool SolveSpaceUI::PruneRequests(hGroup hg) { bool SolveSpaceUI::PruneRequests(hGroup hg) {
int i; auto e = std::find_if(SK.entity.begin(), SK.entity.end(),
for(i = 0; i < SK.entity.n; i++) { [&](Entity &e) { return e.group == hg && !EntityExists(e.workplane); });
Entity *e = &(SK.entity.elem[i]); if(e != SK.entity.end()) {
if(e->group != hg) continue;
if(EntityExists(e->workplane)) continue;
ssassert(e->h.isFromRequest(), "Only explicitly created entities can be pruned");
(deleted.requests)++; (deleted.requests)++;
SK.request.RemoveById(e->h.request()); SK.entity.RemoveById(e->h);
return true; return true;
} }
return false; return false;
} }
bool SolveSpaceUI::PruneConstraints(hGroup hg) { bool SolveSpaceUI::PruneConstraints(hGroup hg) {
int i; auto c = std::find_if(SK.constraint.begin(), SK.constraint.end(), [&](Constraint &c) {
for(i = 0; i < SK.constraint.n; i++) { if(c.group != hg)
Constraint *c = &(SK.constraint.elem[i]); return false;
if(c->group != hg) continue;
if(EntityExists(c->workplane) && if(EntityExists(c.workplane) &&
EntityExists(c->ptA) && EntityExists(c.ptA) &&
EntityExists(c->ptB) && EntityExists(c.ptB) &&
EntityExists(c->entityA) && EntityExists(c.entityA) &&
EntityExists(c->entityB) && EntityExists(c.entityB) &&
EntityExists(c->entityC) && EntityExists(c.entityC) &&
EntityExists(c->entityD)) EntityExists(c.entityD)) {
{ return false;
continue;
} }
return true;
});
if(c != SK.constraint.end()) {
(deleted.constraints)++; (deleted.constraints)++;
if(c->type != Constraint::Type::POINTS_COINCIDENT && if(c->type != Constraint::Type::POINTS_COINCIDENT &&
c->type != Constraint::Type::HORIZONTAL && c->type != Constraint::Type::HORIZONTAL &&
c->type != Constraint::Type::VERTICAL) c->type != Constraint::Type::VERTICAL) {
{
(deleted.nonTrivialConstraints)++; (deleted.nonTrivialConstraints)++;
} }
@ -139,14 +129,13 @@ bool SolveSpaceUI::PruneConstraints(hGroup hg) {
} }
void SolveSpaceUI::GenerateAll(Generate type, bool andFindFree, bool genForBBox) { void SolveSpaceUI::GenerateAll(Generate type, bool andFindFree, bool genForBBox) {
int first = 0, last = 0, i, j; int first = 0, last = 0, i;
uint64_t startMillis = GetMilliseconds(), uint64_t startMillis = GetMilliseconds(),
endMillis; endMillis;
SK.groupOrder.Clear(); SK.groupOrder.Clear();
for(int i = 0; i < SK.group.n; i++) for(auto &g : SK.group) { SK.groupOrder.Add(&g.h); }
SK.groupOrder.Add(&SK.group.elem[i].h);
std::sort(SK.groupOrder.begin(), SK.groupOrder.end(), std::sort(SK.groupOrder.begin(), SK.groupOrder.end(),
[](const hGroup &ha, const hGroup &hb) { [](const hGroup &ha, const hGroup &hb) {
return SK.GetGroup(ha)->order < SK.GetGroup(hb)->order; return SK.GetGroup(ha)->order < SK.GetGroup(hb)->order;
@ -233,14 +222,14 @@ void SolveSpaceUI::GenerateAll(Generate type, bool andFindFree, bool genForBBox)
if(PruneGroups(g->h)) if(PruneGroups(g->h))
goto pruned; goto pruned;
for(j = 0; j < SK.request.n; j++) { for(auto &req : SK.request) {
Request *r = &(SK.request.elem[j]); Request *r = &req;
if(r->group != g->h) continue; if(r->group != g->h) continue;
r->Generate(&(SK.entity), &(SK.param)); r->Generate(&(SK.entity), &(SK.param));
} }
for(j = 0; j < SK.constraint.n; j++) { for(auto &con : SK.constraint) {
Constraint *c = &SK.constraint.elem[j]; Constraint *c = &con;
if(c->group != g->h) continue; if(c->group != g->h) continue;
c->Generate(&(SK.param)); c->Generate(&(SK.param));
@ -254,8 +243,8 @@ void SolveSpaceUI::GenerateAll(Generate type, bool andFindFree, bool genForBBox)
// Use the previous values for params that we've seen before, as // Use the previous values for params that we've seen before, as
// initial guesses for the solver. // initial guesses for the solver.
for(j = 0; j < SK.param.n; j++) { for(auto &p : SK.param) {
Param *newp = &(SK.param.elem[j]); Param *newp = &p;
if(newp->known) continue; if(newp->known) continue;
Param *prevp = prev.FindByIdNoOops(newp->h); Param *prevp = prev.FindByIdNoOops(newp->h);
@ -270,6 +259,7 @@ void SolveSpaceUI::GenerateAll(Generate type, bool andFindFree, bool genForBBox)
g->solved.how = SolveResult::OKAY; g->solved.how = SolveResult::OKAY;
g->clean = true; g->clean = true;
} else { } else {
// this i is an index in groupOrder
if(i >= first && i <= last) { if(i >= first && i <= last) {
// The group falls inside the range, so really solve it, // The group falls inside the range, so really solve it,
// and then regenerate the mesh based on the solved stuff. // and then regenerate the mesh based on the solved stuff.
@ -284,8 +274,8 @@ void SolveSpaceUI::GenerateAll(Generate type, bool andFindFree, bool genForBBox)
// The group falls outside the range, so just assume that // The group falls outside the range, so just assume that
// it's good wherever we left it. The mesh is unchanged, // it's good wherever we left it. The mesh is unchanged,
// and the parameters must be marked as known. // and the parameters must be marked as known.
for(j = 0; j < SK.param.n; j++) { for(auto &p : SK.param) {
Param *newp = &(SK.param.elem[j]); Param *newp = &p;
Param *prevp = prev.FindByIdNoOops(newp->h); Param *prevp = prev.FindByIdNoOops(newp->h);
if(prevp) newp->known = true; if(prevp) newp->known = true;
@ -295,8 +285,8 @@ void SolveSpaceUI::GenerateAll(Generate type, bool andFindFree, bool genForBBox)
} }
// And update any reference dimensions with their new values // And update any reference dimensions with their new values
for(i = 0; i < SK.constraint.n; i++) { for(auto &con : SK.constraint) {
Constraint *c = &(SK.constraint.elem[i]); Constraint *c = &con;
if(c->reference) { if(c->reference) {
c->ModifyToSatisfy(); c->ModifyToSatisfy();
} }
@ -505,20 +495,19 @@ void SolveSpaceUI::SolveGroupAndReport(hGroup hg, bool andFindFree) {
} }
void SolveSpaceUI::WriteEqSystemForGroup(hGroup hg) { void SolveSpaceUI::WriteEqSystemForGroup(hGroup hg) {
int i;
// Clear out the system to be solved. // Clear out the system to be solved.
sys.entity.Clear(); sys.entity.Clear();
sys.param.Clear(); sys.param.Clear();
sys.eq.Clear(); sys.eq.Clear();
// And generate all the params for requests in this group // And generate all the params for requests in this group
for(i = 0; i < SK.request.n; i++) { for(auto &req : SK.request) {
Request *r = &(SK.request.elem[i]); Request *r = &req;
if(r->group != hg) continue; if(r->group != hg) continue;
r->Generate(&(sys.entity), &(sys.param)); r->Generate(&(sys.entity), &(sys.param));
} }
for(i = 0; i < SK.constraint.n; i++) { for(auto &con : SK.constraint) {
Constraint *c = &SK.constraint.elem[i]; Constraint *c = &con;
if(c->group != hg) continue; if(c->group != hg) continue;
c->Generate(&(sys.param)); c->Generate(&(sys.param));
@ -527,8 +516,8 @@ void SolveSpaceUI::WriteEqSystemForGroup(hGroup hg) {
Group *g = SK.GetGroup(hg); Group *g = SK.GetGroup(hg);
g->Generate(&(sys.entity), &(sys.param)); g->Generate(&(sys.entity), &(sys.param));
// Set the initial guesses for all the params // Set the initial guesses for all the params
for(i = 0; i < sys.param.n; i++) { for(auto &param : sys.param) {
Param *p = &(sys.param.elem[i]); Param *p = &param;
p->known = false; p->known = false;
p->val = SK.GetParam(p->h)->val; p->val = SK.GetParam(p->h)->val;
} }

View File

@ -381,7 +381,9 @@ void GraphicsWindow::Init() {
orig.projUp = projUp; orig.projUp = projUp;
// And with the last group active // And with the last group active
activeGroup = SK.groupOrder.elem[SK.groupOrder.n - 1]; ssassert(!SK.groupOrder.IsEmpty(),
"Group order can't be empty since we will activate the last group.");
activeGroup = SK.groupOrder[SK.groupOrder.n - 1];
SK.GetGroup(activeGroup)->Activate(); SK.GetGroup(activeGroup)->Activate();
showWorkplanes = false; showWorkplanes = false;

View File

@ -308,8 +308,8 @@ void Group::MenuGroup(Command id, Platform::Path linkFile) {
SS.UndoRemember(); SS.UndoRemember();
bool afterActive = false; bool afterActive = false;
for(int i = 0; i < SK.groupOrder.n; i++) { for(hGroup hg : SK.groupOrder) {
Group *gi = SK.GetGroup(SK.groupOrder.elem[i]); Group *gi = SK.GetGroup(hg);
if(afterActive) if(afterActive)
gi->order += 1; gi->order += 1;
if(gi->h == SS.GW.activeGroup) { if(gi->h == SS.GW.activeGroup) {
@ -472,6 +472,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
// Get some arbitrary point in the sketch, that will be used // Get some arbitrary point in the sketch, that will be used
// as a reference when defining top and bottom faces. // as a reference when defining top and bottom faces.
hEntity pt = { 0 }; hEntity pt = { 0 };
// Not using range-for here because we're changing the size of entity in the loop.
for(i = 0; i < entity->n; i++) { for(i = 0; i < entity->n; i++) {
Entity *e = &(entity->elem[i]); Entity *e = &(entity->elem[i]);
if(e->group != opA) continue; if(e->group != opA) continue;
@ -505,6 +506,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
// Remapped entity index. // Remapped entity index.
int ai = 1; int ai = 1;
// Not using range-for here because we're changing the size of entity in the loop.
for(i = 0; i < entity->n; i++) { for(i = 0; i < entity->n; i++) {
Entity *e = &(entity->elem[i]); Entity *e = &(entity->elem[i]);
if(e->group != opA) continue; if(e->group != opA) continue;
@ -656,6 +658,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
} }
for(a = a0; a < n; a++) { for(a = a0; a < n; a++) {
// Not using range-for here because we're changing the size of entity in the loop.
for(i = 0; i < entity->n; i++) { for(i = 0; i < entity->n; i++) {
Entity *e = &(entity->elem[i]); Entity *e = &(entity->elem[i]);
if(e->group != opA) continue; if(e->group != opA) continue;
@ -691,6 +694,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
} }
for(a = a0; a < n; a++) { for(a = a0; a < n; a++) {
// Not using range-for here because we're changing the size of entity in the loop.
for(i = 0; i < entity->n; i++) { for(i = 0; i < entity->n; i++) {
Entity *e = &(entity->elem[i]); Entity *e = &(entity->elem[i]);
if(e->group != opA) continue; if(e->group != opA) continue;
@ -717,6 +721,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
AddParam(param, h.param(5), 0); AddParam(param, h.param(5), 0);
AddParam(param, h.param(6), 0); AddParam(param, h.param(6), 0);
// Not using range-for here because we're changing the size of entity in the loop.
for(i = 0; i < impEntity.n; i++) { for(i = 0; i < impEntity.n; i++) {
Entity *ie = &(impEntity.elem[i]); Entity *ie = &(impEntity.elem[i]);
CopyEntity(entity, ie, 0, 0, CopyEntity(entity, ie, 0, 0,

View File

@ -14,13 +14,15 @@ void Group::AssembleLoops(bool *allClosed,
SBezierList sbl = {}; SBezierList sbl = {};
int i; int i;
for(i = 0; i < SK.entity.n; i++) { for(auto &e : SK.entity) {
Entity *e = &(SK.entity.elem[i]); if(e.group != h)
if(e->group != h) continue; continue;
if(e->construction) continue; if(e.construction)
if(e->forceHidden) continue; continue;
if(e.forceHidden)
continue;
e->GenerateBezierCurves(&sbl); e.GenerateBezierCurves(&sbl);
} }
SBezier *sb; SBezier *sb;
@ -235,6 +237,8 @@ void Group::GenerateShellAndMesh() {
// that face, so that the user can select them with the mouse. // that face, so that the user can select them with the mouse.
Vector onOrig = sbls->point; Vector onOrig = sbls->point;
int i; int i;
// Not using range-for here because we're starting at a different place and using
// indices for meaning.
for(i = is; i < thisShell.surface.n; i++) { for(i = is; i < thisShell.surface.n; i++) {
SSurface *ss = &(thisShell.surface.elem[i]); SSurface *ss = &(thisShell.surface.elem[i]);
hEntity face = Entity::NO_ENTITY; hEntity face = Entity::NO_ENTITY;
@ -490,13 +494,15 @@ void Group::GenerateDisplayItems() {
} }
Group *Group::PreviousGroup() const { Group *Group::PreviousGroup() const {
int i; Group *prev = nullptr;
for(i = 0; i < SK.groupOrder.n; i++) { for(auto const &gh : SK.groupOrder) {
Group *g = SK.GetGroup(SK.groupOrder.elem[i]); Group *g = SK.GetGroup(gh);
if(g->h == h) break; if(g->h == h) {
return prev;
}
prev = g;
} }
if(i == 0 || i >= SK.groupOrder.n) return NULL; return nullptr;
return SK.GetGroup(SK.groupOrder.elem[i - 1]);
} }
Group *Group::RunningMeshGroup() const { Group *Group::RunningMeshGroup() const {

View File

@ -12,11 +12,11 @@
// Useful when splitting, tangent arcing, or removing bezier points. // Useful when splitting, tangent arcing, or removing bezier points.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void GraphicsWindow::ReplacePointInConstraints(hEntity oldpt, hEntity newpt) { void GraphicsWindow::ReplacePointInConstraints(hEntity oldpt, hEntity newpt) {
int i; for(auto &c : SK.constraint) {
for(i = 0; i < SK.constraint.n; i++) { if(c.ptA == oldpt)
Constraint *c = &(SK.constraint.elem[i]); c.ptA = newpt;
if(c->ptA == oldpt) c->ptA = newpt; if(c.ptB == oldpt)
if(c->ptB == oldpt) c->ptB = newpt; c.ptB = newpt;
} }
} }
@ -25,14 +25,13 @@ void GraphicsWindow::ReplacePointInConstraints(hEntity oldpt, hEntity newpt) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void GraphicsWindow::RemoveConstraintsForPointBeingDeleted(hEntity hpt) { void GraphicsWindow::RemoveConstraintsForPointBeingDeleted(hEntity hpt) {
SK.constraint.ClearTags(); SK.constraint.ClearTags();
for(int i = 0; i < SK.constraint.n; i++) { for(auto &c : SK.constraint) {
Constraint *c = &(SK.constraint.elem[i]); if(c.ptA == hpt || c.ptB == hpt) {
if(c->ptA == hpt || c->ptB == hpt) { c.tag = 1;
c->tag = 1;
(SS.deleted.constraints)++; (SS.deleted.constraints)++;
if(c->type != Constraint::Type::POINTS_COINCIDENT && if(c.type != Constraint::Type::POINTS_COINCIDENT &&
c->type != Constraint::Type::HORIZONTAL && c.type != Constraint::Type::HORIZONTAL &&
c->type != Constraint::Type::VERTICAL) c.type != Constraint::Type::VERTICAL)
{ {
(SS.deleted.nonTrivialConstraints)++; (SS.deleted.nonTrivialConstraints)++;
} }
@ -270,18 +269,18 @@ void GraphicsWindow::MakeTangentArc() {
hRequest hreq[2]; hRequest hreq[2];
hEntity hent[2]; hEntity hent[2];
bool pointf[2]; bool pointf[2];
for(i = 0; i < SK.request.n; i++) { for(auto &r : SK.request) {
Request *r = &(SK.request.elem[i]); if(r.group != activeGroup)
if(r->group != activeGroup) continue; continue;
if(r->workplane != ActiveWorkplane()) continue; if(r.workplane != ActiveWorkplane())
if(r->construction) continue; continue;
if(r->type != Request::Type::LINE_SEGMENT && if(r.construction)
r->type != Request::Type::ARC_OF_CIRCLE) continue;
{ if(r.type != Request::Type::LINE_SEGMENT && r.type != Request::Type::ARC_OF_CIRCLE) {
continue; continue;
} }
Entity *e = SK.GetEntity(r->h.entity(0)); Entity *e = SK.GetEntity(r.h.entity(0));
Vector ps = e->EndpointStart(), Vector ps = e->EndpointStart(),
pf = e->EndpointFinish(); pf = e->EndpointFinish();
@ -292,8 +291,8 @@ void GraphicsWindow::MakeTangentArc() {
// finish of this entity. // finish of this entity.
ent[c] = e; ent[c] = e;
hent[c] = e->h; hent[c] = e->h;
req[c] = r; req[c] = &r;
hreq[c] = r->h; hreq[c] = r.h;
pointf[c] = (pf.Equals(pshared)); pointf[c] = (pf.Equals(pshared));
} }
c++; c++;
@ -603,15 +602,16 @@ hEntity GraphicsWindow::SplitEntity(hEntity he, Vector pinter) {
// Finally, delete the request that generated the original entity. // Finally, delete the request that generated the original entity.
Request::Type reqType = EntReqTable::GetRequestForEntity(entityType); Request::Type reqType = EntReqTable::GetRequestForEntity(entityType);
SK.request.ClearTags(); SK.request.ClearTags();
for(int i = 0; i < SK.request.n; i++) { for(auto &r : SK.request) {
Request *r = &(SK.request.elem[i]); if(r.group != activeGroup)
if(r->group != activeGroup) continue; continue;
if(r->type != reqType) continue; if(r.type != reqType)
continue;
// If the user wants to keep the old entities around, they can just // If the user wants to keep the old entities around, they can just
// mark them construction first. // mark them construction first.
if(he == r->h.entity(0) && !r->construction) { if(he == r.h.entity(0) && !r.construction) {
r->tag = 1; r.tag = 1;
break; break;
} }
} }

View File

@ -508,16 +508,16 @@ void SEdgeList::MergeCollinearSegments(Vector a, Vector b) {
qsort(l.elem, l.n, sizeof(l.elem[0]), ByTAlongLine); qsort(l.elem, l.n, sizeof(l.elem[0]), ByTAlongLine);
l.ClearTags(); l.ClearTags();
int i; SEdge *prev = nullptr;
for(i = 1; i < l.n; i++) { for(auto &now : l) {
SEdge *prev = &(l.elem[i-1]), if(prev != nullptr) {
*now = &(l.elem[i]); if((prev->b).Equals(now.a) && prev->auxA == now.auxA) {
// The previous segment joins up to us; so merge it into us.
if((prev->b).Equals(now->a) && prev->auxA == now->auxA) { prev->tag = 1;
// The previous segment joins up to us; so merge it into us. now.a = prev->a;
prev->tag = 1; }
now->a = prev->a;
} }
prev = &now;
} }
l.RemoveTagged(); l.RemoveTagged();
} }

View File

@ -20,28 +20,29 @@ const double System::RANK_MAG_TOLERANCE = 1e-4;
const double System::CONVERGE_TOLERANCE = (LENGTH_EPS/(1e2)); const double System::CONVERGE_TOLERANCE = (LENGTH_EPS/(1e2));
bool System::WriteJacobian(int tag) { bool System::WriteJacobian(int tag) {
int a, i, j;
j = 0; int j = 0;
for(a = 0; a < param.n; a++) { for(auto &p : param) {
if(j >= MAX_UNKNOWNS) return false; if(j >= MAX_UNKNOWNS)
return false;
Param *p = &(param.elem[a]); if(p.tag != tag)
if(p->tag != tag) continue; continue;
mat.param[j] = p->h; mat.param[j] = p.h;
j++; j++;
} }
mat.n = j; mat.n = j;
i = 0; int i = 0;
for(a = 0; a < eq.n; a++) {
for(auto &e : eq) {
if(i >= MAX_UNKNOWNS) return false; if(i >= MAX_UNKNOWNS) return false;
Equation *e = &(eq.elem[a]); if(e.tag != tag)
if(e->tag != tag) continue; continue;
mat.eq[i] = e->h; mat.eq[i] = e.h;
Expr *f = e->e->DeepCopyWithParamsAsPointers(&param, &(SK.param)); Expr *f = e.e->DeepCopyWithParamsAsPointers(&param, &(SK.param));
f = f->FoldConstants(); f = f->FoldConstants();
// Hash table (61 bits) to accelerate generation of zero partials. // Hash table (61 bits) to accelerate generation of zero partials.
@ -85,10 +86,8 @@ bool System::IsDragged(hParam p) {
} }
void System::SolveBySubstitution() { void System::SolveBySubstitution() {
int i; for(auto &teq : eq) {
for(i = 0; i < eq.n; i++) { Expr *tex = teq.e;
Equation *teq = &(eq.elem[i]);
Expr *tex = teq->e;
if(tex->op == Expr::Op::MINUS && if(tex->op == Expr::Op::MINUS &&
tex->a->op == Expr::Op::PARAM && tex->a->op == Expr::Op::PARAM &&
@ -108,22 +107,19 @@ void System::SolveBySubstitution() {
std::swap(a, b); std::swap(a, b);
} }
int j; for(auto &req : eq) {
for(j = 0; j < eq.n; j++) { req.e->Substitute(a, b); // A becomes B, B unchanged
Equation *req = &(eq.elem[j]);
(req->e)->Substitute(a, b); // A becomes B, B unchanged
} }
for(j = 0; j < param.n; j++) { for(auto &rp : param) {
Param *rp = &(param.elem[j]); if(rp.substd == a) {
if(rp->substd == a) { rp.substd = b;
rp->substd = b;
} }
} }
Param *ptr = param.FindById(a); Param *ptr = param.FindById(a);
ptr->tag = VAR_SUBSTITUTED; ptr->tag = VAR_SUBSTITUTED;
ptr->substd = b; ptr->substd = b;
teq->tag = EQ_SUBSTITUTED; teq.tag = EQ_SUBSTITUTED;
} }
} }
} }
@ -324,10 +320,9 @@ bool System::NewtonSolve(int tag) {
} }
void System::WriteEquationsExceptFor(hConstraint hc, Group *g) { void System::WriteEquationsExceptFor(hConstraint hc, Group *g) {
int i;
// Generate all the equations from constraints in this group // Generate all the equations from constraints in this group
for(i = 0; i < SK.constraint.n; i++) { for(auto &con : SK.constraint) {
ConstraintBase *c = &(SK.constraint.elem[i]); ConstraintBase *c = &con;
if(c->group != g->h) continue; if(c->group != g->h) continue;
if(c->h == hc) continue; if(c->h == hc) continue;
@ -349,8 +344,8 @@ void System::WriteEquationsExceptFor(hConstraint hc, Group *g) {
c->GenerateEquations(&eq); c->GenerateEquations(&eq);
} }
// And the equations from entities // And the equations from entities
for(i = 0; i < SK.entity.n; i++) { for(auto &ent : SK.entity) {
EntityBase *e = &(SK.entity.elem[i]); EntityBase *e = &ent;
if(e->group != g->h) continue; if(e->group != g->h) continue;
e->GenerateEquations(&eq); e->GenerateEquations(&eq);
@ -360,11 +355,11 @@ void System::WriteEquationsExceptFor(hConstraint hc, Group *g) {
} }
void System::FindWhichToRemoveToFixJacobian(Group *g, List<hConstraint> *bad, bool forceDofCheck) { void System::FindWhichToRemoveToFixJacobian(Group *g, List<hConstraint> *bad, bool forceDofCheck) {
int a, i; int a;
for(a = 0; a < 2; a++) { for(a = 0; a < 2; a++) {
for(i = 0; i < SK.constraint.n; i++) { for(auto &con : SK.constraint) {
ConstraintBase *c = &(SK.constraint.elem[i]); ConstraintBase *c = &con;
if(c->group != g->h) continue; if(c->group != g->h) continue;
if((c->type == Constraint::Type::POINTS_COINCIDENT && a == 0) || if((c->type == Constraint::Type::POINTS_COINCIDENT && a == 0) ||
(c->type != Constraint::Type::POINTS_COINCIDENT && a == 1)) (c->type != Constraint::Type::POINTS_COINCIDENT && a == 1))
@ -431,18 +426,18 @@ SolveResult System::Solve(Group *g, int *rank, int *dof, List<hConstraint> *bad,
// the system is consistent yet, but if it isn't then we'll catch that // the system is consistent yet, but if it isn't then we'll catch that
// later. // later.
int alone = 1; int alone = 1;
for(i = 0; i < eq.n; i++) { for(auto &e : eq) {
Equation *e = &(eq.elem[i]); if(e.tag != 0)
if(e->tag != 0) continue; continue;
hParam hp = e->e->ReferencedParams(&param); hParam hp = e.e->ReferencedParams(&param);
if(hp == Expr::NO_PARAMS) continue; if(hp == Expr::NO_PARAMS) continue;
if(hp == Expr::MULTIPLE_PARAMS) continue; if(hp == Expr::MULTIPLE_PARAMS) continue;
Param *p = param.FindById(hp); Param *p = param.FindById(hp);
if(p->tag != 0) continue; // let rank test catch inconsistency if(p->tag != 0) continue; // let rank test catch inconsistency
e->tag = alone; e.tag = alone;
p->tag = alone; p->tag = alone;
WriteJacobian(alone); WriteJacobian(alone);
if(!NewtonSolve(alone)) { if(!NewtonSolve(alone)) {
@ -480,23 +475,23 @@ SolveResult System::Solve(Group *g, int *rank, int *dof, List<hConstraint> *bad,
} }
// System solved correctly, so write the new values back in to the // System solved correctly, so write the new values back in to the
// main parameter table. // main parameter table.
for(i = 0; i < param.n; i++) { for(auto &p : param) {
Param *p = &(param.elem[i]);
double val; double val;
if(p->tag == VAR_SUBSTITUTED) { if(p.tag == VAR_SUBSTITUTED) {
val = param.FindById(p->substd)->val; val = param.FindById(p.substd)->val;
} else { } else {
val = p->val; val = p.val;
} }
Param *pp = SK.GetParam(p->h); Param *pp = SK.GetParam(p.h);
pp->val = val; pp->val = val;
pp->known = true; pp->known = true;
pp->free = p->free; pp->free = p.free;
} }
return rankOk ? SolveResult::OKAY : SolveResult::REDUNDANT_OKAY; return rankOk ? SolveResult::OKAY : SolveResult::REDUNDANT_OKAY;
didnt_converge: didnt_converge:
SK.constraint.ClearTags(); SK.constraint.ClearTags();
// Not using range-for here because index is used in additional ways
for(i = 0; i < eq.n; i++) { for(i = 0; i < eq.n; i++) {
if(ffabs(mat.B.num[i]) > CONVERGE_TOLERANCE || isnan(mat.B.num[i])) { if(ffabs(mat.B.num[i]) > CONVERGE_TOLERANCE || isnan(mat.B.num[i])) {
// This constraint is unsatisfied. // This constraint is unsatisfied.
@ -553,20 +548,19 @@ void System::MarkParamsFree(bool find) {
// If requested, find all the free (unbound) variables. This might be // If requested, find all the free (unbound) variables. This might be
// more than the number of degrees of freedom. Don't always do this, // more than the number of degrees of freedom. Don't always do this,
// because the display would get annoying and it's slow. // because the display would get annoying and it's slow.
for(int i = 0; i < param.n; i++) { for(auto &p : param) {
Param *p = &(param.elem[i]); p.free = false;
p->free = false;
if(find) { if(find) {
if(p->tag == 0) { if(p.tag == 0) {
p->tag = VAR_DOF_TEST; p.tag = VAR_DOF_TEST;
WriteJacobian(0); WriteJacobian(0);
EvalJacobian(); EvalJacobian();
int rank = CalculateRank(); int rank = CalculateRank();
if(rank == mat.m) { if(rank == mat.m) {
p->free = true; p.free = true;
} }
p->tag = 0; p.tag = 0;
} }
} }
} }

View File

@ -57,8 +57,9 @@ void TextWindow::ScreenToggleGroupShown(int link, uint32_t v) {
} }
void TextWindow::ScreenShowGroupsSpecial(int link, uint32_t v) { void TextWindow::ScreenShowGroupsSpecial(int link, uint32_t v) {
bool state = link == 's'; bool state = link == 's';
for(int i = 0; i < SK.groupOrder.n; i++) { for(hGroup hg : SK.groupOrder) {
Group *g = SK.GetGroup(SK.groupOrder.elem[i]); Group *g = SK.GetGroup(hg);
g->visible = state; g->visible = state;
} }
SS.GW.persistentDirty = true; SS.GW.persistentDirty = true;
@ -98,10 +99,11 @@ void TextWindow::ShowListOfGroups() {
Printf(true, "%Ft active"); Printf(true, "%Ft active");
Printf(false, "%Ft shown dof group-name%E"); Printf(false, "%Ft shown dof group-name%E");
int i;
bool afterActive = false; bool afterActive = false;
for(i = 0; i < SK.groupOrder.n; i++) { bool backgroundParity = false;
Group *g = SK.GetGroup(SK.groupOrder.elem[i]); for(hGroup hg : SK.groupOrder) {
Group *g = SK.GetGroup(hg);
std::string s = g->DescriptionString(); std::string s = g->DescriptionString();
bool active = (g->h == SS.GW.activeGroup); bool active = (g->h == SS.GW.activeGroup);
bool shown = g->visible; bool shown = g->visible;
@ -121,30 +123,32 @@ void TextWindow::ShowListOfGroups() {
} }
} }
bool ref = (g->h == Group::HGROUP_REFERENCES); bool ref = (g->h == Group::HGROUP_REFERENCES);
Printf(false, "%Bp%Fd " Printf(false,
"%Bp%Fd "
"%Ft%s%Fb%D%f%Ll%s%E " "%Ft%s%Fb%D%f%Ll%s%E "
"%Fb%s%D%f%Ll%s%E " "%Fb%s%D%f%Ll%s%E "
"%Fp%D%f%s%Ll%s%E " "%Fp%D%f%s%Ll%s%E "
"%Fl%Ll%D%f%s", "%Fl%Ll%D%f%s",
// Alternate between light and dark backgrounds, for readability // Alternate between light and dark backgrounds, for readability
(i & 1) ? 'd' : 'a', backgroundParity ? 'd' : 'a',
// Link that activates the group // Link that activates the group
ref ? " " : "", ref ? " " : "",
g->h.v, (&TextWindow::ScreenActivateGroup), g->h.v, (&TextWindow::ScreenActivateGroup),
ref ? "" : (active ? radioTrue : radioFalse), ref ? "" : (active ? radioTrue : radioFalse),
// Link that hides or shows the group // Link that hides or shows the group
afterActive ? " - " : "", afterActive ? " - " : "",
g->h.v, (&TextWindow::ScreenToggleGroupShown), g->h.v, (&TextWindow::ScreenToggleGroupShown),
afterActive ? "" : (shown ? checkTrue : checkFalse), afterActive ? "" : (shown ? checkTrue : checkFalse),
// Link to the errors, if a problem occurred while solving // Link to the errors, if a problem occurred while solving
ok ? (warn ? 'm' : (dof > 0 ? 'i' : 's')) : 'x', ok ? (warn ? 'm' : (dof > 0 ? 'i' : 's')) : 'x',
g->h.v, (&TextWindow::ScreenHowGroupSolved), g->h.v, (&TextWindow::ScreenHowGroupSolved),
ok ? (warn ? "err" : sdof) : "", ok ? (warn ? "err" : sdof) : "",
ok ? "" : "ERR", ok ? "" : "ERR",
// Link to a screen that gives more details on the group // Link to a screen that gives more details on the group
g->h.v, (&TextWindow::ScreenSelectGroup), s.c_str()); g->h.v, (&TextWindow::ScreenSelectGroup), s.c_str());
if(active) afterActive = true; if(active) afterActive = true;
backgroundParity = !backgroundParity;
} }
Printf(true, " %Fl%Ls%fshow all%E / %Fl%Lh%fhide all%E", Printf(true, " %Fl%Ls%fshow all%E / %Fl%Lh%fhide all%E",
@ -445,16 +449,17 @@ list_items:
Printf(false, ""); Printf(false, "");
Printf(false, "%Ft requests in group"); Printf(false, "%Ft requests in group");
int i, a = 0; int a = 0;
for(i = 0; i < SK.request.n; i++) { for(auto &r : SK.request) {
Request *r = &(SK.request.elem[i]);
if(r->group == shown.group) { if(r.group == shown.group) {
std::string s = r->DescriptionString(); std::string s = r.DescriptionString();
Printf(false, "%Bp %Fl%Ll%D%f%h%s%E", Printf(false, "%Bp %Fl%Ll%D%f%h%s%E",
(a & 1) ? 'd' : 'a', (a & 1) ? 'd' : 'a',
r->h.v, (&TextWindow::ScreenSelectRequest), r.h.v,
&(TextWindow::ScreenHoverRequest), s.c_str()); (&TextWindow::ScreenSelectRequest),
&(TextWindow::ScreenHoverRequest),
s.c_str());
a++; a++;
} }
} }
@ -463,16 +468,17 @@ list_items:
a = 0; a = 0;
Printf(false, ""); Printf(false, "");
Printf(false, "%Ft constraints in group (%d DOF)", g->solved.dof); Printf(false, "%Ft constraints in group (%d DOF)", g->solved.dof);
for(i = 0; i < SK.constraint.n; i++) { for(auto &c : SK.constraint) {
Constraint *c = &(SK.constraint.elem[i]);
if(c->group == shown.group) { if(c.group == shown.group) {
std::string s = c->DescriptionString(); std::string s = c.DescriptionString();
Printf(false, "%Bp %Fl%Ll%D%f%h%s%E %s", Printf(false, "%Bp %Fl%Ll%D%f%h%s%E %s",
(a & 1) ? 'd' : 'a', (a & 1) ? 'd' : 'a',
c->h.v, (&TextWindow::ScreenSelectConstraint), c.h.v,
(&TextWindow::ScreenHoverConstraint), s.c_str(), (&TextWindow::ScreenSelectConstraint),
c->reference ? "(ref)" : ""); (&TextWindow::ScreenHoverConstraint),
s.c_str(),
c.reference ? "(ref)" : "");
a++; a++;
} }
} }

View File

@ -36,8 +36,6 @@ void SolveSpaceUI::UndoEnableMenus() {
} }
void SolveSpaceUI::PushFromCurrentOnto(UndoStack *uk) { void SolveSpaceUI::PushFromCurrentOnto(UndoStack *uk) {
int i;
if(uk->cnt == MAX_UNDO) { if(uk->cnt == MAX_UNDO) {
UndoClearState(&(uk->d[uk->write])); UndoClearState(&(uk->d[uk->write]));
// And then write in to this one again // And then write in to this one again
@ -48,9 +46,9 @@ void SolveSpaceUI::PushFromCurrentOnto(UndoStack *uk) {
UndoState *ut = &(uk->d[uk->write]); UndoState *ut = &(uk->d[uk->write]);
*ut = {}; *ut = {};
ut->group.ReserveMore(SK.group.n); ut->group.ReserveMore(SK.group.n);
for(i = 0; i < SK.group.n; i++) { for(Group &src : SK.group) {
Group *src = &(SK.group.elem[i]); // Shallow copy
Group dest = *src; Group dest(src);
// And then clean up all the stuff that needs to be a deep copy, // 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. // and zero out all the dynamic stuff that will get regenerated.
dest.clean = false; dest.clean = false;
@ -66,42 +64,32 @@ void SolveSpaceUI::PushFromCurrentOnto(UndoStack *uk) {
dest.displayMesh = {}; dest.displayMesh = {};
dest.displayOutlines = {}; dest.displayOutlines = {};
dest.remap = src->remap; dest.remap = src.remap;
dest.impMesh = {}; dest.impMesh = {};
dest.impShell = {}; dest.impShell = {};
dest.impEntity = {}; dest.impEntity = {};
ut->group.Add(&dest); ut->group.Add(&dest);
} }
for(i = 0; i < SK.groupOrder.n; i++) { for(auto &src : SK.groupOrder) { ut->groupOrder.Add(&src); }
ut->groupOrder.Add(&(SK.groupOrder.elem[i]));
}
ut->request.ReserveMore(SK.request.n); ut->request.ReserveMore(SK.request.n);
for(i = 0; i < SK.request.n; i++) { for(auto &src : SK.request) { ut->request.Add(&src); }
ut->request.Add(&(SK.request.elem[i]));
}
ut->constraint.ReserveMore(SK.constraint.n); ut->constraint.ReserveMore(SK.constraint.n);
for(i = 0; i < SK.constraint.n; i++) { for(auto &src : SK.constraint) {
Constraint *src = &(SK.constraint.elem[i]); // Shallow copy
Constraint dest = *src; Constraint dest(src);
ut->constraint.Add(&dest); ut->constraint.Add(&dest);
} }
ut->param.ReserveMore(SK.param.n); ut->param.ReserveMore(SK.param.n);
for(i = 0; i < SK.param.n; i++) { for(auto &src : SK.param) { ut->param.Add(&src); }
ut->param.Add(&(SK.param.elem[i]));
}
ut->style.ReserveMore(SK.style.n); ut->style.ReserveMore(SK.style.n);
for(i = 0; i < SK.style.n; i++) { for(auto &src : SK.style) { ut->style.Add(&src); }
ut->style.Add(&(SK.style.elem[i]));
}
ut->activeGroup = SS.GW.activeGroup; ut->activeGroup = SS.GW.activeGroup;
uk->write = WRAP(uk->write + 1, MAX_UNDO); uk->write = WRAP(uk->write + 1, MAX_UNDO);
} }
void SolveSpaceUI::PopOntoCurrentFrom(UndoStack *uk) { void SolveSpaceUI::PopOntoCurrentFrom(UndoStack *uk) {
int i;
ssassert(uk->cnt > 0, "Cannot pop from empty undo stack"); ssassert(uk->cnt > 0, "Cannot pop from empty undo stack");
(uk->cnt)--; (uk->cnt)--;
uk->write = WRAP(uk->write - 1, MAX_UNDO); uk->write = WRAP(uk->write - 1, MAX_UNDO);
@ -109,8 +97,8 @@ void SolveSpaceUI::PopOntoCurrentFrom(UndoStack *uk) {
UndoState *ut = &(uk->d[uk->write]); UndoState *ut = &(uk->d[uk->write]);
// Free everything in the main copy of the program before replacing it // Free everything in the main copy of the program before replacing it
for(i = 0; i < SK.groupOrder.n; i++) { for(hGroup hg : SK.groupOrder) {
Group *g = SK.GetGroup(SK.groupOrder.elem[i]); Group *g = SK.GetGroup(hg);
g->Clear(); g->Clear();
} }
SK.group.Clear(); SK.group.Clear();
@ -122,8 +110,7 @@ void SolveSpaceUI::PopOntoCurrentFrom(UndoStack *uk) {
// And then do a shallow copy of the state from the undo list // And then do a shallow copy of the state from the undo list
ut->group.MoveSelfInto(&(SK.group)); ut->group.MoveSelfInto(&(SK.group));
for(i = 0; i < ut->groupOrder.n; i++) for(auto &gh : ut->groupOrder) { SK.groupOrder.Add(&gh); }
SK.groupOrder.Add(&ut->groupOrder.elem[i]);
ut->request.MoveSelfInto(&(SK.request)); ut->request.MoveSelfInto(&(SK.request));
ut->constraint.MoveSelfInto(&(SK.constraint)); ut->constraint.MoveSelfInto(&(SK.constraint));
ut->param.MoveSelfInto(&(SK.param)); ut->param.MoveSelfInto(&(SK.param));
@ -156,12 +143,7 @@ void SolveSpaceUI::UndoClearStack(UndoStack *uk) {
} }
void SolveSpaceUI::UndoClearState(UndoState *ut) { void SolveSpaceUI::UndoClearState(UndoState *ut) {
int i; for(auto &g : ut->group) { g.remap.clear(); }
for(i = 0; i < ut->group.n; i++) {
Group *g = &(ut->group.elem[i]);
g->remap.clear();
}
ut->group.Clear(); ut->group.Clear();
ut->request.Clear(); ut->request.Clear();
ut->constraint.Clear(); ut->constraint.Clear();