b9a2124026
[EBENEN] → [LAYERS], [EBENEN-BE] → [LAYERS-BE] [ZEICHNUNGSEBENEN] → [DRAWING-LEVELS] [GESTALTUNG] → [STYLES] [OBERLEISTE] → [TOOLBAR] [WERKZEUGE] → [TOOLS] [DIMENSIONEN] → [DIMENSIONS] [AUSSCHNITTE] → [VIEWPORTS] [MASSSTAB] → [SCALE] [SCHNITT] → [SECTION], [SCHNITT_GRIPS] → [SECTION-GRIPS] [WAND_GRIPS] → [WALL-GRIPS], [TREPPE_GRIPS] → [STAIR-GRIPS] [CURVE_DOTS] → [CURVE-DOTS] [panel_base] → [CORE] [ALIAS-LOADER] → [ALIASES] [BEGIN-CMD] → [CMD-HOOK]
119 lines
4.5 KiB
Python
119 lines
4.5 KiB
Python
#! python3
|
|
# -*- coding: utf-8 -*-
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
# Copyright (C) 2026 Karim Gabriele Varano
|
|
"""
|
|
treppe_grips.py
|
|
Display-Conduit fuer gruene Marker an Treppen-Achsen. Visuelle
|
|
Indikation wie bei Waenden, aber keine eigene Drag-Logik — der normale
|
|
Partnership-Cascade (elemente._on_select_objects) + Pure-Transform-Pfad
|
|
verschieben die Treppe bereits sauber.
|
|
|
|
Marker-Logik pro Treppen-Art:
|
|
- gerade : PointAtStart, PointAtEnd der Linie
|
|
- L (3-Pt): poly[0] (Start), poly[1] (Eck), poly[2] (Ende) — alle 3
|
|
damit das Eck einzeln gegriffen werden kann
|
|
- L (4-Pt): alle 4 Punkte (Start, Lauf1-Ende, Lauf2-Anfang, Ende)
|
|
- Wendel : poly[1] (Start), poly[2] (Ende) — poly[0] ist Rotations-
|
|
zentrum, nicht der Treppen-Anfang
|
|
"""
|
|
import Rhino
|
|
import Rhino.Display as rd
|
|
import Rhino.DocObjects as rdoc
|
|
import Rhino.Geometry as rg
|
|
import scriptcontext as sc
|
|
import System.Drawing as SD
|
|
|
|
|
|
_MARKER_RADIUS_PX = 7
|
|
_MARKER_FILL = SD.Color.FromArgb(220, 95, 168, 150) # petrol-gruen, gleich wie wand_grips
|
|
_MARKER_BORDER = SD.Color.FromArgb(255, 47, 93, 84)
|
|
|
|
|
|
def _treppe_endpoints(axis_obj):
|
|
"""Liefert Liste von Point3d. Beachtet treppe_art + Polyline-Punktzahl."""
|
|
if axis_obj is None or axis_obj.IsDeleted: return []
|
|
a = axis_obj.Attributes
|
|
if a.GetUserString("dossier_element_type") != "treppe_axis": return []
|
|
geom = axis_obj.Geometry
|
|
if not isinstance(geom, rg.Curve): return []
|
|
art = a.GetUserString("dossier_treppe_art") or "gerade"
|
|
try:
|
|
if art == "wendel":
|
|
ok, poly = geom.TryGetPolyline()
|
|
if not ok or poly is None or poly.Count != 3: return []
|
|
return [poly[1], poly[2]]
|
|
if art == "l":
|
|
ok, poly = geom.TryGetPolyline()
|
|
if not ok or poly is None: return []
|
|
return [poly[i] for i in range(poly.Count)]
|
|
return [geom.PointAtStart, geom.PointAtEnd]
|
|
except Exception:
|
|
return []
|
|
|
|
|
|
def _enumerator_all():
|
|
"""Iterator-Settings die hidden + locked Objekte mit einschliessen —
|
|
Mac-Default skipt sonst hidden-Layer-Objekte."""
|
|
s = rdoc.ObjectEnumeratorSettings()
|
|
s.HiddenObjects = True
|
|
s.LockedObjects = True
|
|
return s
|
|
|
|
|
|
class _TreppeEndpointConduit(rd.DisplayConduit):
|
|
"""Zeichnet gruene Marker an allen selektierten Treppen-Achsen."""
|
|
|
|
def DrawForeground(self, e):
|
|
try:
|
|
doc = Rhino.RhinoDoc.ActiveDoc
|
|
if doc is None: return
|
|
sel = list(doc.Objects.GetSelectedObjects(False, False))
|
|
seen = set()
|
|
for obj in sel:
|
|
a = obj.Attributes
|
|
eid = a.GetUserString("dossier_element_id") or ""
|
|
if not eid or eid in seen: continue
|
|
# Source-Axis via element_id finden — auch wenn auf hidden
|
|
# Layer (User hat z.B. nur 2D-Plansymbol selektiert).
|
|
axis = None
|
|
for o in doc.Objects.GetObjectList(_enumerator_all()):
|
|
if o is None or o.IsDeleted: continue
|
|
try:
|
|
a2 = o.Attributes
|
|
if a2.GetUserString("dossier_element_id") == eid and \
|
|
a2.GetUserString("dossier_element_type") == "treppe_axis":
|
|
axis = o; break
|
|
except Exception: continue
|
|
if axis is None: continue
|
|
seen.add(eid)
|
|
for pt in _treppe_endpoints(axis):
|
|
try:
|
|
e.Display.DrawPoint(pt,
|
|
rd.PointStyle.RoundControlPoint,
|
|
_MARKER_RADIUS_PX, _MARKER_FILL)
|
|
except Exception:
|
|
try: e.Display.DrawDot(pt, "●", _MARKER_FILL, _MARKER_BORDER)
|
|
except Exception: pass
|
|
except Exception as ex:
|
|
print("[STAIR-GRIPS] DrawForeground:", ex)
|
|
|
|
|
|
_STICKY_CONDUIT = "_dossier_treppe_grips_conduit"
|
|
|
|
|
|
def install_handlers():
|
|
"""Idempotente Registrierung. Bei Modul-Reload alten Conduit zuerst
|
|
disablen, dann neuen anhaengen."""
|
|
try:
|
|
old = sc.sticky.get(_STICKY_CONDUIT)
|
|
if old is not None:
|
|
try: old.Enabled = False
|
|
except Exception: pass
|
|
conduit = _TreppeEndpointConduit()
|
|
conduit.Enabled = True
|
|
sc.sticky[_STICKY_CONDUIT] = conduit
|
|
print("[STAIR-GRIPS] Endpoint conduit active")
|
|
except Exception as ex:
|
|
print("[STAIR-GRIPS] install:", ex)
|