from typing import Tuple import numpy as np from numpy import arctan2, cos, sin, sqrt from numpy.typing import NDArray import winkelumrechnungen as wu class EllipsoidBiaxial: """ Klasse für Rotationsellipdoide """ def __init__(self, a: float, b: float): self.a = a self.b = b self.c = a ** 2 / b self.e = sqrt(a ** 2 - b ** 2) / a self.e_ = sqrt(a ** 2 - b ** 2) / b @classmethod def init_name(cls, name: str) -> EllipsoidBiaxial: """ Erstellen eines Rotationsellipdoids nach Namen :param name: Name des Rotationsellipsoids :return: Rotationsellipsoid """ if name == "Bessel": a = 6377397.15508 b = 6356078.96290 return cls(a, b) elif name == "Hayford": a = 6378388 f = 1/297 b = a - a * f return cls(a, b) elif name == "Krassowski": a = 6378245 f = 298.3 b = a - a * f return cls(a, b) elif name == "WGS84": a = 6378137 f = 298.257223563 b = a - a * f return cls(a, b) else: raise Exception(f"EllipsoidBiaxial.init_name: Name {name} unbekannt") @classmethod def init_af(cls, a: float, f: float) -> EllipsoidBiaxial: """ Erstellen eines Rotationsellipdoids aus der großen Halbachse und der Abplattung :param a: große Halbachse :param f: großen Halbachse :return: Rotationsellipsoid """ b = a - a * f return cls(a, b) V = lambda self, phi: sqrt(1 + self.e_ ** 2 * cos(phi) ** 2) M = lambda self, phi: self.c / self.V(phi) ** 3 N = lambda self, phi: self.c / self.V(phi) beta2psi = lambda self, beta: arctan2(self.a * sin(beta), self.b * cos(beta)) beta2phi = lambda self, beta: arctan2(self.a ** 2 * sin(beta), self.b ** 2 * cos(beta)) psi2beta = lambda self, psi: arctan2(self.b * sin(psi), self.a * cos(psi)) psi2phi = lambda self, psi: arctan2(self.a * sin(psi), self.b * cos(psi)) phi2beta = lambda self, phi: arctan2(self.b**2 * sin(phi), self.a**2 * cos(phi)) phi2psi = lambda self, phi: arctan2(self.b * sin(phi), self.a * cos(phi)) phi2p = lambda self, phi: self.N(phi) * cos(phi) def bi_cart2ell(self, point: NDArray, Eh: float = 0.001, Ephi: float = wu.gms2rad([0, 0, 0.001])) -> Tuple[float, float, float]: """ Umrechnung von kartesischen in ellipsoidische Koordinaten auf einem Rotationsellipsoid # TODO: Quelle :param point: Punkt in kartesischen Koordinaten :param Eh: Grenzwert für die Höhe :param Ephi: Grenzwert für die Breite :return: ellipsoidische Breite, Länge, geodätische Höhe """ x, y, z = point lamb = arctan2(y, x) p = sqrt(x**2+y**2) phi_null = arctan2(z, p*(1 - self.e**2)) hi = [0] phii = [phi_null] i = 0 while True: N = self.a / sqrt(1 - self.e**2 * sin(phii[i])**2) h = p / cos(phii[i]) - N phi = arctan2(z, p * (1-(self.e**2*N) / (N+h))) hi.append(h) phii.append(phi) dh = abs(hi[i]-h) dphi = abs(phii[i]-phi) i += 1 if dh < Eh: if dphi < Ephi: break return phi, lamb, h def bi_ell2cart(self, phi: float, lamb: float, h: float) -> NDArray: """ Umrechnung von ellipsoidischen in kartesische Koordinaten auf einem Rotationsellipsoid # TODO: Quelle :param phi: ellipsoidische Breite :param lamb: ellipsoidische Länge :param h: geodätische Höhe :return: Punkt in kartesischen Koordinaten """ W = sqrt(1 - self.e**2 * sin(phi)**2) N = self.a / W x = (N+h) * cos(phi) * cos(lamb) y = (N+h) * cos(phi) * sin(lamb) z = (N * (1-self.e**2) + h) * sin(phi) return np.array([x, y, z])