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

View File

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

View File

@ -434,10 +434,7 @@ public:
}
void ClearTags() {
int i;
for(i = 0; i < n; i++) {
elem[i].tag = 0;
}
for(auto &elt : *this) { elt.tag = 0; }
}
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
// (to make a complete circle), then our distance constraint
// would be redundant and therefore overconstrain things.
int i;
for(i = 0; i < SK.constraint.n; i++) {
ConstraintBase *c = &(SK.constraint.elem[i]);
if(c->group != group) continue;
if(c->type != Constraint::Type::POINTS_COINCIDENT) continue;
if((c->ptA == point[1] && c->ptB == point[2]) ||
(c->ptA == point[2] && c->ptB == point[1]))
{
break;
}
auto it = std::find_if(SK.constraint.begin(), SK.constraint.end(),
[&](ConstraintBase const &con) {
return (con.group == group) &&
(con.type == Constraint::Type::POINTS_COINCIDENT) &&
((con.ptA == point[1] && con.ptB == point[2]) ||
(con.ptA == point[2] && con.ptB == point[1]));
});
if(it != SK.constraint.end()) {
break;
}
if(i < SK.constraint.n) break;
Expr *ra = Constraint::Distance(workplane, point[0], point[1]);
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);
// Collect lines and beziers with custom style & export.
int i;
for(i = 0; i < SK.entity.n; i++) {
Entity *e = &(SK.entity.elem[i]);
for(auto &ent : SK.entity) {
Entity *e = &ent;
if (!e->IsVisible()) continue;
if (e->style.v < Style::FIRST_CUSTOM) continue;
if (!Style::Exportable(e->style.v)) continue;
@ -186,7 +185,6 @@ public:
};
void SolveSpaceUI::ExportViewOrWireframeTo(const Platform::Path &filename, bool exportWireframe) {
int i;
SEdgeList edges = {};
SBezierList beziers = {};
@ -206,8 +204,8 @@ void SolveSpaceUI::ExportViewOrWireframeTo(const Platform::Path &filename, bool
sm = NULL;
}
for(i = 0; i < SK.entity.n; i++) {
Entity *e = &(SK.entity.elem[i]);
for(auto &entity : SK.entity) {
Entity *e = &entity;
if(!e->IsVisible()) 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;
fprintf(f, "stroke-width:%f;\r\n", sw);
fprintf(f, "}\r\n");
for(int i = 0; i < SK.style.n; i++) {
Style *s = &SK.style.elem[i];
for(auto &style : SK.style) {
Style *s = &style;
RgbaColor strokeRgb = Style::Color(s->h, /*forExport=*/true);
StipplePattern pattern = Style::PatternType(s->h);
double stippleScale = Style::StippleScaleMm(s->h);

View File

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

View File

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

View File

@ -381,7 +381,9 @@ void GraphicsWindow::Init() {
orig.projUp = projUp;
// 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();
showWorkplanes = false;

View File

@ -308,8 +308,8 @@ void Group::MenuGroup(Command id, Platform::Path linkFile) {
SS.UndoRemember();
bool afterActive = false;
for(int i = 0; i < SK.groupOrder.n; i++) {
Group *gi = SK.GetGroup(SK.groupOrder.elem[i]);
for(hGroup hg : SK.groupOrder) {
Group *gi = SK.GetGroup(hg);
if(afterActive)
gi->order += 1;
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
// as a reference when defining top and bottom faces.
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++) {
Entity *e = &(entity->elem[i]);
if(e->group != opA) continue;
@ -505,6 +506,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
// Remapped entity index.
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++) {
Entity *e = &(entity->elem[i]);
if(e->group != opA) continue;
@ -656,6 +658,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
}
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++) {
Entity *e = &(entity->elem[i]);
if(e->group != opA) continue;
@ -691,6 +694,7 @@ void Group::Generate(IdList<Entity,hEntity> *entity,
}
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++) {
Entity *e = &(entity->elem[i]);
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(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++) {
Entity *ie = &(impEntity.elem[i]);
CopyEntity(entity, ie, 0, 0,

View File

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

View File

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

View File

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

View File

@ -20,28 +20,29 @@ const double System::RANK_MAG_TOLERANCE = 1e-4;
const double System::CONVERGE_TOLERANCE = (LENGTH_EPS/(1e2));
bool System::WriteJacobian(int tag) {
int a, i, j;
j = 0;
for(a = 0; a < param.n; a++) {
if(j >= MAX_UNKNOWNS) return false;
int j = 0;
for(auto &p : param) {
if(j >= MAX_UNKNOWNS)
return false;
Param *p = &(param.elem[a]);
if(p->tag != tag) continue;
mat.param[j] = p->h;
if(p.tag != tag)
continue;
mat.param[j] = p.h;
j++;
}
mat.n = j;
i = 0;
for(a = 0; a < eq.n; a++) {
int i = 0;
for(auto &e : eq) {
if(i >= MAX_UNKNOWNS) return false;
Equation *e = &(eq.elem[a]);
if(e->tag != tag) continue;
if(e.tag != tag)
continue;
mat.eq[i] = e->h;
Expr *f = e->e->DeepCopyWithParamsAsPointers(&param, &(SK.param));
mat.eq[i] = e.h;
Expr *f = e.e->DeepCopyWithParamsAsPointers(&param, &(SK.param));
f = f->FoldConstants();
// Hash table (61 bits) to accelerate generation of zero partials.
@ -85,10 +86,8 @@ bool System::IsDragged(hParam p) {
}
void System::SolveBySubstitution() {
int i;
for(i = 0; i < eq.n; i++) {
Equation *teq = &(eq.elem[i]);
Expr *tex = teq->e;
for(auto &teq : eq) {
Expr *tex = teq.e;
if(tex->op == Expr::Op::MINUS &&
tex->a->op == Expr::Op::PARAM &&
@ -108,22 +107,19 @@ void System::SolveBySubstitution() {
std::swap(a, b);
}
int j;
for(j = 0; j < eq.n; j++) {
Equation *req = &(eq.elem[j]);
(req->e)->Substitute(a, b); // A becomes B, B unchanged
for(auto &req : eq) {
req.e->Substitute(a, b); // A becomes B, B unchanged
}
for(j = 0; j < param.n; j++) {
Param *rp = &(param.elem[j]);
if(rp->substd == a) {
rp->substd = b;
for(auto &rp : param) {
if(rp.substd == a) {
rp.substd = b;
}
}
Param *ptr = param.FindById(a);
ptr->tag = VAR_SUBSTITUTED;
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) {
int i;
// Generate all the equations from constraints in this group
for(i = 0; i < SK.constraint.n; i++) {
ConstraintBase *c = &(SK.constraint.elem[i]);
for(auto &con : SK.constraint) {
ConstraintBase *c = &con;
if(c->group != g->h) continue;
if(c->h == hc) continue;
@ -349,8 +344,8 @@ void System::WriteEquationsExceptFor(hConstraint hc, Group *g) {
c->GenerateEquations(&eq);
}
// And the equations from entities
for(i = 0; i < SK.entity.n; i++) {
EntityBase *e = &(SK.entity.elem[i]);
for(auto &ent : SK.entity) {
EntityBase *e = &ent;
if(e->group != g->h) continue;
e->GenerateEquations(&eq);
@ -360,11 +355,11 @@ void System::WriteEquationsExceptFor(hConstraint hc, Group *g) {
}
void System::FindWhichToRemoveToFixJacobian(Group *g, List<hConstraint> *bad, bool forceDofCheck) {
int a, i;
int a;
for(a = 0; a < 2; a++) {
for(i = 0; i < SK.constraint.n; i++) {
ConstraintBase *c = &(SK.constraint.elem[i]);
for(auto &con : SK.constraint) {
ConstraintBase *c = &con;
if(c->group != g->h) continue;
if((c->type == Constraint::Type::POINTS_COINCIDENT && a == 0) ||
(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
// later.
int alone = 1;
for(i = 0; i < eq.n; i++) {
Equation *e = &(eq.elem[i]);
if(e->tag != 0) continue;
for(auto &e : eq) {
if(e.tag != 0)
continue;
hParam hp = e->e->ReferencedParams(&param);
hParam hp = e.e->ReferencedParams(&param);
if(hp == Expr::NO_PARAMS) continue;
if(hp == Expr::MULTIPLE_PARAMS) continue;
Param *p = param.FindById(hp);
if(p->tag != 0) continue; // let rank test catch inconsistency
e->tag = alone;
e.tag = alone;
p->tag = alone;
WriteJacobian(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
// main parameter table.
for(i = 0; i < param.n; i++) {
Param *p = &(param.elem[i]);
for(auto &p : param) {
double val;
if(p->tag == VAR_SUBSTITUTED) {
val = param.FindById(p->substd)->val;
if(p.tag == VAR_SUBSTITUTED) {
val = param.FindById(p.substd)->val;
} else {
val = p->val;
val = p.val;
}
Param *pp = SK.GetParam(p->h);
Param *pp = SK.GetParam(p.h);
pp->val = val;
pp->known = true;
pp->free = p->free;
pp->free = p.free;
}
return rankOk ? SolveResult::OKAY : SolveResult::REDUNDANT_OKAY;
didnt_converge:
SK.constraint.ClearTags();
// Not using range-for here because index is used in additional ways
for(i = 0; i < eq.n; i++) {
if(ffabs(mat.B.num[i]) > CONVERGE_TOLERANCE || isnan(mat.B.num[i])) {
// This constraint is unsatisfied.
@ -553,20 +548,19 @@ void System::MarkParamsFree(bool find) {
// If requested, find all the free (unbound) variables. This might be
// more than the number of degrees of freedom. Don't always do this,
// because the display would get annoying and it's slow.
for(int i = 0; i < param.n; i++) {
Param *p = &(param.elem[i]);
p->free = false;
for(auto &p : param) {
p.free = false;
if(find) {
if(p->tag == 0) {
p->tag = VAR_DOF_TEST;
if(p.tag == 0) {
p.tag = VAR_DOF_TEST;
WriteJacobian(0);
EvalJacobian();
int rank = CalculateRank();
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) {
bool state = link == 's';
for(int i = 0; i < SK.groupOrder.n; i++) {
Group *g = SK.GetGroup(SK.groupOrder.elem[i]);
for(hGroup hg : SK.groupOrder) {
Group *g = SK.GetGroup(hg);
g->visible = state;
}
SS.GW.persistentDirty = true;
@ -98,10 +99,11 @@ void TextWindow::ShowListOfGroups() {
Printf(true, "%Ft active");
Printf(false, "%Ft shown dof group-name%E");
int i;
bool afterActive = false;
for(i = 0; i < SK.groupOrder.n; i++) {
Group *g = SK.GetGroup(SK.groupOrder.elem[i]);
bool backgroundParity = false;
for(hGroup hg : SK.groupOrder) {
Group *g = SK.GetGroup(hg);
std::string s = g->DescriptionString();
bool active = (g->h == SS.GW.activeGroup);
bool shown = g->visible;
@ -121,30 +123,32 @@ void TextWindow::ShowListOfGroups() {
}
}
bool ref = (g->h == Group::HGROUP_REFERENCES);
Printf(false, "%Bp%Fd "
Printf(false,
"%Bp%Fd "
"%Ft%s%Fb%D%f%Ll%s%E "
"%Fb%s%D%f%Ll%s%E "
"%Fp%D%f%s%Ll%s%E "
"%Fl%Ll%D%f%s",
// Alternate between light and dark backgrounds, for readability
(i & 1) ? 'd' : 'a',
// Link that activates the group
ref ? " " : "",
g->h.v, (&TextWindow::ScreenActivateGroup),
ref ? "" : (active ? radioTrue : radioFalse),
// Link that hides or shows the group
afterActive ? " - " : "",
g->h.v, (&TextWindow::ScreenToggleGroupShown),
afterActive ? "" : (shown ? checkTrue : checkFalse),
// Link to the errors, if a problem occurred while solving
ok ? (warn ? 'm' : (dof > 0 ? 'i' : 's')) : 'x',
g->h.v, (&TextWindow::ScreenHowGroupSolved),
ok ? (warn ? "err" : sdof) : "",
ok ? "" : "ERR",
// Link to a screen that gives more details on the group
g->h.v, (&TextWindow::ScreenSelectGroup), s.c_str());
// Alternate between light and dark backgrounds, for readability
backgroundParity ? 'd' : 'a',
// Link that activates the group
ref ? " " : "",
g->h.v, (&TextWindow::ScreenActivateGroup),
ref ? "" : (active ? radioTrue : radioFalse),
// Link that hides or shows the group
afterActive ? " - " : "",
g->h.v, (&TextWindow::ScreenToggleGroupShown),
afterActive ? "" : (shown ? checkTrue : checkFalse),
// Link to the errors, if a problem occurred while solving
ok ? (warn ? 'm' : (dof > 0 ? 'i' : 's')) : 'x',
g->h.v, (&TextWindow::ScreenHowGroupSolved),
ok ? (warn ? "err" : sdof) : "",
ok ? "" : "ERR",
// Link to a screen that gives more details on the group
g->h.v, (&TextWindow::ScreenSelectGroup), s.c_str());
if(active) afterActive = true;
backgroundParity = !backgroundParity;
}
Printf(true, " %Fl%Ls%fshow all%E / %Fl%Lh%fhide all%E",
@ -445,16 +449,17 @@ list_items:
Printf(false, "");
Printf(false, "%Ft requests in group");
int i, a = 0;
for(i = 0; i < SK.request.n; i++) {
Request *r = &(SK.request.elem[i]);
int a = 0;
for(auto &r : SK.request) {
if(r->group == shown.group) {
std::string s = r->DescriptionString();
if(r.group == shown.group) {
std::string s = r.DescriptionString();
Printf(false, "%Bp %Fl%Ll%D%f%h%s%E",
(a & 1) ? 'd' : 'a',
r->h.v, (&TextWindow::ScreenSelectRequest),
&(TextWindow::ScreenHoverRequest), s.c_str());
(a & 1) ? 'd' : 'a',
r.h.v,
(&TextWindow::ScreenSelectRequest),
&(TextWindow::ScreenHoverRequest),
s.c_str());
a++;
}
}
@ -463,16 +468,17 @@ list_items:
a = 0;
Printf(false, "");
Printf(false, "%Ft constraints in group (%d DOF)", g->solved.dof);
for(i = 0; i < SK.constraint.n; i++) {
Constraint *c = &(SK.constraint.elem[i]);
for(auto &c : SK.constraint) {
if(c->group == shown.group) {
std::string s = c->DescriptionString();
if(c.group == shown.group) {
std::string s = c.DescriptionString();
Printf(false, "%Bp %Fl%Ll%D%f%h%s%E %s",
(a & 1) ? 'd' : 'a',
c->h.v, (&TextWindow::ScreenSelectConstraint),
(&TextWindow::ScreenHoverConstraint), s.c_str(),
c->reference ? "(ref)" : "");
(a & 1) ? 'd' : 'a',
c.h.v,
(&TextWindow::ScreenSelectConstraint),
(&TextWindow::ScreenHoverConstraint),
s.c_str(),
c.reference ? "(ref)" : "");
a++;
}
}

View File

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