Files
Masterprojekt/dashboard.py

847 lines
29 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from dash import Dash, html, dcc, Input, Output, State, no_update
import dash
import plotly.graph_objects as go
import numpy as np
from ellipsoide import EllipsoidTriaxial
import winkelumrechnungen as wu
import ausgaben as aus
from GHA_triaxial.panou import gha1_ana
from GHA_triaxial.panou import gha1_num
from es_cma_gha1 import gha1_es
from GHA_triaxial.ES_gha2 import gha2_ES
from GHA_triaxial.panou_2013_2GHA_num import gha2_num
app = Dash(__name__, suppress_callback_exceptions=True)
app.title = "Geodätische Hauptaufgaben"
def abplattung(a, b):
return (a - b) / a
def ellipsoid_figure(ell: EllipsoidTriaxial, title="Dreiachsiges Ellipsoid"):
fig = go.Figure()
# Darstellung
rx, ry, rz = 1.05*ell.ax, 1.05*ell.ay, 1.05*ell.b
fig.update_layout(
title=title,
scene=dict(
xaxis=dict(range=[-rx, rx], title="X [m]"),
yaxis=dict(range=[-ry, ry], title="Y [m]"),
zaxis=dict(range=[-rz, rz], title="Z [m]"),
aspectmode="data"
),
margin=dict(l=0, r=0, t=40, b=0),
)
# Ellipsoid
u = np.linspace(-np.pi/2, np.pi/2, 80)
v = np.linspace(-np.pi, np.pi, 160)
U, V = np.meshgrid(u, v)
X, Y, Z = ell.para2cart(U, V)
fig.add_trace(go.Surface(
x=X, y=Y, z=Z, showscale=False, opacity=0.7,
surfacecolor=np.zeros_like(X),
colorscale=[[0, "rgb(200,220,255)"], [1, "rgb(200,220,255)"]],
name="Ellipsoid"
))
return fig
def figure_constant_lines(fig, ell: EllipsoidTriaxial, coordsystem: str = "para"):
if coordsystem == "para":
constants_u = wu.deg2rad(np.arange(0, 360, 15))
all_v = np.linspace(-np.pi / 2, np.pi / 2, 361)
for u in constants_u:
xm, ym, zm = ell.para2cart(u, all_v)
fig.add_trace(go.Scatter3d(
x=xm, y=ym, z=zm, mode="lines",
line=dict(width=1, color="black"),
showlegend=False
))
all_u = np.linspace(0, 2 * np.pi, 361)
constants_v = wu.deg2rad(np.arange(-75, 90, 15))
for v in constants_v:
x, y, z = ell.para2cart(all_u, v)
fig.add_trace(go.Scatter3d(
x=x, y=y, z=z, mode="lines",
line=dict(width=1, color="black"),
showlegend=False
))
elif coordsystem == "ell":
constants_beta = wu.deg2rad(np.arange(-75, 90, 15))
all_lamb = np.linspace(0, 2 * np.pi, 361)
for beta in constants_beta:
xyz = ell.ell2cart(beta, all_lamb)
fig.add_trace(go.Scatter3d(
x=xyz[:, 0], y=xyz[:, 1], z=xyz[:, 2], mode="lines",
line=dict(width=1, color="black"),
showlegend=False
))
all_beta = np.linspace(-np.pi / 2, np.pi / 2, 361)
constants_lamb = wu.deg2rad(np.arange(0, 360, 15))
for lamb in constants_lamb:
xyz = ell.ell2cart(all_beta, lamb)
fig.add_trace(go.Scatter3d(
x=xyz[:, 0], y=xyz[:, 1], z=xyz[:, 2], mode="lines",
line=dict(width=1, color="black"),
showlegend=False
))
elif coordsystem == "geod":
constants_phi = wu.deg2rad(np.arange(-75, 90, 15))
all_lamb = np.linspace(0, 2 * np.pi, 361)
for phi in constants_phi:
x, y, z = ell.geod2cart(phi, all_lamb, 0)
fig.add_trace(go.Scatter3d(
x=x, y=y, z=z, mode="lines",
line=dict(width=1, color="black"),
showlegend=False
))
all_phi = np.linspace(-np.pi / 2, np.pi / 2, 361)
constants_lamb = wu.deg2rad(np.arange(0, 360, 15))
for lamb in constants_lamb:
x, y, z = ell.geod2cart(all_phi, lamb, 0)
fig.add_trace(go.Scatter3d(
x=x, y=y, z=z, mode="lines",
line=dict(width=1, color="black"),
showlegend=False
))
return fig
def figure_points(fig, points):
"""
:param fig: plotly.graph_objects.Figure
:param points: Punktliste [(name, (x,y,z), color)]
:return: plotly.graph_objects.Figure
"""
for name, (px, py, pz), color in points:
fig.add_trace(go.Scatter3d(
x=[px], y=[py], z=[pz],
mode="markers+text",
marker=dict(size=6, color=color),
text=[name], textposition="top center",
name=name, showlegend=False
))
return fig
def figure_lines(fig, line, color):
"""
:param fig: plotly.graph_objects.Figure
:param line: Punktliste [[x1,y1,z1], [x2,y2,z2]]
:param color: Farbe
:return: plotly.graph_objects.Figure
"""
points = np.array(line, dtype=float)
fig.add_trace(go.Scatter3d(
x=points[:, 0], y=points[:, 1], z=points[:, 2],
mode="lines",
line=dict(width=4, color=color),
name="Strecke", showlegend=False
))
return fig
# HTML-Elemente
app.layout = html.Div(
style={"fontFamily": "Arial", "padding": "5px", "width": "70%", "margin-left": "auto"},
children=[
html.H1("Geodätische Hauptaufgaben"),
html.H2("für dreiachsige Ellipsoide"),
# Dropdown und Eingabefelder Ellipsoid
html.Label("Ellipsoid wählen:"),
dcc.Dropdown(
id="dropdown-ellipsoid",
options=[
{"label": "BursaFialova1993", "value": "BursaFialova1993"},
{"label": "BursaSima1980", "value": "BursaSima1980"},
{"label": "BursaSima1980round", "value": "BursaSima1980round"},
{"label": "Eitschberger1978", "value": "Eitschberger1978"},
{"label": "Bursa1972", "value": "Bursa1972"},
{"label": "Bursa1970", "value": "Bursa1970"},
{"label": "BesselBiaxial", "value": "BesselBiaxial"},
{"label": "Fiction", "value": "Fiction"},
#{"label": "Ei", "value": "Ei"},
],
value="",
style={"width": "300px", "marginBottom": "20px"},
),
html.Label("Halbachsen:"),
dcc.Input(
id="input-ax",
type="number",
min=0,
placeholder="ax...[m]",
style={"marginBottom": "10px", "display": "block", "width": "300px"},
),
dcc.Input(
id="input-ay",
type="number",
min=0,
placeholder="ay...[m]",
style={"marginBottom": "10px", "display": "block", "width": "300px"},
),
dcc.Input(
id="input-b",
type="number",
min=0,
placeholder="b...[m]",
style={"marginBottom": "20px", "display": "block", "width": "300px"},
),
html.Button(
"Ellipsoid berechnen",
id="calc-ell",
n_clicks=0,
style={"marginRight": "10px", "marginBottom": "20px"},
),
# Ausgabebereich für Ellipsoid-Berechnung
html.Div(id="output-area", style={"marginBottom": "20px"}),
# Tabs für beide Hauptaufgaben - Inhalt wird per Funktion generiert s.u.
dcc.Tabs(
id="tabs-GHA",
value="tab-GHA1",
style={"marginRight": "10px", "marginBottom": "20px", "width": "50%"},
children=[
dcc.Tab(label="Erste Hauptaufgabe", value="tab-GHA1"),
dcc.Tab(label="Zweite Hauptaufgabe", value="tab-GHA2"),
],
),
html.Div(
id="tabs-GHA-out",
style={"marginRight": "10px", "marginBottom": "20px", "width": "50%"},
),
dcc.Loading(html.Div(id="output-gha1-ana")),
dcc.Loading(html.Div(id="output-gha1-num")),
dcc.Loading(html.Div(id="output-gha1-stoch")),
dcc.Store(id="store-gha1-ana"),
dcc.Store(id="store-gha1-num"),
dcc.Store(id="store-gha1-stoch"),
dcc.Loading(html.Div(id="output-gha2-num")),
dcc.Loading(html.Div(id="output-gha2-stoch")),
dcc.Store(id="store-gha2-num"),
dcc.Store(id="store-gha2-stoch"),
# Ausgabebereich für den Plot
dcc.Graph(
id="ellipsoid-plot",
style={"height": "500px", "width": "700px"},
),
# Fussleiste
html.P(
"© 2025",
style={
"fontSize": "12px",
"color": "gray",
"textAlign": "center",
},
),
],
)
# Funktion zur Wahl der Halbachsen
@app.callback(
Output("input-ax", "value"),
Output("input-ay", "value"),
Output("input-b", "value"),
Input("dropdown-ellipsoid", "value"),
)
def fill_inputs_from_dropdown(selected_ell):
if not selected_ell:
return None, None, None
ell = EllipsoidTriaxial.init_name(selected_ell)
ax = ell.ax
ay = ell.ay
b = ell.b
return ax, ay, b
# Funktion zur Berechnung der Ellipsoid-Parameter
@app.callback(
Output("output-area", "children"),
Input("calc-ell", "n_clicks"),
State("input-ax", "value"),
State("input-ay", "value"),
State("input-b", "value"),
)
def update_output(n_clicks, ax, ay, b):
if not n_clicks:
return ""
if n_clicks and ax is None or ay is None or b is None:
return html.Span("Bitte Ellipsoid auswählen!", style={"color": "red"})
if ay >= ax or b >= ay or ax <= 0 or ay <= 0 or b <= 0:
return html.Span("Eingabe inkorrekt.", style={"color": "red"})
ell = EllipsoidTriaxial(ax, ay, b)
out_ell = []
out_ell.append(
html.Div([
html.P(f"eₓ = {round(ell.ex, 6)}, eᵧ = {round(ell.ey, 6)}, eₑ = {round(ell.ee, 6)}"),
#html.Br(),
html.P(f"Eₓ = {round(ell.Ex, 3)}, Eᵧ = {round(ell.Ey, 3)}, Eₑ = {round(ell.Ee, 3)}"),
]))
return out_ell
# Funktion zur Generierung der Tab-Inhalte
@app.callback(
Output("tabs-GHA-out", "children"),
Input("tabs-GHA", "value"),
)
def render_content(tab):
show1 = {"display": "block"} if tab == "tab-GHA1" else {"display": "none"}
show2 = {"display": "block"} if tab == "tab-GHA2" else {"display": "none"}
pane_gha1 = html.Div(
[
dcc.Input(id="input-GHA1-beta1", type="number", min=-90, max=90, placeholder="β1...[°]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Input(id="input-GHA1-lamb1", type="number", min=-180, max=180, placeholder="λ1...[°]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Input(id="input-GHA1-s", type="number", min=0, placeholder="s...[m]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Input(id="input-GHA1-a", type="number", min=0, max=360, placeholder="α...[°]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Checklist(
id="method-checklist-1",
options=[
{"label": "Analytisch", "value": "analytisch"},
{"label": "Numerisch", "value": "numerisch"},
{"label": "Stochastisch (ES)", "value": "stochastisch"},
],
value=[],
style={"marginBottom": "20px"},
),
html.Div(
[
html.Button(
"Berechnen",
id="button-calc-gha1",
n_clicks=0,
style={"marginRight": "10px"},
),
],
style={"marginBottom": "20px"},
),
html.H4("Erste Hauptaufgabe"),
],
id="pane-gha1",
style=show1,
)
pane_gha2 = html.Div(
[
dcc.Input(id="input-GHA2-beta1", type="number", min=-90, max=90, placeholder="β1...[°]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Input(id="input-GHA2-lamb1", type="number", min=-180, max=180, placeholder="λ1...[°]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Input(id="input-GHA2-beta2", type="number", min=-90, max=90, placeholder="β2...[°]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Input(id="input-GHA2-lamb2", type="number", min=-180, max=180, placeholder="λ2...[°]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Checklist(
id="method-checklist-2",
options=[
{"label": "Numerisch", "value": "numerisch"},
{"label": "Stochastisch (ES)", "value": "stochastisch"},
],
value=[],
style={"marginBottom": "20px"},
),
html.Div(
[
html.Button(
"Berechnen",
id="button-calc-gha2",
n_clicks=0,
style={"marginRight": "10px"},
),
],
style={"marginBottom": "20px"},
),
html.H4("Zweite Hauptaufgabe"),
],
id="pane-gha2",
style=show2,
)
return html.Div([pane_gha1, pane_gha2])
# Funktion zur Berechnung der Hauptaufgaben
# @app.callback(
# Output("output-gha1", "children"),
# Output("output-gha2", "children"),
# Output("ellipsoid-plot", "figure"),
# Input("button-calc-gha1", "n_clicks"),
# Input("button-calc-gha2", "n_clicks"),
# State("input-GHA1-beta1", "value"),
# State("input-GHA1-lamb1", "value"),
# State("input-GHA1-s", "value"),
# State("input-GHA1-a", "value"),
# State("input-GHA2-beta1", "value"),
# State("input-GHA2-lamb1", "value"),
# State("input-GHA2-beta2", "value"),
# State("input-GHA2-lamb2", "value"),
# State("input-ax", "value"),
# State("input-ay", "value"),
# State("input-b", "value"),
# State("method-checklist-1", "value"),
# State("method-checklist-2", "value"),
#
# prevent_initial_call=True,
# )
#
# def calc_and_plot(n1, n2,
# beta11, lamb11, s, a_deg,
# beta21, lamb21, beta22, lamb22,
# ax, ay, b, method1, method2):
#
# if not (n1 or n2):
# return no_update, no_update, no_update
#
# if not ax or not ay or not b:
# return html.Span("Bitte Ellipsoid auswählen!", style={"color": "red"}), "", go.Figure()
#
# ell = EllipsoidTriaxial(ax, ay, b)
#
# if dash.ctx.triggered_id == "button-calc-gha1":
# if None in (beta11, lamb11, s, a_deg):
#
# return html.Span("Bitte β₁, λ₁, s und α eingeben.", style={"color": "red"}), "", go.Figure()
#
# beta_rad = wu.deg2rad(float(beta11))
# lamb_rad = wu.deg2rad(float(lamb11))
# alpha_rad = wu.deg2rad(float(a_deg))
# s_val = float(s)
#
# p1 = tuple(map(float, ell.ell2cart(beta_rad, lamb_rad)))
# out1 = []
#
# if "analytisch" in method1:
# # ana
# x2, y2, z2 = gha1_ana(ell, p1, alpha_rad, s_val, 70)
# p2_ana = (float(x2), float(y2), float(z2))
# beta2, lamb2 = ell.cart2ell([x2, y2, z2])
#
# #out1 += f"kartesisch: x₂={p2[0]:.5f} m, y₂={p2[1]:.5f} m, z₂={p2[2]:.5f} m; ellipsoidisch: {aus.gms("β₂", beta2, 5)}, {aus.gms("λ₂", lamb2, 5)},"
# out1.append(
# html.Div([
# html.Strong("Analytisch: "),
# html.Br(),
# html.Span(f"kartesisch: x₂={x2:.4f} m, y₂={y2:.4f} m, z₂={z2:.4f} m"),
# html.Br(),
# html.Span(f"ellipsoidisch: {aus.gms('β₂', beta2, 4)}, {aus.gms('λ₂', lamb2, 4)}")
# ])
# )
#
# if "numerisch" in method1:
# # num
# x1, y1, z1, werte = gha1_num(ell, p1, alpha_rad, s_val, 10000)
# p2_num = x1, y1, z1
# beta2_num, lamb2_num = ell.cart2ell(p2_num)
#
# out1.append(
# html.Div([
# html.Strong("Numerisch: "),
# html.Br(),
# html.Span(f"kartesisch: x₂={p2_num[0]:.4f} m, y₂={p2_num[1]:.4f} m, z₂={p2_num[2]:.4f} m"),
# html.Br(),
# html.Span(f"ellipsoidisch: {aus.gms('β₂', beta2_num, 4)}, {aus.gms('λ₂', lamb2_num, 4)}")
# ])
# )
#
# geo_line_num1 = []
# for x1, _, y1, _, z1, _ in werte:
# geo_line_num1.append([x1, y1, z1])
#
#
# if "stochastisch" in method1:
# # stoch
# p2_stoch = "noch nicht implementiert.."
#
# out1.append(
# html.Div([
# html.Strong("Stochastisch (ES): "),
# html.Span(f"{p2_stoch}")
# ])
# )
#
# if not method1:
# return html.Span("Bitte Berechnungsverfahren auswählen!", style={"color": "red"}), "", go.Figure()
#
# fig = ellipsoid_figure(ell, title="Erste Hauptaufgabe - analytisch")
# #fig = figure_constant_lines(fig, ell, "geod")
# fig = figure_constant_lines(fig, ell, "ell")
# #fig = figure_constant_lines(fig, ell, "para")
# if "analytisch" in method1:
# fig = figure_points(fig, [("P1", p1, "black"), ("P2", p2_ana, "red")])
# if "numerisch" in method1:
# fig = figure_lines(fig, geo_line_num1, "#ff8c00")
#
# #out1 = f"kartesisch: x₂={p2[0]:.5f} m, y₂={p2[1]:.5f} m, z₂={p2[2]:.5f} m; ellipsoidisch: {aus.gms("β₂", beta2, 5)}, {aus.gms("λ₂", lamb2, 5)}, {p2_num}"
# return out1, "", fig
#
# if dash.ctx.triggered_id == "button-calc-gha2":
# if None in (beta21, lamb21, beta22, lamb22):
# return html.Span("Bitte β₁, λ₁, β₂, λ₂ eingeben.", style={"color": "red"}), "", go.Figure()
#
# p1 = tuple(ell.ell2cart(np.deg2rad(float(beta21)), np.deg2rad(float(lamb21))))
# p2 = tuple(ell.ell2cart(np.deg2rad(float(beta22)), np.deg2rad(float(lamb22))))
#
# out2 = []
#
# if "numerisch" in method2:
# alpha_1, alpha_2, s12, beta_arr, lamb_arr = gha2_num(
# ell,
# np.deg2rad(float(beta21)), np.deg2rad(float(lamb21)),
# np.deg2rad(float(beta22)), np.deg2rad(float(lamb22))
# )
# geo_line_num = []
# for beta, lamb in zip(beta_arr, lamb_arr):
# point = ell.ell2cart(beta, lamb)
# geo_line_num.append(point)
#
# out2.append(
# html.Div([
# html.Strong("Numerisch: "),
# html.Span(f"{aus.gms('α₁₂', alpha_1, 4)}, {aus.gms('α₂₁', alpha_2, 4)}, s = {s12:.4f} m"),
# ])
# )
#
#
# if "stochastisch" in method2:
# # stoch
# a_stoch = "noch nicht implementiert.."
#
# out2.append(
# html.Div([
# html.Strong("Stochastisch (ES): "),
# html.Span(f"{a_stoch}")
# ])
# )
#
# if not method2:
# return html.Span("Bitte Berechnungsverfahren auswählen!", style={"color": "red"}), "", go.Figure()
#
# fig = ellipsoid_figure(ell, title="Zweite Hauptaufgabe")
# fig = figure_constant_lines(fig, ell, "ell")
# if "numerisch" in method2:
# fig = figure_lines(fig, geo_line_num, "#ff8c00")
# fig = figure_points(fig, [("P1", p1, "black"), ("P2", p2, "red")])
#
#
#
# return "", out2, fig
#
# return no_update, no_update, no_update
# -- GHA 1 ---
@app.callback(
Output("output-gha1-ana", "children"),
Output("store-gha1-ana", "data"),
Input("button-calc-gha1", "n_clicks"),
State("input-GHA1-beta1", "value"),
State("input-GHA1-lamb1", "value"),
State("input-GHA1-s", "value"),
State("input-GHA1-a", "value"),
State("input-ax", "value"),
State("input-ay", "value"),
State("input-b", "value"),
State("method-checklist-1", "value"),
prevent_initial_call=True,
)
def compute_gha1_ana(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1):
if not n1:
return no_update, no_update
if None in (ax, ay, b):
return html.Span("Bitte Ellipsoid wählen.", style={"color": "red"}), None
if None in (beta11, lamb11, s, a_deg):
return html.Span("Bitte β₁, λ₁, s und α eingeben.", style={"color": "red"}), None
if not method1:
return html.Span("Bitte Berechnungsverfahren wählen.", style={"color": "red"}), None
if "analytisch" not in (method1 or []):
return no_update, no_update
ell = EllipsoidTriaxial(ax, ay, b)
beta_rad = wu.deg2rad(float(beta11))
lamb_rad = wu.deg2rad(float(lamb11))
alpha_rad = wu.deg2rad(float(a_deg))
s_val = float(s)
p1 = tuple(map(float, ell.ell2cart(beta_rad, lamb_rad)))
x2, y2, z2 = gha1_ana(ell, p1, alpha_rad, s_val, 70)
p2 = (float(x2), float(y2), float(z2))
beta2, lamb2 = ell.cart2ell([x2, y2, z2])
out = html.Div([
html.Strong("Analytisch: "),
html.Br(),
html.Span(f"kartesisch: x₂={x2:.4f} m, y₂={y2:.4f} m, z₂={z2:.4f} m"),
html.Br(),
html.Span(f"ellipsoidisch: {aus.gms('β₂', beta2, 4)}, {aus.gms('λ₂', lamb2, 4)}"),
html.Br(),
])
store = {
"points": [("P1", p1, "black"), ("P2", p2, "red")],
"polyline": None,
"color": "#d62728"
}
return out, store
@app.callback(
Output("output-gha1-num", "children"),
Output("store-gha1-num", "data"),
Input("button-calc-gha1", "n_clicks"),
State("input-GHA1-beta1", "value"),
State("input-GHA1-lamb1", "value"),
State("input-GHA1-s", "value"),
State("input-GHA1-a", "value"),
State("input-ax", "value"),
State("input-ay", "value"),
State("input-b", "value"),
State("method-checklist-1", "value"),
prevent_initial_call=True,
)
def compute_gha1_num(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1):
if not n1:
return no_update, no_update
if "numerisch" not in (method1 or []):
return no_update, no_update
ell = EllipsoidTriaxial(ax, ay, b)
beta_rad = wu.deg2rad(float(beta11))
lamb_rad = wu.deg2rad(float(lamb11))
alpha_rad = wu.deg2rad(float(a_deg))
s_val = float(s)
p1 = tuple(map(float, ell.ell2cart(beta_rad, lamb_rad)))
xN, yN, zN, werte = gha1_num(ell, p1, alpha_rad, s_val, 10000)
p2 = (xN, yN, zN)
beta2_num, lamb2_num = ell.cart2ell(p2)
out = html.Div([
html.Strong("Numerisch: "),
html.Br(),
html.Span(f"kartesisch: x₂={p2[0]:.4f} m, y₂={p2[1]:.4f} m, z₂={p2[2]:.4f} m"),
html.Br(),
html.Span(f"ellipsoidisch: {aus.gms('β₂', beta2_num, 4)}, {aus.gms('λ₂', lamb2_num, 4)}"),
html.Br(),
])
polyline = [[x1, y1, z1] for x1, _, y1, _, z1, _ in werte]
store = {
"points": [("P1", p1, "black"), ("P2", p2, "#ff8c00")],
"polyline": polyline,
"color": "#ff8c00"
}
return out, store
@app.callback(
Output("output-gha1-stoch", "children"),
Output("store-gha1-stoch", "data"),
Input("button-calc-gha1", "n_clicks"),
State("input-GHA1-beta1", "value"),
State("input-GHA1-lamb1", "value"),
State("input-GHA1-s", "value"),
State("input-GHA1-a", "value"),
State("input-ax", "value"),
State("input-ay", "value"),
State("input-b", "value"),
State("method-checklist-1", "value"),
prevent_initial_call=True,
)
def compute_gha1_stoch(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1):
if not n1:
return no_update, no_update
if "stochastisch" not in (method1 or []):
return no_update, no_update
ell = EllipsoidTriaxial(ax, ay, b)
beta_rad = wu.deg2rad(float(beta11))
lamb_rad = wu.deg2rad(float(lamb11))
alpha_rad = wu.deg2rad(float(a_deg))
s_val = float(s)
betas, lambs, alphas, S_real = gha1_es(
beta_rad, lamb_rad, alpha_rad,
s_val,
10000,
ell,
sigma0=1e-10
)
beta2 = betas[-1]
lamb2 = lambs[-1]
alpha2 = alphas[-1]
p1 = ell.ell2cart(beta_rad, lamb_rad)
p2 = ell.ell2cart(beta2, lamb2)
x2, y2, z2 = p2[0], p2[1], p2[2]
out = html.Div([
html.Strong("Stochastisch: "),
html.Br(),
html.Span(f"kartesisch: x₂={x2:.4f} m, y₂={y2:.4f} m, z₂={z2:.4f} m"),
html.Br(),
html.Span(f"ellipsoidisch: {aus.gms('β₂', beta2, 4)}, {aus.gms('λ₂', lamb2, 4)}"),
])
store = {
"points": [("P1", p1, "black"), ("P2", p2, "red")],
"polyline": None,
"color": "#d62728"
}
return out, store
# --- GHA 2 ---
@app.callback(
Output("output-gha2-num", "children"),
Output("store-gha2-num", "data"),
Input("button-calc-gha2", "n_clicks"),
State("input-GHA2-beta1", "value"),
State("input-GHA2-lamb1", "value"),
State("input-GHA2-beta2", "value"),
State("input-GHA2-lamb2", "value"),
State("input-ax", "value"),
State("input-ay", "value"),
State("input-b", "value"),
State("method-checklist-2", "value"),
prevent_initial_call=True,
)
def compute_gha2_num(n2, beta1, lamb1, beta2, lamb2, ax, ay, b, method2):
if not n2:
return no_update, no_update
if None in (ax, ay, b):
return html.Span("Bitte Ellipsoid wählen.", style={"color": "red"}), None
if None in (beta1, lamb1, beta2, lamb2):
return html.Span("Bitte β₁, λ₁, β₂ und λ₂ eingeben.", style={"color": "red"}), None
if not method2:
return html.Span("Bitte Berechnungsverfahren wählen.", style={"color": "red"}), None
if "numerisch" not in (method2 or []):
return no_update, no_update
ell = EllipsoidTriaxial(ax, ay, b)
b1 = wu.deg2rad(float(beta1)); l1 = wu.deg2rad(float(lamb1))
b2 = wu.deg2rad(float(beta2)); l2 = wu.deg2rad(float(lamb2))
p1 = tuple(map(float, ell.ell2cart(b1, l1)))
p2 = tuple(map(float, ell.ell2cart(b2, l2)))
alpha_1, alpha_2, s12, beta_arr, lamb_arr = gha2_num(ell, b1, l1, b2, l2)
# Polyline der Geodäte: [[x,y,z], ...]
polyline = []
for b_rad, l_rad in zip(beta_arr, lamb_arr):
x, y, z = ell.ell2cart(b_rad, l_rad)
polyline.append([float(x), float(y), float(z)])
out = html.Div([
html.Strong("Zweite Hauptaufgabe Numerisch: "),
html.Span(f"{aus.gms('α₁₂', alpha_1, 4)}, {aus.gms('α₂₁', alpha_2, 4)}, s = {s12:.4f} m"),
])
store = {
"points": [("P1", p1, "black"), ("P2", p2, "#1f77b4")],
"polyline": polyline,
"color": "#1f77b4",
}
return out, store
# @app.callback(
# Output("output-gha2-stoch", "children"),
# Output("store-gha2-stoch", "data"),
# Input("button-calc-gha2", "n_clicks"),
# State("input-GHA2-beta1", "value"),
# State("input-GHA2-lamb1", "value"),
# State("input-GHA2-beta2", "value"),
# State("input-GHA2-lamb2", "value"),
# State("input-ax", "value"),
# State("input-ay", "value"),
# State("input-b", "value"),
# State("method-checklist-2", "value"),
# prevent_initial_call=True,
# )
# def compute_gha2_stoch(n2, beta1, lamb1, beta2, lamb2, ax, ay, b, method2):
# if not n2:
# return no_update, no_update
# if "numerisch" not in (method2 or []):
# return no_update, no_update
#
# out = html.Div([
# html.Strong("Zweite Hauptaufgabe Stochastisch (ES): "),
# html.Span("noch nicht implementiert...")
# ])
#
# return out, {"points": None, "polyline": None, "color": "#9467bd"}
@app.callback(
Output("ellipsoid-plot", "figure"),
Input("input-ax", "value"),
Input("input-ay", "value"),
Input("input-b", "value"),
Input("store-gha1-ana", "data"),
Input("store-gha1-num", "data"),
Input("store-gha2-num", "data"),
Input("store-gha2-stoch", "data"),
)
def render_all(ax, ay, b, store_gha1_ana, store_gha1_num, store_gha2_num, store_gha2_stoch):
if None in (ax, ay, b):
return go.Figure()
ell = EllipsoidTriaxial(ax, ay, b)
fig = ellipsoid_figure(ell, title="")
fig = figure_constant_lines(fig, ell, "ell")
def add_from_store(store):
if not store:
return
pts = store.get("points")
if pts:
fig = figure_points(fig, pts)
line = store.get("polyline")
if line:
fig = figure_lines(fig, line, store.get("color", "#ff8c00"))
return fig
for st in (store_gha1_ana, store_gha1_num, store_gha2_num, store_gha2_stoch):
res = add_from_store(st)
if res is not None:
fig = res
return fig
if __name__ == "__main__":
app.run(debug=False)