kleine Anpassungen
This commit is contained in:
379
dashboard.py
Normal file
379
dashboard.py
Normal file
@@ -0,0 +1,379 @@
|
||||
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)
|
||||
ell = EllipsoidTriaxial(ax, ay, b)
|
||||
X, Y, Z = ell.para2cart(U, V)
|
||||
|
||||
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:
|
||||
um = np.deg2rad(lon_deg)
|
||||
vm = lat_line
|
||||
xm, ym, zm = ell.para2cart(um, vm)
|
||||
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:
|
||||
vp = np.deg2rad(lat_deg)
|
||||
up = lon_line
|
||||
xp, yp, zp = ell.para2cart(up, vp)
|
||||
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, 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
|
||||
))
|
||||
|
||||
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, "red")],
|
||||
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, "red")],
|
||||
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)
|
||||
Reference in New Issue
Block a user