discontinuedPackage jet_cad_floor_plan has been discontinued and replaced by jet_cad_2d_plan.

traceRoomAmong function

TraceResult traceRoomAmong(
  1. Vector2 seed,
  2. PlaceSource source
)

The room around seed among every contributor source holds, tracing only those near its face (spec 10 D7). The result is, bit for bit, traceRoom(seed, every input) (LZ1):

  1. Growth. Trace among placedIn(B), B = seed ⊕ r, from r = kGrowthStart. SeedInWall is final: the wall holding the seed touches B. Unbounded: double r and repeat until B contains U (PlaceSource.bounds); then Unbounded is final. With nothing placed at all, Unbounded at once.
  2. Certificate. On Traced(F), C = placedIn(box(F) ⊕ m), m = kCertificateMargin. While C holds a contributor not yet traced, add it and trace again. The face can only shrink or gain holes, so one round always suffices; the loop's exit is the certificate itself.
  3. Canonical trace. The trace among exactly C: a function of C and the seed only, whatever growth rounds led there (D16's no-drift proof needs this). When the last trace was already among exactly C, it is that trace: the same inputs give the same bits.

Why exact: every contributor outside C is disjoint from the closed face grown by m, and so changes nothing inside it.

A seed with a non-finite coordinate is Unbounded: no box around it ever contains U.

Implementation

TraceResult traceRoomAmong(Vector2 seed, PlaceSource source) {
  final u = source.bounds;
  if (u == null || !seed.x.isFinite || !seed.y.isFinite) {
    return const Unbounded();
  }
  List<RoomInput> inputsOf(Iterable<Handle> hs) => [
        for (final h in hs)
          if (source.inputOf(h) case final input?) input,
      ];

  // 1. Growth.
  var r = kGrowthStart;
  List<Handle> traced;
  Traced face;
  while (true) {
    final b = Aabb2.raw(seed.x - r, seed.y - r, seed.x + r, seed.y + r);
    traced = source.placedIn(b);
    final result = traceRoom(seed, inputsOf(traced));
    if (result is Traced) {
      face = result;
      break;
    }
    if (result is SeedInWall || _holds(b, u)) return result;
    r *= 2;
  }

  // 2. The certificate.
  Aabb2 grown(Traced f) =>
      Aabb2.fromPoints(f.ring).expandedBy(kCertificateMargin);
  final set = {...traced};
  var c = source.placedIn(grown(face));
  while (!c.every(set.contains)) {
    set.addAll(c);
    traced = [...set]..sort((a, b) => a.value.compareTo(b.value));
    final result = traceRoom(seed, inputsOf(traced));
    // Unreachable (D7: more inputs only shrink the face, and the wall
    // holding the seed would have touched B), but never a wrong answer.
    if (result is! Traced) return result;
    face = result;
    c = source.placedIn(grown(face));
  }

  // 3. The canonical trace, among exactly C.
  if (_sameHandles(traced, c)) return face;
  return traceRoom(seed, inputsOf(c));
}