Add and use IdList::IsEmpty. NFC.

Removes consuming code from the implementation details, easing swap of
the underlying container, etc.
This commit is contained in:
Ryan Pavlik 2018-01-03 15:10:18 -06:00 committed by whitequark
parent b5f36a4f01
commit 5ada4dbd9c
22 changed files with 65 additions and 49 deletions

View File

@ -287,7 +287,7 @@ void GraphicsWindow::MenuClipboard(Command id) {
}
case Command::PASTE_TRANSFORM: {
if(SS.clipboard.r.n == 0) {
if(SS.clipboard.r.IsEmpty()) {
Error(_("Clipboard is empty; nothing to paste."));
break;
}

View File

@ -329,7 +329,8 @@ Lighting GraphicsWindow::GetLighting() const {
GraphicsWindow::Selection GraphicsWindow::ChooseFromHoverToSelect() {
Selection sel = {};
if(hoverList.n == 0) return sel;
if(hoverList.IsEmpty())
return sel;
Group *activeGroup = SK.GetGroup(SS.GW.activeGroup);
int bestOrder = -1;

View File

@ -34,18 +34,18 @@ void Entity::GenerateEdges(SEdgeList *el) {
}
SBezierList *Entity::GetOrGenerateBezierCurves() {
if(beziers.l.n == 0)
if(beziers.l.IsEmpty())
GenerateBezierCurves(&beziers);
return &beziers;
}
SEdgeList *Entity::GetOrGenerateEdges() {
if(edges.l.n != 0) {
if(!edges.l.IsEmpty()) {
if(EXACT(edgesChordTol == SS.ChordTolMm()))
return &edges;
edges.l.Clear();
}
if(edges.l.n == 0)
if(edges.l.IsEmpty())
GenerateEdges(&edges);
edgesChordTol = SS.ChordTolMm();
return &edges;
@ -55,7 +55,7 @@ BBox Entity::GetOrGenerateScreenBBox(bool *hasBBox) {
SBezierList *sbl = GetOrGenerateBezierCurves();
// We don't bother with bounding boxes for workplanes, etc.
*hasBBox = (IsPoint() || IsNormal() || sbl->l.n > 0);
*hasBBox = (IsPoint() || IsNormal() || !sbl->l.IsEmpty());
if(!*hasBBox) return {};
if(screenBBoxValid)
@ -67,16 +67,14 @@ BBox Entity::GetOrGenerateScreenBBox(bool *hasBBox) {
} else if(IsNormal()) {
Vector proj = SK.GetEntity(point[0])->PointGetNum();
screenBBox = BBox::From(proj, proj);
} else if(sbl->l.n > 0) {
} else if(!sbl->l.IsEmpty()) {
Vector first = SS.GW.ProjectPoint3(sbl->l.elem[0].ctrl[0]);
screenBBox = BBox::From(first, first);
for(int i = 0; i < sbl->l.n; i++) {
SBezier *sb = &sbl->l.elem[i];
for(int i = 0; i <= sb->deg; i++) {
screenBBox.Include(SS.GW.ProjectPoint3(sb->ctrl[i]));
}
for(auto &sb : sbl->l) {
for(int i = 0; i < sb.deg; ++i) { screenBBox.Include(SS.GW.ProjectPoint3(sb.ctrl[i])); }
}
} else ssassert(false, "Expected entity to be a point or have beziers");
} else
ssassert(false, "Expected entity to be a point or have beziers");
screenBBoxValid = true;
return screenBBox;

View File

@ -325,8 +325,12 @@ public:
int n;
int elemsAllocated;
bool IsEmpty() const {
return n == 0;
}
uint32_t MaximumId() {
if(n == 0) {
if(IsEmpty()) {
return 0;
} else {
return elem[n - 1].h.v;
@ -385,6 +389,9 @@ public:
}
int IndexOf(H h) {
if(IsEmpty()) {
return -1;
}
int first = 0, last = n-1;
while(first <= last) {
int mid = (first + last)/2;
@ -401,6 +408,9 @@ public:
}
T *FindByIdNoOops(H h) {
if(IsEmpty()) {
return nullptr;
}
int first = 0, last = n-1;
while(first <= last) {
int mid = (first + last)/2;
@ -417,10 +427,10 @@ public:
}
T *First() {
return (n == 0) ? NULL : &(elem[0]);
return (IsEmpty()) ? NULL : &(elem[0]);
}
T *NextAfter(T *prev) {
if(!prev) return NULL;
if(IsEmpty() || !prev) return NULL;
if(prev - elem == (n - 1)) return NULL;
return prev + 1;
}

View File

@ -296,12 +296,13 @@ void StepFileWriter::ExportSurfacesTo(const Platform::Path &filename) {
Group *g = SK.GetGroup(SS.GW.activeGroup);
SShell *shell = &(g->runningShell);
if(shell->surface.n == 0) {
if(shell->surface.IsEmpty()) {
Error("The model does not contain any surfaces to export.%s",
g->runningMesh.l.n > 0 ?
"\n\nThe model does contain triangles from a mesh, but "
"a triangle mesh cannot be exported as a STEP file. Try "
"File -> Export Mesh... instead." : "");
!g->runningMesh.l.IsEmpty()
? "\n\nThe model does contain triangles from a mesh, but "
"a triangle mesh cannot be exported as a STEP file. Try "
"File -> Export Mesh... instead."
: "");
return;
}
@ -318,7 +319,8 @@ void StepFileWriter::ExportSurfacesTo(const Platform::Path &filename) {
SSurface *ss;
for(ss = shell->surface.First(); ss; ss = shell->surface.NextAfter(ss)) {
if(ss->trim.n == 0) continue;
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

View File

@ -549,7 +549,7 @@ bool SolveSpaceUI::LoadFromFile(const Platform::Path &filename, bool canCancel)
Error(_("Unrecognized data in file. This file may be corrupt, or "
"from a newer version of the program."));
// At least leave the program in a non-crashing state.
if(SK.group.n == 0) {
if(SK.group.IsEmpty()) {
NewFile();
}
}

View File

@ -1306,7 +1306,7 @@ void GraphicsWindow::ToggleBool(bool *v) {
// If the mesh or edges were previously hidden, they haven't been generated,
// and if we are going to show them, we need to generate them first.
Group *g = SK.GetGroup(SS.GW.activeGroup);
if(*v && (g->displayOutlines.l.n == 0 && (v == &showEdges || v == &showOutlines))) {
if(*v && (g->displayOutlines.l.IsEmpty() && (v == &showEdges || v == &showOutlines))) {
SS.GenerateAll(SolveSpaceUI::Generate::UNTIL_ACTIVE);
}

View File

@ -297,7 +297,7 @@ void Group::MenuGroup(Command id, Platform::Path linkFile) {
}
// Copy color from the previous mesh-contributing group.
if(g.IsMeshGroup() && SK.groupOrder.n > 0) {
if(g.IsMeshGroup() && !SK.groupOrder.IsEmpty()) {
Group *running = SK.GetRunningMeshGroupFor(SS.GW.activeGroup);
if(running != NULL) {
g.color = running->color;

View File

@ -466,7 +466,7 @@ void Group::GenerateDisplayItems() {
if(SS.GW.showEdges || SS.GW.showOutlines) {
SOutlineList rawOutlines = {};
if(runningMesh.l.n > 0) {
if(!runningMesh.l.IsEmpty()) {
// Triangle mesh only; no shell or emphasized edges.
runningMesh.MakeOutlinesInto(&rawOutlines, EdgeKind::EMPHASIZED);
} else {
@ -706,7 +706,8 @@ void Group::DrawPolyError(Canvas *canvas) {
void Group::DrawFilledPaths(Canvas *canvas) {
for(const SBezierLoopSet &sbls : bezierLoops.l) {
if(sbls.l.n == 0 || sbls.l.elem[0].l.n == 0) continue;
if(sbls.l.IsEmpty() || sbls.l[0].l.IsEmpty())
continue;
// In an assembled loop, all the styles should be the same; so doesn't
// matter which one we grab.
@ -740,7 +741,8 @@ void Group::DrawContourAreaLabels(Canvas *canvas) {
Vector gu = camera.projUp.ScaledBy(1 / camera.scale);
for(SBezierLoopSet &sbls : bezierLoops.l) {
if(sbls.l.n == 0 || sbls.l.elem[0].l.n == 0) continue;
if(sbls.l.IsEmpty() || sbls.l[0].l.IsEmpty())
continue;
Vector min = sbls.l.elem[0].l.elem[0].ctrl[0];
Vector max = min;

View File

@ -182,7 +182,7 @@ default: dbp("bad constraint type %d", sc->type); return;
c.other2 = (sc->other2) ? true : false;
c.Generate(&params);
if(params.n > 0) {
if(!params.IsEmpty()) {
for(Param &p : params) {
p.h = SK.param.AddAndAssignId(&p);
c.valP = p.h;

View File

@ -318,9 +318,7 @@ void SMesh::MakeFromTransformationOf(SMesh *a, Vector trans,
}
}
bool SMesh::IsEmpty() const {
return (l.n == 0);
}
bool SMesh::IsEmpty() const { return (l.IsEmpty()); }
uint32_t SMesh::FirstIntersectionWith(Point2d mp) const {
Vector rayPoint = SS.GW.UnProjectPoint3(Vector::From(mp.x, mp.y, 0.0));

View File

@ -682,7 +682,7 @@ void GraphicsWindow::SplitLinesOrCurves() {
sbla.AllIntersectionsWith(&sblb, &inters);
// If there's multiple points, then take the one closest to the mouse pointer.
if(inters.l.n > 0) {
if(!inters.l.IsEmpty()) {
double dmin = VERY_POSITIVE;
SPoint *sp;
for(sp = inters.l.First(); sp; sp = inters.l.NextAfter(sp)) {

View File

@ -755,7 +755,7 @@ void GraphicsWindow::MouseRightUp(double x, double y) {
[&]() { MenuEdit(Command::SELECT_ALL); });
}
if((SS.clipboard.r.n > 0 || SS.clipboard.c.n > 0) && LockedInWorkplane()) {
if((!SS.clipboard.r.IsEmpty() || !SS.clipboard.c.IsEmpty()) && LockedInWorkplane()) {
menu->AddItem(_("Paste"),
[&]() { MenuClipboard(Command::PASTE); });
menu->AddItem(_("Paste Transformed..."),

View File

@ -752,7 +752,8 @@ void SPolygon::FixContourDirections() {
}
bool SPolygon::IsEmpty() const {
if(l.n == 0 || l.elem[0].l.n == 0) return true;
if(l.IsEmpty() || l[0].l.IsEmpty())
return true;
return false;
}

View File

@ -255,7 +255,8 @@ void SurfaceRenderer::ConvertBeziersToEdges() {
void SurfaceRenderer::CullOccludedStrokes() {
// Perform occlusion testing, if necessary.
if(mesh.l.n == 0) return;
if(mesh.l.IsEmpty())
return;
// We can't perform hidden line removal on exact curves.
ConvertBeziersToEdges();

View File

@ -458,7 +458,8 @@ void OpenGl3Renderer::DrawEdges(const SEdgeList &el, hStroke hcs) {
}
void OpenGl3Renderer::DrawOutlines(const SOutlineList &ol, hStroke hcs, DrawOutlinesAs mode) {
if(ol.l.n == 0) return;
if(ol.l.IsEmpty())
return;
Stroke *stroke = SelectStroke(hcs);
ssassert(stroke->stipplePattern != StipplePattern::ZIGZAG &&

View File

@ -938,7 +938,7 @@ void SolveSpaceUI::ShowNakedEdges(bool reportOnlyWhenNotOkay) {
root->MakeCertainEdgesInto(&(SS.nakedEdges),
EdgeKind::NAKED_OR_SELF_INTER, /*coplanarIsInter=*/true, &inters, &leaks);
if(reportOnlyWhenNotOkay && !inters && !leaks && SS.nakedEdges.l.n == 0) {
if(reportOnlyWhenNotOkay && !inters && !leaks && SS.nakedEdges.l.IsEmpty()) {
return;
}
SS.GW.Invalidate();
@ -954,7 +954,7 @@ void SolveSpaceUI::ShowNakedEdges(bool reportOnlyWhenNotOkay) {
_("\n\nThe model contains %d triangles, from %d surfaces."),
g->displayMesh.l.n, g->runningShell.surface.n);
if(SS.nakedEdges.l.n == 0) {
if(SS.nakedEdges.l.IsEmpty()) {
Message(_("%s\n\n%s\n\nZero problematic edges, good.%s"),
intersMsg, leaksMsg, cntMsg.c_str());
} else {

View File

@ -59,7 +59,7 @@ SCurve SCurve::MakeCopySplitAgainst(SShell *agnstA, SShell *agnstB,
agnstB->AllPointsIntersecting(prev.p, p->p, &il,
/*asSegment=*/true, /*trimmed=*/false, /*inclTangent=*/true);
if(il.n > 0) {
if(!il.IsEmpty()) {
// The intersections were generated by intersecting the pwl
// edge against a surface; so they must be refined to lie
// exactly on the original curve.
@ -297,7 +297,7 @@ static void DEBUGEDGELIST(SEdgeList *sel, SSurface *surf) {
void SSurface::FindChainAvoiding(SEdgeList *src, SEdgeList *dest,
SPointList *avoid)
{
ssassert(src->l.n > 0, "Need at least one edge");
ssassert(!src->l.IsEmpty(), "Need at least one edge");
// Start with an arbitrary edge.
dest->l.Add(&(src->l.elem[0]));
src->l.ClearTags();
@ -512,7 +512,7 @@ SSurface SSurface::MakeCopyTrimAgainst(SShell *parent,
// our original and intersecting edge lists.
SEdgeList final = {};
while(orig.l.n > 0) {
while(!orig.l.IsEmpty()) {
SEdgeList chain = {};
FindChainAvoiding(&orig, &chain, &choosing);
@ -546,7 +546,7 @@ SSurface SSurface::MakeCopyTrimAgainst(SShell *parent,
chain.Clear();
}
while(inter.l.n > 0) {
while(!inter.l.IsEmpty()) {
SEdgeList chain = {};
FindChainAvoiding(&inter, &chain, &choosing);
@ -731,7 +731,7 @@ void SShell::MakeFromBoolean(SShell *a, SShell *b, SSurface::CombineAs type) {
a->MakeClassifyingBsps(this);
b->MakeClassifyingBsps(this);
if(b->surface.n == 0 || a->surface.n == 0) {
if(b->surface.IsEmpty() || a->surface.IsEmpty()) {
I = 1000000;
} else {
I = 0;

View File

@ -311,7 +311,7 @@ bool SBezierList::GetPlaneContainingBeziers(Vector *p, Vector *u, Vector *v,
int i;
// Get any point on any Bezier; or an arbitrary point if list is empty.
if(l.n > 0) {
if(!l.IsEmpty()) {
pt = l.elem[0].Start();
} else {
pt = Vector::From(0, 0, 0);
@ -402,7 +402,7 @@ SBezierLoop SBezierLoop::FromCurves(SBezierList *sbl,
sbl->l.RemoveTagged();
while(sbl->l.n > 0 && !hanging.Equals(start)) {
while(!sbl->l.IsEmpty() && !hanging.Equals(start)) {
int i;
bool foundNext = false;
for(i = 0; i < sbl->l.n; i++) {

View File

@ -17,7 +17,8 @@ void SShell::MergeCoincidentSurfaces() {
if(si->tag) continue;
// Let someone else clean up the empty surfaces; we can certainly merge
// them, but we don't know how to calculate a reasonable bounding box.
if(si->trim.n == 0) continue;
if(si->trim.IsEmpty())
continue;
// And for now we handle only coincident planes, so no sense wasting
// time on other surfaces.
if(si->degm != 1 || si->degn != 1) continue;

View File

@ -1055,7 +1055,7 @@ void SShell::TriangulateInto(SMesh *sm) {
}
bool SShell::IsEmpty() const {
return (surface.n == 0);
return surface.IsEmpty();
}
void SShell::Clear() {

View File

@ -326,7 +326,8 @@ void SSurface::IntersectAgainst(SSurface *b, SShell *agnstA, SShell *agnstB,
srfB->AllPointsIntersecting(se->a, se->b, &lsi,
/*asSegment=*/true, /*trimmed=*/true, /*inclTangent=*/false);
if(lsi.n == 0) continue;
if(lsi.IsEmpty())
continue;
// Find the other surface that this curve trims.
hSCurve hsc = { (uint32_t)se->auxA };