feat(understand): room frames, the nearest panel and possible packages — what the field test asked for
The takeoffs were run again on a real P&ID pair (kept outside the repository)
and compared with the hand-made workbooks. The user chose how three gaps
should close:
- Rooms drawn as frames. A room label that no wall face holds takes the
smallest closed, straight-sided polyline around it, provided it holds no
other room number and is at least ten label heights a side (label+frame,
0.8). A P&ID draws its rooms this way, so P&ID lengths are now cut at the
frames rather than sent to the nearest label. An unnumbered mention inside
a frame ('hot room') does not deny it.
- The nearest panel, flagged. cable_takeoff(panel_rule="nearest") is the
default: a load that no callout places takes the nearest panel on the
layout, among names with a panel prefix (is_panel_name: CP, JB, DB,
MCC ...) or names a callout gives. The row is flagged panel_inferred, and
an inferred panel never makes a package. panel_rule="stated" keeps the old
behaviour. The takeoff_roundtrip gate and the cable correctness check read
stated panels only: a guess is no evidence.
- Possible packages and detail copies. pipe_takeoff reports detail_copies:
compact groups of tags drawn twice (repeated), and compact groups of one
equipment's own parts, such as M150B, M150C and M150D of M150 (family). A
vendor package or an equipment detail shows up this way. Nothing is
removed until exclude_regions names a region. The runs left out go to the
control rows as excluded_region and to excluded_m. The workbook's method
sheet names the regions.
Each change has a synthetic test that failed first. Suite: 4986 passed, 1
xfailed. The inventory and the document numbers match (README: 4987
collected).
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
db5b4d3ef8
commit
554daff8d0
@@ -11149,6 +11149,14 @@ async def pipe_takeoff(
|
||||
"drawing, 0.001 on a metre one).",
|
||||
),
|
||||
] = None,
|
||||
exclude_regions: Annotated[
|
||||
list[str] | None,
|
||||
Field(
|
||||
default=None,
|
||||
description="Ids of reported detail copies (detail_copies: D1, D2 ...) whose runs "
|
||||
"repeat pipes drawn elsewhere and are left out. Omitted, every copy is counted.",
|
||||
),
|
||||
] = None,
|
||||
ctx: Context = None,
|
||||
) -> dict:
|
||||
"""A pipe takeoff: topology from the P&ID, lengths from the layout, rows by room x service x diameter.
|
||||
@@ -11201,6 +11209,7 @@ async def pipe_takeoff(
|
||||
force=force,
|
||||
layers=layers,
|
||||
tol=tol,
|
||||
exclude_regions=exclude_regions,
|
||||
)
|
||||
except (ValueError, OSError) as exc:
|
||||
raise ToolError(str(exc)) from exc
|
||||
@@ -11263,6 +11272,14 @@ async def cable_takeoff(
|
||||
"e.g. [{'max_kw': 5.5, 'section': '5x2.5'}]. Omitted, no section is proposed.",
|
||||
),
|
||||
] = None,
|
||||
panel_rule: Annotated[
|
||||
str,
|
||||
Field(
|
||||
default="nearest",
|
||||
description="A load no wiring callout places: 'nearest' takes the nearest panel on "
|
||||
"the layout and flags the row panel_inferred; 'stated' leaves it open.",
|
||||
),
|
||||
] = "nearest",
|
||||
ctx: Context = None,
|
||||
) -> dict:
|
||||
"""A cable takeoff: one row per electrical load, the shop's cable method made repeatable.
|
||||
@@ -11271,7 +11288,9 @@ async def cable_takeoff(
|
||||
texts near each tag (Russian, Turkish and English spellings). **Power is
|
||||
never invented**: a load with no stated kW keeps an empty cell and an open
|
||||
item. The panel comes from the layout's wiring callouts ('Wiring to CP1'
|
||||
and its variants, normalised to CP-1), else from the P&ID. The length is the
|
||||
and its variants, normalised to CP-1), else from the P&ID ('к CP1'); a load
|
||||
neither places takes the nearest panel on the layout, flagged
|
||||
`panel_inferred` (`panel_rule='stated'` leaves it open). The length is the
|
||||
Manhattan distance on the layout from the load's tag to its panel's tag,
|
||||
and the cable is ROUNDUP(length x (1 + allowance)) to the metre. Room and
|
||||
panel totals count known power once: a load wired to a panel that states
|
||||
@@ -11306,6 +11325,7 @@ async def cable_takeoff(
|
||||
lang=lang,
|
||||
allowance=allowance,
|
||||
section_rules=section_rules,
|
||||
panel_rule=panel_rule,
|
||||
)
|
||||
except (ValueError, OSError) as exc:
|
||||
raise ToolError(str(exc)) from exc
|
||||
|
||||
Reference in New Issue
Block a user