feat(task-8): SECTION 25 grid and symbols - arch_grid, arch_symbol
engineering/arch/symbols.py is pure: grid_prims() draws each structural axis on the grid role - its CENTER linetype comes from the A-GRID-E-N row, no primitive sets one - with a 5 mm (paper) bubble and its label touching both ends, on the symbol role so the circle does not print dashed. Numbers run along x and letters along y (A..Z, AA, ... none skipped) unless labels names them; positions are sorted, duplicates and label-count mismatches refused by path. symbol_prims() draws the four plan symbols: the north arrow (a circle, an arrow turned CCW from +Y, the vocab(lang) north letter upright beyond the tip), the section mark (the cut line, a labelled bubble past each end and a viewing arrow at each end, p1/p2 relative to the origin), the level mark (the triangle, its line and the value formatted +3.00 / ±0.00, with a decimal comma in Turkish) and the elevation mark (a circle whose pointers are the tangents from r*sqrt(2) touching it at +/-45 degrees). An unknown kind is refused with the list, a parameter the kind does not take with the ones it does. Every size is a declared paper-mm drafting choice times the plot scale, not a standards value. arch_grid and arch_symbol draw through draw_prims with ARCH_ROLE_LAYER; alias records (COLUMNGRIDADD, English and Turkish synonyms), a regenerated inventory, the README snapshot at 233 tools and the branch-local group snapshot (entity_creation 21) complete the registration. Beyond the plan: grid_axes refuses a labels value that is not a dict and a labels.x / labels.y that is not a list (a string was split into one label per character, a number raised a bare TypeError). No new ActiveX member: a live run on AutoCAD 2026 (scratch document, closed after) drew the grid and all four symbols through draw_prims - A-GRID-E-N created with CENTER, bubbles, texts and symbols on A-SYMB-T-N, the Turkish north letter K and the level "+3,00". Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FKFStjEFzpGyLq5bMpWxTd
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
afd42356b5
commit
f5f11178a9
@@ -9781,7 +9781,7 @@ async def drawing_export_dwg(
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ── SECTION 25: Architecture (2 tools) ──────────────────────────────────────
|
||||
# ── SECTION 25: Architecture (4 tools) ──────────────────────────────────────
|
||||
# ---------------------------------------------------------------------------
|
||||
# ── arch: catalogue (group C) ──
|
||||
|
||||
@@ -9888,6 +9888,139 @@ async def arch_catalogue_insert(
|
||||
raise ToolError(str(exc)) from exc
|
||||
|
||||
|
||||
@cad_tool(
|
||||
summary="Draw a structural grid: axis lines with numbered and lettered bubbles at both ends.",
|
||||
cost="mutate",
|
||||
)
|
||||
@mcp.tool(
|
||||
annotations={"title": "Architecture: Structural Grid", "destructiveHint": False},
|
||||
tags={"arch", "create"},
|
||||
)
|
||||
async def arch_grid(
|
||||
x_axes: Annotated[
|
||||
list[float],
|
||||
Field(description="X positions (WCS) of the vertical axes; numbered 1, 2, 3 left to right"),
|
||||
],
|
||||
y_axes: Annotated[
|
||||
list[float],
|
||||
Field(
|
||||
description="Y positions (WCS) of the horizontal axes; lettered A, B, C bottom to top"
|
||||
),
|
||||
],
|
||||
labels: Annotated[
|
||||
dict | None,
|
||||
Field(
|
||||
default=None,
|
||||
description=(
|
||||
"Override the labels: {'x': [...], 'y': [...]} (either key), one label per "
|
||||
"position in the order the positions were given"
|
||||
),
|
||||
),
|
||||
] = None,
|
||||
extension: Annotated[
|
||||
float,
|
||||
Field(
|
||||
default=1500.0,
|
||||
gt=0,
|
||||
description="Drawing units each axis runs past the outermost crossing axis",
|
||||
),
|
||||
] = 1500.0,
|
||||
scale: Annotated[
|
||||
float,
|
||||
Field(
|
||||
default=50.0,
|
||||
gt=0,
|
||||
description="Plot-scale denominator (50 = 1:50): bubbles and labels are paper mm x scale",
|
||||
),
|
||||
] = 50.0,
|
||||
ctx: Context = None,
|
||||
) -> dict:
|
||||
"""Axis lines on the arch grid layer (its CENTER linetype comes from the layer) and a
|
||||
5 mm bubble with its label at both ends of each axis, on the symbol layer.
|
||||
|
||||
Numbers run along x and letters along y (A..Z, then AA, AB - no letter is
|
||||
skipped) unless `labels` names them. The bubble and label sizes are this
|
||||
server's declared drafting sizes in paper millimetres, not a standards value.
|
||||
Refusals, all before any write: an empty axis list in either direction, a
|
||||
non-finite or duplicate position, a label list whose length does not match
|
||||
its positions, a duplicate or empty label, an unknown `labels` key, and a
|
||||
non-positive `extension` or `scale`.
|
||||
"""
|
||||
from engineering.arch.symbols import draw_grid
|
||||
|
||||
await ctx.info(f"arch grid: {len(x_axes)} x {len(y_axes)} axes at 1:{scale:g}")
|
||||
try:
|
||||
return await draw_grid(
|
||||
_backend(ctx), x_axes, y_axes, labels=labels, extension=extension, scale=scale
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise ToolError(str(exc)) from exc
|
||||
|
||||
|
||||
@cad_tool(
|
||||
summary="Draw a plan symbol: north arrow, section mark, level mark or elevation mark.",
|
||||
cost="mutate",
|
||||
)
|
||||
@mcp.tool(
|
||||
annotations={"title": "Architecture: Symbol", "destructiveHint": False},
|
||||
tags={"arch", "create"},
|
||||
)
|
||||
async def arch_symbol(
|
||||
kind: Annotated[
|
||||
str,
|
||||
Field(description="north_arrow | section_mark | level | elevation_mark"),
|
||||
],
|
||||
x: Annotated[float, Field(description="Symbol origin X (WCS)")],
|
||||
y: Annotated[float, Field(description="Symbol origin Y (WCS)")],
|
||||
params: Annotated[
|
||||
dict | None,
|
||||
Field(
|
||||
default=None,
|
||||
description=(
|
||||
"north_arrow: {rotation} (degrees CCW from +Y; 0 = north up). "
|
||||
"section_mark: {p1, p2, label, side} - p1/p2 are [x, y] relative to (x, y), "
|
||||
"side left|right is where the section looks, seen from p1 towards p2. "
|
||||
"level: {value} in metres (0 -> '±0.00'). "
|
||||
"elevation_mark: {label, directions} - directions from up|right|down|left"
|
||||
),
|
||||
),
|
||||
] = None,
|
||||
lang: Annotated[
|
||||
str,
|
||||
Field(default="en", description="en | tr - the north letter and the decimal separator"),
|
||||
] = "en",
|
||||
scale: Annotated[
|
||||
float,
|
||||
Field(
|
||||
default=50.0,
|
||||
gt=0,
|
||||
description="Plot-scale denominator (50 = 1:50): symbol sizes are paper mm x scale",
|
||||
),
|
||||
] = 50.0,
|
||||
ctx: Context = None,
|
||||
) -> dict:
|
||||
"""Draw one architectural symbol on the arch symbol layer.
|
||||
|
||||
Sizes are this server's declared drafting sizes in paper millimetres times
|
||||
`scale` (a 16 mm north-arrow circle, 10 mm section and elevation bubbles),
|
||||
not standards values. Refusals, all before any write: an unknown `kind`
|
||||
(with the list), a parameter the kind does not take (with the ones it
|
||||
does), a section mark without p1/p2, with an empty label, an unknown side
|
||||
or a cut line too short for its two arrows, an elevation direction outside
|
||||
up/right/down/left or named twice, a non-finite level value, and a `lang`
|
||||
other than en/tr.
|
||||
"""
|
||||
from engineering.arch.symbols import draw_symbol
|
||||
|
||||
await ctx.info(f"arch symbol: {kind} at ({x}, {y})")
|
||||
try:
|
||||
return await draw_symbol(
|
||||
_backend(ctx), kind, (x, y), lang=lang, scale=scale, **(params or {})
|
||||
)
|
||||
except (TypeError, ValueError) as exc:
|
||||
raise ToolError(str(exc)) from exc
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ── RESOURCES ───────────────────────────────────────────────────────────────
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user