Files
Masterprojekt/dashborad.py
2025-12-16 16:31:24 +01:00

517 lines
18 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 GHA_triaxial.panou import gha1_ana
from GHA_triaxial.panou import gha1_num
from GHA_triaxial.panou_2013_2GHA_num import gha2_num
from ellipsoide import EllipsoidTriaxial
import winkelumrechnungen as wu
import ausgaben as aus
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, lines):
"""
:param fig: plotly.graph_objects.Figure
:param lines: Linienliste [((x1,y1,z1), (x2,y2,z2), color)]
:return: plotly.graph_objects.Figure
"""
for (p1, p2, color) in lines:
xline = [p1[0], p2[0]]
yline = [p1[1], p2[1]]
zline = [p1[2], p2[2]]
fig.add_trace(go.Scatter3d(
x=xline, y=yline, z=zline,
mode="lines",
line=dict(width=4, color=color),
showlegend=False
))
return fig
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"),
html.Label("Ellipsoid wählen:"),
dcc.Dropdown(
id="my-dropdown",
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-1",
type="number",
min=0,
placeholder="ax...[m]",
style={"marginBottom": "10px", "display": "block", "width": "300px"},
),
dcc.Input(
id="input-2",
type="number",
min=0,
placeholder="ay...[m]",
style={"marginBottom": "10px", "display": "block", "width": "300px"},
),
dcc.Input(
id="input-3",
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"},
),
html.Div(id="output-area", style={"marginBottom": "20px"}),
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%"},
),
html.Div(id="output-gha1", style={"marginBottom": "20px"}),
html.Div(id="output-gha2", style={"marginBottom": "20px"}),
dcc.Graph(
id="ellipsoid-plot",
style={"height": "500px", "width": "700px"},
),
html.P(
"© 2025",
style={
"fontSize": "12px",
"color": "gray",
"textAlign": "center",
},
),
],
)
@app.callback(
Output("input-1", "value"),
Output("input-2", "value"),
Output("input-3", "value"),
Input("my-dropdown", "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
@app.callback(
Output("output-area", "children"),
Input("calc-ell", "n_clicks"),
State("input-1", "value"),
State("input-2", "value"),
State("input-3", "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)
return f"ex = {round(ell.ex, 6)}, ", f"ey = {round(ell.ey, 6)}, ", f"ee = {round(ell.ee, 6)}"
@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"},
),
],
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"},
),
],
id="pane-gha2",
style=show2,
)
return html.Div([pane_gha1, pane_gha2])
@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-1", "value"),
State("input-2", "value"),
State("input-3", "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
#p2_num = gha1_num(ell, p1, alpha_rad, s_val, 1000)
p2_num = 5
#out1 += f" {p2_num}"
out1.append(
html.Div([
html.Strong("Numerisch: "),
html.Span(f"{p2_num}")
])
)
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 - analystisch")
#fig = figure_constant_lines(fig, ell, "geod")
fig = figure_constant_lines(fig, ell, "ell")
#fig = figure_constant_lines(fig, ell, "para")
fig = figure_points(fig, [("P1", p1, "black"), ("P2", p2_ana, "red")])
fig = figure_lines(fig, [(p1, p2_ana, "red")])
#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 = gha2_num(
ell,
np.deg2rad(float(beta21)), np.deg2rad(float(lamb21)),
np.deg2rad(float(beta22)), np.deg2rad(float(lamb22))
)
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")
fig = figure_points(fig, [("P1", p1, "black"), ("P2", p2, "red")])
fig = figure_lines(fig, [(p1, p2, "red")])
return "", out2, fig
return no_update, no_update, no_update
if __name__ == "__main__":
app.run(debug=False)