Files
Masterprojekt/dashborad.py
Tammo.Weber 520f0973f0 Dashboard
2025-12-10 10:05:57 +01:00

385 lines
12 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_2013_2GHA_num import gha2_num
from ellipsoide import EllipsoidTriaxial
import winkelumrechnungen as wu
app = Dash(__name__, suppress_callback_exceptions=True)
app.title = "Geodätische Hauptaufgaben"
def abplattung(a, b):
return (a - b) / a
def ellipsoid_figure(ax, ay, b, pts=None, lines=None, title="Dreiachsiges 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 = ax * np.cos(U) * np.cos(V)
Y = ay * np.cos(U) * np.sin(V)
Z = b * np.sin(U)
fig = go.Figure()
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"
))
meridians_deg = np.arange(0, 360, 15)
lat_line = np.linspace(-np.pi/2, np.pi/2, 240)
for lon_deg in meridians_deg:
lam = np.deg2rad(lon_deg)
phi = lat_line
xm = ax * np.cos(phi) * np.cos(lam)
ym = ay * np.cos(phi) * np.sin(lam)
zm = b * np.sin(phi)
fig.add_trace(go.Scatter3d(
x=xm, y=ym, z=zm, mode="lines",
line=dict(width=1, color="black"),
showlegend=False
))
parallels_deg = np.arange(-75, 90, 15)
lon_line = np.linspace(0, 2*np.pi, 360)
for lat_deg in parallels_deg:
phi = np.deg2rad(lat_deg)
lam = lon_line
xp = ax * np.cos(phi) * np.cos(lam)
yp = ay * np.cos(phi) * np.sin(lam)
zp = b * np.sin(phi) * np.ones_like(lam)
fig.add_trace(go.Scatter3d(
x=xp, y=yp, z=zp, mode="lines",
line=dict(width=1, color="black"),
showlegend=False
))
if pts:
for name, (px, py, pz), color in pts:
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
))
if lines:
for (p1, p2) 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="red"),
showlegend=False
))
rx, ry, rz = 1.05*ax, 1.05*ay, 1.05*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),
)
return fig
app.layout = html.Div(
style={"fontFamily": "Arial", "margin": "40px"},
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": "Bessel-biaxial", "value": "Bessel-biaxial"},
#{"label": "Ei", "value": "Ei"},
],
value="",
style={"width": "300px", "marginBottom": "20px"},
),
html.Label("Halbachsen:"),
dcc.Input(
id="input-1",
type="number",
placeholder="ax...",
style={"marginBottom": "10px", "display": "block", "width": "300px"},
),
dcc.Input(
id="input-2",
type="number",
placeholder="ay...",
style={"marginBottom": "10px", "display": "block", "width": "300px"},
),
dcc.Input(
id="input-3",
type="number",
placeholder="b...",
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={
"margin": 0,
"fontSize": "12px",
"color": "gray",
"textAlign": "center",
"padding": "5px 0",
},
),
],
)
@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-3", "value"),
)
def update_output(n_clicks, ax, b):
if not n_clicks or ax is None or b is None:
return ""
f = abplattung(ax, b)
return f"Abplattung f = {f:.10e}"
@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", placeholder="β1...[°]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Input(id="input-GHA1-lamb1", type="number", placeholder="λ1...[°]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Input(id="input-GHA1-s", type="number", placeholder="s...[m]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Input(id="input-GHA1-a", type="number", 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", placeholder="β1...[°]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Input(id="input-GHA2-lamb1", type="number", placeholder="λ1...[°]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Input(id="input-GHA2-beta2", type="number", placeholder="β2...[°]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Input(id="input-GHA2-lamb2", type="number", placeholder="λ2...[°]",
style={"marginBottom": "20px", "display": "block", "width": "300px"}),
dcc.Checklist(
id="method-checklist-2",
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-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("my-dropdown", "value"),
prevent_initial_call=True,
)
def calc_and_plot(n1, n2,
beta11, lamb11, s, a_deg,
beta1, lamb1, beta2, lamb2,
ell_name):
if not (n1 or n2):
return no_update, no_update, no_update
if not ell_name:
return "Bitte Ellipsoid wählen.", "", go.Figure()
ell = EllipsoidTriaxial.init_name(ell_name)
if dash.ctx.triggered_id == "button-calc-gha1":
if None in (beta11, lamb11, s, a_deg):
return "Bitte β₁, λ₁, s und α eingeben.", "", 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)))
x2, y2, z2 = gha1_ana(ell, p1, alpha_rad, s_val, 70)
p2 = (float(x2), float(y2), float(z2))
fig = ellipsoid_figure(
ell.ax, ell.ay, ell.b,
pts=[("P1", p1, "black"), ("P2", p2, "red")],
lines=[(p1, p2)],
title="Erste Hauptaufgabe - analystisch"
)
out1 = f"x₂={p2[0]:.3f}, y₂={p2[1]:.3f}, z₂={p2[2]:.3f}"
return out1, "", fig
if dash.ctx.triggered_id == "button-calc-gha2":
if None in (beta1, lamb1, beta2, lamb2):
return "", "Bitte β₁, λ₁, β₂, λ₂ eingeben.", go.Figure()
alpha_1, alpha_2, s12 = gha2_num(
ell,
np.deg2rad(float(beta1)), np.deg2rad(float(lamb1)),
np.deg2rad(float(beta2)), np.deg2rad(float(lamb2))
)
p1 = tuple(ell.ell2cart(np.deg2rad(float(beta1)), np.deg2rad(float(lamb1))))
p2 = tuple(ell.ell2cart(np.deg2rad(float(beta2)), np.deg2rad(float(lamb2))))
fig = ellipsoid_figure(
ell.ax, ell.ay, ell.b,
pts=[("P1", p1, "black"), ("P2", p2, "red")],
lines=[(p1, p2)],
title=f"Zweite Hauptaufgabe - numerisch"
)
out2 = f"a₁₂={np.rad2deg(alpha_1):.6f}°, a₂₁={np.rad2deg(alpha_2):.6f}°, s={s12:.4f} m"
return "", out2, fig
return no_update, no_update, no_update
if __name__ == "__main__":
app.run(debug=False)