dJoin: T-Join Ergaenzung — Endpunkt einer Wand mitten auf andere snappen
Bisher konnte dJoin nur L-Verbindungen herstellen (zwei Endpunkte zum Schnittpunkt der verlaengerten Tangenten ziehen). Neu auch T-Verbindungen: _t_join_attempt: pro Endpunkt-Kombination wird der naechste Punkt auf der ANDEREN Curve gesucht. Wenn distance < 20cm UND nicht nahe deren Endpunkt (= waere L-Sache) → snap diesen Endpunkt exakt auf die Curve. Die andere Curve bleibt unveraendert (= Through-Wand stays). _run: T-Join wird ZUERST probiert (spezifischer), L-Join als Fallback. UX: User selektiert 2 Waende die fast aber nicht ganz verbinden → Cmd+J (dJoin) → System erkennt T- oder L-Konfig und snappt entsprechend. Predictable + intentional, kein auto-snap-Magic mehr.
This commit is contained in:
@@ -124,6 +124,58 @@ def _walls_and_curves_from_sel(doc, sel):
|
||||
return axes, generic
|
||||
|
||||
|
||||
def _t_join_attempt(doc, sel):
|
||||
"""T-Join: 2 OFFENE Kurven wobei der EINE Endpunkt der einen Kurve
|
||||
nahe (< 20cm) auf der ANDEREN Kurve mitten landet (zwischen deren
|
||||
Endpunkten). Schiebt diesen Endpunkt exakt auf die andere Kurve.
|
||||
Die andere Kurve bleibt unveraendert.
|
||||
|
||||
Liefert True wenn ausgefuehrt."""
|
||||
axes, generic = _walls_and_curves_from_sel(doc, sel)
|
||||
if len(axes) == 2 and len(generic) == 0:
|
||||
o1, o2 = axes[0], axes[1]
|
||||
elif len(axes) == 0 and len(generic) == 2:
|
||||
o1, o2 = generic[0], generic[1]
|
||||
else:
|
||||
return False
|
||||
c1 = o1.Geometry; c2 = o2.Geometry
|
||||
if not (isinstance(c1, rg.Curve) and isinstance(c2, rg.Curve)):
|
||||
return False
|
||||
if c1.IsClosed or c2.IsClosed: return False
|
||||
tol_snap = 0.20 # 20 cm Snap-Radius fuer T-Verbindung
|
||||
end_tol = 0.05 # 5cm: wenn closest-point nahe Endpunkt → eigentlich L
|
||||
candidates = []
|
||||
# Pro Endpunkt der einen Kurve: ClosestPoint auf der ANDEREN Kurve
|
||||
for (a_obj, ac, b_obj, bc) in ((o1, c1, o2, c2), (o2, c2, o1, c1)):
|
||||
for end in (0, 1):
|
||||
ep = ac.PointAtStart if end == 0 else ac.PointAtEnd
|
||||
try:
|
||||
rc, t = bc.ClosestPoint(ep)
|
||||
if not rc: continue
|
||||
cp = bc.PointAt(t)
|
||||
d = cp.DistanceTo(ep)
|
||||
# Skip wenn schon snapped oder zu weit
|
||||
if d < 1e-6 or d > tol_snap: continue
|
||||
# Skip wenn cp nahe einem Endpunkt von bc — das ist L-Join Territory
|
||||
ps = bc.PointAtStart; pe = bc.PointAtEnd
|
||||
if cp.DistanceTo(ps) < end_tol or cp.DistanceTo(pe) < end_tol:
|
||||
continue
|
||||
candidates.append((d, a_obj, ac, end, cp))
|
||||
except Exception: continue
|
||||
if not candidates: return False
|
||||
# Naechster Endpunkt → der wird gesnappt
|
||||
candidates.sort(key=lambda x: x[0])
|
||||
_d, a_obj, ac, end, cp = candidates[0]
|
||||
new_c = _replace_curve_endpoint(ac, end, cp)
|
||||
if new_c is None: return False
|
||||
ur = doc.BeginUndoRecord("DOSSIER T-Join")
|
||||
try:
|
||||
ok = doc.Objects.Replace(a_obj.Id, new_c)
|
||||
return bool(ok)
|
||||
finally:
|
||||
doc.EndUndoRecord(ur)
|
||||
|
||||
|
||||
def _l_join_attempt(doc, sel):
|
||||
"""Wenn genau 2 OFFENE Kurven (Wand-Achsen oder generische Lines)
|
||||
selektiert sind, deren End-Tangenten sich in einem Punkt schneiden →
|
||||
@@ -187,9 +239,17 @@ def _run():
|
||||
if not sel:
|
||||
Rhino.RhinoApp.RunScript("_Join", False); return
|
||||
|
||||
# L-Join: genau 2 offene Kurven die sich (verlaengert) treffen wuerden.
|
||||
# Walls werden via ihrer Achse automatisch regenert (Replace-Listener).
|
||||
if len(sel) == 2:
|
||||
# T-Join: Endpunkt der einen Curve trifft mitten auf die andere → snap.
|
||||
# L-Join: beide Endpunkte werden zum Schnittpunkt der verlaengerten Linien
|
||||
# gezogen. T zuerst probieren (= spezifischer), dann L als Fallback.
|
||||
if len(sel) >= 2:
|
||||
try:
|
||||
if _t_join_attempt(doc, sel):
|
||||
doc.Views.Redraw()
|
||||
print("[SMART-JOIN] T-Join: Endpunkt auf Achse gesnappt")
|
||||
return
|
||||
except Exception as ex:
|
||||
print("[SMART-JOIN] T-Join error:", ex)
|
||||
try:
|
||||
if _l_join_attempt(doc, sel):
|
||||
doc.Views.Redraw()
|
||||
|
||||
Reference in New Issue
Block a user