Give each TRO type its own CAD symbol and add a TROEDIT dialog
Replaces the generic marker with one shape per type, so the types are distinguishable in the drawing without relying on colour. The shape belongs to the type, so it sits in tro_catalog next to the colour - colour groups (6 groups), shape identifies (10 types): 1Sep circle 1Sep1Swi triangle 1Sep2Swi pentagon 1Sep_SSCC 2 circles Vario rectangle Vario_workStation hexagon PinStore_Auto square EmptyCarrBuffer diamond LoadingBoom arrow 2Sep1Swi triangle down The visible attributes are now ID and TYPE, as those are what the dialog edits; FB_BLOCK stays visible under --fb and ITEMS/CONFIDENCE/SEPARATORS stay hidden data. Note this renames the former TRO_ID/TRO_TYPE tags, so drawings annotated with an earlier version need regenerating. Marker layers now take the *stroke* colour instead of the fill. A CAD symbol is line work, and the pastel fills of the palette were nearly invisible as lines - LoadingBoom in particular came out almost white on white. cad/tro_edit.dcl and cad/tro_edit.lsp add the TROEDIT command: pick a TRO_SYM_* block, edit ID and TYPE, write back on OK. TYPE is a picklist rather than free text so it cannot drift from the catalogue; the list comes from cad/tro_types.lsp, which "tro_annotate.py --emit-lisp" generates from TRO_CATALOG. If that file is missing the dialog degrades to the block's current type instead of failing. The dialog deliberately changes attributes only. The marker shape belongs to the block definition of the type and FB_BLOCK is derived from it, so both follow on the next annotation run - the dialog says so, and TROEDIT prints a reminder when the type was changed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+61
-13
@@ -8,14 +8,15 @@ Dieses Modul ist die **einzige** Quelle fuer alles, was zur Erzeugung eines TRO
|
||||
gebraucht wird. Es liest keine Dateien und braucht kein Markdown zur Laufzeit -
|
||||
die Herkunft der Daten steht nur noch in den Kommentaren.
|
||||
|
||||
Ein TRO-Typ wird durch vier Dinge beschrieben:
|
||||
Ein TRO-Typ wird durch fuenf Dinge beschrieben:
|
||||
|
||||
1. Name - Kurztyp, wie in FB_Main und connect.ini verwendet ("1Sep")
|
||||
2. FB-Baustein - der Siemens-Funktionsbaustein ("FB_ILS_MTRO_1Sep")
|
||||
3. Bauteile - welche Elemente in diesem TRO stecken und wie viele
|
||||
(1Sep = 1x Separator, 1Sep1Swi = 1x Separator + 1x Weiche)
|
||||
4. Darstellung - Farbe/Gruppe fuer Zeichnungen (Graphviz, Mermaid, spaeter
|
||||
das BricsCAD-Symbol)
|
||||
4. Farbe - Farbgruppe fuer Zeichnungen (Graphviz, Mermaid, CAD)
|
||||
5. Symbol - Form des CAD-Markers, je Typ eine eigene (Kreis, Dreieck,
|
||||
Rechteck, Raute ...)
|
||||
|
||||
Herkunft der Daten (Stand :data:`CATALOG_AS_OF`)
|
||||
-----------------------------------------------
|
||||
@@ -66,6 +67,7 @@ __all__ = [
|
||||
"CATALOG_AS_OF",
|
||||
"TroItem",
|
||||
"TroStyle",
|
||||
"TroSymbol",
|
||||
"TroDefinition",
|
||||
"ITEM_FB",
|
||||
"STYLES",
|
||||
@@ -130,6 +132,36 @@ ITEM_FB: dict[str, str] = {
|
||||
}
|
||||
|
||||
|
||||
class TroSymbol:
|
||||
"""
|
||||
Zeichensymbole fuer die Marker in der Zeichnung.
|
||||
|
||||
Die Farbe gruppiert (siehe TroStyle), das Symbol unterscheidet den einzelnen
|
||||
Typ. Alle TROs eines Typs bekommen dasselbe Symbol. Die Formen sind absichtlich
|
||||
einfach - Kreis, Vielecke, Rechteck - damit sie in jedem Zoom erkennbar
|
||||
bleiben und als LWPOLYLINE bzw. CIRCLE in den Block passen.
|
||||
"""
|
||||
|
||||
CIRCLE = "circle" # Kreis
|
||||
DOUBLE_CIRCLE = "double_circle" # Kreis mit zweitem Kreis innen
|
||||
TRIANGLE = "triangle" # Dreieck, Spitze oben
|
||||
TRIANGLE_DOWN = "triangle_down" # Dreieck, Spitze unten
|
||||
SQUARE = "square" # Quadrat
|
||||
DIAMOND = "diamond" # Raute
|
||||
PENTAGON = "pentagon" # Fuenfeck
|
||||
HEXAGON = "hexagon" # Sechseck
|
||||
RECT = "rect" # liegendes Rechteck
|
||||
ARROW = "arrow" # Pfeil/Fahne
|
||||
|
||||
@classmethod
|
||||
def all(cls) -> tuple[str, ...]:
|
||||
return tuple(
|
||||
value
|
||||
for key, value in vars(cls).items()
|
||||
if key.isupper() and isinstance(value, str)
|
||||
)
|
||||
|
||||
|
||||
class TroStyle(BaseModel):
|
||||
"""
|
||||
Darstellung einer TRO-Typgruppe.
|
||||
@@ -247,6 +279,11 @@ class TroDefinition(BaseModel):
|
||||
default=STYLE_EXT,
|
||||
description="Farbgruppe fuer Zeichnungen (Graphviz, Mermaid, CAD-Symbol)",
|
||||
)
|
||||
symbol: str = Field(
|
||||
default=TroSymbol.CIRCLE,
|
||||
min_length=1,
|
||||
description="Zeichensymbol des Markers im CAD, z. B. 'triangle'",
|
||||
)
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -254,6 +291,7 @@ class TroDefinition(BaseModel):
|
||||
fb_block: str | None = None,
|
||||
items: dict[str, int] | None = None,
|
||||
style: TroStyle | None = None,
|
||||
symbol: str | None = None,
|
||||
**data,
|
||||
) -> None:
|
||||
# Positionsargumente auf Feldnamen abbilden, damit die bisherige
|
||||
@@ -266,6 +304,8 @@ class TroDefinition(BaseModel):
|
||||
data["items"] = items
|
||||
if style is not None:
|
||||
data["style"] = style
|
||||
if symbol is not None:
|
||||
data["symbol"] = symbol
|
||||
super().__init__(**data)
|
||||
|
||||
@field_validator("items", mode="after")
|
||||
@@ -319,6 +359,10 @@ class TroDefinition(BaseModel):
|
||||
"""Darstellung (Farbgruppe) dieses Typs."""
|
||||
return self.style
|
||||
|
||||
def get_symbol(self) -> str:
|
||||
"""Zeichensymbol des Markers, z. B. 'triangle'."""
|
||||
return self.symbol
|
||||
|
||||
def get_group(self) -> str:
|
||||
"""Kurzname der Farbgruppe, z. B. 'vario'."""
|
||||
return self.style.group
|
||||
@@ -348,6 +392,10 @@ class TroDefinition(BaseModel):
|
||||
"""Darstellung (Farbgruppe) setzen."""
|
||||
self.style = style
|
||||
|
||||
def set_symbol(self, symbol: str) -> None:
|
||||
"""Zeichensymbol des Markers setzen."""
|
||||
self.symbol = symbol
|
||||
|
||||
def set_item(self, item: str, count: int) -> None:
|
||||
"""
|
||||
Anzahl einer Bauteilart setzen.
|
||||
@@ -394,29 +442,29 @@ TRO_CATALOG: tuple[TroDefinition, ...] = (
|
||||
# (PriorityManager, JamArea Entry/Exit, HMI, Safety, MachineState).
|
||||
TroDefinition("1Sep", "FB_ILS_MTRO_1Sep", {
|
||||
TroItem.SEPARATOR: 1,
|
||||
}, STYLE_SEP),
|
||||
}, STYLE_SEP, TroSymbol.CIRCLE),
|
||||
# laut TRO_Typen.md: Basis + 1x Switch-Modul
|
||||
TroDefinition("1Sep1Swi", "FB_ILS_MTRO_1Sep1Swi", {
|
||||
TroItem.SEPARATOR: 1,
|
||||
TroItem.SWITCH: 1,
|
||||
}, STYLE_SWI),
|
||||
}, STYLE_SWI, TroSymbol.TRIANGLE),
|
||||
# laut TRO_Typen.md: Basis + 2x Switch-Modul + Scanner-Modul
|
||||
TroDefinition("1Sep2Swi", "FB_ILS_MTRO_1Sep2Swi", {
|
||||
TroItem.SEPARATOR: 1,
|
||||
TroItem.SWITCH: 2,
|
||||
TroItem.SCANNER: 1,
|
||||
}, STYLE_SWI),
|
||||
}, STYLE_SWI, TroSymbol.PENTAGON),
|
||||
# laut TRO_Typen.md: Basis + Scanner-Modul + SSCC-Modul (Messsensor + WCS)
|
||||
TroDefinition("1Sep_SSCC", "FB_ILS_MTRO_1Sep_SSCC", {
|
||||
TroItem.SEPARATOR: 1,
|
||||
TroItem.SCANNER: 1,
|
||||
TroItem.SSCC: 1,
|
||||
}, STYLE_SSCC),
|
||||
}, STYLE_SSCC, TroSymbol.DOUBLE_CIRCLE),
|
||||
# laut TRO_Typen.md: Basis + Vario-Antriebsmodul
|
||||
TroDefinition("Vario", "FB_ILS_MTRO_Vario", {
|
||||
TroItem.SEPARATOR: 1,
|
||||
TroItem.VARIO_DRIVE: 1,
|
||||
}, STYLE_VARIO),
|
||||
}, STYLE_VARIO, TroSymbol.RECT),
|
||||
# laut TRO_Typen.md: Basis (Pin-Separator) + 19x Storage-Line + Scanner
|
||||
# + Encoder + StorageRemoval-Schnittstelle
|
||||
TroDefinition("PinStore_Auto", "FB_ILS_MTRO_PinStore_Auto", {
|
||||
@@ -424,7 +472,7 @@ TRO_CATALOG: tuple[TroDefinition, ...] = (
|
||||
TroItem.STORAGE_LINE: 19,
|
||||
TroItem.SCANNER: 1,
|
||||
TroItem.ENCODER: 1,
|
||||
}, STYLE_STORE),
|
||||
}, STYLE_STORE, TroSymbol.SQUARE),
|
||||
# aus SCL belegt (FB_ILS_MTRO_Vario_workStation.scl, VAR ab Zeile 77):
|
||||
# fbSeparator1, fbConvVario, fbSepWait, fbBarcodeReader.
|
||||
# Der Vario-Antrieb ist hier die WorkStation-Variante des STRO-Bausteins.
|
||||
@@ -434,7 +482,7 @@ TRO_CATALOG: tuple[TroDefinition, ...] = (
|
||||
TroItem.WORK_STATION: 1,
|
||||
TroItem.ACCUMULATE: 1,
|
||||
TroItem.SCANNER: 1,
|
||||
}, STYLE_VARIO),
|
||||
}, STYLE_VARIO, TroSymbol.HEXAGON),
|
||||
# aus SCL belegt (FB_EmptyCarrBuffer.scl): arfbSeparatorStorage als
|
||||
# Array[1..5] of FB_ILS_STRO_Sep + 5x fbCarrierWaitStore.
|
||||
# Kein eigener Eingangs-Separator - der "inTro" ist ein separater 1Sep-TRO
|
||||
@@ -442,7 +490,7 @@ TRO_CATALOG: tuple[TroDefinition, ...] = (
|
||||
TroDefinition("EmptyCarrBuffer", "FB_EmptyCarrBuffer", {
|
||||
TroItem.STORAGE_LINE: 5,
|
||||
TroItem.ACCUMULATE: 5,
|
||||
}, STYLE_STORE),
|
||||
}, STYLE_STORE, TroSymbol.DIAMOND),
|
||||
# aus SCL belegt (FB_LoadingBoom_INBOUND.scl): fbTiltSensor,
|
||||
# fbDistanceFoot, fbWorkSation. Bewusst KEIN Separator und KEINE Weiche -
|
||||
# der einzige nicht additive Typ.
|
||||
@@ -450,7 +498,7 @@ TRO_CATALOG: tuple[TroDefinition, ...] = (
|
||||
TroItem.BOOM: 1,
|
||||
TroItem.FOOT: 1,
|
||||
TroItem.TILT_SENSOR: 1,
|
||||
}, STYLE_EXT),
|
||||
}, STYLE_EXT, TroSymbol.ARROW),
|
||||
# aus SCL belegt (FB_ILS_MTRO_2Sep1Swi.scl, VAR ab Zeile 115):
|
||||
# fbSeparator1, fbSeparator2, fbSwitch1, fbBarcodeReader1, fbBarcodeReader2.
|
||||
# Die Mapping-Tabelle in TRO_Typen.md nennt die beiden Scanner nicht -
|
||||
@@ -459,7 +507,7 @@ TRO_CATALOG: tuple[TroDefinition, ...] = (
|
||||
TroItem.SEPARATOR: 2,
|
||||
TroItem.SWITCH: 1,
|
||||
TroItem.SCANNER: 2,
|
||||
}, STYLE_SWI),
|
||||
}, STYLE_SWI, TroSymbol.TRIANGLE_DOWN),
|
||||
)
|
||||
|
||||
_BY_NAME: dict[str, TroDefinition] = {t.get_name(): t for t in TRO_CATALOG}
|
||||
|
||||
Reference in New Issue
Block a user