This commit is contained in:
2026-01-22 08:51:18 +01:00
parent 7a170f5ead
commit 7c1b335b1c
5 changed files with 49478 additions and 49398 deletions

View File

@@ -15,37 +15,43 @@ class Genauigkeitsmaße:
return float(s0apost)
@staticmethod
def helmert_punktfehler(Qxx, s0_apost, unbekannten_liste, dim=3):
diagQ = np.diag(Qxx)
daten = []
namen_str = [str(sym) for sym in unbekannten_liste]
n_punkte = len(unbekannten_liste) // 3
punkt_ids = []
for n in namen_str:
if n.upper().startswith('X'):
punkt_ids.append(n[1:])
for i in range(n_punkte):
sym_x = str(unbekannten_liste[3 * i]) # z.B. "X10009"
punkt = sym_x[1:] # -> "10009"
for pid in punkt_ids:
try:
idx_x = next(i for i, n in enumerate(namen_str) if n.upper() == f"X{pid}".upper())
idx_y = next(i for i, n in enumerate(namen_str) if n.upper() == f"Y{pid}".upper())
qx = diagQ[3 * i]
qy = diagQ[3 * i + 1]
qz = diagQ[3 * i + 2]
qx = diagQ[idx_x]
qy = diagQ[idx_y]
qz = 0.0
sx = s0_apost * np.sqrt(qx)
sy = s0_apost * np.sqrt(qy)
sz = s0_apost * np.sqrt(qz)
if dim == 3:
try:
idx_z = next(i for i, n in enumerate(namen_str) if n.upper() == f"Z{pid}".upper())
qz = diagQ[idx_z]
except StopIteration:
qz = 0.0
sx = s0_apost * np.sqrt(qx)
sy = s0_apost * np.sqrt(qy)
sz = s0_apost * np.sqrt(qz) if dim == 3 else 0
if dim == 2:
sP = s0_apost * np.sqrt(qx + qy)
else:
sP = s0_apost * np.sqrt(qx + qy + qz)
daten.append([
punkt,
float(sx),
float(sy),
float(sz),
float(sP)
])
daten.append([pid, float(sx), float(sy), float(sz), float(sP)])
except:
continue
helmert_punktfehler = pd.DataFrame(daten, columns=["Punkt", "σx", "σy", "σz", f"σP_{dim}D"])
return helmert_punktfehler
@@ -256,4 +262,173 @@ def plot_netz_komplett_final(x_vektor, unbekannten_labels, beobachtungs_labels,
align='left', showarrow=False, xref='paper', yref='paper', x=0.02, y=0.05,
bgcolor="white", bordercolor="black", borderwidth=1)
fig.show(config={'scrollZoom': True})
fig.show(config={'scrollZoom': True})
def plot_netz_final_mit_df_ellipsen(x_vektor, unbekannten_labels, beobachtungs_labels, df_ellipsen, v_faktor=1000):
# 1. Punkte extrahieren
coords = {}
# Wir nehmen an, dass die Reihenfolge im x_vektor X, Y, Z pro Punkt ist
punkt_ids = sorted(set(str(l)[1:] for l in unbekannten_labels if str(l).startswith(('X', 'Y', 'Z'))))
for pid in punkt_ids:
try:
ix = next(i for i, s in enumerate(unbekannten_labels) if str(s) == f"X{pid}")
iy = next(i for i, s in enumerate(unbekannten_labels) if str(s) == f"Y{pid}")
coords[pid] = (float(x_vektor[ix]), float(x_vektor[iy]))
except:
continue
fig = go.Figure()
# 2. Beobachtungslinien (Gruppiert)
beob_typen = {
'GNSS-Basislinien': {'pattern': 'gnss', 'color': 'rgba(255, 100, 0, 0.4)'},
'Nivellement': {'pattern': 'niv', 'color': 'rgba(0, 200, 100, 0.4)'},
'Tachymeter': {'pattern': '', 'color': 'rgba(100, 100, 100, 0.3)'}
}
for typ, info in beob_typen.items():
x_l, y_l = [], []
for bl in beobachtungs_labels:
bl_str = str(bl).lower()
# Einfache Logik zur Typtrennung
if (info['pattern'] in bl_str and info['pattern'] != '') or \
(info['pattern'] == '' and 'gnss' not in bl_str and 'niv' not in bl_str):
pts = [pid for pid in coords if f"_{pid}" in str(bl) or str(bl).startswith(f"{pid}_")]
if len(pts) >= 2:
x_l.extend([coords[pts[0]][0], coords[pts[1]][0], None])
y_l.extend([coords[pts[0]][1], coords[pts[1]][1], None])
if x_l:
fig.add_trace(go.Scatter(x=x_l, y=y_l, mode='lines', name=typ, line=dict(color=info['color'], width=1)))
# 3. Ellipsen aus dem DataFrame zeichnen
for _, row in df_ellipsen.iterrows():
pid = str(row['Punkt'])
if pid in coords:
x0, y0 = coords[pid]
# Werte aus DF (mit v_faktor skalieren)
a = row['a_K'] * v_faktor
b = row['b_K'] * v_faktor
theta_gon = row['θ [gon]']
# Umrechnung: gon -> rad für die Rotation
# Da im Plot X horizontal und Y vertikal ist, entspricht theta_gon dem Winkel zur X-Achse
theta_rad = theta_gon * (np.pi / 200.0)
# Ellipsen berechnen
t = np.linspace(0, 2 * np.pi, 50)
e_x = a * np.cos(t)
e_y = b * np.sin(t)
# Ausrichtung der Ellipsen
R = np.array([[np.cos(theta_rad), -np.sin(theta_rad)],
[np.sin(theta_rad), np.cos(theta_rad)]])
rot = np.dot(R, np.array([e_x, e_y]))
fig.add_trace(go.Scatter(
x=rot[0, :] + x0, y=rot[1, :] + y0,
mode='lines', line=dict(color='red', width=1.5),
name='Konfidenzellipsen',
legendgroup='Ellipsen',
showlegend=(pid == df_ellipsen.iloc[0]['Punkt']),
hoverinfo='text',
text=f"Punkt {pid}<br>a_K: {row['a_K']:.4f}m<br>b_K: {row['b_K']:.4f}m"
))
# Punkte plotten
df_pts = pd.DataFrame([(pid, c[0], c[1]) for pid, c in coords.items()], columns=['ID', 'X', 'Y'])
fig.add_trace(go.Scatter(
x=df_pts['X'], y=df_pts['Y'], mode='markers+text',
text=df_pts['ID'], textposition="top center",
marker=dict(size=8, color='black'), name="Netzpunkte"))
# Layout
fig.update_layout(
title=f"Netzplot (Ellipsen {v_faktor}x überhöht)",
xaxis=dict(title="X [m]", tickformat="f", separatethousands=True, scaleanchor="y", scaleratio=1,
showgrid=True, gridcolor='lightgrey'),
yaxis=dict(title="Y [m]", tickformat="f", separatethousands=True, showgrid=True, gridcolor='lightgrey'),
width=1100, height=900,
plot_bgcolor='white')
# Maßstabsangabe
fig.add_annotation(
text=f"<b>Skalierung:</b><br>Ellipsengröße im Plot = {v_faktor} × Realität",
align='left', showarrow=False, xref='paper', yref='paper', x=0.02, y=0.02,
bgcolor="rgba(255,255,255,0.8)", bordercolor="black", borderwidth=1)
fig.show(config={'scrollZoom': True})
import plotly.graph_objects as go
import numpy as np
def plot_netz_3D(x_vektor, unbekannten_labels, beobachtungs_labels, df_ellipsen, v_faktor=1000):
"""
Erzeugt einen interaktiven 3D-Plot des Netzes.
- v_faktor: Vergrößerung der Genauigkeits-Achsen (z.B. 1000 für mm -> m)
"""
# 1. Punkte extrahieren
pts = {}
punkt_ids = sorted(set(str(l)[1:] for l in unbekannten_labels if str(l).startswith(('X', 'Y', 'Z'))))
for pid in punkt_ids:
try:
ix = next(i for i, s in enumerate(unbekannten_labels) if str(s) == f"X{pid}")
iy = next(i for i, s in enumerate(unbekannten_labels) if str(s) == f"Y{pid}")
iz = next(i for i, s in enumerate(unbekannten_labels) if str(s) == f"Z{pid}")
pts[pid] = (float(x_vektor[ix]), float(x_vektor[iy]), float(x_vektor[iz]))
except:
continue
fig = go.Figure()
# 2. Beobachtungen (Linien im Raum)
# Wir zeichnen hier einfach alle Verbindungen
x_line, y_line, z_line = [], [], []
for bl in beobachtungs_labels:
p_in_l = [pid for pid in pts if f"_{pid}" in str(bl) or str(bl).startswith(f"{pid}_")]
if len(p_in_l) >= 2:
p1, p2 = pts[p_in_l[0]], pts[p_in_l[1]]
x_line.extend([p1[0], p2[0], None])
y_line.extend([p1[1], p2[1], None])
z_line.extend([p1[2], p2[2], None])
fig.add_trace(go.Scatter3d(
x=x_line, y=y_line, z=z_line,
mode='lines', line=dict(color='gray', width=2),
name='Beobachtungen'
))
# 3. Punkte & "Fehler-Kreuze" (als Ersatz für Ellipsoide)
# Ein echtes 3D-Ellipsoid ist grafisch schwer, daher zeichnen wir 3 Achsen
for pid, coord in pts.items():
# Hier könnten wir die echten Halbachsen aus der 3D-Eigenwertanalyse nutzen
# Für den Anfang plotten wir die Standardabweichungen sX, sY, sZ als Kreuz
fig.add_trace(go.Scatter3d(
x=[coord[0]], y=[coord[1]], z=[coord[2]],
mode='markers+text', text=[pid],
marker=dict(size=4, color='black'), name=f'Punkt {pid}'
))
# 4. Layout
fig.update_layout(
scene=dict(
xaxis_title='X [m]',
yaxis_title='Y [m]',
zaxis_title='Z [m]',
aspectmode='data' # WICHTIG: Verhältnisse 1:1:1 bewahren
),
width=1000, height=800,
title="Geozentrisches Netz in 3D"
)
fig.show()
# Aufruf