b9f661cdb3
- startup.py: all user-visible messages translated to English - panel_base.py: icon/rendering log messages translated - toolbar.py: display mode check messages translated - Global: Panel registered/opened/listener-active across all modules - Fix: elemente.py and other files with stale 'import rhinopanel' were missing from PROJECTS sync — now properly copied
162 lines
5.8 KiB
Python
162 lines
5.8 KiB
Python
#! python3
|
|
# -*- coding: utf-8 -*-
|
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
# Copyright (C) 2026 Karim Gabriele Varano
|
|
"""
|
|
curve_vertex_dots.py
|
|
Display-only Vertex-Dots fuer GENERISCHE Curves (Polylinen, Linien,
|
|
Rectangles, NurbsCurves etc). Zeigt gruene Punkte an allen Vertices
|
|
selektierter Curves — hilft beim Visuell-Finden von Grip-Positionen
|
|
wenn die Curve eine Fuellung (Hatch) hat und schwer per Klick auf
|
|
einen einzelnen Vertex zu treffen ist.
|
|
|
|
Display-only — kein eigener Drag-Handler. User editiert Vertices via
|
|
Rhino's native _Grips (Punkte sichtbar machen + Standard-Drag) oder
|
|
direktes Object-Snapping waehrend Drag.
|
|
|
|
Skipt dossier-managed Curves (wand_axis, treppe_axis, schnitt_axis,
|
|
wand_outline, wand_centerline, raum_polylinie etc) — die haben ihre
|
|
eigenen Conduits oder duerfen nicht via Vertex editiert werden.
|
|
"""
|
|
import Rhino
|
|
import Rhino.Display as rd
|
|
import Rhino.Geometry as rg
|
|
import scriptcontext as sc
|
|
import System.Drawing as SD
|
|
|
|
|
|
# --- Konstanten ------------------------------------------------------------
|
|
|
|
_MARKER_RADIUS_PX = 6
|
|
_MARKER_FILL = SD.Color.FromArgb(200, 95, 168, 150) # accent-gruen
|
|
_MARKER_BORDER = SD.Color.FromArgb(255, 47, 93, 84)
|
|
|
|
# Dossier-managed Element-Types die NICHT mit generic dots versehen werden
|
|
# (= haben eigene Conduits oder sind nicht editierbar via Vertex-Click).
|
|
_SKIP_TYPES = {
|
|
"wand_axis", "wand_centerline", "wand_outline", "wand_volume",
|
|
"treppe_axis", "treppe_outline", "treppe_volume",
|
|
"schnitt_axis", "schnitt_outline",
|
|
"raum_polylinie", "raum_stempel",
|
|
"ausschnitt_polylinie",
|
|
"decke_polylinie", "decke_volume",
|
|
"dach_polylinie", "dach_volume",
|
|
}
|
|
|
|
|
|
# --- Helpers --------------------------------------------------------------
|
|
|
|
def _is_dossier_managed(obj):
|
|
"""True wenn obj ein dossier-managed Element ist (= Skip)."""
|
|
if obj is None or obj.IsDeleted: return True
|
|
try:
|
|
t = obj.Attributes.GetUserString("dossier_element_type") or ""
|
|
return t in _SKIP_TYPES
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def _curve_vertices(curve):
|
|
"""Liefert Liste von rg.Point3d fuer alle relevanten Vertices der
|
|
Curve. Verschiedene Curve-Types haben verschiedene Vertices:
|
|
- LineCurve: 2 Endpunkte
|
|
- PolylineCurve: alle Polyline-Punkte (deduplizert wenn closed)
|
|
- PolyCurve: rekursiv Segmente
|
|
- NurbsCurve/sonst: Start + End (control points nicht — zu viele)"""
|
|
pts = []
|
|
if curve is None: return pts
|
|
try:
|
|
if isinstance(curve, rg.PolylineCurve):
|
|
ok, pline = curve.TryGetPolyline()
|
|
if ok and pline is not None:
|
|
n = pline.Count
|
|
# Deduplizieren wenn closed (letzter Punkt = erster)
|
|
last = n
|
|
try:
|
|
if (n >= 2
|
|
and pline[0].DistanceTo(pline[n - 1]) < 1e-6):
|
|
last = n - 1
|
|
except Exception: pass
|
|
for i in range(last):
|
|
pts.append(rg.Point3d(pline[i]))
|
|
return pts
|
|
if isinstance(curve, rg.LineCurve):
|
|
pts.append(curve.PointAtStart)
|
|
pts.append(curve.PointAtEnd)
|
|
return pts
|
|
if isinstance(curve, rg.PolyCurve):
|
|
for i in range(curve.SegmentCount):
|
|
seg = curve.SegmentCurve(i)
|
|
if seg is None: continue
|
|
# Nur Start jedes Segments (End ist Start des naechsten)
|
|
pts.append(seg.PointAtStart)
|
|
# Letztes Segment-End anhaengen
|
|
try:
|
|
pts.append(curve.PointAtEnd)
|
|
except Exception: pass
|
|
return pts
|
|
# Generic Curve: nur Start + End
|
|
try:
|
|
pts.append(curve.PointAtStart)
|
|
pts.append(curve.PointAtEnd)
|
|
except Exception: pass
|
|
except Exception:
|
|
pass
|
|
return pts
|
|
|
|
|
|
# --- Conduit -------------------------------------------------------------
|
|
|
|
class _VertexDotConduit(rd.DisplayConduit):
|
|
"""Zeichnet bei jeder selektierten generischen Curve gruene Punkte
|
|
an allen Vertices."""
|
|
|
|
def DrawForeground(self, e):
|
|
try:
|
|
doc = Rhino.RhinoDoc.ActiveDoc
|
|
if doc is None: return
|
|
try:
|
|
sel = list(doc.Objects.GetSelectedObjects(False, False))
|
|
except Exception: return
|
|
seen_curve_ids = set()
|
|
for obj in sel:
|
|
if _is_dossier_managed(obj): continue
|
|
try:
|
|
cid = str(obj.Id)
|
|
except Exception: continue
|
|
if cid in seen_curve_ids: continue
|
|
seen_curve_ids.add(cid)
|
|
geom = obj.Geometry
|
|
if not isinstance(geom, rg.Curve): continue
|
|
for pt in _curve_vertices(geom):
|
|
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("[CURVE_DOTS] DrawForeground:", ex)
|
|
|
|
|
|
# --- Install -------------------------------------------------------------
|
|
|
|
_STICKY_CONDUIT = "_dossier_curve_vertex_dots_conduit"
|
|
|
|
|
|
def install_curve_vertex_dots():
|
|
"""Idempotent: alten Conduit disable, neuen installieren."""
|
|
try:
|
|
old = sc.sticky.get(_STICKY_CONDUIT)
|
|
if old is not None:
|
|
try: old.Enabled = False
|
|
except Exception: pass
|
|
conduit = _VertexDotConduit()
|
|
conduit.Enabled = True
|
|
sc.sticky[_STICKY_CONDUIT] = conduit
|
|
print("[CURVE_DOTS] Vertex dot conduit active")
|
|
except Exception as ex:
|
|
print("[CURVE_DOTS] install:", ex)
|