Files
autocad-mcp-pro/docs/superpowers/specs/2026-09-23-v1.6-arch-design.md
T
Umut CANandClaude Opus 5.5 83f192ac2f docs: track F (architectural 2D) design spec — the plan model
One plan model — a wall network with hosted openings — and one engine that
resolves L/T/X junctions, cuts openings, hatches cut walls by material and
computes rooms as the faces the walls enclose, so areas are measured, never
typed. A pure planar-face finder reads rooms from foreign plans on both
engines (the live engine has no boundary_trace). Furniture/sanitary catalogue,
grid, symbols, exterior dimension chains, schedules from the model.

12 tools (SECTION 25, pack arch), English by default with lang="tr", poché by
material, three arch_* critique focuses, benchmark arch_roundtrip.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
2026-09-23 14:40:34 +03:00

12 KiB
Raw Blame History

v1.6 Track F — architectural 2D: the plan model

Date: 2026-09-23 · Status: design approved in conversation · Parent: 2026-09-15-v1.6-roadmap-design.md (track F) · Baseline: main after tracks B + G (2bba18d, 229 tools, 4005 tests)

1. Summary

An architectural plan is not a set of lines: a door opens the wall it sits in, two walls that meet join into one clean corner, and a room's area is the floor the walls enclose — a number that must be measured, never typed. Drawing a plan from primitives gets all three wrong, silently: the door lies on top of an uncut wall, the corner overlaps, and the area in the label is whatever the model wrote.

This track applies the lesson of tracks B + G: one plan model and one engine, not a zoo of element tools. The model is a network of walls (an axis polyline, a thickness, a justification and a material) with hosted openings (doors and windows placed by distance along their wall). The engine turns it into clean wall outlines — L, T and X junctions resolved, openings cut, cut faces hatched by material — and rooms are computed as the faces the wall outlines enclose. Door, window and room schedules are read back from the model; a separate reader finds rooms in a foreign plan made of plain lines. Both run on both engines by construction: the planar-face finder is pure geometry and does not need boundary_trace, which the live engine does not have.

Around it: a furniture and sanitary block catalogue (the standard-parts pattern of track B), the structural grid, the architectural symbols and exterior dimension chains.

