liveElements function

Iterable<int> liveElements(
  1. EditMesh mesh,
  2. ElementLevel level
)

Every live element of level, each exactly once, in id order.

Lazy, so a caller that wants the first ten pays for ten. That is what describeElements's own cap does with it; a selection command that wants all of them walks all of them and allocates nothing but the ids it keeps.

Implementation

Iterable<int> liveElements(EditMesh mesh, ElementLevel level) sync* {
  switch (level) {
    case ElementLevel.vertex:
      for (var vertex = 0; vertex < mesh.vertexSlotCount; vertex++) {
        if (mesh.isVertexAlive(vertex)) yield vertex;
      }
    case ElementLevel.face:
      for (var face = 0; face < mesh.faceSlotCount; face++) {
        if (mesh.isFaceAlive(face)) yield face;
      }
    case ElementLevel.edge:
      // An edge is not stored — see `EditMesh.edgeOf`. Sweeping the live
      // faces' own half-edges and keeping only the canonical one of each
      // twinned pair visits every edge exactly once, which is the same walk
      // `selection_commands.dart`'s own `_everyEdge` does and for the same
      // reason.
      final seen = <int>{};
      for (var face = 0; face < mesh.faceSlotCount; face++) {
        if (!mesh.isFaceAlive(face)) continue;
        final List<int> halves = <int>[];
        mesh.forEachHalfEdge(face, halves.add);
        for (final int half in halves) {
          final int edge = mesh.edgeOf(half);
          if (seen.add(edge)) yield edge;
        }
      }
  }
}