Raumstempel: masstab-Modus — Texthoehe als Paper-mm @ Plan-Massstab
Neuer UserString dossier_raum_txt_modus = "fix" | "masstab" (default fix).
- fix: raum_txt_h ist Meter (Modellhoehe, bisheriges Verhalten)
- masstab: raum_txt_h ist Paper-mm. Render-Hoehe (m) =
paper_mm * applied_scale / 1000 — wird zur Render-Zeit aus
massstab.get_applied_scale_ratio() gelesen, Fallback 1:100.
Massstab-Sync:
- massstab._apply_scale ruft nach Skala-Wechsel elemente.regen_masstab_raeume(doc)
→ alle Raeume im masstab-Modus regennen automatisch, Texthoehe folgt der
neuen Skala (z.B. Switch 1:100 → 1:50 halbiert die Modellhoehe).
_sync_raum_stamps_to_source masstab-aware: im masstab-Modus wird die
TextHeight am Stempel NICHT zurueck auf raum_txt_h gespiegelt (sie ist
abgeleitet, nicht die Wahrheit) — sonst waere der naechste Regen sofort
falsch positioniert. Offset + Font/Style werden weiterhin gespiegelt.
UI: Modus-Toggle "fix m" / "masstab mm" + Hoehen-Input + Einheits-Suffix
in RaumProperties zwischen Ausrichtung und Funktion.
This commit is contained in:
+88
-8
@@ -314,6 +314,10 @@ _KEY_RAUM_SHOW_SIA = "dossier_raum_show_sia"
|
||||
# naechsten Outline-Modify nicht wieder auf den Centroid zurueck-snapped.
|
||||
_KEY_RAUM_STAMP_DX = "dossier_raum_stamp_dx"
|
||||
_KEY_RAUM_STAMP_DY = "dossier_raum_stamp_dy"
|
||||
# Texthoehen-Modus:
|
||||
# "fix" → raum_txt_h ist Meter (Modellhoehe), aktuelles Default-Verhalten
|
||||
# "masstab" → raum_txt_h ist Paper-mm (gerendert × applied_scale / 1000)
|
||||
_KEY_RAUM_TXT_MODUS = "dossier_raum_txt_modus"
|
||||
# Field-Layout als JSON-Array von Rows. Jede Row ist eine Liste von
|
||||
# Field-IDs. Z.B. [["nummer","name","area"],["funktion"]] → eine Zeile mit
|
||||
# Nummer+Name+Flaeche, dann Funktion auf eigener Zeile. Leer = legacy
|
||||
@@ -2597,7 +2601,7 @@ def _attach_meta(obj_attrs, wall_id, type_, geschoss, dicke, uk_over, ok_over,
|
||||
raum_show_funktion=None, raum_show_area=None,
|
||||
raum_show_sia=None,
|
||||
raum_stamp_dx=None, raum_stamp_dy=None,
|
||||
raum_layout=None,
|
||||
raum_layout=None, raum_txt_modus=None,
|
||||
wand_layered=None, wand_layers=None, wand_layer_idx=None,
|
||||
wand_chain_members=None,
|
||||
aussp_parent=None):
|
||||
@@ -2800,6 +2804,8 @@ def _attach_meta(obj_attrs, wall_id, type_, geschoss, dicke, uk_over, ok_over,
|
||||
_json.dumps(raum_layout))
|
||||
except Exception as ex:
|
||||
print("[ELEMENTE] raum_layout set:", ex)
|
||||
if raum_txt_modus is not None and raum_txt_modus in ("fix", "masstab"):
|
||||
obj_attrs.SetUserString(_KEY_RAUM_TXT_MODUS, raum_txt_modus)
|
||||
# Wand-Schichten
|
||||
if wand_layered is not None:
|
||||
obj_attrs.SetUserString(_KEY_WAND_LAYERED,
|
||||
@@ -2995,6 +3001,9 @@ def _read_meta(obj):
|
||||
except Exception: r_stamp_dx = 0.0
|
||||
try: r_stamp_dy = float(a.GetUserString(_KEY_RAUM_STAMP_DY) or "0")
|
||||
except Exception: r_stamp_dy = 0.0
|
||||
# Texthoehen-Modus (default "fix" — Backwards-Compat)
|
||||
r_txt_modus = a.GetUserString(_KEY_RAUM_TXT_MODUS) or "fix"
|
||||
if r_txt_modus not in ("fix", "masstab"): r_txt_modus = "fix"
|
||||
# Field-Layout — parsed JSON list of rows
|
||||
r_layout_raw = a.GetUserString(_KEY_RAUM_LAYOUT) or ""
|
||||
r_layout = []
|
||||
@@ -3115,6 +3124,7 @@ def _read_meta(obj):
|
||||
"raum_stamp_dx": r_stamp_dx,
|
||||
"raum_stamp_dy": r_stamp_dy,
|
||||
"raum_layout": r_layout,
|
||||
"raum_txt_modus": r_txt_modus,
|
||||
"wand_layered": w_layered,
|
||||
"wand_layers": w_layers,
|
||||
"wand_layer_idx": w_layer_idx,
|
||||
@@ -4712,6 +4722,27 @@ def _format_area(area, rundung):
|
||||
return "{:.2f}".format(a) # exakt
|
||||
|
||||
|
||||
def _resolve_raum_text_height_m(value, modus):
|
||||
"""Konvertiert raum_txt_h (User-Wert) in Modell-Meter, je nach Modus:
|
||||
modus=fix → value ist bereits Meter
|
||||
modus=masstab → value ist Paper-mm, Modell-Meter = value*scale/1000
|
||||
(scale aus aktivem Viewport via massstab.get_applied_scale_ratio)
|
||||
Fallback bei fehlendem Massstab: 100 (1:100).
|
||||
"""
|
||||
try: v = float(value)
|
||||
except Exception: v = 0.20
|
||||
if (modus or "fix") != "masstab":
|
||||
return v
|
||||
try:
|
||||
import massstab as _ms
|
||||
sc_ratio = _ms.get_applied_scale_ratio() or _ms.get_current_scale_ratio()
|
||||
except Exception:
|
||||
sc_ratio = None
|
||||
if not sc_ratio or sc_ratio <= 0:
|
||||
sc_ratio = 100.0
|
||||
return float(v) * float(sc_ratio) / 1000.0
|
||||
|
||||
|
||||
def _make_raum_stamp_text(centroid, name, nummer, funktion, area, rundung,
|
||||
text_height, z=0.0, align="mid",
|
||||
font=None, bold=False, italic=False,
|
||||
@@ -6163,6 +6194,10 @@ def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name
|
||||
sx = float(meta.get("raum_stamp_dx", 0.0))
|
||||
sy = float(meta.get("raum_stamp_dy", 0.0))
|
||||
stamp_pt = rg.Point3d(ctr.X + sx, ctr.Y + sy, ctr.Z)
|
||||
# Texthoehe: bei modus=masstab aus Paper-mm + aktuellem Scale aufloesen
|
||||
eff_h = _resolve_raum_text_height_m(
|
||||
meta.get("raum_txt_h", 0.20),
|
||||
meta.get("raum_txt_modus", "fix"))
|
||||
te = _make_raum_stamp_text(
|
||||
stamp_pt,
|
||||
meta.get("raum_name", "Raum"),
|
||||
@@ -6170,7 +6205,7 @@ def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name
|
||||
meta.get("raum_funktion", ""),
|
||||
area,
|
||||
_resolve_raum_rundung(meta, doc),
|
||||
meta.get("raum_txt_h", 0.20),
|
||||
eff_h,
|
||||
z=z_uk,
|
||||
align=meta.get("raum_align", "mid"),
|
||||
font=meta.get("raum_txt_font", ""),
|
||||
@@ -6205,7 +6240,8 @@ def _regenerate_element_body(doc, element_id, src_obj, meta, geom, geschoss_name
|
||||
raum_show_name=meta.get("raum_show_name"),
|
||||
raum_show_funktion=meta.get("raum_show_funktion"),
|
||||
raum_show_area=meta.get("raum_show_area"),
|
||||
raum_show_sia=meta.get("raum_show_sia"))
|
||||
raum_show_sia=meta.get("raum_show_sia"),
|
||||
raum_txt_modus=meta.get("raum_txt_modus"))
|
||||
try: doc.Objects.AddText(te, attrs)
|
||||
except Exception as ex: print("[ELEMENTE] Raum AddText:", ex)
|
||||
return True
|
||||
@@ -6542,6 +6578,7 @@ class ElementeBridge(panel_base.BaseBridge):
|
||||
"showArea": bool(meta.get("raum_show_area", True)),
|
||||
"showSia": bool(meta.get("raum_show_sia", False)),
|
||||
"layout": meta.get("raum_layout") or [],
|
||||
"txtModus": meta.get("raum_txt_modus", "fix"),
|
||||
"area": area,
|
||||
"areaFmt": _format_area(area, rnd_eff),
|
||||
"umfang": perim,
|
||||
@@ -10038,6 +10075,8 @@ class ElementeBridge(panel_base.BaseBridge):
|
||||
# nicht im Patch → vom alten meta uebernehmen.
|
||||
r_layout = p.get("layout", old_meta.get("raum_layout", []))
|
||||
if not isinstance(r_layout, list): r_layout = []
|
||||
r_modus = p.get("txtModus", old_meta.get("raum_txt_modus", "fix"))
|
||||
if r_modus not in ("fix", "masstab"): r_modus = "fix"
|
||||
gstart = p.get("geschoss", old_meta["geschoss"])
|
||||
attrs = axis_obj.Attributes
|
||||
if gstart != old_meta["geschoss"]:
|
||||
@@ -10062,7 +10101,8 @@ class ElementeBridge(panel_base.BaseBridge):
|
||||
raum_show_funktion=r_show_fkt,
|
||||
raum_show_area=r_show_are,
|
||||
raum_show_sia=r_show_sia,
|
||||
raum_layout=r_layout)
|
||||
raum_layout=r_layout,
|
||||
raum_txt_modus=r_modus)
|
||||
axis_obj.Attributes = attrs
|
||||
axis_obj.CommitChanges()
|
||||
_save_last(raum_name_last=r_name, raum_rundung=r_rnd,
|
||||
@@ -10076,7 +10116,8 @@ class ElementeBridge(panel_base.BaseBridge):
|
||||
raum_show_funktion=r_show_fkt,
|
||||
raum_show_area=r_show_are,
|
||||
raum_show_sia=r_show_sia,
|
||||
raum_layout=r_layout)
|
||||
raum_layout=r_layout,
|
||||
raum_txt_modus=r_modus)
|
||||
_regenerate_volume(doc, wall_id)
|
||||
doc.Views.Redraw()
|
||||
self._send_state()
|
||||
@@ -12035,6 +12076,37 @@ def _on_command_begin(sender, e):
|
||||
sc.sticky["_dossier_undo_serial"] = None
|
||||
|
||||
|
||||
def regen_masstab_raeume(doc=None):
|
||||
"""Regennt alle Raeume im masstab-Modus. Wird vom Massstab-Modul
|
||||
aufgerufen wenn der Plan-Massstab des aktiven Viewports geaendert wird
|
||||
— die Stempel-Texthoehe haengt am applied_scale und muss neu gerendert
|
||||
werden. Idempotent: macht nichts wenn keine masstab-Raeume da sind."""
|
||||
if doc is None: doc = Rhino.RhinoDoc.ActiveDoc
|
||||
if doc is None: return 0
|
||||
if sc.sticky.get(_REGEN_BUSY): return 0
|
||||
ids = []
|
||||
for obj in doc.Objects:
|
||||
try:
|
||||
m = _read_meta(obj)
|
||||
if not m or m.get("type") != "raum_outline": continue
|
||||
if m.get("raum_txt_modus") == "masstab":
|
||||
ids.append(m["id"])
|
||||
except Exception: pass
|
||||
if not ids: return 0
|
||||
_was_busy = sc.sticky.get(_REGEN_BUSY, False)
|
||||
sc.sticky[_REGEN_BUSY] = True
|
||||
try:
|
||||
for rid in ids:
|
||||
try: _regenerate_element(doc, rid)
|
||||
except Exception as ex:
|
||||
print("[ELEMENTE] regen_masstab_raeume", rid, ":", ex)
|
||||
finally:
|
||||
sc.sticky[_REGEN_BUSY] = _was_busy
|
||||
try: doc.Views.Redraw()
|
||||
except Exception: pass
|
||||
return len(ids)
|
||||
|
||||
|
||||
def _sync_raum_stamps_to_source(doc):
|
||||
"""Sync raum_stamp TextEntities → raum_outline Source-UserStrings.
|
||||
|
||||
@@ -12108,10 +12180,17 @@ def _sync_raum_stamps_to_source(doc):
|
||||
old_face = meta.get("raum_txt_font", "") or ""
|
||||
old_bold = bool(meta.get("raum_txt_bold", False))
|
||||
old_ital = bool(meta.get("raum_txt_italic", False))
|
||||
# Im masstab-Modus ist die TextHeight am Stempel abgeleitet
|
||||
# (paper_mm * scale / 1000) — NICHT zurueck-spiegeln, sonst
|
||||
# waere der naechste Regen sofort verschoben. Wenn der User
|
||||
# die Hoehe via Oberleiste aendert: er muss erst zurueck in
|
||||
# den fix-Modus, oder die Paper-mm in der UI editieren.
|
||||
modus = meta.get("raum_txt_modus", "fix")
|
||||
sync_height = (modus != "masstab")
|
||||
changed = (
|
||||
abs(new_dx - old_dx) > 1e-6 or
|
||||
abs(new_dy - old_dy) > 1e-6 or
|
||||
abs(new_h - old_h) > 1e-6 or
|
||||
(sync_height and abs(new_h - old_h) > 1e-6) or
|
||||
new_face != old_face or
|
||||
new_bold != old_bold or
|
||||
new_ital != old_ital
|
||||
@@ -12122,8 +12201,9 @@ def _sync_raum_stamps_to_source(doc):
|
||||
"{:.6f}".format(new_dx))
|
||||
attrs.SetUserString(_KEY_RAUM_STAMP_DY,
|
||||
"{:.6f}".format(new_dy))
|
||||
attrs.SetUserString(_KEY_RAUM_TXT_H,
|
||||
"{:.4f}".format(new_h))
|
||||
if sync_height:
|
||||
attrs.SetUserString(_KEY_RAUM_TXT_H,
|
||||
"{:.4f}".format(new_h))
|
||||
attrs.SetUserString(_KEY_RAUM_TXT_FONT, new_face)
|
||||
attrs.SetUserString(_KEY_RAUM_TXT_BOLD,
|
||||
"1" if new_bold else "0")
|
||||
|
||||
@@ -890,6 +890,16 @@ def _apply_scale(doc, vp, ratio):
|
||||
apply_scaled_hatches(doc, float(ratio))
|
||||
except Exception as ex:
|
||||
print("[MASSSTAB] Hatch-Rescale:", ex)
|
||||
# Raumstempel im masstab-Modus skalieren mit dem Scale-Wechsel —
|
||||
# ihre TextHeight ist (paper_mm * scale / 1000) und muss neu
|
||||
# gerendert werden. Lazy-Import um circular dep zu vermeiden.
|
||||
try:
|
||||
import elemente as _el
|
||||
n_regen = _el.regen_masstab_raeume(doc)
|
||||
if n_regen > 0:
|
||||
print("[MASSSTAB] {} masstab-Raum/Raeume regenned".format(n_regen))
|
||||
except Exception as ex:
|
||||
print("[MASSSTAB] Raumstempel-Regen:", ex)
|
||||
# Neuen Wert persistieren — sowohl per-Viewport (fuer das Dropdown,
|
||||
# damit jeder Viewport seinen eigenen Massstab behaelt) als auch als
|
||||
# globaler "letzter Wert" (Legacy-Key; wird von Plotweight/Hatch-Rescale
|
||||
|
||||
Reference in New Issue
Block a user