A T recorded its cut on the crossing segment as a distance from that
segment's start; when the start was carried onto a third wall later in the
same pass the cut went stale, so [c,b,a] drew a free-end jamb inside wall a,
an uncut face and a double-hatched overlap where [c,a,b] was right. Cuts are
now stored as points and measured against the final axis.
A near-straight join whose faces are offset (a thickness or justification
change, or a rounding kink between such walls) mitred at offset/sin(kink):
faces 1e8 mm long and a clockwise region for a 0.01 mm rounding. A
straight-through pair whose mitre lies more than _MITRE_REACH (2) thicknesses
from the node now steps on the line bisecting the join - both sides of a
two-end node together, so the pieces tile without a sliver - and every piece
and hub ring is refused unless counter-clockwise, not only when it crosses
itself.
Pure geometry: no ActiveX member is touched, so no live probe applies.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
engineering/arch/walls.py turns a wall network - axis polylines with a
thickness, a justification and a material - into clean outlines. One rule
resolves every junction: at each node the segment ends are sorted by angle and
the left face of each meets the right face of the next one counter-clockwise.
That mitres an L, stops a T's stem on the crossing wall's near face (cut there,
while the far face stays one line) and cuts all four faces of an X. A T is an
axis end lying inside another wall: it is carried onto the crossing axis and
the crossing segment is split. The hub a three- or four-way node leaves is a
region of its own, so the poche has no hole.
Openings remove their width from both faces and are closed by jambs; a free
end is closed by a jamb. Each solid piece is one CCW region and one HatchArea
in the wall's material. The two face lines across each opening are kept as
thresholds - never drawn - so room_segments hands the face finder closed rooms
instead of rooms merged through their doorways.
Refused by name before any geometry: a duplicate id, an unknown material or
justification, a zero-length segment, a junction below 5 degrees, a corner
inside another wall off its axis, an end whose axis meets the other wall past
its end, a segment lying wholly inside the wall it joins, and one too short
for its junctions (engineering.measure.is_self_intersecting on its outline).
An opening that runs into a junction is returned in omitted, never dropped.
Every corner in the tests is hand-computed: two 200 mm walls at the origin
meet at (100, 100) inside and (-100, -100) outside.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd