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
83 lines
1.7 KiB
Python
83 lines
1.7 KiB
Python
"""Architectural 2D: the plan model and the engine that draws it (track F).
|
|
|
|
Merge rule for the three track-F branches: the re-exports below are additive
|
|
and alphabetical - keep every side's names.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from .lang import LANGS, fmt_area_m2, fmt_number, tag_prefix, vocab
|
|
from .layers import ARCH_LAYER_DEFS, ARCH_LAYER_ROLES, ARCH_LAYERS, ARCH_ROLE_LAYER
|
|
from .materials import WALL_HATCH_TABLE, WALL_MATERIALS, wall_hatch
|
|
from .model import (
|
|
APP_ID,
|
|
KINDS,
|
|
Opening,
|
|
Room,
|
|
Stair,
|
|
Wall,
|
|
axis_segments,
|
|
decode,
|
|
encode,
|
|
from_payload,
|
|
opening_from_dict,
|
|
room_from_dict,
|
|
segment_of,
|
|
stair_from_dict,
|
|
to_payload,
|
|
to_values,
|
|
validate_openings,
|
|
wall_from_dict,
|
|
wall_length,
|
|
)
|
|
from .walls import (
|
|
MIN_JOIN_ANGLE_DEG,
|
|
WallGeometry,
|
|
face_offsets,
|
|
room_segments,
|
|
wall_geometry,
|
|
wall_geometry_by_wall,
|
|
wall_segments,
|
|
)
|
|
|
|
__all__ = [
|
|
"APP_ID",
|
|
"ARCH_LAYERS",
|
|
"ARCH_LAYER_DEFS",
|
|
"ARCH_LAYER_ROLES",
|
|
"ARCH_ROLE_LAYER",
|
|
"KINDS",
|
|
"LANGS",
|
|
"MIN_JOIN_ANGLE_DEG",
|
|
"Opening",
|
|
"Room",
|
|
"Stair",
|
|
"WALL_HATCH_TABLE",
|
|
"WALL_MATERIALS",
|
|
"Wall",
|
|
"WallGeometry",
|
|
"axis_segments",
|
|
"decode",
|
|
"encode",
|
|
"face_offsets",
|
|
"fmt_area_m2",
|
|
"fmt_number",
|
|
"from_payload",
|
|
"opening_from_dict",
|
|
"room_from_dict",
|
|
"room_segments",
|
|
"segment_of",
|
|
"stair_from_dict",
|
|
"tag_prefix",
|
|
"to_payload",
|
|
"to_values",
|
|
"validate_openings",
|
|
"vocab",
|
|
"wall_from_dict",
|
|
"wall_geometry",
|
|
"wall_geometry_by_wall",
|
|
"wall_hatch",
|
|
"wall_length",
|
|
"wall_segments",
|
|
]
|