discontinuedPackage jet_cad_floor_plan has been discontinued and replaced by jet_cad_2d_plan.

outline function

({bool fellBack, List<Handle>? hole, List<Vector2> ring}) outline(
  1. WorldWall w,
  2. List<WorldWall> others, {
  3. bool fallback = true,
})

A wall's world outline: an anticlockwise ring, end cap then start cap (spec 07 D5, D6).

  • ring is empty for a degenerate wall (D2).
  • fellBack is true when the joined ring was not simple and anticlockwise, so this wall alone squared both ends at its own endpoints (D6's short wall). Its neighbours are unaffected: squaring them too would make them depend on each other through this wall, a two-hop dependency 06's closure does not regenerate.
  • hole lists the node's member walls (Ruling 07-3), ascending, when a crossing lobe of positive area was dropped at one of this wall's ends and this wall owns that lobe (D5.6, D12: reported once, by the owner). If both ends own one, it lists both nodes' members, ascending, once each.

The ring is simplified (D6): exact consecutive duplicates and zero-width spikes, which do occur (a closing duplicate at some right-angle Ls of round sizes), are removed. No measured triangulation outcome has depended on it, since lobes split at exactly repeated vertices and the triangulator tolerates consecutive duplicates; it stays as D6's guard.

fallback false returns the joined ring even when it is not simple — a measurement hook, never used to store an outline.

Implementation

({List<Vector2> ring, bool fellBack, List<Handle>? hole}) outline(
    WorldWall w, List<WorldWall> others,
    {bool fallback = true}) {
  if (w.degenerate) {
    return (ring: const <Vector2>[], fellBack: false, hole: null);
  }
  final je = classify(w, 1, others), js = classify(w, 0, others);
  final ce = cap(End(w, 1), je), cs = cap(End(w, 0), js);
  final owned = <int>{
    if (ce.ownsHole)
      for (final h in (je as NodeJoint).members) h.value,
    if (cs.ownsHole)
      for (final h in (js as NodeJoint).members) h.value,
  }.toList()
    ..sort();
  final hole = owned.isEmpty ? null : [for (final h in owned) Handle(h)];
  final ring = simplifyRing([...ce.points, ...cs.points]);
  if (fallback && !isSimpleCcw(ring)) {
    return (
      ring: [
        ...cap(End(w, 1), const Free()).points,
        ...cap(End(w, 0), const Free()).points,
      ],
      fellBack: true,
      hole: hole,
    );
  }
  return (ring: ring, fellBack: false, hole: hole);
}