Tool budget: +12 → 241. New pack arch (SECTION 25). Labels and schedules speak English by default and Turkish with lang="tr" (the user's decision, 2026-09-23), including the decimal comma.

2. Scope

In: SECTION 25 Architecture (12 tools, §8), the arch ISO 13567 layer set, three arch_* critique focuses, benchmark task arch_roundtrip, correctness checks and a live COM smoke.

Out of 1.6 (recorded):

  • AutoCAD Architecture / Revit objects (AEC walls, door styles), IFC, 3D walls, generated elevations and sections — the section mark is a symbol; no view is derived from a plan.
  • Curved walls. A wall axis is a polyline of straight segments; an arc segment is refused by name rather than approximated.
  • Annotative objects (recorded in track E): text heights are computed from the plot scale instead (scale="1:50" → 2.5 mm × 50 = 125 drawing units).
  • Code compliance (fire escape widths, accessibility, national stair rules): the stair tool checks the Blondel relation and reports it; it does not claim a building code.

3. Architecture

engineering/arch/
  __init__.py
  layers.py        the `arch` ISO 13567 layer set + role → layer map
  materials.py     wall materials → ISO 128-50 area hatch (brick, aac, concrete, …)
  lang.py          EN / TR vocabulary: schedule headers, designations, area format
  model.py         Wall, Opening, Stair, Room — dataclasses, validation, ACADMCP_ARCH payload
  walls.py         the wall engine: offset outlines, junction clean-up, opening cuts, poché
  openings.py      door and window geometry (leaf, swing, frame, glazing, sill)
  stairs.py        straight / L / U stair plan symbols, the Blondel check
  faces.py         the planar-face finder: segments → closed faces (DCEL), areas
  rooms.py         room labels (measured area), the foreign-plan reader
  schedule.py      door / window / room schedules from the model
  catalogue.py     furniture + sanitary blocks as typed primitive specs (block_define)
  symbols.py       grid bubbles, north arrow, section mark, level mark
  dimension.py     exterior dimension chains (openings / walls / overall)
  draw.py          the async layer — the only module that touches a backend
  critique.py      the three arch_* critique focuses

Everything but draw.py is pure: numbers in, primitive descriptions out, using the typed primitives of engineering/mech/primitives.py (Line, Arc, Poly, HatchArea, Text, DimIntent) with the arch role → layer map. No new contract member: every tool composes the generic ones (entity_create_*, dimension_*, block_define, entity_set_xdata, entity_list), so it works on both engines as written, exactly like the mechanical tools.

The plan is written onto the drawing as ACADMCP_ARCH XDATA (the chunked codec of track B, generalised to take an application id): a wall record on each wall outline, an opening record on each opening, a room record on each label — so a schedule is a read of the drawing, and a second arch_opening call months later finds the wall it cuts.

4. The plan model

class Wall:          # frozen dataclass
    id: str
    axis: tuple[Pt, ...]          # 2+ points, straight segments, WCS
    thickness: float              # > 0
    justification: "center" | "left" | "right"   # side of the axis, looking along it
    material: str = "brick"       # → poché hatch
    closed: bool = False

class Opening:
    id: str
    wall: str                     # the Wall id it is hosted in
    kind: "door" | "window"
    offset: float                 # along the wall axis, from its start, to the opening's near jamb
    width: float
    swing: "in" | "out" = "in"    # doors
    hand: "left" | "right" = "left"
    sill: float | None = None     # windows, informational (schedule)
    height: float | None = None   # schedule
    tag: str | None = None        # D1 / W1 (EN), K1 / P1 (TR) when omitted

class Stair:
    id: str
    start: Pt; direction_deg: float; width: float
    risers: int; riser_height: float; going: float
    kind: "straight" | "l" | "u" = "straight"; turn: "left" | "right" = "left"

class Room:
    id: str; name: str; number: str | None; at: Pt   # a point inside the face
    area: float                                     # measured, written by the tool

Validation before any write (the repository rule): finite positive numbers by path (walls[2].thickness), an axis of ≥ 2 distinct points with no zero-length segment, an opening whose offset + width lies inside its wall segment and does not straddle a vertex, two openings on one wall that overlap refused with both ids, an unknown material or language refused with the list.

5. The wall engine

  • Outlines. Each segment is offset by the justification into two faces.
  • Junctions. Where segments meet — within one wall or between walls — the faces are trimmed or extended to their intersections: an L corner mitres, a T junction stops the stem's faces on the crossing wall's face, an X junction cuts all four. A junction the engine cannot resolve (a segment ending inside another wall at a shallow angle below 5°) is refused by name, not overlapped.
  • Openings. An opening removes its width from both faces of its wall and closes the two jambs; a door draws its leaf at 90° and the swing as a quarter arc on the swing side; a window draws the frame line on each face and two glazing lines between.
  • Poché. Each closed cut-face region between openings and junctions is a HatchArea with the material's ISO 128-50 pattern; poche=False draws the outlines only.
  • Honesty. Anything the engine cannot place is returned in omitted: [{element, reason}] — never silently dropped.

6. Rooms

faces.py builds a planar graph (a doubly connected edge list) from line and polyline segments: segments are split at every intersection, near-coincident endpoints are merged within a tolerance (default 1 mm), and the bounded faces are walked. A room is the face containing the label point; its area is the face's polygon area and is written into the label and the room record.

arch_rooms_detect runs the same finder on a foreign plan — any lines and polylines on the layers it is given (default: every layer whose name contains WALL or DUVAR) — and returns faces above a minimum area with their areas, centroids and a confidence (1.0 for a face enclosed only by our walls, 0.6 for plain lines), the way pid_graph does. It never modifies the drawing.

7. Schedules, symbols, catalogue, dimensions

  • arch_schedule(kind="doors"|"windows"|"rooms", at, lang) reads the ACADMCP_ARCH records and draws a real TABLE (the parts-list code of track G): doors and windows by tag with width, height, swing/hand and wall; rooms by number with name and measured area, plus the total.
  • arch_symbol(kind="north_arrow"|"section_mark"|"level"|"elevation_mark", …).
  • arch_grid(x_axes, y_axes, labels) — axis lines on the grid layer with bubbles at both ends; numbers one way and letters the other (ISO 4157-style).
  • arch_catalogue_list / arch_catalogue_insert — ~20 authored blocks in two families: furniture (bed single/double, wardrobe, sofa, armchair, dining table
    • chairs, desk, kitchen counter, fridge) and sanitary (WC, basin, shower tray, bathtub, kitchen sink). Sizes are nominal catalogue dimensions stated in the block's own data, not standards values, and the tool says so.
  • arch_dimension_chains(sides, offsets) — the three exterior chains an architectural plan carries: openings, wall segments / axes, overall.

8. Tool surface

# Tool What it does
1 arch_wall add walls to the plan network and redraw the junctions they touch
2 arch_opening host a door or a window in a wall (kind=), cutting it
3 arch_stair a straight / L / U stair in plan, with the Blondel check
4 arch_room label a room with its measured area
5 arch_rooms_detect read rooms and areas from any plan (never modifies)
6 arch_schedule door / window / room schedule table
7 arch_grid structural grid with bubbles
8 arch_symbol north arrow, section mark, level, elevation mark
9 arch_catalogue_list search the furniture / sanitary catalogue
10 arch_catalogue_insert insert a catalogue block
11 arch_dimension_chains the exterior dimension chains
12 arch_plan_from_spec walls + openings + stairs + rooms + chains + schedules in one transaction

Pack arch holds all twelve. Lean gains arch_wall, arch_opening, arch_room, arch_plan_from_spec (→ 64). drawing_apply_iso_layers("arch") applies the new layer set. Every tool has an alias record with the AutoCAD commands a drafter would reach for (WALL, DOOR, WINDOW, STAIR, BOUNDARY, AREA) and shop synonyms in both languages (duvar, kapı, pencere, merdiven, oda, alan, kat planı, vaziyet).

9. Critique focuses

  • arch_room_unlabelled — a closed face above the minimum area with no room label inside it.
  • arch_wall_gap — two wall ends within 50 mm of each other that are not joined: the room leaks and its area is wrong.
  • arch_opening_clash — two openings overlapping on one wall, or an opening that runs past its wall segment.

All three return nothing on a drawing with no ACADMCP_ARCH records.

10. Evidence

  • Benchmark arch_roundtrip (roadmap evidence for F): a two-room plan with an entrance door, an interior door, two windows and a stair drawn by arch_plan_from_spec; arch_rooms_detect reads it back and each room's area agrees with the model's within 0.1 %; the door and window schedules list the drawn tags; drawing_critique(focus=None) returns 0 issues and drawing_finalize scores ≥ 90. Matrix v6 (19 tasks).
  • Correctness checks: arch_junction_l_t_x (outline vertices of the three junction kinds against hand-computed coordinates), arch_room_area_net (a 4 × 5 m room between 200 mm walls measures 20.00 m², not the axis area), arch_opening_cuts_wall (the wall faces are interrupted across the opening), arch_rooms_detect_foreign (a plan of plain lines yields the same areas).
  • Live smoke scripts/smoke_arch_com.py on AutoCAD 2026.