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
@@ -16,6 +16,7 @@ from engineering.understand.network import build_network
|
||||
from engineering.understand.report import check_lang, write_workbook
|
||||
from engineering.understand.snapshot import take_snapshot
|
||||
from engineering.understand.takeoff import (
|
||||
PANEL_RULES,
|
||||
cable_rows,
|
||||
check_allowance,
|
||||
check_pipe_options,
|
||||
@@ -51,6 +52,7 @@ async def run_pipe_takeoff(
|
||||
force: bool = False,
|
||||
layers=None,
|
||||
tol: float | None = None,
|
||||
exclude_regions=None,
|
||||
) -> dict:
|
||||
"""`pipe_rows` over a P&ID and an optional layout, plus the workbook when `output` is named.
|
||||
|
||||
@@ -85,6 +87,7 @@ async def run_pipe_takeoff(
|
||||
vertical_allowance=options["vertical_allowance"],
|
||||
length_source=options["length_source"],
|
||||
force=bool(force),
|
||||
exclude_regions=tuple(exclude_regions or ()),
|
||||
)
|
||||
|
||||
result = await asyncio.to_thread(compute)
|
||||
@@ -105,15 +108,25 @@ async def run_cable_takeoff(
|
||||
lang: str = "en",
|
||||
allowance: float = 0.20,
|
||||
section_rules=None,
|
||||
panel_rule: str = "nearest",
|
||||
) -> dict:
|
||||
"""`cable_rows` over a P&ID and an optional layout, plus the workbook when `output` is named."""
|
||||
check_lang(lang)
|
||||
allowance = check_allowance(allowance)
|
||||
rules = check_section_rules(section_rules)
|
||||
if panel_rule not in PANEL_RULES:
|
||||
raise ValueError(
|
||||
f"panel_rule: {panel_rule!r} unknown; choose from {', '.join(PANEL_RULES)}"
|
||||
)
|
||||
pid = await take_snapshot(backend, pid_path)
|
||||
layout = await take_snapshot(backend, layout_path) if layout_path else None
|
||||
result = await asyncio.to_thread(
|
||||
cable_rows, pid, layout, allowance=allowance, section_rules=list(rules) or None
|
||||
cable_rows,
|
||||
pid,
|
||||
layout,
|
||||
allowance=allowance,
|
||||
section_rules=list(rules) or None,
|
||||
panel_rule=panel_rule,
|
||||
)
|
||||
result["files"] = (
|
||||
await asyncio.to_thread(write_workbook, result, kind="cable", lang=lang, path=output)
|
||||
|
||||
Reference in New Issue
Block a user