Compare commits
2 Commits
5fd6aefd34
...
b14eb1e5dd
| Author | SHA1 | Date | |
|---|---|---|---|
| b14eb1e5dd | |||
| 68411a0ce9 |
@@ -767,10 +767,15 @@ def apply_visibility(doc, zeichnungsebenen, ebenen, active_z_id, active_code, z_
|
|||||||
is_active_e = (code == active_code)
|
is_active_e = (code == active_code)
|
||||||
eye_v = e_eye_vis.get(code, True)
|
eye_v = e_eye_vis.get(code, True)
|
||||||
eye_l = e_eye_locked.get(code, False)
|
eye_l = e_eye_locked.get(code, False)
|
||||||
|
# 'all_force' ueberschreibt das Eye-Flag (zeigt jede Ebene auch
|
||||||
|
# wenn die User-Sichtbarkeit aus war). 'all' respektiert das
|
||||||
|
# Flag (= "Ausgewählte" im UI).
|
||||||
if is_active_e:
|
if is_active_e:
|
||||||
e_vis, e_grey, e_lock = True, False, False
|
e_vis, e_grey, e_lock = True, False, False
|
||||||
elif e_mode == "active":
|
elif e_mode == "active":
|
||||||
e_vis, e_grey, e_lock = False, False, False
|
e_vis, e_grey, e_lock = False, False, False
|
||||||
|
elif e_mode == "all_force":
|
||||||
|
e_vis, e_grey, e_lock = True, False, False
|
||||||
elif not eye_v:
|
elif not eye_v:
|
||||||
e_vis, e_grey, e_lock = False, False, False
|
e_vis, e_grey, e_lock = False, False, False
|
||||||
elif e_mode == "all":
|
elif e_mode == "all":
|
||||||
|
|||||||
+22
-12
@@ -13,6 +13,7 @@ Collections die wir nutzen:
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import json
|
import json
|
||||||
|
import math
|
||||||
import zipfile
|
import zipfile
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
@@ -590,7 +591,7 @@ def xyz_to_grid(path, target_step=2.0, clip_bbox=None, progress=None):
|
|||||||
try: float(first[0])
|
try: float(first[0])
|
||||||
except Exception: start_idx = 1
|
except Exception: start_idx = 1
|
||||||
|
|
||||||
# --- 1. Pass: raw Step + Origin aus ersten ~200 Punkten erkennen
|
# --- 1. Pass: raw Step aus ersten ~200 Punkten erkennen
|
||||||
sample = []
|
sample = []
|
||||||
for ln in lines[start_idx:start_idx + 500]:
|
for ln in lines[start_idx:start_idx + 500]:
|
||||||
parts = ln.split()
|
parts = ln.split()
|
||||||
@@ -612,18 +613,25 @@ def xyz_to_grid(path, target_step=2.0, clip_bbox=None, progress=None):
|
|||||||
for i in range(len(sample) - 1)
|
for i in range(len(sample) - 1)
|
||||||
if abs(sample[i+1][1] - sample[i][1]) > 0.001})
|
if abs(sample[i+1][1] - sample[i][1]) > 0.001})
|
||||||
raw_n_step = n_diffs[0] if n_diffs else 0.5
|
raw_n_step = n_diffs[0] if n_diffs else 0.5
|
||||||
origin_e = min(p[0] for p in sample)
|
|
||||||
origin_n = min(p[1] for p in sample)
|
|
||||||
# Sub-Sampling-Faktoren — nur ganzzahlig damit das Raster regulaer bleibt
|
# Sub-Sampling-Faktoren — nur ganzzahlig damit das Raster regulaer bleibt
|
||||||
factor_e = max(1, int(round(target_step / raw_e_step)))
|
factor_e = max(1, int(round(target_step / raw_e_step)))
|
||||||
factor_n = max(1, int(round(target_step / raw_n_step)))
|
factor_n = max(1, int(round(target_step / raw_n_step)))
|
||||||
actual_step_e = raw_e_step * factor_e
|
actual_step_e = raw_e_step * factor_e
|
||||||
actual_step_n = raw_n_step * factor_n
|
actual_step_n = raw_n_step * factor_n
|
||||||
|
# Phase relativ zum globalen LV95-Raster: swissALTI3D 0.5m liegt z.B.
|
||||||
|
# auf .25-Marken (cell-center). Phase aus erstem Sample-Punkt ermitteln —
|
||||||
|
# gilt global fuer alle Tiles, da das Raster LV95-aligned ist.
|
||||||
|
e_phase = sample[0][0] - math.floor(sample[0][0] / raw_e_step) * raw_e_step
|
||||||
|
n_phase = sample[0][1] - math.floor(sample[0][1] / raw_n_step) * raw_n_step
|
||||||
if progress:
|
if progress:
|
||||||
progress("XYZ raw {:.2f}m → target {:.2f}m → sub-sample {}x{} ({:.2f}m actual)".format(
|
progress("XYZ raw {:.2f}m → target {:.2f}m → sub-sample {}x{} ({:.2f}m actual, phase {:.2f}/{:.2f})".format(
|
||||||
raw_e_step, target_step, factor_e, factor_n, actual_step_e))
|
raw_e_step, target_step, factor_e, factor_n, actual_step_e, e_phase, n_phase))
|
||||||
|
|
||||||
# --- 2. Pass: alle Punkte auf dem Sub-Raster behalten (+ optional clip)
|
# --- 2. Pass: alle Punkte auf dem Sub-Raster behalten (+ optional clip)
|
||||||
|
# WICHTIG: Sub-Sampling-Filter benutzt den GLOBALEN LV95-Raster-Index
|
||||||
|
# (mit detected phase) statt eines tile-lokalen origin. Sonst waehlt
|
||||||
|
# jedes Tile seine eigene Phase und am Tile-Boundary fehlen Faces /
|
||||||
|
# das Mesh ist nicht durchgehend.
|
||||||
points = {}
|
points = {}
|
||||||
es = set(); ns = set()
|
es = set(); ns = set()
|
||||||
cb = clip_bbox
|
cb = clip_bbox
|
||||||
@@ -635,13 +643,15 @@ def xyz_to_grid(path, target_step=2.0, clip_bbox=None, progress=None):
|
|||||||
except Exception: continue
|
except Exception: continue
|
||||||
if cb is not None:
|
if cb is not None:
|
||||||
if e < cb[0] or e > cb[2] or n < cb[1] or n > cb[3]: continue
|
if e < cb[0] or e > cb[2] or n < cb[1] or n > cb[3]: continue
|
||||||
# Raster-Pruefung: nur jeden factor_e-ten E-Schritt + factor_n-ten N-Schritt
|
# Globaler Index im swissALTI3D-Raster: alle Tiles teilen Phase
|
||||||
di = int(round((e - origin_e) / raw_e_step))
|
gi = int(round((e - e_phase) / raw_e_step))
|
||||||
dj = int(round((n - origin_n) / raw_n_step))
|
gj = int(round((n - n_phase) / raw_n_step))
|
||||||
if di % factor_e != 0 or dj % factor_n != 0: continue
|
if gi % factor_e != 0 or gj % factor_n != 0: continue
|
||||||
# Auf snapped Koords runden um Float-Drift zu vermeiden
|
# Originale Koordinaten als Key (Tile A und Tile B teilen Phase,
|
||||||
e_snap = origin_e + di * raw_e_step
|
# also matchen ihre Keys am Boundary direkt). round(3) gegen
|
||||||
n_snap = origin_n + dj * raw_n_step
|
# Float-Drift.
|
||||||
|
e_snap = round(e, 3)
|
||||||
|
n_snap = round(n, 3)
|
||||||
points[(e_snap, n_snap)] = z
|
points[(e_snap, n_snap)] = z
|
||||||
es.add(e_snap); ns.add(n_snap)
|
es.add(e_snap); ns.add(n_snap)
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import ContextMenu from './ContextMenu'
|
|||||||
import { setLayerStyle, deleteEbene, moveSelectionToEbene, openEbenenSettings } from '../lib/rhinoBridge'
|
import { setLayerStyle, deleteEbene, moveSelectionToEbene, openEbenenSettings } from '../lib/rhinoBridge'
|
||||||
|
|
||||||
const MODES = [
|
const MODES = [
|
||||||
{ value: 'all', label: 'Alle anzeigen' },
|
{ value: 'all_force', label: 'Alle anzeigen' },
|
||||||
|
{ value: 'all', label: 'Ausgewählte' },
|
||||||
{ value: 'active', label: 'Nur aktive' },
|
{ value: 'active', label: 'Nur aktive' },
|
||||||
{ value: 'grey', label: 'Andere grau' },
|
{ value: 'grey', label: 'Andere grau' },
|
||||||
{ value: 'grey_locked', label: 'Andere grau & gesperrt' },
|
{ value: 'grey_locked', label: 'Andere grau & gesperrt' },
|
||||||
@@ -208,11 +209,33 @@ function _allCodes(ebenen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function EbeneRow({ e, depth, hasChildren, expanded, onToggleExpand, active, mode, onClick, onContextMenu, onToggleVisible, onToggleLock, onColorChange, onLwChange, onNameChange, onCodeChange, onDelete, autoEditCode, autoEditName, rowRef }) {
|
function EbeneRow({ e, depth, hasChildren, expanded, onToggleExpand, active, mode, onClick, onContextMenu, onToggleVisible, onToggleLock, onColorChange, onLwChange, onNameChange, onCodeChange, onDelete, autoEditCode, autoEditName, rowRef }) {
|
||||||
// Auge zeigt den Eye-State (User-Intention) — auch fuer die aktive Ebene.
|
// Auge-Logik analog GeschossManager: immer rendern, nur dimmen wenn Mode
|
||||||
// So sieht man auf einen Blick ob sie "normalerweise" sichtbar waere.
|
// das Eye-Flag ueberschreibt (active / all_force). Klick auf Auge in
|
||||||
// Aktive Ebene rendert Rhino zwar immer sichtbar, das visible-Flag bleibt
|
// diesen Modi wechselt zu "Ausgewählte" damit die Aktion wirkt.
|
||||||
// aber die gespeicherte Intention bis sie wieder de-aktiviert wird.
|
let eyeIcon, eyeOn, eyeOpacity, eyeTitle
|
||||||
const eyeShown = mode !== 'active'
|
if (active) {
|
||||||
|
eyeIcon = e.visible !== false ? 'visibility' : 'visibility_off'
|
||||||
|
eyeOn = true
|
||||||
|
eyeOpacity = 1
|
||||||
|
eyeTitle = e.visible !== false
|
||||||
|
? 'Normalerweise sichtbar (aktive Ebene wird trotzdem gezeigt)'
|
||||||
|
: 'Normalerweise ausgeblendet — wird nur sichtbar weil aktiv'
|
||||||
|
} else if (mode === 'all_force') {
|
||||||
|
eyeIcon = 'visibility'
|
||||||
|
eyeOn = true
|
||||||
|
eyeOpacity = 0.35
|
||||||
|
eyeTitle = 'Im „Alle anzeigen"-Mode immer sichtbar — Klick wechselt in „Ausgewählte"'
|
||||||
|
} else if (mode === 'active') {
|
||||||
|
eyeIcon = e.visible !== false ? 'visibility' : 'visibility_off'
|
||||||
|
eyeOn = false
|
||||||
|
eyeOpacity = 0.35
|
||||||
|
eyeTitle = 'Im „Nur aktive"-Mode ausgeblendet — Klick wechselt in „Ausgewählte"'
|
||||||
|
} else {
|
||||||
|
eyeIcon = e.visible !== false ? 'visibility' : 'visibility_off'
|
||||||
|
eyeOn = e.visible !== false
|
||||||
|
eyeOpacity = 1
|
||||||
|
eyeTitle = e.visible !== false ? 'Ausblenden' : 'Einblenden'
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={rowRef}
|
ref={rowRef}
|
||||||
@@ -247,21 +270,12 @@ function EbeneRow({ e, depth, hasChildren, expanded, onToggleExpand, active, mod
|
|||||||
) : (
|
) : (
|
||||||
<span style={{ width: 14, flexShrink: 0 }} />
|
<span style={{ width: 14, flexShrink: 0 }} />
|
||||||
)}
|
)}
|
||||||
{eyeShown ? (
|
<button
|
||||||
<button
|
className={`btn-icon-sm ${eyeOn ? 'is-on' : ''}`}
|
||||||
className={`btn-icon-sm ${e.visible !== false ? 'is-on' : ''}`}
|
onClick={(ev) => { ev.stopPropagation(); onToggleVisible() }}
|
||||||
onClick={(ev) => { ev.stopPropagation(); onToggleVisible() }}
|
title={eyeTitle}
|
||||||
title={
|
style={{ opacity: eyeOpacity }}
|
||||||
active
|
><Icon name={eyeIcon} size={14} /></button>
|
||||||
? (e.visible !== false
|
|
||||||
? 'Normalerweise sichtbar (aktive Ebene wird trotzdem gezeigt)'
|
|
||||||
: 'Normalerweise ausgeblendet — wird nur sichtbar weil aktiv')
|
|
||||||
: (e.visible !== false ? 'Ausblenden' : 'Einblenden')
|
|
||||||
}
|
|
||||||
><Icon name={e.visible !== false ? 'visibility' : 'visibility_off'} size={14} /></button>
|
|
||||||
) : (
|
|
||||||
<span style={{ width: 18, flexShrink: 0 }} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
<EditableText
|
<EditableText
|
||||||
value={e.code}
|
value={e.code}
|
||||||
@@ -382,6 +396,10 @@ export default function EbenenManager({
|
|||||||
const handleToggleVisible = (code) => {
|
const handleToggleVisible = (code) => {
|
||||||
const cur = _findInTree(ebenen, code)
|
const cur = _findInTree(ebenen, code)
|
||||||
if (cur) updateByCode(code, { visible: !(cur.visible !== false) })
|
if (cur) updateByCode(code, { visible: !(cur.visible !== false) })
|
||||||
|
// In "active" / "all_force" greift visible-Flag nicht — wer aufs Auge
|
||||||
|
// klickt will offensichtlich Sichtbarkeit kontrollieren, also direkt
|
||||||
|
// in den "Ausgewählte"-Mode wechseln damit die Aktion wirkt.
|
||||||
|
if (mode === 'active' || mode === 'all_force') onModeChange('all')
|
||||||
}
|
}
|
||||||
const handleToggleLock = (code) => {
|
const handleToggleLock = (code) => {
|
||||||
const cur = _findInTree(ebenen, code)
|
const cur = _findInTree(ebenen, code)
|
||||||
@@ -555,11 +573,13 @@ export default function EbenenManager({
|
|||||||
const anyVisible = ebenen.some(e => e.visible !== false)
|
const anyVisible = ebenen.some(e => e.visible !== false)
|
||||||
// Wenn irgendeine sichtbar -> alle aus. Wenn keine sichtbar -> alle an.
|
// Wenn irgendeine sichtbar -> alle aus. Wenn keine sichtbar -> alle an.
|
||||||
onChange(ebenen.map(e => ({ ...e, visible: !anyVisible })))
|
onChange(ebenen.map(e => ({ ...e, visible: !anyVisible })))
|
||||||
|
if (mode === 'active' || mode === 'all_force') onModeChange('all')
|
||||||
}}
|
}}
|
||||||
title={ebenen.every(e => e.visible !== false)
|
title={ebenen.every(e => e.visible !== false)
|
||||||
? 'Alle Ebenen ausblenden'
|
? 'Alle Ebenen ausblenden'
|
||||||
: 'Alle Ebenen einblenden'}
|
: 'Alle Ebenen einblenden'}
|
||||||
style={{ width: 18, height: 18 }}
|
style={{ width: 18, height: 18,
|
||||||
|
opacity: (mode === 'active' || mode === 'all_force') ? 0.5 : 1 }}
|
||||||
>
|
>
|
||||||
<Icon
|
<Icon
|
||||||
name={ebenen.every(e => e.visible !== false) ? 'visibility' : 'visibility_off'}
|
name={ebenen.every(e => e.visible !== false) ? 'visibility' : 'visibility_off'}
|
||||||
|
|||||||
Reference in New Issue
Block a user