anpassung ellipsoide und so

This commit is contained in:
2026-02-11 17:51:22 +01:00
parent f2a83d63e7
commit 8b928c1bb7
3 changed files with 30312 additions and 30138 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -393,7 +393,7 @@ class ENU:
""" """
@staticmethod @staticmethod
def berechne_schwerpunkt_fuer_enu(berechnungen, dict_xyz: dict) -> tuple: def berechne_schwerpunkt_fuer_enu(berechnungen: Any, dict_xyz: dict) -> tuple:
""" """
Berechnet die ENU-Referenz (B0, L0) aus dem Schwerpunkt gegebener XYZ-Koordinaten. Berechnet die ENU-Referenz (B0, L0) aus dem Schwerpunkt gegebener XYZ-Koordinaten.
@@ -413,7 +413,7 @@ class ENU:
@staticmethod @staticmethod
def berechne_R0_ENU(berechnungen, B: float, L:float) -> np.ndarray: def berechne_R0_ENU(berechnungen: Any, B: float, L:float) -> np.ndarray:
""" """
Erzeugt die 3×3-Rotationsmatrix R0 für die Transformation von XYZ nach ENU. Erzeugt die 3×3-Rotationsmatrix R0 für die Transformation von XYZ nach ENU.

View File

@@ -13,11 +13,12 @@ class Genauigkeitsmaße:
Die Klasse stellt Methoden zur Verfügung für: Die Klasse stellt Methoden zur Verfügung für:
- Berechnung der a-posteriori Standardabweichung der Gewichtseinheit σ̂₀ - Berechnung der a posteriori Standardabweichung der Gewichtseinheit σ̂₀
- Berechnung des Helmertschen Punktfehlers (2D/3D), - Berechnung des Helmertschen Punktfehlers (2D/3D),
- Berechnung der Standardellipse (Helmertschen Fehlerellipse), - Berechnung der Standardellipsoide,
- Berechnung der Konfidenzellipse auf Basis eines Konfidenzniveaus (alpha) mit Skalierung über die F-Verteilung, - Berechnung der Konfidenzellipsoide auf Basis eines Konfidenzniveaus (alpha) mit Skalierung über die F-Verteilung,
- Berechnung von Konfidenzellipsen im lokalen ENU-System durch Transformation von Qxx → Qxx_ENU, - Berechnung der Konfidenzellipsen auf Basis eines Konfidenzniveaus (alpha) mit Skalierung über die F-Verteilung,
- Berechnung von Konfidenzellipsen im lokalen ENU-System durch Transformation von Qxx zu Qxx_ENU,
inkl. Ausgabe/Export tabellarischer Ergebnisse. inkl. Ausgabe/Export tabellarischer Ergebnisse.
""" """
@@ -27,7 +28,7 @@ class Genauigkeitsmaße:
""" """
Berechnet die a-posteriori Standardabweichung der Gewichtseinheit σ̂₀. Berechnet die a-posteriori Standardabweichung der Gewichtseinheit σ̂₀.
Die a-posteriori Standardabweichung dient als Qualitätsmaß für die Die a posteriori Standardabweichung dient als Qualitätsmaß für die
Ausgleichung nach der Methode der kleinsten Quadrate. Dabei beschreibt Ausgleichung nach der Methode der kleinsten Quadrate. Dabei beschreibt
r die Redundanz (Freiheitsgrade). r die Redundanz (Freiheitsgrade).
@@ -55,7 +56,7 @@ class Genauigkeitsmaße:
Berechnet den Helmertschen Punktfehler (2D/3D) anhand der Standardabweichungen der Koordinaten der Punkte. Berechnet den Helmertschen Punktfehler (2D/3D) anhand der Standardabweichungen der Koordinaten der Punkte.
Aus der Kofaktor-Matrix der Unbekannten Qxx werden die Kofaktoren punktweise ausgelesen. Durch Multiplikation Aus der Kofaktor-Matrix der Unbekannten Qxx werden die Kofaktoren punktweise ausgelesen. Durch Multiplikation
mit der a-posteriori Standardabweichung der Gewichtseinheit σ̂₀ werden die Standardabweichungen je Koordinate mit der a posteriori Standardabweichung der Gewichtseinheit σ̂₀ werden die Standardabweichungen je Koordinate
(σx, σy, σz) sowie der Helmert'sche Punktfehler σP berechnet: (σx, σy, σz) sowie der Helmert'sche Punktfehler σP berechnet:
Die Punktzuordnung erfolgt über die Symbolnamen der Unbekanntenliste. Die Punktzuordnung erfolgt über die Symbolnamen der Unbekanntenliste.
@@ -108,7 +109,7 @@ class Genauigkeitsmaße:
continue continue
helmert_punktfehler = pd.DataFrame(daten, columns=["Punkt", "σ̂x", "σ̂y", "σ̂z", f"σ̂P_{dim}D"]) helmert_punktfehler = pd.DataFrame(daten, columns=["Punkt", "σ̂x", "σ̂y", "σ̂z", f"σ̂P_{dim}D"])
mittel_sP = helmert_punktfehler[f"σ̂P_{dim}D"].mean() mittel_sP = helmert_punktfehler[f"σ̂P_{dim}D"].mean()
print(f"Mittlerer Helmert-Punktfehler über alle Punkte: {mittel_sP:.4f} [m]") print(f"Mittlerer Helmert-Punktfehler über alle Punkte: {mittel_sP:.6f} [m]")
display(HTML(helmert_punktfehler.to_html(index=False))) display(HTML(helmert_punktfehler.to_html(index=False)))
helmert_punktfehler.to_excel(r"Netzqualitaet\Standardabweichungen_Helmertscher_Punktfehler.xlsx",index=False) helmert_punktfehler.to_excel(r"Netzqualitaet\Standardabweichungen_Helmertscher_Punktfehler.xlsx",index=False)
return helmert_punktfehler return helmert_punktfehler
@@ -118,7 +119,7 @@ class Genauigkeitsmaße:
@staticmethod @staticmethod
def standardellipsoid(Qxx: np.ndarray, sigma0_apost: float, unbekannten_liste: list) -> pd.DataFrame: def standardellipsoid(Qxx: np.ndarray, sigma0_apost: float, unbekannten_liste: list) -> pd.DataFrame:
""" """
Berechnet Achsenlängen des Fehlerellipsoids (a, b, c) sowie den 2D-Richtungswinkel θ aus Qxx und σ̂₀ a posteriori. Berechnet das Standardellipsoid aus Qxx und σ̂₀ a posteriori.
Für jeden Punkt wird aus der Kofaktor-Matrix der Unbekannten Qxx die 3×3-Submatrix Für jeden Punkt wird aus der Kofaktor-Matrix der Unbekannten Qxx die 3×3-Submatrix
der Koordinaten (X, Y, Z) gebildet. Daraus werden zunächst die Standardabweichungen der Koordinaten (X, Y, Z) gebildet. Daraus werden zunächst die Standardabweichungen
@@ -129,8 +130,9 @@ class Genauigkeitsmaße:
- Halbachse b aus dem mittleren Eigenwert, - Halbachse b aus dem mittleren Eigenwert,
- Halbachse c aus dem kleinsten Eigenwert. - Halbachse c aus dem kleinsten Eigenwert.
Zusätzlich wird zur zweidimensionalen Darstellung ein Richtungswinkel θ in der X/Y-Ebene Die Orientierung des Ellipsoids im Raum wird über die zugehörigen Eigenvektoren bestimmt.
aus den Kovarianzanteilen (qxx, qyy, qyx) berechnet (Winkel in gon). Aus der Modalmatrix M, bestehend aus den sortierten Eigenvektoren, werden die drei Eulerwinkel α, β und γ
berechnet.
Die Punktzuordnung erfolgt über die Symbolnamen der Unbekanntenliste. Die Punktzuordnung erfolgt über die Symbolnamen der Unbekanntenliste.
Die Ergebnisse werden tabellarisch ausgegeben und in eine Excel-Datei exportiert. Die Ergebnisse werden tabellarisch ausgegeben und in eine Excel-Datei exportiert.
@@ -141,7 +143,7 @@ class Genauigkeitsmaße:
:type sigma0_apost: float :type sigma0_apost: float
:param unbekannten_liste: Liste der Unbekannten. :param unbekannten_liste: Liste der Unbekannten.
:type unbekannten_liste: list :type unbekannten_liste: list
:return: Tabelle mit Standardabweichungen (σx, σy, σz), Ellipsoid-Halbachsen (a, b, c) und Richtungswinkel θ je Punkt. :return: Tabelle mit Standardabweichungen, Ellipsoid-Halbachsen, Eulerwinkel.
:rtype: pandas.DataFrame :rtype: pandas.DataFrame
""" """
@@ -170,35 +172,44 @@ class Genauigkeitsmaße:
# Eigenwertzerlegung # Eigenwertzerlegung
eigenwerte, eigenvektoren = np.linalg.eigh(Q_sub) eigenwerte, eigenvektoren = np.linalg.eigh(Q_sub)
eigenwerte = np.sort(eigenwerte)[::-1] reihenfolge = np.argsort(eigenwerte)[::-1]
eigenwerte = eigenwerte[reihenfolge]
eigenwerte = np.clip(eigenwerte, 0.0, None)
M = eigenvektoren[:, reihenfolge]
if np.linalg.det(M) < 0:
M[:, 2] *= -1
# Halbachsen # Halbachsen des Standardellipsoids
s_a = sigma0_apost * np.sqrt(eigenwerte[0]) # Große Halbachse a s_a = sigma0_apost * np.sqrt(eigenwerte[0]) # Große Halbachse a
s_b = sigma0_apost * np.sqrt(eigenwerte[1]) # Mittlere Halbachse b s_b = sigma0_apost * np.sqrt(eigenwerte[1]) # Mittlere Halbachse b
s_c = sigma0_apost * np.sqrt(eigenwerte[2]) # Kleine Halbachse c s_c = sigma0_apost * np.sqrt(eigenwerte[2]) # Kleine Halbachse c
# Richtungswinkel theta in gon: # Eulerwinkel aus M
qyx = Q_sub[1, 0] beta = np.arcsin(-M[2, 0])
qxx = Q_sub[0, 0] alpha = np.arctan2(M[2, 1], M[2, 2])
qyy = Q_sub[1, 1] gamma = np.arctan2(M[1, 0], M[0, 0])
t_gon = 0.5 * np.arctan2(2 * qyx, qxx - qyy) * (200 / np.pi) alpha_gon = (alpha * 200 / np.pi)% 400.0
if t_gon < 0: beta_gon = (beta * 200 / np.pi)% 400.0
t_gon += 200 gamma_gon = (gamma * 200 / np.pi)% 400.0
daten.append([ daten.append([
pid, float(sx), float(sy), float(sz), pid,
float(s_a), float(s_b), float(s_c), float(t_gon) float(sx), float(sy), float(sz),
float(s_a), float(s_b), float(s_c),
float(alpha_gon), float(beta_gon), float(gamma_gon)
]) ])
except: except:
continue continue
standardellipsoid = pd.DataFrame(daten, columns=["Punkt", "σ̂x [m]", "σ̂y [m]", "σ̂z [m]", "Halbachse a [m]", "Halbachse b [m]", "Halbachse c [m]", "θ [gon]"]) standardellipsoid = pd.DataFrame(daten, columns=["Punkt", "σ̂x [m]", "σ̂y [m]", "σ̂z [m]", "Halbachse a [m]", "Halbachse b [m]", "Halbachse c [m]", "α [gon]", "β [gon]", "γ [gon]"])
standardellipsoid["σ̂x [m]"] = standardellipsoid["σ̂x [m]"].astype(float).round(4) standardellipsoid["σ̂x [m]"] = standardellipsoid["σ̂x [m]"].astype(float).round(6)
standardellipsoid["σ̂y [m]"] = standardellipsoid["σ̂y [m]"].astype(float).round(4) standardellipsoid["σ̂y [m]"] = standardellipsoid["σ̂y [m]"].astype(float).round(6)
standardellipsoid["σ̂z [m]"] = standardellipsoid["σ̂z [m]"].astype(float).round(4) standardellipsoid["σ̂z [m]"] = standardellipsoid["σ̂z [m]"].astype(float).round(6)
standardellipsoid["Halbachse a [m]"] = standardellipsoid["Halbachse a [m]"].astype(float).round(4) standardellipsoid["Halbachse a [m]"] = standardellipsoid["Halbachse a [m]"].astype(float).round(6)
standardellipsoid["Halbachse b [m]"] = standardellipsoid["Halbachse b [m]"].astype(float).round(4) standardellipsoid["Halbachse b [m]"] = standardellipsoid["Halbachse b [m]"].astype(float).round(6)
standardellipsoid["Halbachse c [m]"] = standardellipsoid["Halbachse c [m]"].astype(float).round(4) standardellipsoid["Halbachse c [m]"] = standardellipsoid["Halbachse c [m]"].astype(float).round(6)
standardellipsoid["θ [gon]"] = standardellipsoid["θ [gon]"].astype(float).round(3) standardellipsoid["α [gon]"] = standardellipsoid["α [gon]"].astype(float).round(3)
standardellipsoid["β [gon]"] = standardellipsoid["β [gon]"].astype(float).round(3)
standardellipsoid["γ [gon]"] = standardellipsoid["γ [gon]"].astype(float).round(3)
display(HTML(standardellipsoid.to_html(index=False))) display(HTML(standardellipsoid.to_html(index=False)))
standardellipsoid.to_excel(r"Netzqualitaet\Standardellipsoid.xlsx", index=False) standardellipsoid.to_excel(r"Netzqualitaet\Standardellipsoid.xlsx", index=False)
return standardellipsoid return standardellipsoid
@@ -206,29 +217,30 @@ class Genauigkeitsmaße:
@staticmethod @staticmethod
def konfidenzellipsoid(Qxx: np.ndarray, sigma0_apost: float, unbekannten_liste: list, R: int, ausgabe_erfolgt: bool) -> tuple[pd.DataFrame, float]: def konfidenzellipsoid(Qxx: np.ndarray, sigma0_apost: float, unbekannten_liste: list, R: int) -> tuple[pd.DataFrame, float]:
""" """
Berechnet die Konfidenzellipsoid für Punkte aus Qxx und einem Konfidenzniveau. Berechnet das Konfidenzellipsoid aus Qxx, σ̂₀ a posteriori und einem Konfidenzniveau.
Auf Basis der Kovarianz-Matrix der Unbekannten Qxx und der a-posteriori Auf Basis der Kovarianz-Matrix der Unbekannten Qxx und der a posteriori
Standardabweichung der Gewichtseinheit σ̂₀ werden für jeden Punkt die Parameter Standardabweichung der Gewichtseinheit σ̂₀ werden für jeden Punkt die Parameter
des Konfidenzellipsoids berechnet. Das Konfidenzniveau wird mittels einer Eingabe des Konfidenzellipsoids berechnet. Das Konfidenzniveau wird mittels einer Eingabe
über alpha festgelegt (Standard: 0.05 für 95%). über alpha festgelegt.
Für jeden Punkt wird die 3×3-Submatrix der Koordinaten (X, Y, Z) aus Qxx gebildet. Für jeden Punkt wird die 3×3-Submatrix der Koordinaten aus Qxx gebildet.
Über eine Eigenwertzerlegung dieser Submatrix werden die drei Hauptachsen des Über eine Eigenwertzerlegung dieser Submatrix werden die drei Hauptachsen des
Fehlerellipsoids bestimmt. Die Halbachsen des Konfidenzellipsoids ergeben sich aus: Ellipsoids bestimmt. Die Halbachsen des Konfidenzellipsoids ergeben sich aus:
- Aₖ: große Halbachse des Konfidenzellipsoids, - Aₖ: große Halbachse des Konfidenzellipsoids,
- Bₖ: mittlere Halbachse des Konfidenzellipsoids, - Bₖ: mittlere Halbachse des Konfidenzellipsoids,
- Cₖ: kleine Halbachse des Konfidenzellipsoids, - Cₖ: kleine Halbachse des Konfidenzellipsoids,
unter Verwendung eines Faktors aus der F-Verteilung in Abhängigkeit vom unter Verwendung eines Faktors aus der F-Verteilung in Abhängigkeit vom Konfidenzniveau und den Freiheitsgraden.
Konfidenzniveau und den Freiheitsgraden. Die Orientierung des Ellipsoids im Raum wird über die zugehörigen Eigenvektoren bestimmt.
Aus der Modalmatrix M, bestehend aus den sortierten Eigenvektoren, werden die drei Eulerwinkel α, β und γ
berechnet.
Die Punktzuordnung erfolgt über die Symbolnamen der Unbekanntenliste. Die Punktzuordnung erfolgt über die Symbolnamen der Unbekanntenliste.
Optional wird die Tabelle ausgegeben und als Excel-Datei exportiert, abhängig von Optional wird die Tabelle ausgegeben und als Excel-Datei exportiert.
ausgabe_erfolgt.
:param Qxx: Kofaktor-Matrix der geschätzten Unbekannten. :param Qxx: Kofaktor-Matrix der geschätzten Unbekannten.
:type Qxx: np.ndarray :type Qxx: np.ndarray
@@ -238,8 +250,6 @@ class Genauigkeitsmaße:
:type unbekannten_liste: list :type unbekannten_liste: list
:param R: Redundanz (Freiheitsgrade) für die F-Verteilung. :param R: Redundanz (Freiheitsgrade) für die F-Verteilung.
:type R: int :type R: int
:param ausgabe_erfolgt: Steuert, ob eine Ausgabe/Dateischreibung erfolgen soll (False = Ausgabe).
:type ausgabe_erfolgt: bool
:return: Tabelle der Konfidenzellipse je Punkt, verwendetes alpha. :return: Tabelle der Konfidenzellipse je Punkt, verwendetes alpha.
:rtype: tuple[pandas.DataFrame, float] :rtype: tuple[pandas.DataFrame, float]
""" """
@@ -274,36 +284,137 @@ class Genauigkeitsmaße:
# Eigenwertzerlegung # Eigenwertzerlegung
eigenwerte, eigenvektoren = np.linalg.eigh(Q_sub) eigenwerte, eigenvektoren = np.linalg.eigh(Q_sub)
eigenwerte = np.sort(eigenwerte)[::-1] order = np.argsort(eigenwerte)[::-1]
eigenwerte = eigenwerte[order]
eigenwerte = np.clip(eigenwerte, 0.0, None)
M = eigenvektoren[:, order]
if np.linalg.det(M) < 0:
M[:, 2] *= -1
# Halbachsen des Konfidenzellipoid # Halbachsen des Konfidenzellipoid
A_K = k * sigma0_apost * np.sqrt(eigenwerte[0]) A_K = k * sigma0_apost * np.sqrt(eigenwerte[0])
B_K = k * sigma0_apost * np.sqrt(eigenwerte[1]) B_K = k * sigma0_apost * np.sqrt(eigenwerte[1])
C_K = k * sigma0_apost * np.sqrt(eigenwerte[2]) C_K = k * sigma0_apost * np.sqrt(eigenwerte[2])
# Richtungswinkel theta in gon: # Eulerwinkel aus M
qyx = Q_sub[1, 0] beta = np.arcsin(-M[2, 0])
qxx = Q_sub[0, 0] alpha_ = np.arctan2(M[2, 1], M[2, 2])
qyy = Q_sub[1, 1] gamma = np.arctan2(M[1, 0], M[0, 0])
t_gon = 0.5 * np.arctan2(2 * qyx, qxx - qyy) * (200 / np.pi)
if t_gon < 0: alpha_gon = (alpha_ * 200.0 / np.pi) % 400.0
t_gon += 200 beta_gon = (beta * 200.0 / np.pi) % 400.0
gamma_gon = (gamma * 200.0 / np.pi) % 400.0
daten.append([ daten.append([
pid, float(sx), float(sy), float(sz), pid,
float(A_K), float(B_K), float(C_K), float(t_gon) float(sx), float(sy), float(sz),
float(A_K), float(B_K), float(C_K),
float(alpha_gon), float(beta_gon), float(gamma_gon)
]) ])
except: except:
continue continue
konfidenzellipoid = pd.DataFrame(daten, columns=["Punkt", "σ̂x [m]", "σ̂y [m]", "σ̂z [m]", "Halbachse a_k [m]", "Halbachse b_k [m]", "Halbachse c_k [m]", "θ [gon]"]) konfidenzellipoid = pd.DataFrame(daten, columns=["Punkt", "σ̂x [m]", "σ̂y [m]", "σ̂z [m]", "Halbachse a_k [m]", "Halbachse b_k [m]", "Halbachse c_k [m]", "α [gon]", "β [gon]", "γ [gon]"])
if ausgabe_erfolgt == False: konfidenzellipoid["σ̂x [m]"] = konfidenzellipoid["σ̂x [m]"].astype(float).round(6)
display(HTML(konfidenzellipoid.to_html(index=False))) konfidenzellipoid["σ̂y [m]"] = konfidenzellipoid["σ̂y [m]"].astype(float).round(6)
konfidenzellipoid.to_excel(r"Netzqualitaet\Konfidenzellipoid.xlsx", index=False) konfidenzellipoid["σ̂z [m]"] = konfidenzellipoid["σ̂z [m]"].astype(float).round(6)
konfidenzellipoid["Halbachse a_k [m]"] = konfidenzellipoid["Halbachse a_k [m]"].astype(float).round(6)
konfidenzellipoid["Halbachse b_k [m]"] = konfidenzellipoid["Halbachse b_k [m]"].astype(float).round(6)
konfidenzellipoid["Halbachse c_k [m]"] = konfidenzellipoid["Halbachse c_k [m]"].astype(float).round(6)
konfidenzellipoid["α [gon]"] = konfidenzellipoid["α [gon]"].astype(float).round(3)
konfidenzellipoid["β [gon]"] = konfidenzellipoid["β [gon]"].astype(float).round(3)
konfidenzellipoid["γ [gon]"] = konfidenzellipoid["γ [gon]"].astype(float).round(3)
display(HTML(konfidenzellipoid.to_html(index=False)))
konfidenzellipoid.to_excel(r"Netzqualitaet\Konfidenzellipoid.xlsx", index=False)
return konfidenzellipoid, alpha return konfidenzellipoid, alpha
@staticmethod
def konfidenzellipsen(Qxx: np.ndarray, sigma0_apost: float, unbekannten_liste: list, r_gesamt: int) -> pd.DataFrame:
"""
Berechnet Konfidenzellipsen für Punkte aus der Kofaktor-Matrix Qxx.
Für jeden Punkt werden aus der 2×2-Submatrix der Koordinaten die Parameter der Konfidenzellipse bestimmt.
Grundlage ist die a posteriori Standardabweichung der Gewichtseinheit sowie ein Konfidenzniveau, das über
die Irrtumswahrscheinlichkeit α festgelegt wird.
Die Halbachsen der Konfidenzellipse werden aus den Eigenwerten der Kovarianzmatrix berechnet.
Der Skalierungsfaktor ergibt sich aus der F-Verteilung.Der Richtungswinkel θ wird aus dem
Eigenvektor der großen Halbachse bestimmt und in gon ausgegeben.
Die Punktzuordnung erfolgt über die Symbolnamen der Unbekanntenliste.
:param Qxx: Kofaktor-Matrix der geschätzten Unbekannten.
:type Qxx: numpy.ndarray
:param sigma0_apost: a posteriori Standardabweichung der Gewichtseinheit.
:type sigma0_apost: float
:param unbekannten_liste: Liste der Unbekannten.
:type unbekannten_liste: list
:param r_gesamt: Redundanz (Freiheitsgrade) des Netzes.
:type r_gesamt: int
:return: Tabelle der Konfidenzellipsen je Punkt.
:rtype: pd.DataFrame
"""
# Irrtumswahrscheinlichkeit alpha
alpha_input = input("Irrtumswahrscheinlichkeit α wählen (z.B. 0.05, 0.01) [Standard=0.05]: ")
if alpha_input.strip() == "":
alpha = 0.05
else:
alpha = float(alpha_input)
print(f"→ Verwende alpha = {alpha} (Konfidenz = {(1 - alpha) * 100:.1f}%)")
Qxx = np.asarray(Qxx, float)
daten = []
namen_str = [str(sym) for sym in unbekannten_liste]
punkt_ids = [n[1:] for n in namen_str if n.upper().startswith("X")]
# Faktor für die Konfidenzellipe (F-Verteilung)
k2 = float(np.sqrt(2.0 * f.ppf(1.0 - alpha, 2, r_gesamt)))
for pid in punkt_ids:
try:
idx_1 = next(i for i, n in enumerate(namen_str) if n.upper() == f"X{pid}".upper())
idx_2 = next(i for i, n in enumerate(namen_str) if n.upper() == f"Y{pid}".upper())
index = [idx_1, idx_2]
Q_sub = Qxx[np.ix_(index, index)]
# Standardabweichungen
sigma1 = sigma0_apost * np.sqrt(Q_sub[0, 0])
sigma2 = sigma0_apost * np.sqrt(Q_sub[1, 1])
# Eigenwertzerlegung 2D
eigenwerte, eigenvektoren = np.linalg.eigh(Q_sub)
reihenfolge = np.argsort(eigenwerte)[::-1]
eigenwerte = eigenwerte[reihenfolge]
eigenwerte = np.clip(eigenwerte, 0.0, None)
eigenvektoren = eigenvektoren[:, reihenfolge]
# Halbachsen der Konfidenzellipse
a = k2 * sigma0_apost * np.sqrt(eigenwerte[0])
b = k2 * sigma0_apost * np.sqrt(eigenwerte[1])
# Winkel aus Eigenvektor der großen Halbachse
v = eigenvektoren[:, 0]
t_gon = (np.arctan2(v[1], v[0]) * (200.0 / np.pi)) % 400.0
daten.append([pid, float(sigma1), float(sigma2), float(a), float(b), float(t_gon)])
except StopIteration:
continue
Konfidenzellipse = pd.DataFrame(daten, columns=[
"Punkt", "σ̂x [m]", "σ̂y [m]",
"Halbachse a_k [m]", "Halbachse b_k [m]", "θ [gon]"
])
return Konfidenzellipse
@staticmethod @staticmethod
def konfidenzellipsen_enu(a: float, b: float, ausgabe_parameterschaetzung: dict, liste_unbekannte: list, ausgleichungsergebnis: dict, sigma0apost: float, r_gesamt: int) -> tuple[pd.DataFrame, np.ndarray]: def konfidenzellipsen_enu(a: float, b: float, ausgabe_parameterschaetzung: dict, liste_unbekannte: list, ausgleichungsergebnis: dict, sigma0apost: float, r_gesamt: int) -> tuple[pd.DataFrame, np.ndarray]:
""" """
@@ -312,7 +423,7 @@ class Genauigkeitsmaße:
Die Funktion transformiert zunächst die Kofaktor-Matrix der Unbekannten Qxx Die Funktion transformiert zunächst die Kofaktor-Matrix der Unbekannten Qxx
in ein East-North-Up-System (ENU) bezogen auf den Schwerpunkt der verwendeten in ein East-North-Up-System (ENU) bezogen auf den Schwerpunkt der verwendeten
Punkte (B0, L0). Anschließend wird auf Basis der transformierten Matrix die Punkte (B0, L0). Anschließend wird auf Basis der transformierten Matrix die
Konfidenzellipse über die Funktion "konfidenzellipsoid" bestimmt. Konfidenzellipse über die Funktion "konfidenzellipsen" bestimmt.
Zum Schluss werden Spaltennamen an die ENU-Notation angepasst, Werte gerundet, Zum Schluss werden Spaltennamen an die ENU-Notation angepasst, Werte gerundet,
tabellarisch ausgegeben und als Excel-Datei exportiert. tabellarisch ausgegeben und als Excel-Datei exportiert.
@@ -347,31 +458,29 @@ class Genauigkeitsmaße:
print( print(
f"ENU-Referenz (Schwerpunkt): B0={Einheitenumrechnung.Einheitenumrechnung.rad_to_gon_Decimal(B0):.8f} rad, L0={Einheitenumrechnung.Einheitenumrechnung.rad_to_gon_Decimal(L0):.8f} rad") f"ENU-Referenz (Schwerpunkt): B0={Einheitenumrechnung.Einheitenumrechnung.rad_to_gon_Decimal(B0):.8f} rad, L0={Einheitenumrechnung.Einheitenumrechnung.rad_to_gon_Decimal(L0):.8f} rad")
# 2) Konfidenzellipoid im ENU-System # 2) Konfidenzellipsen im ENU-System
Konfidenzellipse_ENU, alpha = Genauigkeitsmaße.konfidenzellipsoid( Konfidenzellipse_ENU = Genauigkeitsmaße.konfidenzellipsen(
Qxx_enu, Qxx_enu,
sigma0apost, sigma0apost,
liste_unbekannte, liste_unbekannte,
r_gesamt, r_gesamt
ausgabe_erfolgt = True
) )
# 3) Spaltennamen anpassen # 3) Spaltennamen anpassen
Konfidenzellipse_ENU = Konfidenzellipse_ENU.rename(columns={ Konfidenzellipse_ENU = Konfidenzellipse_ENU.rename(columns={
"σ̂x [m]": "σ̂E [m]", "σ̂x [m]": "σ̂E [m]",
"σ̂y [m]": "σ̂N [m]", "σ̂y [m]": "σ̂N [m]",
"σ̂z [m]": "σ̂U [m]", "Halbachse a_k [m]": "Halbachse a_k_EN [m]",
"Halbachse b_k [m]": "Halbachse b_k_EN [m]",
"θ [gon]": "θ_EN [gon]" "θ [gon]": "θ_EN [gon]"
}) })
# 4) Runden und Anzeigen # 4) Runden und Anzeigen
Konfidenzellipse_ENU["σ̂E [m]"] = Konfidenzellipse_ENU["σ̂E [m]"].round(6) Konfidenzellipse_ENU["σ̂E [m]"] = Konfidenzellipse_ENU["σ̂E [m]"].round(6)
Konfidenzellipse_ENU["σ̂N [m]"] = Konfidenzellipse_ENU["σ̂N [m]"].round(6) Konfidenzellipse_ENU["σ̂N [m]"] = Konfidenzellipse_ENU["σ̂N [m]"].round(6)
Konfidenzellipse_ENU["σ̂U [m]"] = Konfidenzellipse_ENU["σ̂U [m]"].round(6) Konfidenzellipse_ENU["Halbachse a_k_EN [m]"] = Konfidenzellipse_ENU["Halbachse a_k_EN [m]"].round(6)
Konfidenzellipse_ENU["Halbachse a_k [m]"] = Konfidenzellipse_ENU["Halbachse a_k [m]"].round(4) Konfidenzellipse_ENU["Halbachse b_k_EN [m]"] = Konfidenzellipse_ENU["Halbachse b_k_EN [m]"].round(6)
Konfidenzellipse_ENU["Halbachse b_k [m]"] = Konfidenzellipse_ENU["Halbachse b_k [m]"].round(4) Konfidenzellipse_ENU["θ_EN [gon]"] = Konfidenzellipse_ENU["θ_EN [gon]"].round(3)
Konfidenzellipse_ENU["Halbachse c_k [m]"] = Konfidenzellipse_ENU["Halbachse c_k [m]"].round(4)
Konfidenzellipse_ENU["θ_EN [gon]"] = Konfidenzellipse_ENU["θ_EN [gon]"].round(4)
display(HTML(Konfidenzellipse_ENU.to_html(index=False))) display(HTML(Konfidenzellipse_ENU.to_html(index=False)))
@@ -406,12 +515,11 @@ class Plot:
Die Funktion visualisiert das geodätische Netz im East-North-Up-System (ENU) mit Plotly. Die Funktion visualisiert das geodätische Netz im East-North-Up-System (ENU) mit Plotly.
Dabei werden: Dabei werden:
- Beobachtungen als Verbindungslinien zwischen Punkten dargestellt (als separate Traces/Legenden-Einträge), - Beobachtungen als Verbindungslinien zwischen Punkten dargestellt,
- Konfidenzellipsen je Punkt (Halbachsen und Richtungswinkel), - Konfidenzellipsen je Punkt,
- Netzpunkte mit Punkt-ID und Koordinaten im Hover-Text angezeigt. - Netzpunkte mit Punkt-ID und Koordinaten im Hover-Text angezeigt.
Die Ellipsen werden zur besseren Sichtbarkeit mit dem Faktor "skalierung" vergrößert. Die Ellipsen werden zur besseren Sichtbarkeit mit dem Faktor "skalierung" vergrößert.
Der Richtungswinkel wird in gon erwartet und intern nach Radiant umgerechnet.
Zusätzlich wird eine PNG-Grafik über "plot.write_image(...)" exportiert. Zusätzlich wird eine PNG-Grafik über "plot.write_image(...)" exportiert.
:param Koord_ENU: Dictionary der Punktkoordinaten im ENU-System. :param Koord_ENU: Dictionary der Punktkoordinaten im ENU-System.
@@ -484,9 +592,9 @@ class Plot:
if pid not in Koord_ENU: if pid not in Koord_ENU:
continue continue
a = float(row["Halbachse a_k [m]"]) * skalierung a = float(row["Halbachse a_k_EN [m]"]) * skalierung
b = float(row["Halbachse b_k [m]"]) * skalierung b = float(row["Halbachse b_k_EN [m]"]) * skalierung
theta = float(row[theta_col]) * np.pi / 200.0 # gon->rad theta = float(row["θ_EN [gon]"]) * np.pi / 200.0
ex = a * np.cos(t) ex = a * np.cos(t)
ey = b * np.sin(t) ey = b * np.sin(t)