Schichtdurchdringung am T-Junction: pro Schicht material-basiertes Verbinden
Bisher: bei T-Junction stoppen ALLE Layers des T-Stems uniform am Near-Face der Through-Wand (uniformer T-Miter pro Wand). Neu: per-Schicht Logik im _make_wand_layer_breps: - T-Stem-Schicht mit Material das in Through-Wand auch vorkommt → Layer-Axis extends um through_dicke/2 → Layer durchstoesst Through-Wand bis zur Far-Face → visuell verbunden, kein sichtbarer Joint - Schicht ohne Material-Match in Through-Wand → standard T-Miter, stoppt am Near-Face Beispiel "Aussenwand 30cm" (Beton/Daemmung/Putz) T auf gleicher Aussenwand: alle 3 Schichten matchen → durchgehend gemerged. Beispiel "Aussenwand 30cm" T auf "Beton solid 15cm": - T-Stem Beton matched (Through-Solid hat Beton via Style) → durchstoesst - T-Stem Daemmung/Putz: kein Match → stoppen am Through-Beton-Aussenkante Implementation: - _make_wand_layer_breps: per_layer_ext_start/end + per_layer_miter_start/end - _t_junction_layer_overrides(doc, my_meta, through_meta, ...): baut die per-Layer Overrides via Material-Set-Lookup. Solid through wird via _wand_solid_material auf Style-Material aufgeloest. - Regen-Pfad: t_junction_start/end speichern (oid+tan+dicke+ep+out_dir), vor _make_wand_layer_breps die Overrides bauen.
This commit is contained in:
+112
-7
@@ -3600,6 +3600,53 @@ def _wand_meta_prio(doc, meta):
|
|||||||
except Exception: return 500
|
except Exception: return 500
|
||||||
|
|
||||||
|
|
||||||
|
def _t_junction_layer_overrides(doc, my_meta, through_meta, ep_pt, out_dir,
|
||||||
|
b_tan, b_dicke):
|
||||||
|
"""Per-Layer Schichtdurchdringung bei T-Junction zwischen layered Waenden.
|
||||||
|
|
||||||
|
Pro T-Stem-Schicht wird in der Through-Wand nach einer Schicht mit
|
||||||
|
GLEICHEM MATERIAL gesucht:
|
||||||
|
- Match: T-Stem-Layer extends durch die Through-Wand (Axis-Extension um
|
||||||
|
b_dicke/2 = bis Far-Face) → visuell verbunden
|
||||||
|
- No Match: T-Stem-Layer stoppt am Near-Face (Standard T-Miter)
|
||||||
|
|
||||||
|
Returns (per_layer_ext, per_layer_miter) — Listen pro T-Stem-Layer.
|
||||||
|
Wenn my keine Layers hat: (None, None) (Caller faellt auf uniform Miter
|
||||||
|
zurueck)."""
|
||||||
|
if not my_meta or not through_meta: return None, None
|
||||||
|
my_layers = my_meta.get("wand_layers") or []
|
||||||
|
if not my_layers: return None, None
|
||||||
|
th_layers = through_meta.get("wand_layers") or []
|
||||||
|
# Through-Material-Set sammeln
|
||||||
|
th_materials = set()
|
||||||
|
if through_meta.get("wand_layered") and th_layers:
|
||||||
|
for l in th_layers:
|
||||||
|
mat = (l.get("material") or "").strip()
|
||||||
|
if mat: th_materials.add(mat)
|
||||||
|
else:
|
||||||
|
# Through ist solid → 1 Material aus Style
|
||||||
|
try:
|
||||||
|
sm = _wand_solid_material(doc, through_meta) if doc else ""
|
||||||
|
if sm: th_materials.add(sm)
|
||||||
|
except Exception: pass
|
||||||
|
|
||||||
|
standard_miter = _t_junction_miter(ep_pt, out_dir, b_tan, b_dicke)
|
||||||
|
extension = float(b_dicke) * 0.5 # bis Far-Face
|
||||||
|
per_ext = []
|
||||||
|
per_miter = []
|
||||||
|
for layer in my_layers:
|
||||||
|
mat = (layer.get("material") or "").strip()
|
||||||
|
if mat and mat in th_materials:
|
||||||
|
# Match → durchstossen
|
||||||
|
per_ext.append(extension)
|
||||||
|
per_miter.append(None)
|
||||||
|
else:
|
||||||
|
# Kein Match → an Near-Face stoppen
|
||||||
|
per_ext.append(0.0)
|
||||||
|
per_miter.append(standard_miter)
|
||||||
|
return per_ext, per_miter
|
||||||
|
|
||||||
|
|
||||||
def _wand_should_apply_t_miter(doc, my_meta, through_wid):
|
def _wand_should_apply_t_miter(doc, my_meta, through_wid):
|
||||||
"""Entscheidet ob ich (T-Stem-Kandidat) am T-Junction zur Through-Wand
|
"""Entscheidet ob ich (T-Stem-Kandidat) am T-Junction zur Through-Wand
|
||||||
angeschmiegt werden soll (= T-mitered). Per-Wand Joint-Rolle hat Vorrang
|
angeschmiegt werden soll (= T-mitered). Per-Wand Joint-Rolle hat Vorrang
|
||||||
@@ -3867,25 +3914,56 @@ def _ensure_pbr_material(doc, mat_dict):
|
|||||||
|
|
||||||
|
|
||||||
def _make_wand_layer_breps(axis_curve, layers, dicke, referenz, uk, ok,
|
def _make_wand_layer_breps(axis_curve, layers, dicke, referenz, uk, ok,
|
||||||
miter_start=None, miter_end=None):
|
miter_start=None, miter_end=None,
|
||||||
|
per_layer_ext_start=None, per_layer_ext_end=None,
|
||||||
|
per_layer_miter_start=None, per_layer_miter_end=None):
|
||||||
"""Baut eine Liste (brep, color_hex, name) pro Schicht. Schicht-Reihen-
|
"""Baut eine Liste (brep, color_hex, name) pro Schicht. Schicht-Reihen-
|
||||||
folge: von der +perp-Seite zur -perp-Seite (links→rechts entlang der
|
folge: von der +perp-Seite zur -perp-Seite (links→rechts entlang der
|
||||||
Wand-Achse). layers = Liste von dicts mit Keys 'dicke', 'color', 'name'."""
|
Wand-Achse). layers = Liste von dicts mit Keys 'dicke', 'color', 'name'.
|
||||||
|
|
||||||
|
Per-Layer Overrides (alle optional, jede Liste len(layers)):
|
||||||
|
- per_layer_ext_start/end: zusaetzliche Axis-Verlaengerung pro Layer am
|
||||||
|
jeweiligen Ende (fuer Schichtdurchdringung bei T-Junction)
|
||||||
|
- per_layer_miter_start/end: per-Layer Miter (= clip am Through-Face)
|
||||||
|
→ ueberschreibt die globalen miter_start/_end args fuer diesen Layer"""
|
||||||
out = []
|
out = []
|
||||||
if not layers:
|
if not layers:
|
||||||
return out
|
return out
|
||||||
start_off, d_total = _wall_offsets_from_referenz(dicke, referenz)
|
start_off, d_total = _wall_offsets_from_referenz(dicke, referenz)
|
||||||
cur = start_off
|
cur = start_off
|
||||||
max_ext = float(d_total) * 5.0
|
max_ext = float(d_total) * 5.0
|
||||||
for layer in layers:
|
for layer_idx, layer in enumerate(layers):
|
||||||
try: d = float(layer.get("dicke", 0))
|
try: d = float(layer.get("dicke", 0))
|
||||||
except Exception: d = 0.0
|
except Exception: d = 0.0
|
||||||
if d <= 0: continue
|
if d <= 0: continue
|
||||||
d_left = cur
|
d_left = cur
|
||||||
d_right = cur - d
|
d_right = cur - d
|
||||||
brep = _make_wall_layer_brep(axis_curve, d_left, d_right, uk, ok,
|
# Per-Layer Overrides ziehen
|
||||||
miter_start=miter_start,
|
m_start = miter_start
|
||||||
miter_end=miter_end,
|
m_end = miter_end
|
||||||
|
if (per_layer_miter_start is not None
|
||||||
|
and layer_idx < len(per_layer_miter_start)):
|
||||||
|
m_start = per_layer_miter_start[layer_idx]
|
||||||
|
if (per_layer_miter_end is not None
|
||||||
|
and layer_idx < len(per_layer_miter_end)):
|
||||||
|
m_end = per_layer_miter_end[layer_idx]
|
||||||
|
ext_s = 0.0; ext_e = 0.0
|
||||||
|
if (per_layer_ext_start is not None
|
||||||
|
and layer_idx < len(per_layer_ext_start)):
|
||||||
|
try: ext_s = float(per_layer_ext_start[layer_idx] or 0)
|
||||||
|
except Exception: ext_s = 0.0
|
||||||
|
if (per_layer_ext_end is not None
|
||||||
|
and layer_idx < len(per_layer_ext_end)):
|
||||||
|
try: ext_e = float(per_layer_ext_end[layer_idx] or 0)
|
||||||
|
except Exception: ext_e = 0.0
|
||||||
|
# Axis ggf. extenden (fuer Schichtdurchdringung)
|
||||||
|
if ext_s > 1e-9 or ext_e > 1e-9:
|
||||||
|
axis_for_layer = _extend_axis_curve(axis_curve, ext_s, ext_e)
|
||||||
|
else:
|
||||||
|
axis_for_layer = axis_curve
|
||||||
|
brep = _make_wall_layer_brep(axis_for_layer, d_left, d_right, uk, ok,
|
||||||
|
miter_start=m_start,
|
||||||
|
miter_end=m_end,
|
||||||
max_miter_extend=max_ext)
|
max_miter_extend=max_ext)
|
||||||
out.append((brep, layer.get("color", ""), layer.get("name", "")))
|
out.append((brep, layer.get("color", ""), layer.get("name", "")))
|
||||||
cur = d_right
|
cur = d_right
|
||||||
@@ -8406,6 +8484,8 @@ def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name
|
|||||||
# liegen ja schon in der gejointen Polyline drin.
|
# liegen ja schon in der gejointen Polyline drin.
|
||||||
miter_start = None
|
miter_start = None
|
||||||
miter_end = None
|
miter_end = None
|
||||||
|
t_junction_start = None # (through_wid, b_tan, b_dicke, ep_pt, out_dir) bei T-Junction
|
||||||
|
t_junction_end = None
|
||||||
chain_set = set(chain_ids) if (chain_ids and len(chain_ids) > 1) else {element_id}
|
chain_set = set(chain_ids) if (chain_ids and len(chain_ids) > 1) else {element_id}
|
||||||
try:
|
try:
|
||||||
joints = _collect_wall_joints(doc, meta["geschoss"])
|
joints = _collect_wall_joints(doc, meta["geschoss"])
|
||||||
@@ -8431,6 +8511,9 @@ def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name
|
|||||||
if _wand_should_apply_t_miter(doc, meta, _oid):
|
if _wand_should_apply_t_miter(doc, meta, _oid):
|
||||||
tm = _t_junction_miter(p_s, out_s, b_tan, b_dicke)
|
tm = _t_junction_miter(p_s, out_s, b_tan, b_dicke)
|
||||||
if tm is not None: miter_start = tm
|
if tm is not None: miter_start = tm
|
||||||
|
# Through-Meta merken fuer per-Layer Schicht-
|
||||||
|
# durchdringung (s. unten bei layer_breps build)
|
||||||
|
t_junction_start = (_oid, b_tan, b_dicke, p_s, out_s)
|
||||||
else:
|
else:
|
||||||
# 3+ Joint: ich bin T-Stem wenn meine Tangente NICHT
|
# 3+ Joint: ich bin T-Stem wenn meine Tangente NICHT
|
||||||
# collinear mit zwei collinearen Partner-Tangenten ist.
|
# collinear mit zwei collinearen Partner-Tangenten ist.
|
||||||
@@ -8462,6 +8545,7 @@ def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name
|
|||||||
if _wand_should_apply_t_miter(doc, meta, _oid):
|
if _wand_should_apply_t_miter(doc, meta, _oid):
|
||||||
tm = _t_junction_miter(p_e, out_e, b_tan, b_dicke)
|
tm = _t_junction_miter(p_e, out_e, b_tan, b_dicke)
|
||||||
if tm is not None: miter_end = tm
|
if tm is not None: miter_end = tm
|
||||||
|
t_junction_end = (_oid, b_tan, b_dicke, p_e, out_e)
|
||||||
else:
|
else:
|
||||||
# 3+ Joint: T-Stem-Erkennung (analog start)
|
# 3+ Joint: T-Stem-Erkennung (analog start)
|
||||||
_my_t = geom.TangentAtEnd
|
_my_t = geom.TangentAtEnd
|
||||||
@@ -8480,10 +8564,31 @@ def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name
|
|||||||
layers_def = meta.get("wand_layers") or []
|
layers_def = meta.get("wand_layers") or []
|
||||||
is_layered = bool(meta.get("wand_layered")) and len(layers_def) > 0
|
is_layered = bool(meta.get("wand_layered")) and len(layers_def) > 0
|
||||||
if is_layered:
|
if is_layered:
|
||||||
|
# Per-Layer Schichtdurchdringung bei T-Junctions:
|
||||||
|
# Pro Schicht des T-Stems suchen wir in der Through-Wand eine
|
||||||
|
# Schicht mit gleichem Material. Match → durchstossen (Layer-
|
||||||
|
# Axis extension). Kein Match → standard T-Miter.
|
||||||
|
pl_ext_s = None; pl_ext_e = None
|
||||||
|
pl_miter_s = None; pl_miter_e = None
|
||||||
|
if t_junction_start is not None:
|
||||||
|
_toid, _btan, _bdk, _ep, _od = t_junction_start
|
||||||
|
_tm = _wand_meta_by_id(doc, _toid)
|
||||||
|
if _tm is not None:
|
||||||
|
pl_ext_s, pl_miter_s = _t_junction_layer_overrides(
|
||||||
|
doc, meta, _tm, _ep, _od, _btan, _bdk)
|
||||||
|
if t_junction_end is not None:
|
||||||
|
_toid, _btan, _bdk, _ep, _od = t_junction_end
|
||||||
|
_tm = _wand_meta_by_id(doc, _toid)
|
||||||
|
if _tm is not None:
|
||||||
|
pl_ext_e, pl_miter_e = _t_junction_layer_overrides(
|
||||||
|
doc, meta, _tm, _ep, _od, _btan, _bdk)
|
||||||
layer_breps = _make_wand_layer_breps(
|
layer_breps = _make_wand_layer_breps(
|
||||||
geom, layers_def, meta["dicke"],
|
geom, layers_def, meta["dicke"],
|
||||||
meta.get("referenz", "mid"), uk, ok,
|
meta.get("referenz", "mid"), uk, ok,
|
||||||
miter_start=miter_start, miter_end=miter_end)
|
miter_start=miter_start, miter_end=miter_end,
|
||||||
|
per_layer_ext_start=pl_ext_s, per_layer_ext_end=pl_ext_e,
|
||||||
|
per_layer_miter_start=pl_miter_s,
|
||||||
|
per_layer_miter_end=pl_miter_e)
|
||||||
else:
|
else:
|
||||||
single_brep = _make_volume_geometry(
|
single_brep = _make_volume_geometry(
|
||||||
geom, meta["dicke"], uk, ok,
|
geom, meta["dicke"], uk, ok,
|
||||||
|
|||||||
Reference in New Issue
Block a user