T-Junction Phase 2 mit 3D Brep Union + Material-Prio-Carve
Asymmetric L-merge fuer Schichtdurchdringung: - Backbone (= hoechste Material-Prio in beiden Waenden) bildet T-form - Non-backbone Layer werden gecarved mit backbone-Column + through-Bands hoeherer Prio - ext=0 fuer T-Stem-Axis (= column endet am snap, kein "drueber") - 3D Brep Union via Brep.CreateBooleanUnion mit cross-junction safety (= aktueller through-Brep statt von Meta neu zu bauen) - Cleanup: MergeCoplanarFaces Plus: - Innenwand Beton 20cm Style (Putz + Beton + Putz, ref-mid) - curve_vertex_dots.py: gruene Vertex-Punkte fuer Polylinen/Curves - Cluster-Volume Select Handler: Shift-Modifier fuer Multi-Select - startup.py: Top-View maximieren on Doc-Open Known limitation: Putz-Schicht kann in bestimmten Konfigurationen visuell suedlich des Daemm-Band-Top weiter sichtbar sein (= edge case fuer asymmetric layers). Naechster Schritt: manuelle 2D-Polygon-Konstruktion statt 3D Boolean.
This commit is contained in:
@@ -0,0 +1,161 @@
|
||||
#! 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 aktiv")
|
||||
except Exception as ex:
|
||||
print("[CURVE_DOTS] install:", ex)
|
||||
Reference in New Issue
Block a user