Use Range-based for Loops Instead of NextAfter for all IdList Objects

Based on commit '3b395bb5a7' by pjanx

Resolves a performance regression of iteration being O(n * log n)
rather than O(n).
pull/1040/head
Přemysl Eric Janouch 2021-04-03 19:07:53 +02:00 committed by phkahler
parent 7674be791e
commit 9dd67c7ba0
15 changed files with 210 additions and 241 deletions

View File

@ -138,18 +138,17 @@ void GraphicsWindow::CopySelection() {
}
}
Constraint *c;
for(c = SK.constraint.First(); c; c = SK.constraint.NextAfter(c)) {
if(!SS.clipboard.ContainsEntity(c->ptA) ||
!SS.clipboard.ContainsEntity(c->ptB) ||
!SS.clipboard.ContainsEntity(c->entityA) ||
!SS.clipboard.ContainsEntity(c->entityB) ||
!SS.clipboard.ContainsEntity(c->entityC) ||
!SS.clipboard.ContainsEntity(c->entityD) ||
c->type == Constraint::Type::COMMENT) {
for(Constraint &c : SK.constraint) {
if(!SS.clipboard.ContainsEntity(c.ptA) ||
!SS.clipboard.ContainsEntity(c.ptB) ||
!SS.clipboard.ContainsEntity(c.entityA) ||
!SS.clipboard.ContainsEntity(c.entityB) ||
!SS.clipboard.ContainsEntity(c.entityC) ||
!SS.clipboard.ContainsEntity(c.entityD) ||
c.type == Constraint::Type::COMMENT) {
continue;
}
SS.clipboard.c.Add(c);
SS.clipboard.c.Add(&c);
}
}

View File

@ -210,16 +210,15 @@ void GraphicsWindow::SelectByMarquee() {
BBox marqueeBBox = BBox::From(Vector::From(marqueePoint.x, marqueePoint.y, VERY_NEGATIVE),
Vector::From(orig.mouse.x, orig.mouse.y, VERY_POSITIVE));
Entity *e;
for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
if(e->group != SS.GW.activeGroup) continue;
if(e->IsFace() || e->IsDistance()) continue;
if(!e->IsVisible()) continue;
for(Entity &e : SK.entity) {
if(e.group != SS.GW.activeGroup) continue;
if(e.IsFace() || e.IsDistance()) continue;
if(!e.IsVisible()) continue;
bool entityHasBBox;
BBox entityBBox = e->GetOrGenerateScreenBBox(&entityHasBBox);
BBox entityBBox = e.GetOrGenerateScreenBBox(&entityHasBBox);
if(entityHasBBox && entityBBox.Overlaps(marqueeBBox)) {
MakeSelected(e->h);
MakeSelected(e.h);
}
}
}
@ -412,8 +411,8 @@ void GraphicsWindow::HitTestMakeSelection(Point2d mp) {
cached.projRight = projRight;
cached.projUp = projUp;
cached.scale = scale;
for(Entity *e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
e->screenBBoxValid = false;
for(Entity &e : SK.entity) {
e.screenBBoxValid = false;
}
}

View File

@ -353,22 +353,21 @@ void StepFileWriter::ExportSurfacesTo(const Platform::Path &filename) {
advancedFaces = {};
SSurface *ss;
for(ss = shell->surface.First(); ss; ss = shell->surface.NextAfter(ss)) {
if(ss->trim.IsEmpty())
for(SSurface &ss : shell->surface) {
if(ss.trim.IsEmpty())
continue;
// Get all of the loops of Beziers that trim our surface (with each
// Bezier split so that we use the section as t goes from 0 to 1), and
// the piecewise linearization of those loops in xyz space.
SBezierList sbl = {};
ss->MakeSectionEdgesInto(shell, NULL, &sbl);
ss.MakeSectionEdgesInto(shell, NULL, &sbl);
// Apply the export scale factor.
ss->ScaleSelfBy(1.0/SS.exportScale);
ss.ScaleSelfBy(1.0/SS.exportScale);
sbl.ScaleSelfBy(1.0/SS.exportScale);
ExportSurface(ss, &sbl);
ExportSurface(&ss, &sbl);
sbl.Clear();
}

View File

@ -170,22 +170,21 @@ public:
}
if(writer->constraint) {
Constraint *c;
for(c = writer->constraint->First(); c; c = writer->constraint->NextAfter(c)) {
if(!writer->NeedToOutput(c)) continue;
switch(c->type) {
for(Constraint &c : *writer->constraint) {
if(!writer->NeedToOutput(&c)) continue;
switch(c.type) {
case Constraint::Type::PT_PT_DISTANCE: {
Vector ap = SK.GetEntity(c->ptA)->PointGetNum();
Vector bp = SK.GetEntity(c->ptB)->PointGetNum();
Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(c->disp.offset);
Vector ap = SK.GetEntity(c.ptA)->PointGetNum();
Vector bp = SK.GetEntity(c.ptB)->PointGetNum();
Vector ref = ((ap.Plus(bp)).ScaledBy(0.5)).Plus(c.disp.offset);
writeAlignedDimension(xfrm(ap), xfrm(bp), xfrm(ref),
xfrm(ref), c->Label(), c->GetStyle(), c->valA);
xfrm(ref), c.Label(), c.GetStyle(), c.valA);
break;
}
case Constraint::Type::PT_LINE_DISTANCE: {
Vector pt = SK.GetEntity(c->ptA)->PointGetNum();
Entity *line = SK.GetEntity(c->entityA);
Vector pt = SK.GetEntity(c.ptA)->PointGetNum();
Entity *line = SK.GetEntity(c.entityA);
Vector lA = SK.GetEntity(line->point[0])->PointGetNum();
Vector lB = SK.GetEntity(line->point[1])->PointGetNum();
Vector dl = lB.Minus(lA);
@ -194,7 +193,7 @@ public:
if(pt.Equals(closest)) break;
Vector ref = ((closest.Plus(pt)).ScaledBy(0.5)).Plus(c->disp.offset);
Vector ref = ((closest.Plus(pt)).ScaledBy(0.5)).Plus(c.disp.offset);
Vector refClosest = ref.ClosestPointOnLine(lA, dl);
double ddl = dl.Dot(dl);
@ -209,54 +208,54 @@ public:
Vector xdl = xfrm(lB).Minus(xfrm(lA));
writeLinearDimension(xfrm(pt), xfrm(refClosest), xfrm(ref),
xfrm(ref), c->Label(),
xfrm(ref), c.Label(),
atan2(xdl.y, xdl.x) / PI * 180.0 + 90.0, 0.0,
c->GetStyle(), c->valA);
c.GetStyle(), c.valA);
break;
}
case Constraint::Type::DIAMETER: {
Entity *circle = SK.GetEntity(c->entityA);
Entity *circle = SK.GetEntity(c.entityA);
Vector center = SK.GetEntity(circle->point[0])->PointGetNum();
Quaternion q = SK.GetEntity(circle->normal)->NormalGetNum();
Vector n = q.RotationN().WithMagnitude(1);
double r = circle->CircleGetRadiusNum();
Vector ref = center.Plus(c->disp.offset);
Vector ref = center.Plus(c.disp.offset);
// Force the label into the same plane as the circle.
ref = ref.Minus(n.ScaledBy(n.Dot(ref) - n.Dot(center)));
Vector rad = ref.Minus(center).WithMagnitude(r);
if(/*isRadius*/c->other) {
if(/*isRadius*/c.other) {
writeRadialDimension(
xfrm(center), xfrm(center.Plus(rad)),
xfrm(ref), c->Label(), c->GetStyle(), c->valA);
xfrm(ref), c.Label(), c.GetStyle(), c.valA);
} else {
writeDiametricDimension(
xfrm(center.Minus(rad)), xfrm(center.Plus(rad)),
xfrm(ref), c->Label(), c->GetStyle(), c->valA);
xfrm(ref), c.Label(), c.GetStyle(), c.valA);
}
break;
}
case Constraint::Type::ANGLE: {
Entity *a = SK.GetEntity(c->entityA);
Entity *b = SK.GetEntity(c->entityB);
Entity *a = SK.GetEntity(c.entityA);
Entity *b = SK.GetEntity(c.entityB);
Vector a0 = a->VectorGetStartPoint();
Vector b0 = b->VectorGetStartPoint();
Vector da = a->VectorGetNum();
Vector db = b->VectorGetNum();
if(/*otherAngle*/c->other) {
if(/*otherAngle*/c.other) {
a0 = a0.Plus(da);
da = da.ScaledBy(-1);
}
bool skew = false;
Vector ref = c->disp.offset;
Vector ref = c.disp.offset;
Vector pi = Vector::AtIntersectionOfLines(a0, a0.Plus(da), b0, b0.Plus(db),
&skew);
if(!skew) ref = pi.Plus(c->disp.offset);
if(!skew) ref = pi.Plus(c.disp.offset);
Vector norm = da.Cross(db);
Vector dna = norm.Cross(da).WithMagnitude(1.0);
@ -277,7 +276,7 @@ public:
Vector bisect = da.WithMagnitude(1.0).ScaledBy(cos(thetaf / 2.0)).Plus(
dna.ScaledBy(sin(thetaf / 2.0)));
ref = pi.Plus(bisect.WithMagnitude(c->disp.offset.Magnitude()));
ref = pi.Plus(bisect.WithMagnitude(c.disp.offset.Magnitude()));
// Get lines again to write exact line.
a0 = a->VectorGetStartPoint();
@ -287,15 +286,15 @@ public:
writeAngularDimension(
xfrm(a0), xfrm(a0.Plus(da)), xfrm(b0), xfrm(b0.Plus(db)), xfrm(ref),
xfrm(ref), c->Label(), c->GetStyle(), c->valA);
xfrm(ref), c.Label(), c.GetStyle(), c.valA);
break;
}
case Constraint::Type::COMMENT: {
Style *st = SK.style.FindById(c->GetStyle());
writeText(xfrm(c->disp.offset), c->Label(),
Style::TextHeight(c->GetStyle()) / SS.GW.scale,
st->textAngle, st->textOrigin, c->GetStyle());
Style *st = SK.style.FindById(c.GetStyle());
writeText(xfrm(c.disp.offset), c.Label(),
Style::TextHeight(c.GetStyle()) / SS.GW.scale,
st->textAngle, st->textOrigin, c.GetStyle());
break;
}

View File

@ -354,19 +354,18 @@ bool SolveSpaceUI::SaveToFile(const Platform::Path &filename) {
}
SShell *s = &g->runningShell;
SSurface *srf;
for(srf = s->surface.First(); srf; srf = s->surface.NextAfter(srf)) {
for(SSurface &srf : s->surface) {
fprintf(fh, "Surface %08x %08x %08x %d %d\n",
srf->h.v, srf->color.ToPackedInt(), srf->face, srf->degm, srf->degn);
for(i = 0; i <= srf->degm; i++) {
for(j = 0; j <= srf->degn; j++) {
srf.h.v, srf.color.ToPackedInt(), srf.face, srf.degm, srf.degn);
for(i = 0; i <= srf.degm; i++) {
for(j = 0; j <= srf.degn; j++) {
fprintf(fh, "SCtrl %d %d %.20f %.20f %.20f Weight %20.20f\n",
i, j, CO(srf->ctrl[i][j]), srf->weight[i][j]);
i, j, CO(srf.ctrl[i][j]), srf.weight[i][j]);
}
}
STrimBy *stb;
for(stb = srf->trim.First(); stb; stb = srf->trim.NextAfter(stb)) {
for(stb = srf.trim.First(); stb; stb = srf.trim.NextAfter(stb)) {
fprintf(fh, "TrimBy %08x %d %.20f %.20f %.20f %.20f %.20f %.20f\n",
stb->curve.v, stb->backwards ? 1 : 0,
CO(stb->start), CO(stb->finish));
@ -374,21 +373,20 @@ bool SolveSpaceUI::SaveToFile(const Platform::Path &filename) {
fprintf(fh, "AddSurface\n");
}
SCurve *sc;
for(sc = s->curve.First(); sc; sc = s->curve.NextAfter(sc)) {
for(SCurve &sc : s->curve) {
fprintf(fh, "Curve %08x %d %d %08x %08x\n",
sc->h.v,
sc->isExact ? 1 : 0, sc->exact.deg,
sc->surfA.v, sc->surfB.v);
sc.h.v,
sc.isExact ? 1 : 0, sc.exact.deg,
sc.surfA.v, sc.surfB.v);
if(sc->isExact) {
for(i = 0; i <= sc->exact.deg; i++) {
if(sc.isExact) {
for(i = 0; i <= sc.exact.deg; i++) {
fprintf(fh, "CCtrl %d %.20f %.20f %.20f Weight %.20f\n",
i, CO(sc->exact.ctrl[i]), sc->exact.weight[i]);
i, CO(sc.exact.ctrl[i]), sc.exact.weight[i]);
}
}
SCurvePt *scpt;
for(scpt = sc->pts.First(); scpt; scpt = sc->pts.NextAfter(scpt)) {
for(scpt = sc.pts.First(); scpt; scpt = sc.pts.NextAfter(scpt)) {
fprintf(fh, "CurvePt %d %.20f %.20f %.20f\n",
scpt->vertex ? 1 : 0, CO(scpt->p));
}

View File

@ -968,20 +968,19 @@ void GraphicsWindow::ForceTextWindowShown() {
}
void GraphicsWindow::DeleteTaggedRequests() {
Request *r;
// Delete any requests that were affected by this deletion.
for(r = SK.request.First(); r; r = SK.request.NextAfter(r)) {
if(r->workplane == Entity::FREE_IN_3D) continue;
if(!r->workplane.isFromRequest()) continue;
Request *wrkpl = SK.GetRequest(r->workplane.request());
for(Request &r : SK.request) {
if(r.workplane == Entity::FREE_IN_3D) continue;
if(!r.workplane.isFromRequest()) continue;
Request *wrkpl = SK.GetRequest(r.workplane.request());
if(wrkpl->tag)
r->tag = 1;
r.tag = 1;
}
// Rewrite any point-coincident constraints that were affected by this
// deletion.
for(r = SK.request.First(); r; r = SK.request.NextAfter(r)) {
if(!r->tag) continue;
FixConstraintsForRequestBeingDeleted(r->h);
for(Request &r : SK.request) {
if(!r.tag) continue;
FixConstraintsForRequestBeingDeleted(r.h);
}
// and then delete the tagged requests.
SK.request.RemoveTagged();
@ -1045,9 +1044,8 @@ void GraphicsWindow::MenuEdit(Command id) {
SS.centerOfMass.draw = false;
// This clears the marks drawn to indicate which points are
// still free to drag.
Param *p;
for(p = SK.param.First(); p; p = SK.param.NextAfter(p)) {
p->free = false;
for(Param &p : SK.param) {
p.free = false;
}
if(SS.exportMode) {
SS.exportMode = false;
@ -1057,13 +1055,12 @@ void GraphicsWindow::MenuEdit(Command id) {
break;
case Command::SELECT_ALL: {
Entity *e;
for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
if(e->group != SS.GW.activeGroup) continue;
if(e->IsFace() || e->IsDistance()) continue;
if(!e->IsVisible()) continue;
for(Entity &e : SK.entity) {
if(e.group != SS.GW.activeGroup) continue;
if(e.IsFace() || e.IsDistance()) continue;
if(!e.IsVisible()) continue;
SS.GW.MakeSelected(e->h);
SS.GW.MakeSelected(e.h);
}
SS.GW.Invalidate();
SS.ScheduleShowTW();
@ -1071,24 +1068,23 @@ void GraphicsWindow::MenuEdit(Command id) {
}
case Command::SELECT_CHAIN: {
Entity *e;
int newlySelected = 0;
bool didSomething;
do {
didSomething = false;
for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
if(e->group != SS.GW.activeGroup) continue;
if(!e->HasEndpoints()) continue;
if(!e->IsVisible()) continue;
for(Entity &e : SK.entity) {
if(e.group != SS.GW.activeGroup) continue;
if(!e.HasEndpoints()) continue;
if(!e.IsVisible()) continue;
Vector st = e->EndpointStart(),
fi = e->EndpointFinish();
Vector st = e.EndpointStart(),
fi = e.EndpointFinish();
bool onChain = false, alreadySelected = false;
List<Selection> *ls = &(SS.GW.selection);
for(Selection *s = ls->First(); s; s = ls->NextAfter(s)) {
if(!s->entity.v) continue;
if(s->entity == e->h) {
if(s->entity == e.h) {
alreadySelected = true;
continue;
}
@ -1105,7 +1101,7 @@ void GraphicsWindow::MenuEdit(Command id) {
}
}
if(onChain && !alreadySelected) {
SS.GW.MakeSelected(e->h);
SS.GW.MakeSelected(e.h);
newlySelected++;
didSomething = true;
}

View File

@ -83,13 +83,12 @@ void Group::GenerateLoops() {
}
void SShell::RemapFaces(Group *g, int remap) {
SSurface *ss;
for(ss = surface.First(); ss; ss = surface.NextAfter(ss)){
hEntity face = { ss->face };
for(SSurface &ss : surface){
hEntity face = { ss.face };
if(face == Entity::NO_ENTITY) continue;
face = g->Remap(face, remap);
ss->face = face.v;
ss.face = face.v;
}
}
@ -292,13 +291,12 @@ void Group::GenerateShellAndMesh() {
// So these are the sides
if(ss->degm != 1 || ss->degn != 1) continue;
Entity *e;
for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
if(e->group != opA) continue;
if(e->type != Entity::Type::LINE_SEGMENT) continue;
for(Entity &e : SK.entity) {
if(e.group != opA) continue;
if(e.type != Entity::Type::LINE_SEGMENT) continue;
Vector a = SK.GetEntity(e->point[0])->PointGetNum(),
b = SK.GetEntity(e->point[1])->PointGetNum();
Vector a = SK.GetEntity(e.point[0])->PointGetNum(),
b = SK.GetEntity(e.point[1])->PointGetNum();
a = a.Plus(ttop);
b = b.Plus(ttop);
// Could get taken backwards, so check all cases.
@ -307,7 +305,7 @@ void Group::GenerateShellAndMesh() {
(a.Equals(ss->ctrl[0][1]) && b.Equals(ss->ctrl[1][1])) ||
(b.Equals(ss->ctrl[0][1]) && a.Equals(ss->ctrl[1][1])))
{
face = Remap(e->h, REMAP_LINE_TO_FACE);
face = Remap(e.h, REMAP_LINE_TO_FACE);
ss->face = face.v;
break;
}

View File

@ -50,38 +50,36 @@ void GraphicsWindow::FixConstraintsForRequestBeingDeleted(hRequest hr) {
Request *r = SK.GetRequest(hr);
if(r->group != SS.GW.activeGroup) return;
Entity *e;
for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
if(!(e->h.isFromRequest())) continue;
if(e->h.request() != hr) continue;
for(Entity &e : SK.entity) {
if(!(e.h.isFromRequest())) continue;
if(e.h.request() != hr) continue;
if(e->type != Entity::Type::POINT_IN_2D &&
e->type != Entity::Type::POINT_IN_3D)
if(e.type != Entity::Type::POINT_IN_2D &&
e.type != Entity::Type::POINT_IN_3D)
{
continue;
}
// This is a point generated by the request being deleted; so fix
// the constraints for that.
FixConstraintsForPointBeingDeleted(e->h);
FixConstraintsForPointBeingDeleted(e.h);
}
}
void GraphicsWindow::FixConstraintsForPointBeingDeleted(hEntity hpt) {
List<hEntity> ld = {};
Constraint *c;
SK.constraint.ClearTags();
for(c = SK.constraint.First(); c; c = SK.constraint.NextAfter(c)) {
if(c->type != Constraint::Type::POINTS_COINCIDENT) continue;
if(c->group != SS.GW.activeGroup) continue;
for(Constraint &c : SK.constraint) {
if(c.type != Constraint::Type::POINTS_COINCIDENT) continue;
if(c.group != SS.GW.activeGroup) continue;
if(c->ptA == hpt) {
ld.Add(&(c->ptB));
c->tag = 1;
if(c.ptA == hpt) {
ld.Add(&(c.ptB));
c.tag = 1;
}
if(c->ptB == hpt) {
ld.Add(&(c->ptA));
c->tag = 1;
if(c.ptB == hpt) {
ld.Add(&(c.ptA));
c.tag = 1;
}
}
// Remove constraints without waiting for regeneration; this way
@ -225,21 +223,21 @@ void GraphicsWindow::ParametricCurve::CreateRequestTrimmedTo(double t,
// happens to exist, then constrain that point coincident to hpt.
//-----------------------------------------------------------------------------
void GraphicsWindow::ParametricCurve::ConstrainPointIfCoincident(hEntity hpt) {
Entity *e, *pt;
Entity *pt;
pt = SK.GetEntity(hpt);
Vector ev, ptv;
ptv = pt->PointGetNum();
for(e = SK.entity.First(); e; e = SK.entity.NextAfter(e)) {
if(e->h == pt->h) continue;
if(!e->IsPoint()) continue;
if(e->group != pt->group) continue;
if(e->workplane != pt->workplane) continue;
for(Entity &e : SK.entity) {
if(e.h == pt->h) continue;
if(!e.IsPoint()) continue;
if(e.group != pt->group) continue;
if(e.workplane != pt->workplane) continue;
ev = e->PointGetNum();
ev = e.PointGetNum();
if(!ev.Equals(ptv)) continue;
Constraint::ConstrainCoincident(hpt, e->h);
Constraint::ConstrainCoincident(hpt, e.h);
break;
}
}

View File

@ -713,11 +713,12 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
if(gs.points == 1) {
Entity *p = SK.GetEntity(gs.point[0]);
Constraint *c;
Constraint *c = nullptr;
IdList<Constraint,hConstraint> *lc = &(SK.constraint);
for(c = lc->First(); c; c = lc->NextAfter(c)) {
if(c->type != Constraint::Type::POINTS_COINCIDENT) continue;
if(c->ptA == p->h || c->ptB == p->h) {
for(Constraint &ci : *lc) {
if(ci.type != Constraint::Type::POINTS_COINCIDENT) continue;
if(ci.ptA == p->h || ci.ptB == p->h) {
c = &ci;
break;
}
}
@ -727,11 +728,10 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
SS.UndoRemember();
SK.constraint.ClearTags();
Constraint *c;
for(c = SK.constraint.First(); c; c = SK.constraint.NextAfter(c)) {
if(c->type != Constraint::Type::POINTS_COINCIDENT) continue;
if(c->ptA == p->h || c->ptB == p->h) {
c->tag = 1;
for(Constraint &c : SK.constraint) {
if(c.type != Constraint::Type::POINTS_COINCIDENT) continue;
if(c.ptA == p->h || c.ptB == p->h) {
c.tag = 1;
}
}
SK.constraint.RemoveTagged();

View File

@ -521,20 +521,19 @@ SSurface SSurface::MakeCopyTrimAgainst(SShell *parent,
SEdgeList inter = {};
SSurface *ss;
SCurve *sc;
for(sc = into->curve.First(); sc; sc = into->curve.NextAfter(sc)) {
if(sc->source != SCurve::Source::INTERSECTION) continue;
for(SCurve &sc : into->curve) {
if(sc.source != SCurve::Source::INTERSECTION) continue;
if(opA) {
if(sc->surfA != h) continue;
ss = shb->surface.FindById(sc->surfB);
if(sc.surfA != h) continue;
ss = shb->surface.FindById(sc.surfB);
} else {
if(sc->surfB != h) continue;
ss = sha->surface.FindById(sc->surfA);
if(sc.surfB != h) continue;
ss = sha->surface.FindById(sc.surfA);
}
int i;
for(i = 1; i < sc->pts.n; i++) {
Vector a = sc->pts[i-1].p,
b = sc->pts[i].p;
for(i = 1; i < sc.pts.n; i++) {
Vector a = sc.pts[i-1].p,
b = sc.pts[i].p;
Point2d auv, buv;
ss->ClosestPointTo(a, &(auv.x), &(auv.y));
@ -560,9 +559,9 @@ SSurface SSurface::MakeCopyTrimAgainst(SShell *parent,
bkwds = !bkwds;
}
if(bkwds) {
inter.AddEdge(tb, ta, sc->h.v, 1);
inter.AddEdge(tb, ta, sc.h.v, 1);
} else {
inter.AddEdge(ta, tb, sc->h.v, 0);
inter.AddEdge(ta, tb, sc.h.v, 0);
}
}
}
@ -711,20 +710,18 @@ void SShell::MakeIntersectionCurvesAgainst(SShell *agnst, SShell *into) {
for(int i = 0; i< surface.n; i++) {
SSurface *sa = &surface[i];
SSurface *sb;
for(sb = agnst->surface.First(); sb; sb = agnst->surface.NextAfter(sb)){
for(SSurface &sb : agnst->surface){
// Intersect every surface from our shell against every surface
// from agnst; this will add zero or more curves to the curve
// list for into.
sa->IntersectAgainst(sb, this, agnst, into);
sa->IntersectAgainst(&sb, this, agnst, into);
}
}
}
void SShell::CleanupAfterBoolean() {
SSurface *ss;
for(ss = surface.First(); ss; ss = surface.NextAfter(ss)) {
ss->edges.Clear();
for(SSurface &ss : surface) {
ss.edges.Clear();
}
}
@ -734,10 +731,9 @@ void SShell::CleanupAfterBoolean() {
// by their new IDs.
//-----------------------------------------------------------------------------
void SShell::RewriteSurfaceHandlesForCurves(SShell *a, SShell *b) {
SCurve *sc;
for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) {
sc->surfA = sc->GetSurfaceA(a, b)->newH,
sc->surfB = sc->GetSurfaceB(a, b)->newH;
for(SCurve &sc : curve) {
sc.surfA = sc.GetSurfaceA(a, b)->newH,
sc.surfB = sc.GetSurfaceB(a, b)->newH;
}
}
@ -759,32 +755,32 @@ void SShell::MakeFromAssemblyOf(SShell *a, SShell *b) {
// First, copy over all the curves. Note which shell (a or b) each curve
// came from, but assign it a new ID.
curve.ReserveMore(a->curve.n + b->curve.n);
SCurve *c, cn;
SCurve cn;
for(i = 0; i < 2; i++) {
ab = (i == 0) ? a : b;
for(c = ab->curve.First(); c; c = ab->curve.NextAfter(c)) {
cn = SCurve::FromTransformationOf(c, t, q, 1.0);
for(SCurve &c : ab->curve) {
cn = SCurve::FromTransformationOf(&c, t, q, 1.0);
cn.source = (i == 0) ? SCurve::Source::A : SCurve::Source::B;
// surfA and surfB are wrong now, and we can't fix them until
// we've assigned IDs to the surfaces. So we'll get that later.
c->newH = curve.AddAndAssignId(&cn);
c.newH = curve.AddAndAssignId(&cn);
}
}
// Likewise copy over all the surfaces.
surface.ReserveMore(a->surface.n + b->surface.n);
SSurface *s, sn;
SSurface sn;
for(i = 0; i < 2; i++) {
ab = (i == 0) ? a : b;
for(s = ab->surface.First(); s; s = ab->surface.NextAfter(s)) {
sn = SSurface::FromTransformationOf(s, t, q, 1.0, /*includingTrims=*/true);
for(SSurface &s : ab->surface) {
sn = SSurface::FromTransformationOf(&s, t, q, 1.0, /*includingTrims=*/true);
// All the trim curve IDs get rewritten; we know the new handles
// to the curves since we recorded them in the previous step.
STrimBy *stb;
for(stb = sn.trim.First(); stb; stb = sn.trim.NextAfter(stb)) {
stb->curve = ab->curve.FindById(stb->curve)->newH;
}
s->newH = surface.AddAndAssignId(&sn);
s.newH = surface.AddAndAssignId(&sn);
}
}
@ -809,12 +805,11 @@ void SShell::MakeFromBoolean(SShell *a, SShell *b, SSurface::CombineAs type) {
// the surfaces in B (which is all of the intersection curves).
a->MakeIntersectionCurvesAgainst(b, this);
SCurve *sc;
for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) {
SSurface *srfA = sc->GetSurfaceA(a, b),
*srfB = sc->GetSurfaceB(a, b);
for(SCurve &sc : curve) {
SSurface *srfA = sc.GetSurfaceA(a, b),
*srfB = sc.GetSurfaceB(a, b);
sc->RemoveShortSegments(srfA, srfB);
sc.RemoveShortSegments(srfA, srfB);
}
// And clean up the piecewise linear things we made as a calculation aid

View File

@ -58,10 +58,9 @@ void SShell::MergeCoincidentSurfaces() {
// All the references to this surface get replaced with the
// new srf
SCurve *sc;
for(sc = curve.First(); sc; sc = curve.NextAfter(sc)) {
if(sc->surfA == sj->h) sc->surfA = si->h;
if(sc->surfB == sj->h) sc->surfB = si->h;
for(SCurve &sc : curve) {
if(sc.surfA == sj->h) sc.surfA = si->h;
if(sc.surfB == sj->h) sc.surfB = si->h;
}
}

View File

@ -381,9 +381,8 @@ void SShell::AllPointsIntersecting(Vector a, Vector b,
List<SInter> *il,
bool asSegment, bool trimmed, bool inclTangent)
{
SSurface *ss;
for(ss = surface.First(); ss; ss = surface.NextAfter(ss)) {
ss->AllPointsIntersecting(a, b, il,
for(SSurface &ss : surface) {
ss.AllPointsIntersecting(a, b, il,
asSegment, trimmed, inclTangent);
}
}
@ -434,11 +433,10 @@ bool SShell::ClassifyEdge(Class *indir, Class *outdir,
// First, check for edge-on-edge
int edge_inters = 0;
Vector inter_surf_n[2], inter_edge_n[2];
SSurface *srf;
for(srf = surface.First(); srf; srf = surface.NextAfter(srf)) {
if(srf->LineEntirelyOutsideBbox(ea, eb, /*asSegment=*/true)) continue;
for(SSurface &srf : surface) {
if(srf.LineEntirelyOutsideBbox(ea, eb, /*asSegment=*/true)) continue;
SEdgeList *sel = &(srf->edges);
SEdgeList *sel = &(srf.edges);
SEdge *se;
for(se = sel->l.First(); se; se = sel->l.NextAfter(se)) {
if((ea.Equals(se->a) && eb.Equals(se->b)) ||
@ -448,9 +446,9 @@ bool SShell::ClassifyEdge(Class *indir, Class *outdir,
if(edge_inters < 2) {
// Edge-on-edge case
Point2d pm;
srf->ClosestPointTo(p, &pm, /*mustConverge=*/false);
srf.ClosestPointTo(p, &pm, /*mustConverge=*/false);
// A vector normal to the surface, at the intersection point
inter_surf_n[edge_inters] = srf->NormalAt(pm);
inter_surf_n[edge_inters] = srf.NormalAt(pm);
// A vector normal to the intersecting edge (but within the
// intersecting surface) at the intersection point, pointing
// out.
@ -520,25 +518,25 @@ bool SShell::ClassifyEdge(Class *indir, Class *outdir,
// are on surface) and for numerical stability, so we don't pick up
// the additional error from the line intersection.
for(srf = surface.First(); srf; srf = surface.NextAfter(srf)) {
if(srf->LineEntirelyOutsideBbox(ea, eb, /*asSegment=*/true)) continue;
for(SSurface &srf : surface) {
if(srf.LineEntirelyOutsideBbox(ea, eb, /*asSegment=*/true)) continue;
Point2d puv;
srf->ClosestPointTo(p, &(puv.x), &(puv.y), /*mustConverge=*/false);
Vector pp = srf->PointAt(puv);
srf.ClosestPointTo(p, &(puv.x), &(puv.y), /*mustConverge=*/false);
Vector pp = srf.PointAt(puv);
if((pp.Minus(p)).Magnitude() > LENGTH_EPS) continue;
Point2d dummy = { 0, 0 };
SBspUv::Class c = (srf->bsp) ? srf->bsp->ClassifyPoint(puv, dummy, srf) : SBspUv::Class::OUTSIDE;
SBspUv::Class c = (srf.bsp) ? srf.bsp->ClassifyPoint(puv, dummy, &srf) : SBspUv::Class::OUTSIDE;
if(c == SBspUv::Class::OUTSIDE) continue;
// Edge-on-face (unless edge-on-edge above superceded)
Point2d pin, pout;
srf->ClosestPointTo(p.Plus(edge_n_in), &pin, /*mustConverge=*/false);
srf->ClosestPointTo(p.Plus(edge_n_out), &pout, /*mustConverge=*/false);
srf.ClosestPointTo(p.Plus(edge_n_in), &pin, /*mustConverge=*/false);
srf.ClosestPointTo(p.Plus(edge_n_out), &pout, /*mustConverge=*/false);
Vector surf_n_in = srf->NormalAt(pin),
surf_n_out = srf->NormalAt(pout);
Vector surf_n_in = srf.NormalAt(pin),
surf_n_out = srf.NormalAt(pout);
*indir = ClassifyRegion(edge_n_in, surf_n_in, surf_n);
*outdir = ClassifyRegion(edge_n_out, surf_n_out, surf_n);

View File

@ -1038,35 +1038,31 @@ void SShell::MakeFromTransformationOf(SShell *a,
{
booleanFailed = false;
surface.ReserveMore(a->surface.n);
SSurface *s;
for(s = a->surface.First(); s; s = a->surface.NextAfter(s)) {
for(SSurface &s : a->surface) {
SSurface n;
n = SSurface::FromTransformationOf(s, t, q, scale, /*includingTrims=*/true);
n = SSurface::FromTransformationOf(&s, t, q, scale, /*includingTrims=*/true);
surface.Add(&n); // keeping the old ID
}
curve.ReserveMore(a->curve.n);
SCurve *c;
for(c = a->curve.First(); c; c = a->curve.NextAfter(c)) {
for(SCurve &c : a->curve) {
SCurve n;
n = SCurve::FromTransformationOf(c, t, q, scale);
n = SCurve::FromTransformationOf(&c, t, q, scale);
curve.Add(&n); // keeping the old ID
}
}
void SShell::MakeEdgesInto(SEdgeList *sel) {
SSurface *s;
for(s = surface.First(); s; s = surface.NextAfter(s)) {
s->MakeEdgesInto(this, sel, SSurface::MakeAs::XYZ);
for(SSurface &s : surface) {
s.MakeEdgesInto(this, sel, SSurface::MakeAs::XYZ);
}
}
void SShell::MakeSectionEdgesInto(Vector n, double d, SEdgeList *sel, SBezierList *sbl)
{
SSurface *s;
for(s = surface.First(); s; s = surface.NextAfter(s)) {
if(s->CoincidentWithPlane(n, d)) {
s->MakeSectionEdgesInto(this, sel, sbl);
for(SSurface &s : surface) {
if(s.CoincidentWithPlane(n, d)) {
s.MakeSectionEdgesInto(this, sel, sbl);
}
}
}
@ -1088,15 +1084,13 @@ bool SShell::IsEmpty() const {
}
void SShell::Clear() {
SSurface *s;
for(s = surface.First(); s; s = surface.NextAfter(s)) {
s->Clear();
for(SSurface &s : surface) {
s.Clear();
}
surface.Clear();
SCurve *c;
for(c = curve.First(); c; c = curve.NextAfter(c)) {
c->Clear();
for(SCurve &c : curve) {
c.Clear();
}
curve.Clear();
}

View File

@ -23,20 +23,20 @@ void SSurface::AddExactIntersectionCurve(SBezier *sb, SSurface *srfB,
// Now we have to piecewise linearize the curve. If there's already an
// identical curve in the shell, then follow that pwl exactly, otherwise
// calculate from scratch.
SCurve split, *existing = NULL, *se;
SCurve split, *existing = NULL;
SBezier sbrev = *sb;
sbrev.Reverse();
bool backwards = false;
#pragma omp critical(into)
{
for(se = into->curve.First(); se; se = into->curve.NextAfter(se)) {
if(se->isExact) {
if(sb->Equals(&(se->exact))) {
existing = se;
for(SCurve &se : into->curve) {
if(se.isExact) {
if(sb->Equals(&(se.exact))) {
existing = &se;
break;
}
if(sbrev.Equals(&(se->exact))) {
existing = se;
if(sbrev.Equals(&(se.exact))) {
existing = &se;
backwards = true;
break;
}
@ -332,15 +332,14 @@ void SSurface::IntersectAgainst(SSurface *b, SShell *agnstA, SShell *agnstB,
shext = agnstA;
}
bool foundExact = false;
SCurve *sc;
for(sc = shext->curve.First(); sc; sc = shext->curve.NextAfter(sc)) {
if(sc->source == SCurve::Source::INTERSECTION) continue;
if(!sc->isExact) continue;
if((sc->surfA != sext->h) && (sc->surfB != sext->h)) continue;
for(SCurve &sc : shext->curve) {
if(sc.source == SCurve::Source::INTERSECTION) continue;
if(!sc.isExact) continue;
if((sc.surfA != sext->h) && (sc.surfB != sext->h)) continue;
// we have a curve belonging to the curved surface and not the plane.
// does it lie completely in the plane?
if(splane->ContainsPlaneCurve(sc)) {
SBezier bezier = sc->exact;
if(splane->ContainsPlaneCurve(&sc)) {
SBezier bezier = sc.exact;
AddExactIntersectionCurve(&bezier, b, agnstA, agnstB, into);
foundExact = true;
}
@ -571,10 +570,9 @@ bool SSurface::ContainsPlaneCurve(SCurve *sc) const {
void SShell::MakeCoincidentEdgesInto(SSurface *proto, bool sameNormal,
SEdgeList *el, SShell *useCurvesFrom)
{
SSurface *ss;
for(ss = surface.First(); ss; ss = surface.NextAfter(ss)) {
if(proto->CoincidentWith(ss, sameNormal)) {
ss->MakeEdgesInto(this, el, SSurface::MakeAs::XYZ, useCurvesFrom);
for(SSurface &ss : surface) {
if(proto->CoincidentWith(&ss, sameNormal)) {
ss.MakeEdgesInto(this, el, SSurface::MakeAs::XYZ, useCurvesFrom);
}
}

View File

@ -470,14 +470,13 @@ void TextWindow::ShowListOfStyles() {
Printf(true, "%Ft color style-name");
bool darkbg = false;
Style *s;
for(s = SK.style.First(); s; s = SK.style.NextAfter(s)) {
for(Style &s : SK.style) {
Printf(false, "%Bp %Bz %Bp %Fl%Ll%f%D%s%E",
darkbg ? 'd' : 'a',
&s->color,
&s.color,
darkbg ? 'd' : 'a',
ScreenShowStyleInfo, s->h.v,
s->DescriptionString().c_str());
ScreenShowStyleInfo, s.h.v,
s.DescriptionString().c_str());
darkbg = !darkbg;
}