Revert "Unit-aware: m → Doc-Units im Regen-Pfad"

This reverts commit dd5ccec881.
This commit is contained in:
2026-05-26 22:06:27 +02:00
parent dd5ccec881
commit cd626b0707
+28 -135
View File
@@ -535,42 +535,6 @@ _OEFF_PIECE_DEFS = {
# Doc-Wechsel, aber NICHT Rhino-Restart — was passt: "ich hab gerade 0.30 # Doc-Wechsel, aber NICHT Rhino-Restart — was passt: "ich hab gerade 0.30
# fuer eine Wand benutzt, neue Wand soll auch 0.30 sein". # fuer eine Wand benutzt, neue Wand soll auch 0.30 sein".
def _m2u(value, doc=None):
"""Konvertiert einen Wert in Metern in Doc-Units. Nutzt RhinoMath.UnitScale.
Bei doc=meter ist scale=1 no-op. Bei doc=mm ist scale=1000.
DOSSIER-Konvention: UI typt in Metern, Geometrie wird in Doc-Units gebaut.
"""
try:
v = float(value)
except Exception:
return value
if doc is None: doc = Rhino.RhinoDoc.ActiveDoc
if doc is None: return v
try:
scale = Rhino.RhinoMath.UnitScale(
Rhino.UnitSystem.Meters, doc.ModelUnitSystem)
return v * float(scale)
except Exception:
return v
def _u2m(value, doc=None):
"""Inverse von _m2u: Doc-Units → Meter. Fuer State-Emit zum Frontend."""
try:
v = float(value)
except Exception:
return value
if doc is None: doc = Rhino.RhinoDoc.ActiveDoc
if doc is None: return v
try:
scale = Rhino.RhinoMath.UnitScale(
Rhino.UnitSystem.Meters, doc.ModelUnitSystem)
if scale == 0: return v
return v / float(scale)
except Exception:
return v
def _last(key, default): def _last(key, default):
# `_reset_panels.py` cleart sticky via `= None` (statt del), daher kann # `_reset_panels.py` cleart sticky via `= None` (statt del), daher kann
# sc.sticky.get() den default ueberlesen und ein None zurueckgeben. # sc.sticky.get() den default ueberlesen und ein None zurueckgeben.
@@ -630,17 +594,14 @@ def _active_geschoss_name(doc):
def _resolve_uk_ok(doc, gid, uk_over, ok_over): def _resolve_uk_ok(doc, gid, uk_over, ok_over):
"""Wand: UK = OKFF, OK = OKFF + Hoehe (Standard fuer Geschoss-volle Wand). """Wand: UK = OKFF, OK = OKFF + Hoehe (Standard fuer Geschoss-volle Wand)."""
Geschoss-Heights JSON ist in METERN hier auf Doc-Units konvertieren,
damit Geometrie-Code direkt arbeiten kann. uk_over/ok_over kommen
bereits in Doc-Units von _regenerate_element_body's Meta-Normalisierung."""
g = _geschoss_by_id(doc, gid) g = _geschoss_by_id(doc, gid)
if g is None: if g is None:
uk = float(uk_over) if uk_over not in (None, "") else 0.0 uk = float(uk_over) if uk_over not in (None, "") else 0.0
ok = float(ok_over) if ok_over not in (None, "") else _m2u(3.0, doc) ok = float(ok_over) if ok_over not in (None, "") else 3.0
return uk, ok return uk, ok
okff = _m2u(g.get("okff", 0.0), doc) okff = float(g.get("okff", 0.0))
hoehe = _m2u(g.get("hoehe", 3.0), doc) hoehe = float(g.get("hoehe", 3.0))
auto_uk = okff auto_uk = okff
auto_ok = okff + hoehe auto_ok = okff + hoehe
uk = float(uk_over) if uk_over not in (None, "") else auto_uk uk = float(uk_over) if uk_over not in (None, "") else auto_uk
@@ -656,11 +617,9 @@ def _resolve_decke_z(doc, gid, dicke, uk_over, ok_over):
Override-Logik: Override-Logik:
- Nur OK_override gesetzt OK = override, UK = OK - dicke - Nur OK_override gesetzt OK = override, UK = OK - dicke
- Nur UK_override gesetzt UK = override, OK = UK + dicke - Nur UK_override gesetzt UK = override, OK = UK + dicke
- Beide gesetzt beide literal - Beide gesetzt beide literal"""
Alle Werte hier in Doc-Units (Geschoss-JSON wird via _m2u konvertiert)."""
g = _geschoss_by_id(doc, gid) g = _geschoss_by_id(doc, gid)
okff = _m2u(g.get("okff", 0.0), doc) if g else 0.0 okff = float(g.get("okff", 0.0)) if g else 0.0
auto_ok = okff auto_ok = okff
has_ok = ok_over not in (None, "") has_ok = ok_over not in (None, "")
has_uk = uk_over not in (None, "") has_uk = uk_over not in (None, "")
@@ -3814,13 +3773,12 @@ def _find_target_volume(doc, element_id):
def _resolve_dach_base(doc, gid, uk_over): def _resolve_dach_base(doc, gid, uk_over):
"""Basis-Hoehe des Dachs an der Traufe (= Eave) = OKFF + Hoehe des """Basis-Hoehe des Dachs an der Traufe (= Eave) = OKFF + Hoehe des
Geschosses (Oberkante der Waende). uk_override kann das ueberschreiben. Geschosses (Oberkante der Waende). uk_override kann das ueberschreiben."""
Geschoss-Heights JSON ist in METERN hier auf Doc-Units konvertieren."""
g = _geschoss_by_id(doc, gid) g = _geschoss_by_id(doc, gid)
if g is None: if g is None:
return float(uk_over) if uk_over not in (None, "") else _m2u(3.0, doc) return float(uk_over) if uk_over not in (None, "") else 3.0
okff = _m2u(g.get("okff", 0.0), doc) okff = float(g.get("okff", 0.0))
hoehe = _m2u(g.get("hoehe", 3.0), doc) hoehe = float(g.get("hoehe", 3.0))
auto = okff + hoehe auto = okff + hoehe
return float(uk_over) if uk_over not in (None, "") else auto return float(uk_over) if uk_over not in (None, "") else auto
@@ -4777,23 +4735,16 @@ def _format_area(area, rundung):
return "{:.2f}".format(a) # exakt return "{:.2f}".format(a) # exakt
def _resolve_raum_text_height_m(value, modus, doc=None): def _resolve_raum_text_height_m(value, modus):
"""Konvertiert raum_txt_h (User-Wert) in MODELL-DOC-UNITS, je nach Modus: """Konvertiert raum_txt_h (User-Wert) in Modell-Meter, je nach Modus:
modus=fix value ist Meter, Modell-Doc-Units = m * UnitScale modus=fix value ist bereits Meter
(Doc=Meter no-op; Doc=mm ×1000) modus=masstab value ist Paper-mm, Modell-Meter = value*scale/1000
modus=masstab value ist Paper-mm, Modell-Doc-Units = (scale aus aktivem Viewport via massstab.get_applied_scale_ratio)
(value * scale / 1000) * UnitScale
(scale aus aktivem Viewport via massstab)
Fallback bei fehlendem Massstab: 100 (1:100). Fallback bei fehlendem Massstab: 100 (1:100).
Hinweis: im Aufruf-Pfad in _regenerate_element_body wurde raum_txt_h
bereits durch die Meta-Normalisierung in Doc-Units konvertiert FUER
fix-Modus. Hier behandeln wir den masstab-Pfad sauber und lassen den
fix-Pfad als no-op.
""" """
try: v = float(value) try: v = float(value)
except Exception: v = 0.20 except Exception: v = 0.20
if (modus or "fix") != "masstab": if (modus or "fix") != "masstab":
# value ist schon in Doc-Units (vor-konvertiert in _regenerate_element_body)
return v return v
try: try:
import massstab as _ms import massstab as _ms
@@ -4802,9 +4753,7 @@ def _resolve_raum_text_height_m(value, modus, doc=None):
sc_ratio = None sc_ratio = None
if not sc_ratio or sc_ratio <= 0: if not sc_ratio or sc_ratio <= 0:
sc_ratio = 100.0 sc_ratio = 100.0
# masstab: Paper-mm → Modell-Meter → Modell-Doc-Units return float(v) * float(sc_ratio) / 1000.0
m_value = float(v) * float(sc_ratio) / 1000.0
return _m2u(m_value, doc)
def _make_raum_stamp_text(centroid, name, nummer, funktion, area, rundung, def _make_raum_stamp_text(centroid, name, nummer, funktion, area, rundung,
@@ -5567,60 +5516,7 @@ def _regenerate_element(doc, element_id):
def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name): def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name):
"""Eigentliche Implementierung des Regen — der aeussere Wrapper """Eigentliche Implementierung des Regen — der aeussere Wrapper
`_regenerate_element` setzt _REGEN_BUSY und dispatcht oeffnung_point. `_regenerate_element` setzt _REGEN_BUSY und dispatcht oeffnung_point."""
UNIT-NORMALISIERUNG: DOSSIER-Storage ist immer in METERN (UI-Konvention).
Hier am Eingang konvertieren wir ALLE m-Werte Doc-Units. So bleibt der
Geometrie-Code unten unveraendert und funktioniert in jedem Doc-Unit-
System (Meter, Millimeter, ).
"""
# Meta-Werte normalisieren: Liste m-typischer Felder → _m2u
_M_FIELDS = ("dicke", "uk_override", "ok_override",
"oeff_breite", "oeff_hoehe", "oeff_brueest",
"oeff_rahmen_b", "oeff_rahmen_tiefe", "oeff_rahmen_offset",
"treppe_breite", "treppe_lauf_d", "treppe_h_over",
"trag_b", "trag_h", "trag_d", "trag_t", "trag_z_over",
"raum_stamp_dx", "raum_stamp_dy")
for _k in _M_FIELDS:
if _k in meta:
_v = meta[_k]
if _v == "" or _v is None: continue
try: meta[_k] = _m2u(_v, doc)
except Exception: pass
# raum_txt_h: nur im fix-Modus in m (sonst paper-mm) → entsprechend
# konvertieren. Im masstab-Modus uebernimmt _resolve_raum_text_height_m
# die Berechnung (selber doc-unit-aware).
if meta.get("type") == "raum_outline" and meta.get("raum_txt_modus") != "masstab":
try: meta["raum_txt_h"] = _m2u(meta.get("raum_txt_h", 0.20), doc)
except Exception: pass
# Wand-Schichten: jede Schicht hat eine eigene dicke
if isinstance(meta.get("wand_layers"), list):
for _ly in meta["wand_layers"]:
if isinstance(_ly, dict) and "dicke" in _ly:
try: _ly["dicke"] = _m2u(_ly["dicke"], doc)
except Exception: pass
# Treppe Soll-Werte: dict mit s/a/sa Range-Listen
if isinstance(meta.get("treppe_soll"), dict):
for _k in ("s", "a", "sa"):
_arr = meta["treppe_soll"].get(_k)
if isinstance(_arr, list) and len(_arr) >= 2:
try:
_arr[0] = _m2u(_arr[0], doc)
_arr[1] = _m2u(_arr[1], doc)
except Exception: pass
# Geschoss-Lookup-Wrapper: konvertiert hoehe + okff → Doc-Units.
# ALLE Geometrie-Aufrufe unten benutzen _gs() statt _geschoss_by_id().
def _gs(gid):
g = _geschoss_by_id(doc, gid)
if g is None: return None
g = dict(g)
try: g["hoehe"] = _m2u(g.get("hoehe", 3.0), doc)
except Exception: pass
try: g["okff"] = _m2u(g.get("okff", 0.0), doc)
except Exception: pass
return g
if meta["type"] == "wand_axis": if meta["type"] == "wand_axis":
# Chain-Detection: wenn diese Wand mit Nachbarn (gleiche Geometrie/ # Chain-Detection: wenn diese Wand mit Nachbarn (gleiche Geometrie/
# Material/Hoehe, 2-Wall-Joints) zu einem Polyline-Chain gehoert, # Material/Hoehe, 2-Wall-Joints) zu einem Polyline-Chain gehoert,
@@ -6075,8 +5971,8 @@ def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name
elif meta["type"] == "treppe_axis": elif meta["type"] == "treppe_axis":
# Start- und Zielgeschoss → uk/ok aus OKFF-Differenz. # Start- und Zielgeschoss → uk/ok aus OKFF-Differenz.
# H-Override hat Vorrang vor Zielgeschoss. # H-Override hat Vorrang vor Zielgeschoss.
g_start = _gs(meta["geschoss"]) g_start = _geschoss_by_id(doc, meta["geschoss"])
g_end = _gs(meta.get("geschoss_end", "")) g_end = _geschoss_by_id(doc, meta.get("geschoss_end", ""))
if g_start is None: if g_start is None:
return False return False
uk = float(g_start.get("okff", 0.0)) uk = float(g_start.get("okff", 0.0))
@@ -6119,7 +6015,7 @@ def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name
pt = geom.Location pt = geom.Location
else: else:
pt = geom # Point3d pt = geom # Point3d
g_start = _gs(meta["geschoss"]) g_start = _geschoss_by_id(doc, meta["geschoss"])
uk = float(g_start.get("okff", 0.0)) if g_start else 0.0 uk = float(g_start.get("okff", 0.0)) if g_start else 0.0
z_over = meta.get("trag_z_over", "") z_over = meta.get("trag_z_over", "")
if z_over: if z_over:
@@ -6141,7 +6037,7 @@ def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name
src_layer = layer src_layer = layer
elif meta["type"] == "traeger_axis": elif meta["type"] == "traeger_axis":
# Achse + z_top aus Geschoss + Override # Achse + z_top aus Geschoss + Override
g_start = _gs(meta["geschoss"]) g_start = _geschoss_by_id(doc, meta["geschoss"])
uk = float(g_start.get("okff", 0.0)) if g_start else 0.0 uk = float(g_start.get("okff", 0.0)) if g_start else 0.0
h = float(g_start.get("hoehe", 3.0)) if g_start else 3.0 h = float(g_start.get("hoehe", 3.0)) if g_start else 3.0
z_over = meta.get("trag_z_over", "") z_over = meta.get("trag_z_over", "")
@@ -6179,8 +6075,8 @@ def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name
doc.Objects.ModifyAttributes(src_obj, new_attrs, True) doc.Objects.ModifyAttributes(src_obj, new_attrs, True)
except Exception: pass except Exception: pass
area, perim, ctr = _raum_amp(geom) area, perim, ctr = _raum_amp(geom)
# Z-Lage: auf Geschoss-OKFF (Doc-Units via _gs) # Z-Lage: auf Geschoss-OKFF
g_start = _gs(meta["geschoss"]) g_start = _geschoss_by_id(doc, meta["geschoss"])
z_uk = float(g_start.get("okff", 0.0)) if g_start else 0.0 z_uk = float(g_start.get("okff", 0.0)) if g_start else 0.0
# Alte Stempel + Fills loeschen # Alte Stempel + Fills loeschen
@@ -6314,8 +6210,7 @@ def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name
# Texthoehe: bei modus=masstab aus Paper-mm + aktuellem Scale aufloesen # Texthoehe: bei modus=masstab aus Paper-mm + aktuellem Scale aufloesen
eff_h = _resolve_raum_text_height_m( eff_h = _resolve_raum_text_height_m(
meta.get("raum_txt_h", 0.20), meta.get("raum_txt_h", 0.20),
meta.get("raum_txt_modus", "fix"), meta.get("raum_txt_modus", "fix"))
doc=doc)
te = _make_raum_stamp_text( te = _make_raum_stamp_text(
stamp_pt, stamp_pt,
meta.get("raum_name", "Raum"), meta.get("raum_name", "Raum"),
@@ -12297,12 +12192,10 @@ def _sync_raum_stamps_to_source(doc):
if not isinstance(src_geom, rg.Curve): continue if not isinstance(src_geom, rg.Curve): continue
_, _, ctr = _raum_amp(src_geom) _, _, ctr = _raum_amp(src_geom)
if ctr is None: continue if ctr is None: continue
# Stempel-Position ist in Doc-Units → fuer Storage (Meter) konvertieren new_dx = pos.X - ctr.X
new_dx = _u2m(pos.X - ctr.X, doc) new_dy = pos.Y - ctr.Y
new_dy = _u2m(pos.Y - ctr.Y, doc) # Font/Style/Size aus der TextEntity lesen
# Font/Style/Size aus der TextEntity lesen. try: new_h = float(te.TextHeight)
# TextHeight ist in Doc-Units → fuer Storage (Meter) konvertieren
try: new_h = _u2m(float(te.TextHeight), doc)
except Exception: new_h = float(meta.get("raum_txt_h", 0.20)) except Exception: new_h = float(meta.get("raum_txt_h", 0.20))
cur_font = None cur_font = None
try: cur_font = te.Font try: cur_font = te.Font