127 lines
4.0 KiB
Python
127 lines
4.0 KiB
Python
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])
|