Projekt aufgeräumt, gha1 getestet, Runge-Kutta angepasst (gha2_num sollte jetzt deutlich schneller sein)

This commit is contained in:
2026-01-09 17:49:49 +01:00
parent cf756e3d9a
commit 797afdfd6f
23 changed files with 832 additions and 868 deletions

View File

@@ -1,8 +1,9 @@
import numpy as np
from numpy import sin, cos, arctan, arctan2, sqrt
from numpy import sin, cos, arctan, arctan2, sqrt, pi, arccos
import winkelumrechnungen as wu
import ausgaben as aus
import jacobian_Ligas
import matplotlib.pyplot as plt
class EllipsoidBiaxial:
@@ -10,8 +11,8 @@ class EllipsoidBiaxial:
self.a = a
self.b = b
self.c = a ** 2 / b
self.e = np.sqrt(a ** 2 - b ** 2) / a
self.e_ = np.sqrt(a ** 2 - b ** 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):
@@ -40,28 +41,28 @@ class EllipsoidBiaxial:
b = a - a * f
return cls(a, b)
V = lambda self, phi: np.sqrt(1 + self.e_ ** 2 * np.cos(phi) ** 2)
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: np.arctan(self.a / self.b * np.tan(beta))
beta2phi = lambda self, beta: np.arctan(self.a ** 2 / self.b ** 2 * np.tan(beta))
beta2psi = lambda self, beta: arctan(self.a / self.b * np.tan(beta))
beta2phi = lambda self, beta: arctan(self.a ** 2 / self.b ** 2 * np.tan(beta))
psi2beta = lambda self, psi: np.arctan(self.b / self.a * np.tan(psi))
psi2phi = lambda self, psi: np.arctan(self.a / self.b * np.tan(psi))
psi2beta = lambda self, psi: arctan(self.b / self.a * np.tan(psi))
psi2phi = lambda self, psi: arctan(self.a / self.b * np.tan(psi))
phi2beta = lambda self, phi: np.arctan(self.b ** 2 / self.a ** 2 * np.tan(phi))
phi2psi = lambda self, phi: np.arctan(self.b / self.a * np.tan(phi))
phi2beta = lambda self, phi: arctan(self.b ** 2 / self.a ** 2 * np.tan(phi))
phi2psi = lambda self, phi: arctan(self.b / self.a * np.tan(phi))
phi2p = lambda self, phi: self.N(phi) * np.cos(phi)
phi2p = lambda self, phi: self.N(phi) * cos(phi)
def cart2ell(self, Eh, Ephi, x, y, z):
p = np.sqrt(x**2+y**2)
p = sqrt(x**2+y**2)
# print(f"p = {round(p, 5)} m")
lamb = np.arctan(y/x)
lamb = arctan(y/x)
phi_null = np.arctan(z/p*(1-self.e**2)**-1)
phi_null = arctan(z/p*(1-self.e**2)**-1)
hi = [0]
phii = [phi_null]
@@ -69,9 +70,9 @@ class EllipsoidBiaxial:
i = 0
while True:
N = self.a*(1-self.e**2*np.sin(phii[i])**2)**(-1/2)
h = p/np.cos(phii[i])-N
phi = np.arctan(z/p*(1-(self.e**2*N)/(N+h))**(-1))
N = self.a*(1-self.e**2*sin(phii[i])**2)**(-1/2)
h = p/cos(phii[i])-N
phi = arctan(z/p*(1-(self.e**2*N)/(N+h))**(-1))
hi.append(h)
phii.append(phi)
dh = abs(hi[i]-h)
@@ -86,11 +87,11 @@ class EllipsoidBiaxial:
return phi, lamb, h
def ell2cart(self, phi, lamb, h):
W = np.sqrt(1 - self.e**2 * np.sin(phi)**2)
W = sqrt(1 - self.e**2 * sin(phi)**2)
N = self.a / W
x = (N+h) * np.cos(phi) * np.cos(lamb)
y = (N+h) * np.cos(phi) * np.sin(lamb)
z = (N * (1-self.e**2) + h) * np.sin(lamb)
x = (N+h) * cos(phi) * cos(lamb)
y = (N+h) * cos(phi) * sin(lamb)
z = (N * (1-self.e**2) + h) * sin(lamb)
return x, y, z
class EllipsoidTriaxial:
@@ -98,15 +99,15 @@ class EllipsoidTriaxial:
self.ax = ax
self.ay = ay
self.b = b
self.ex = np.sqrt((self.ax**2 - self.b**2) / self.ax**2)
self.ey = np.sqrt((self.ay**2 - self.b**2) / self.ay**2)
self.ee = np.sqrt((self.ax**2 - self.ay**2) / self.ax**2)
self.ex_ = np.sqrt((self.ax**2 - self.b**2) / self.b**2)
self.ey_ = np.sqrt((self.ay**2 - self.b**2) / self.b**2)
self.ee_ = np.sqrt((self.ax**2 - self.ay**2) / self.ay**2)
self.Ex = np.sqrt(self.ax**2 - self.b**2)
self.Ey = np.sqrt(self.ay**2 - self.b**2)
self.Ee = np.sqrt(self.ax**2 - self.ay**2)
self.ex = sqrt((self.ax**2 - self.b**2) / self.ax**2)
self.ey = sqrt((self.ay**2 - self.b**2) / self.ay**2)
self.ee = sqrt((self.ax**2 - self.ay**2) / self.ax**2)
self.ex_ = sqrt((self.ax**2 - self.b**2) / self.b**2)
self.ey_ = sqrt((self.ay**2 - self.b**2) / self.b**2)
self.ee_ = sqrt((self.ax**2 - self.ay**2) / self.ay**2)
self.Ex = sqrt(self.ax**2 - self.b**2)
self.Ey = sqrt(self.ay**2 - self.b**2)
self.Ee = sqrt(self.ax**2 - self.ay**2)
@classmethod
def init_name(cls, name: str):
@@ -156,22 +157,21 @@ class EllipsoidTriaxial:
b = 4000000
return cls(ax, ay, b)
elif name == "KarneyTest2024":
ax = np.sqrt(2)
ax = sqrt(2)
ay = 1
b = 1 / np.sqrt(2)
b = 1 / sqrt(2)
return cls(ax, ay, b)
def point_on(self, point: np.ndarray) -> bool:
"""
Test, ob ein Punkt auf dem Ellipsoid liegt.
:param point: kartesische 3D-Koordinaten
:return: Punkt auf dem Ellispoid?
"""
value = point[0]**2/self.ax**2 + point[1]**2/self.ay**2 + point[2]**2/self.b**2
if abs(1-value) < 0.000001:
return True
else:
return False
def func_H(self, x: float, y: float, z: float):
return x ** 2 + y ** 2 / (1 - self.ee ** 2) ** 2 + z ** 2 / (1 - self.ex ** 2) ** 2
def func_n(self, x: float, y: float, z: float, H: float = None):
if H is None:
H = self.func_H(x, y, z)
sqrtH = sqrt(H)
return np.array([x / sqrtH,
y / ((1 - self.ee ** 2) * sqrtH),
z / ((1 - self.ex ** 2) * sqrtH)])
def ellu2cart(self, beta: float, lamb: float, u: float) -> np.ndarray:
"""
@@ -184,60 +184,12 @@ class EllipsoidTriaxial:
:param u: Größe entlang der z-Achse
:return: Punkt in kartesischen Koordinaten
"""
# s1 = u**2 - self.b**2
# s2 = -self.ay**2 * np.sin(beta)**2 - self.b**2 * np.cos(beta)**2
# s3 = -self.ax**2 * np.sin(lamb)**2 - self.ay**2 * np.cos(lamb)**2
# print(s1, s2, s3)
# xe = np.sqrt(((self.ax**2+s1) * (self.ax**2+s2) * (self.ax**2+s3)) /
# ((self.ax**2-self.ay**2) * (self.ax**2-self.b**2)))
# ye = np.sqrt(((self.ay**2+s1) * (self.ay**2+s2) * (self.ay**2+s3)) /
# ((self.ay**2-self.ax**2) * (self.ay**2-self.b**2)))
# ze = np.sqrt(((self.b**2+s1) * (self.b**2+s2) * (self.b**2+s3)) /
# ((self.b**2-self.ax**2) * (self.b**2-self.ay**2)))
x = np.sqrt(u**2 + self.Ex**2) * np.sqrt(np.cos(beta)**2 + self.Ee**2/self.Ex**2 * np.sin(beta)**2) * np.cos(lamb)
y = np.sqrt(u**2 + self.Ey**2) * np.cos(beta) * np.sin(lamb)
z = u * np.sin(beta) * np.sqrt(1 - self.Ee**2/self.Ex**2 * np.cos(lamb)**2)
x = sqrt(u**2 + self.Ex**2) * sqrt(cos(beta)**2 + self.Ee**2/self.Ex**2 * sin(beta)**2) * cos(lamb)
y = sqrt(u**2 + self.Ey**2) * cos(beta) * sin(lamb)
z = u * sin(beta) * sqrt(1 - self.Ee**2/self.Ex**2 * cos(lamb)**2)
return np.array([x, y, z])
def ell2cart(self, beta: float | np.ndarray, lamb: float | np.ndarray) -> np.ndarray:
"""
Panou, Korakitis 2019 2
:param beta: elliptische Breite [rad]
:param lamb: elliptische Länge [rad]
:return: Punkt in kartesischen Koordinaten
"""
beta = np.asarray(beta, dtype=float)
lamb = np.asarray(lamb, dtype=float)
beta, lamb = np.broadcast_arrays(beta, lamb)
B = self.Ex ** 2 * np.cos(beta) ** 2 + self.Ee ** 2 * np.sin(beta) ** 2
L = self.Ex ** 2 - self.Ee ** 2 * np.cos(lamb) ** 2
x = self.ax / self.Ex * np.sqrt(B) * np.cos(lamb)
y = self.ay * np.cos(beta) * np.sin(lamb)
z = self.b / self.Ex * np.sin(beta) * np.sqrt(L)
xyz = np.stack((x, y, z), axis=-1)
# Pole
mask_south = beta == -np.pi / 2
mask_north = beta == np.pi / 2
xyz[mask_south] = np.array([0, 0, -self.b])
xyz[mask_north] = np.array([0, 0, self.b])
# Äquator
mask_eq = beta == 0
xyz[mask_eq & (lamb == -np.pi / 2)] = np.array([0, -self.ay, 0])
xyz[mask_eq & (lamb == np.pi / 2)] = np.array([0, self.ay, 0])
xyz[mask_eq & (lamb == 0)] = np.array([self.ax, 0, 0])
xyz[mask_eq & (lamb == np.pi)] = np.array([-self.ax, 0, 0])
return xyz
def cart2ellu(self, point: np.ndarray) -> tuple[float, float, float]:
"""
Panou 2014 15ff.
@@ -253,25 +205,137 @@ class EllipsoidTriaxial:
p = (c2**2 - 3*c1) / 9
q = (9*c1*c2 - 27*c0 - 2*c2**3) / 54
omega = np.arccos(q / np.sqrt(p**3))
omega = arccos(q / sqrt(p**3))
s1 = 2 * np.sqrt(p) * np.cos(omega/3) - c2/3
s2 = 2 * np.sqrt(p) * np.cos(omega/3 - 2*np.pi/3) - c2/3
s3 = 2 * np.sqrt(p) * np.cos(omega/3 - 4*np.pi/3) - c2/3
s1 = 2 * sqrt(p) * cos(omega/3) - c2/3
s2 = 2 * sqrt(p) * cos(omega/3 - 2*pi/3) - c2/3
s3 = 2 * sqrt(p) * cos(omega/3 - 4*pi/3) - c2/3
# print(s1, s2, s3)
beta = np.arctan(np.sqrt((-self.b**2 - s2) / (self.ay**2 + s2)))
beta = arctan(sqrt((-self.b**2 - s2) / (self.ay**2 + s2)))
if abs((-self.ay**2 - s3) / (self.ax**2 + s3)) > 1e-7:
lamb = np.arctan(np.sqrt((-self.ay**2 - s3) / (self.ax**2 + s3)))
lamb = arctan(sqrt((-self.ay**2 - s3) / (self.ax**2 + s3)))
else:
lamb = 0
u = np.sqrt(self.b**2 + s1)
u = sqrt(self.b**2 + s1)
return beta, lamb, u
def cart2ell(self, point: np.ndarray) -> tuple[float, float]:
def ell2cart(self, beta: float | np.ndarray, lamb: float | np.ndarray) -> np.ndarray:
"""
Panou, Korakitis 2019 2f.
Panou, Korakitis 2019 2
:param beta: elliptische Breite [rad]
:param lamb: elliptische Länge [rad]
:return: Punkt in kartesischen Koordinaten
"""
beta = np.asarray(beta, dtype=float)
lamb = np.asarray(lamb, dtype=float)
beta, lamb = np.broadcast_arrays(beta, lamb)
B = self.Ex ** 2 * cos(beta) ** 2 + self.Ee ** 2 * sin(beta) ** 2
L = self.Ex ** 2 - self.Ee ** 2 * cos(lamb) ** 2
x = self.ax / self.Ex * sqrt(B) * cos(lamb)
y = self.ay * cos(beta) * sin(lamb)
z = self.b / self.Ex * sin(beta) * sqrt(L)
xyz = np.stack((x, y, z), axis=-1)
# Pole
mask_south = beta == -pi / 2
mask_north = beta == pi / 2
xyz[mask_south] = np.array([0, 0, -self.b])
xyz[mask_north] = np.array([0, 0, self.b])
# Äquator
mask_eq = beta == 0
xyz[mask_eq & (lamb == -pi / 2)] = np.array([0, -self.ay, 0])
xyz[mask_eq & (lamb == pi / 2)] = np.array([0, self.ay, 0])
xyz[mask_eq & (lamb == 0)] = np.array([self.ax, 0, 0])
xyz[mask_eq & (lamb == pi)] = np.array([-self.ax, 0, 0])
return xyz
def ell2cart_bektas(self, beta: float | np.ndarray, omega: float | np.ndarray):
"""
Bektas 2015
:param beta:
:param omega:
:return:
"""
x = self.ax * cos(omega) * sqrt((self.ax**2 - self.ay**2 * sin(beta)**2 - self.b**2 * cos(beta)**2) / (self.ax**2 - self.b**2))
y = self.ay * cos(beta) * sin(omega)
z = self.b * sin(beta) * sqrt((self.ax**2 * sin(omega)**2 + self.ay**2 * cos(omega)**2 - self.b**2) / (self.ax**2 - self.b**2))
return np.array([x, y, z])
def ell2cart_karney(self, beta: float | np.ndarray, lamb: float | np.ndarray) -> np.ndarray:
"""
Karney 2025 Geographic Lib
:param beta:
:param lamb:
:return:
"""
e = sqrt(self.ax**2 - self.b**2) / self.ay
k = sqrt(self.ay**2 - self.b**2) / sqrt(self.ax**2 - self.b**2)
k_ = sqrt(self.ax**2 - self.ay**2) / sqrt(self.ax**2 - self.b**2)
X = self.ax * cos(lamb) * sqrt(k**2*cos(beta)**2+k_**2)
Y = self.ay * cos(beta) * sin(lamb)
Z = self.b * sin(beta) * sqrt(k**2 + k_**2 * sin(lamb)**2)
return np.array([X, Y, Z])
def cart2ell(self, point, eps=1e-12, maxI = 100) -> tuple[float, float]:
"""
Panou, Korakitis 2019 3f. (num)
:param point:
:param eps:
:return:
"""
x, y, z = point
beta, lamb = self.cart2ell_panou(point)
delta_ell = np.array([np.inf, np.inf]).T
i = 0
while np.sum(delta_ell) > eps and i < maxI:
x0, y0, z0 = self.ell2cart(beta, lamb)
delta_l = np.array([x-x0, y-y0, z-z0]).T
B = self.Ex ** 2 * cos(beta) ** 2 + self.Ee ** 2 * sin(beta) ** 2
L = self.Ex ** 2 - self.Ee ** 2 * cos(lamb) ** 2
J = np.array([[(-self.ax * self.Ey ** 2) / (2 * self.Ex) * sin(2 * beta) / sqrt(B) * cos(lamb),
-self.ax / self.Ex * sqrt(B) * sin(lamb)],
[-self.ay * sin(beta) * sin(lamb),
self.ay * cos(beta) * cos(lamb)],
[self.b / self.Ex * cos(beta) * sqrt(L),
(self.b * self.Ee ** 2) / (2 * self.Ex) * sin(beta) * sin(2 * lamb) / sqrt(L)]])
N = J.T @ J
det = N[0,0] * N[1,1] - N[0,1] * N[1,0]
if abs(det) < eps:
det = eps
N_inv = 1 / det * np.array([[N[1,1], -N[0,1]], [-N[1,0], N[0,0]]])
delta_ell = N_inv @ J.T @ delta_l
beta += delta_ell[0]
lamb += delta_ell[1]
i += 1
if i == maxI:
raise Exception("Umrechung ist nicht konvergiert")
point_n = self.ell2cart(beta, lamb)
delta_r = np.linalg.norm(point - point_n, axis=-1)
if delta_r > 1e-4:
# raise Exception("Fehler in der Umrechnung cart2ell")
print(f"Fehler in der Umrechnung cart2ell, deltaR = {delta_r}m")
return beta, lamb
def cart2ell_panou(self, point: np.ndarray) -> tuple[float, float]:
"""
Panou, Korakitis 2019 2f. (analytisch -> Näherung)
:param point: Punkt in kartesischen Koordinaten
:return: elliptische Breite, elliptische Länge
"""
@@ -280,18 +344,18 @@ class EllipsoidTriaxial:
eps = 1e-9
if abs(x) < eps and abs(y) < eps: # Punkt in der z-Achse
beta = np.pi / 2 if z > 0 else -np.pi / 2
beta = pi / 2 if z > 0 else -pi / 2
lamb = 0.0
return beta, lamb
elif abs(x) < eps and abs(z) < eps: # Punkt in der y-Achse
beta = 0.0
lamb = np.pi / 2 if y > 0 else -np.pi / 2
lamb = pi / 2 if y > 0 else -pi / 2
return beta, lamb
elif abs(y) < eps and abs(z) < eps: # Punkt in der x-Achse
beta = 0.0
lamb = 0.0 if x > 0 else np.pi
lamb = 0.0 if x > 0 else pi
return beta, lamb
# ---- Allgemeiner Fall -----
@@ -300,15 +364,18 @@ class EllipsoidTriaxial:
c0 = (self.ax ** 2 * self.ay ** 2 + self.ax ** 2 * self.b ** 2 + self.ay ** 2 * self.b ** 2 -
(self.ay ** 2 + self.b ** 2) * x ** 2 - (self.ax ** 2 + self.b ** 2) * y ** 2 - (
self.ax ** 2 + self.ay ** 2) * z ** 2)
t2 = (-c1 + np.sqrt(c1 ** 2 - 4 * c0)) / 2
t2 = (-c1 + sqrt(c1 ** 2 - 4 * c0)) / 2
if t2 == 0:
t2 = 1e-14
t1 = c0 / t2
num_beta = max(t1 - self.b ** 2, 0)
den_beta = max(self.ay ** 2 - t1, 0)
num_lamb = max(t2 - self.ay ** 2, 0)
den_lamb = max(self.ax ** 2 - t2, 0)
beta = np.arctan(np.sqrt(num_beta / den_beta))
lamb = np.arctan(np.sqrt(num_lamb / den_lamb))
beta = arctan(sqrt(num_beta / den_beta))
lamb = arctan(sqrt(num_lamb / den_lamb))
if z < 0:
beta = -beta
@@ -317,19 +384,62 @@ class EllipsoidTriaxial:
lamb = -lamb
if x < 0:
lamb = np.pi - lamb
lamb = pi - lamb
if abs(x) < eps:
lamb = -np.pi/2 if y < 0 else np.pi/2
lamb = -pi/2 if y < 0 else pi/2
elif abs(y) < eps:
lamb = 0 if x > 0 else np.pi
lamb = 0 if x > 0 else pi
elif abs(z) < eps:
beta = 0
return beta, lamb
def cart2ell_bektas(self, point, eps=1e-12, maxI = 100) -> tuple[float, float]:
"""
Bektas 2015
:param point:
:param eps:
:param maxI:
:return:
"""
x, y, z = point
phi, lamb = self.cart2para(point)
p = sqrt((self.ax**2 - self.ay**2) / (self.ax**2 - self.b**2))
d_phi = np.inf
d_lamb = np.inf
i = 0
while d_phi > eps and d_lamb > eps and i < maxI:
lamb_new = arctan2(self.ax * y * sqrt((p**2-1) * sin(phi)**2 + 1), self.ay * x * cos(phi))
phi_new = arctan2(self.ay * z * sin(lamb), self.b * y * sqrt(1 - p**2 * cos(lamb)**2))
d_phi = abs(phi_new - phi)
phi = phi_new
d_lamb = abs(lamb_new - lamb)
lamb = lamb_new
i += 1
if i == maxI:
raise Exception("Umrechung ist nicht konvergiert")
return phi, lamb
def geod2cart(self, phi: float | np.ndarray, lamb: float | np.ndarray, h: float) -> np.ndarray:
"""
Ligas 2012, 250
:param phi: geodätische Breite [rad]
:param lamb: geodätische Länge [rad]
:param h: Höhe über dem Ellipsoid
:return: kartesische Koordinaten
"""
v = self.ax / sqrt(1 - self.ex**2*sin(phi)**2-self.ee**2*cos(phi)**2*sin(lamb)**2)
xG = (v + h) * cos(phi) * cos(lamb)
yG = (v * (1-self.ee**2) + h) * cos(phi) * sin(lamb)
zG = (v * (1-self.ex**2) + h) * sin(phi)
return np.array([xG, yG, zG])
def cart2geod(self, point: np.ndarray, mode: str = "ligas3", maxIter: int = 30, maxLoa: float = 0.005) -> tuple[float, float, float]:
"""
Ligas 2012
@@ -344,24 +454,24 @@ class EllipsoidTriaxial:
eps = 1e-9
if abs(xG) < eps and abs(yG) < eps: # Punkt in der z-Achse
phi = np.pi / 2 if zG > 0 else -np.pi / 2
phi = pi / 2 if zG > 0 else -pi / 2
lamb = 0.0
h = abs(zG) - self.b
return phi, lamb, h
elif abs(xG) < eps and abs(zG) < eps: # Punkt in der y-Achse
phi = 0.0
lamb = np.pi / 2 if yG > 0 else -np.pi / 2
lamb = pi / 2 if yG > 0 else -pi / 2
h = abs(yG) - self.ay
return phi, lamb, h
elif abs(yG) < eps and abs(zG) < eps: # Punkt in der x-Achse
phi = 0.0
lamb = 0.0 if xG > 0 else np.pi
lamb = 0.0 if xG > 0 else pi
h = abs(xG) - self.ax
return phi, lamb, h
rG = np.sqrt(xG ** 2 + yG ** 2 + zG ** 2)
rG = sqrt(xG ** 2 + yG ** 2 + zG ** 2)
pE = np.array([self.ax * xG / rG, self.ax * yG / rG, self.ax * zG / rG], dtype=np.float64)
E = 1 / self.ax**2
@@ -380,38 +490,98 @@ class EllipsoidTriaxial:
invJ, fxE = jacobian_Ligas.case3(E, F, G, np.array([xG, yG, zG]), pE)
pEi = pE.reshape(-1, 1) - invJ @ fxE.reshape(-1, 1)
pEi = pEi.reshape(1, -1).flatten()
loa = np.sqrt((pEi[0]-pE[0])**2 + (pEi[1]-pE[1])**2 + (pEi[2]-pE[2])**2)
loa = sqrt((pEi[0]-pE[0])**2 + (pEi[1]-pE[1])**2 + (pEi[2]-pE[2])**2)
pE = pEi
i += 1
phi = np.arctan((1-self.ee**2) / (1-self.ex**2) * pE[2] / np.sqrt((1-self.ee**2)**2 * pE[0]**2 + pE[1]**2))
lamb = np.arctan(1/(1-self.ee**2) * pE[1]/pE[0])
h = np.sign(zG - pE[2]) * np.sign(pE[2]) * np.sqrt((pE[0] - xG) ** 2 + (pE[1] - yG) ** 2 + (pE[2] - zG) ** 2)
phi = arctan((1-self.ee**2) / (1-self.ex**2) * pE[2] / sqrt((1-self.ee**2)**2 * pE[0]**2 + pE[1]**2))
lamb = arctan(1/(1-self.ee**2) * pE[1]/pE[0])
h = np.sign(zG - pE[2]) * np.sign(pE[2]) * sqrt((pE[0] - xG) ** 2 + (pE[1] - yG) ** 2 + (pE[2] - zG) ** 2)
if xG < 0 and yG < 0:
lamb = -np.pi + lamb
lamb = -pi + lamb
elif xG < 0:
lamb = np.pi + lamb
lamb = pi + lamb
if abs(zG) < eps:
phi = 0
return phi, lamb, h
def geod2cart(self, phi: float | np.ndarray, lamb: float | np.ndarray, h: float) -> np.ndarray:
def para2cart(self, u: float | np.ndarray, v: float | np.ndarray) -> np.ndarray:
"""
Ligas 2012, 250
:param phi: geodätische Breite [rad]
:param lamb: geodätische Länge [rad]
:param h: Höhe über dem Ellipsoid
:return: kartesische Koordinaten
Panou, Korakitits 2020, 4
:param u: Parameter u
:param v: Parameter v
:return: Punkt in kartesischen Koordinaten
"""
v = self.ax / np.sqrt(1 - self.ex**2*np.sin(phi)**2-self.ee**2*np.cos(phi)**2*np.sin(lamb)**2)
xG = (v + h) * np.cos(phi) * np.cos(lamb)
yG = (v * (1-self.ee**2) + h) * np.cos(phi) * np.sin(lamb)
zG = (v * (1-self.ex**2) + h) * np.sin(phi)
return np.array([xG, yG, zG])
x = self.ax * cos(u) * cos(v)
y = self.ay * cos(u) * sin(v)
z = self.b * sin(u)
z = np.broadcast_to(z, np.shape(x))
return np.array([x, y, z])
def cart2para(self, point: np.ndarray) -> tuple[float, float]:
"""
Panou, Korakitits 2020, 4
:param point: Punkt in kartesischen Koordinaten
:return: parametrische Koordinaten
"""
x, y, z = point
u_check1 = z*sqrt(1 - self.ee**2)
u_check2 = sqrt(x**2 * (1-self.ee**2) + y**2) * sqrt(1-self.ex**2)
if u_check1 <= u_check2:
u = arctan2(u_check1, u_check2)
else:
u = pi/2 - arctan2(u_check2, u_check1)
v_check1 = y
v_check2 = x*sqrt(1-self.ee**2)
v_factor = sqrt(x**2*(1-self.ee**2)+y**2)
if v_check1 <= v_check2:
v = 2 * arctan2(v_check1, v_check2 + v_factor)
else:
v = pi/2 - 2 * arctan2(v_check2, v_check1 + v_factor)
return u, v
def ell2para(self, beta: float, lamb: float) -> tuple[float, float]:
cart = self.ell2cart(beta, lamb)
return self.cart2para(cart)
def para2ell(self, u: float, v: float) -> tuple[float, float]:
cart = self.para2cart(u, v)
return self.cart2ell(cart)
def para2geod(self, u: float, v: float, mode: str = "ligas3", maxIter: int = 30, maxLoa: float = 0.005) -> tuple[float, float, float]:
cart = self.para2cart(u, v)
return self.cart2geod(cart, mode, maxIter, maxLoa)
def geod2para(self, phi: float, lamb: float, h: float) -> tuple[float, float]:
cart = self.geod2cart(phi, lamb, h)
return self.cart2para(cart)
def ell2geod(self, beta: float, lamb: float, mode: str = "ligas3", maxIter: int = 30, maxLoa: float = 0.005) -> tuple[float, float, float]:
cart = self.ell2cart(beta, lamb)
return self.cart2geod(cart, mode, maxIter, maxLoa)
def geod2ell(self, phi: float, lamb: float, h: float) -> tuple[float, float]:
cart = self.geod2cart(phi, lamb, h)
return self.cart2ell(cart)
def point_on(self, point: np.ndarray) -> bool:
"""
Test, ob ein Punkt auf dem Ellipsoid liegt.
:param point: kartesische 3D-Koordinaten
:return: Punkt auf dem Ellispoid?
"""
value = point[0]**2/self.ax**2 + point[1]**2/self.ay**2 + point[2]**2/self.b**2
if abs(1-value) < 1e-6:
return True
else:
return False
def cartonell(self, point: np.ndarray) -> tuple[np.ndarray, float, float, float]:
"""
@@ -434,144 +604,64 @@ class EllipsoidTriaxial:
pointH = self. geod2cart(phi, lamb, h)
return pointH
def para2cart(self, u: float | np.ndarray, v: float | np.ndarray) -> np.ndarray:
"""
Panou, Korakitits 2020, 4
:param u: Parameter u
:param v: Parameter v
:return: Punkt in kartesischen Koordinaten
"""
x = self.ax * np.cos(u) * np.cos(v)
y = self.ay * np.cos(u) * np.sin(v)
z = self.b * np.sin(u)
z = np.broadcast_to(z, np.shape(x))
return np.array([x, y, z])
def cart2para(self, point: np.ndarray) -> tuple[float, float]:
"""
Panou, Korakitits 2020, 4
:param point: Punkt in kartesischen Koordinaten
:return: parametrische Koordinaten
"""
x, y, z = point
u_check1 = z*np.sqrt(1 - self.ee**2)
u_check2 = np.sqrt(x**2 * (1-self.ee**2) + y**2) * np.sqrt(1-self.ex**2)
if u_check1 <= u_check2:
u = np.arctan2(u_check1, u_check2)
else:
u = np.pi/2 - np.arctan2(u_check2, u_check1)
v_check1 = y
v_check2 = x*np.sqrt(1-self.ee**2)
v_factor = np.sqrt(x**2*(1-self.ee**2)+y**2)
if v_check1 <= v_check2:
v = 2 * np.arctan2(v_check1, v_check2 + v_factor)
else:
v = np.pi/2 - 2 * np.arctan2(v_check2, v_check1 + v_factor)
return u, v
def ell2para(self, beta, lamb) -> tuple[float, float]:
cart = self.ell2cart(beta, lamb)
return self.cart2para(cart)
def para2ell(self, u, v) -> tuple[float, float]:
cart = self.para2cart(u, v)
return self.cart2ell(cart)
def para2geod(self, u: float, v: float, mode: str = "ligas3", maxIter: int = 30, maxLoa: float = 0.005) -> tuple[float, float, float]:
cart = self.para2cart(u, v)
return self.cart2geod(cart, mode, maxIter, maxLoa)
def geod2para(self, phi, lamb, h) -> tuple[float, float]:
cart = self.geod2cart(phi, lamb, h)
return self.cart2para(cart)
def ell2geod(self, beta, lamb, mode: str = "ligas3", maxIter: int = 30, maxLoa: float = 0.005) -> tuple[float, float, float]:
cart = self.ell2cart(beta, lamb)
return self.cart2geod(cart, mode, maxIter, maxLoa)
def func_H(self, x, y, z):
return x ** 2 + y ** 2 / (1 - self.ee ** 2) ** 2 + z ** 2 / (1 - self.ex ** 2) ** 2
def func_n(self, x, y, z, H=None):
if H is None:
H = self.func_H(x, y, z)
return np.array([x / sqrt(H),
y / ((1 - self.ee ** 2) * sqrt(H)),
z / ((1 - self.ex ** 2) * sqrt(H))])
def p_q(self, x, y, z) -> tuple[np.ndarray, np.ndarray]:
"""
Berechnung sämtlicher Größen
:param x: x
:param y: y
:param z: z
:return: Dictionary sämtlicher Größen
"""
n = self.func_n(x, y, z)
beta, lamb = self.cart2ell(np.array([x, y, z]))
B = self.Ex ** 2 * np.cos(beta) ** 2 + self.Ee ** 2 * np.sin(beta) ** 2
L = self.Ex ** 2 - self.Ee ** 2 * np.cos(lamb) ** 2
c1 = x ** 2 + y ** 2 + z ** 2 - (self.ax ** 2 + self.ay ** 2 + self.b ** 2)
c0 = (self.ax ** 2 * self.ay ** 2 + self.ax ** 2 * self.b ** 2 + self.ay ** 2 * self.b ** 2 -
(self.ay ** 2 + self.b ** 2) * x ** 2 - (self.ax ** 2 + self.b ** 2) * y ** 2 - (
self.ax ** 2 + self.ay ** 2) * z ** 2)
t2 = (-c1 + np.sqrt(c1 ** 2 - 4 * c0)) / 2
t1 = c0 / t2
t2e = self.ax ** 2 * np.sin(lamb) ** 2 + self.ay ** 2 * np.cos(lamb) ** 2
t1e = self.ay ** 2 * np.sin(beta) ** 2 + self.b ** 2 * np.cos(beta) ** 2
F = self.Ey ** 2 * np.cos(beta) ** 2 + self.Ee ** 2 * np.sin(lamb) ** 2
p1 = -np.sqrt(L / (F * t2)) * self.ax / self.Ex * np.sqrt(B) * np.sin(lamb)
p2 = np.sqrt(L / (F * t2)) * self.ay * np.cos(beta) * np.cos(lamb)
p3 = 1 / np.sqrt(F * t2) * (self.b * self.Ee ** 2) / (2 * self.Ex) * np.sin(beta) * np.sin(2 * lamb)
# p1 = -np.sign(y) * np.sqrt(L / (F * t2)) * self.ax / (self.Ex * self.Ee) * np.sqrt(B) * np.sqrt(t2 - self.ay ** 2)
# p2 = np.sign(x) * np.sqrt(L / (F * t2)) * self.ay / (self.Ey * self.Ee) * np.sqrt((ell.ay ** 2 - t1) * (self.ax ** 2 - t2))
# p3 = np.sign(x) * np.sign(y) * np.sign(z) * 1 / np.sqrt(F * t2) * self.b / (self.Ex * self.Ey) * np.sqrt(
# (t1 - self.b ** 2) * (t2 - self.ay ** 2) * (self.ax ** 2 - t2))
p = np.array([p1, p2, p3])
q = np.array([n[1] * p[2] - n[2] * p[1],
n[2] * p[0] - n[0] * p[2],
n[0] * p[1] - n[1] * p[0]])
return p, q
if __name__ == "__main__":
ell = EllipsoidTriaxial.init_name("Eitschberger1978")
ell = EllipsoidTriaxial.init_name("BursaSima1980round")
diff_list = []
for beta_deg in range(-150, 210, 30):
for lamb_deg in range(-150, 210, 30):
beta = wu.deg2rad(beta_deg)
lamb = wu.deg2rad(lamb_deg)
point = ell.ell2cart(beta, lamb)
diffs_para = []
diffs_ell = []
diffs_geod = []
points = []
for v_deg in range(-180, 181, 5):
for u_deg in range(-90, 91, 5):
v = wu.deg2rad(v_deg)
u = wu.deg2rad(u_deg)
point = ell.para2cart(u, v)
points.append(point)
elli = ell.cart2ell(point)
cart_elli = ell.ell2cart(elli[0], elli[1])
diff_ell = np.sum(np.abs(point-cart_elli))
diff_ell = np.linalg.norm(point - cart_elli, axis=-1)
para = ell.cart2para(point)
cart_para = ell.para2cart(para[0], para[1])
diff_para = np.sum(np.abs(point-cart_para))
# geod = ell.cart2geod(point, "ligas1")
# cart_geod = ell.geod2cart(geod[0], geod[1], geod[2])
# diff_geod1 = np.sum(np.abs(point-cart_geod))
#
# geod = ell.cart2geod(point, "ligas2")
# cart_geod = ell.geod2cart(geod[0], geod[1], geod[2])
# diff_geod2 = np.sum(np.abs(point-cart_geod))
diff_para = np.linalg.norm(point - cart_para, axis=-1)
geod = ell.cart2geod(point, "ligas3")
cart_geod = ell.geod2cart(geod[0], geod[1], geod[2])
diff_geod3 = np.sum(np.abs(point-cart_geod))
diff_geod3 = np.linalg.norm(point - cart_geod, axis=-1)
diff_list.append([beta_deg, lamb_deg, diff_ell, diff_para, diff_geod3])
diff_list.append([diff_ell])
diff_list.append([v_deg, u_deg, diff_ell, diff_para, diff_geod3]) #
diffs_ell.append([diff_ell])
diffs_para.append([diff_para])
diffs_geod.append([diff_geod3])
diff_list = np.array(diff_list)
pass
diffs_ell = np.array(diffs_ell)
diffs_para = np.array(diffs_para)
diffs_geod = np.array(diffs_geod)
pass
points = np.array(points)
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
sc = ax.scatter(
points[:, 0],
points[:, 1],
points[:, 2],
c=diffs_ell, # Farbcode = diff
cmap='viridis', # Colormap
s=10 + 20 * diffs_ell, # optional: Größe abhängig vom diff
alpha=0.8
)
# Farbskala
cbar = plt.colorbar(sc)
cbar.set_label("diff")
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
plt.show()