fix(understand): a network layer holds lines — valve, pump and annotation layers are no pipes
The field test ran the takeoffs on a real P&ID pair, kept outside the repository. It showed that the default network layers took every layer the vocabulary files under piping or electrical. That included the valve layers (KLEPPEN, Valve_*), the pump layers (a "product pumps" layer reads as product), and annotation layers such as pipe sizes, materials and valve numbers. Symbol outlines and leader lines became pipe runs. vocab.is_network_layer is now the one rule. A layer is a network layer when it is piping or electrical at 0.9, its name names no equipment (equipment_kind: valve, pump, tank, motor, panel, reducer), and it names no annotation (sizes, materials, numbers, hatching, or an annotation word). build_network's default layers, drawing_topology_check and the topo_* focuses all use it, so they agree on which lines are the network. Sixteen parametrized cases pin it, across symbol, annotation, pipe and cable layers. 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
ba41428c88
commit
307ccc799f
@@ -32,6 +32,7 @@ __all__ = [
|
||||
"classify_layer",
|
||||
"equipment_kind",
|
||||
"fold",
|
||||
"is_network_layer",
|
||||
"room_label",
|
||||
"supply_return",
|
||||
]
|
||||
@@ -438,6 +439,43 @@ def room_label(text: str | None) -> dict | None:
|
||||
return None
|
||||
|
||||
|
||||
#: Words that make a piping or electrical layer hold annotation, not lines: pipe
|
||||
#: sizes, materials, valve or line numbers, hatching. Matched like every other
|
||||
#: keyword here (a word of five letters or more anywhere in the name).
|
||||
_NOT_A_LINE_WORDS = (
|
||||
("annotation", "diameter", "en"),
|
||||
("annotation", "sizes", "en"),
|
||||
("annotation", "size", "en"),
|
||||
("annotation", "material", "en"),
|
||||
("annotation", "number", "en"),
|
||||
("annotation", "nummer", "nl"),
|
||||
("annotation", "arcering", "nl"),
|
||||
("annotation", "hatch", "en"),
|
||||
)
|
||||
|
||||
|
||||
def is_network_layer(name: str | None) -> bool:
|
||||
"""A layer whose lines are pipes or cables.
|
||||
|
||||
`classify_layer` files it under piping or electrical at 0.9, and its name
|
||||
says neither that it holds symbols - a valve, pump, tank, motor, panel or
|
||||
reducer (`equipment_kind`), whose outlines are no pipe - nor that it holds
|
||||
annotation: sizes, materials, numbers, hatching, or an annotation word.
|
||||
Field P&IDs keep valves and pumps on their own layers (``KLEPPEN``,
|
||||
``PRODUCT PUMPS``) that a service keyword alone would read as piping.
|
||||
"""
|
||||
meaning = classify_layer(name)
|
||||
if meaning["discipline"] not in ("piping", "electrical") or meaning["confidence"] < DIRECT:
|
||||
return False
|
||||
if equipment_kind(name) is not None:
|
||||
return False
|
||||
folded = fold(name)
|
||||
if _first(_NOT_A_LINE_WORDS, folded) is not None:
|
||||
return False
|
||||
annotation = [row for row in _DISCIPLINE_WORDS if row[0] == "annotation"]
|
||||
return _first(annotation, folded) is None
|
||||
|
||||
|
||||
def equipment_kind(block_name: str | None) -> dict | None:
|
||||
"""The kind of equipment a block name says it is: ``{"kind", "keyword", "language"}``.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user