Änderungen mergen

This commit is contained in:
Tammo.Weber
2026-02-05 10:59:17 +01:00
parent 96e489a116
commit a3ec069c1a

View File

@@ -1,34 +1,93 @@
from dash import Dash, html, dcc, Input, Output, State, no_update from dash import Dash, html, dcc, Input, Output, State, no_update
import plotly.graph_objects as go import plotly.graph_objects as go
import numpy as np import numpy as np
import dash_bootstrap_components as dbc
import webbrowser
from threading import Timer
from ellipsoide import EllipsoidTriaxial from ellipsoide import EllipsoidTriaxial
import winkelumrechnungen as wu import winkelumrechnungen as wu
import ausgaben as aus import ausgaben as aus
from GHA_triaxial.panou import gha1_ana from GHA_triaxial.gha1_ana import gha1_ana
from GHA_triaxial.panou import gha1_num from GHA_triaxial.gha1_num import gha1_num
from GHA_triaxial.approx_gha1 import gha1_approx from GHA_triaxial.gha1_approx import gha1_approx
from GHA_triaxial.panou_2013_2GHA_num import gha2_num from GHA_triaxial.gha2_num import gha2_num
from GHA_triaxial.ES_gha2 import gha2_ES from GHA_triaxial.gha2_ES import gha2_ES
from GHA_triaxial.approx_gha2 import gha2_approx from GHA_triaxial.gha2_approx import gha2_approx
app = Dash(__name__, suppress_callback_exceptions=True) app = Dash(__name__, suppress_callback_exceptions=True, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.title = "Geodätische Hauptaufgaben" app.title = "Geodätische Hauptaufgaben"
def inputfeld(left_text, input_id, right_text="", width=200, min=None, max=None): def inputfeld(left_text, input_id, right_text="", width=200, min=None, max=None):
return html.Div( return html.Div(
[ children=[
html.Span(f"{left_text} =", style={"minWidth": 36, "textAlign": "right", "marginRight": 5}), html.Span(f"{left_text} =", style={"minWidth": 36, "textAlign": "right", "marginRight": 5}),
dcc.Input(id=input_id, type="number", placeholder=f"{left_text}...[{right_text}]", min=min, max=max, style={"width": width, "display": "block",}), dcc.Input(
id=input_id,
type="number",
placeholder=f"{left_text}...[{right_text}]",
min=min,
max=max,
style={"width": width, "display": "block"},
persistence=True,
persistence_type="memory", # oder "session"/"local"
),
html.Span(right_text, style={"marginLeft": 5}) if right_text else html.Span() html.Span(right_text, style={"marginLeft": 5}) if right_text else html.Span()
], ],
style={"display": "flex", "alignItems": "center", "marginBottom": "10px"} style={"display": "flex", "alignItems": "center", "marginBottom": "10px"},
) )
def method_row(label, cb_id, input_id, placeholder=""):
if placeholder == "":
return html.Div(
[
dcc.Checklist(
id=cb_id,
options=[{"label": "", "value": "on"}],
value=[],
style={"margin": "0"},
persistence=True,
persistence_type="memory",
),
html.Span(label, style={"marginLeft": "6px", "minWidth": "110px"}),
],
style={"display": "flex", "alignItems": "center", "gap": "6px",
"marginLeft": "10px", "marginBottom": "6px"},
)
else:
return html.Div(
[
dcc.Checklist(
id=cb_id,
options=[{"label": "", "value": "on"}],
value=[],
style={"margin": "0"},
persistence=True,
persistence_type="memory",
),
html.Span(label, style={"marginLeft": "6px", "minWidth": "110px"}),
dcc.Input(
id=input_id,
type="number",
placeholder=placeholder,
style={"width": "80px", "marginLeft": "10px"},
disabled=True,
persistence=True,
persistence_type="memory",
),
],
style={"display": "flex", "alignItems": "center", "gap": "6px",
"marginLeft": "10px", "marginBottom": "6px"},
)
def ellipsoid_figure(ell: EllipsoidTriaxial, title="Dreiachsiges Ellipsoid"): def ellipsoid_figure(ell: EllipsoidTriaxial, title="Dreiachsiges Ellipsoid"):
fig = go.Figure() fig = go.Figure()
@@ -171,6 +230,107 @@ def figure_lines(fig, line, color):
)) ))
return fig return fig
pane_gha1 = html.Div(
[
inputfeld("β₀", "input-GHA1-beta0", "°", min=-90, max=90),
inputfeld("λ₀", "input-GHA1-lamb0", "°", min=-180, max=180),
inputfeld("s", "input-GHA1-s", "m", min=0),
inputfeld("α₀", "input-GHA1-a", "°", min=0, max=360),
dcc.Checklist(
id="method-checklist-1",
options=[
{"label": "Analytisch", "value": "analytisch"},
{"label": "Numerisch", "value": "numerisch"},
{"label": "Approximiert", "value": "approx"},
],
value=[],
style={"marginBottom": "10px", "marginLeft": "10px"},
persistence=True,
persistence_type="memory",
persisted_props=["value"],
),
method_row("Analytisch", "cb-ana-1", "input-ana1", ""),
method_row("Numerisch", "cb-num-1", "input-num-n-1", "n"),
method_row("Stochastisch", "cb-stoch-1", "input-stoch-n-1", "n"),
method_row("Approximiert", "cb-approx-1", "input-approx-ds-1", "ds"),
html.Div(
[
html.Button(
"Berechnen",
id="button-calc-gha1",
n_clicks=0,
className="btn btn-secondary btn-lg shadow",
style={"marginRight": "10px", "marginLeft": "10px", "marginTop": "30px"},
),
],
style={"marginBottom": "20px"},
),
html.Div(id="tabs-GHA1-out", style={"marginBottom": "10px"}),
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.Loading(html.Div(id="output-gha1-approx")),
dcc.Store(id="store-gha1-ana"),
dcc.Store(id="store-gha1-num"),
dcc.Store(id="store-gha1-stoch"),
dcc.Store(id="store-gha1-approx"),
],
id="pane-gha1",
style={"display": "block"},
)
pane_gha2 = html.Div(
[
inputfeld("β₀", "input-GHA2-beta0", "°", min=-90, max=90),
inputfeld("λ₀", "input-GHA2-lamb0", "°", min=-180, max=180),
inputfeld("β₁", "input-GHA2-beta1", "°", min=-90, max=90),
inputfeld("λ₁", "input-GHA2-lamb1", "°", min=-180, max=180),
dcc.Checklist(
id="method-checklist-2",
options=[
{"label": "Numerisch", "value": "numerisch"},
{"label": "Stochastisch (ES)", "value": "stochastisch"},
{"label": "Approximiert", "value": "approx"},
],
value=[],
style={"marginBottom": "10px", "marginLeft": "10px"},
persistence=True,
persistence_type="memory",
persisted_props=["value"],
),
html.Div(
[
html.Button(
"Berechnen",
id="button-calc-gha2",
n_clicks=0,
style={"marginRight": "10px", "marginLeft": "10px"},
),
],
style={"marginBottom": "20px"},
),
html.Div(id="tabs-GHA2-out", style={"marginBottom": "10px"}),
dcc.Loading(html.Div(id="output-gha2-num")),
dcc.Loading(html.Div(id="output-gha2-stoch")),
dcc.Loading(html.Div(id="output-gha2-approx")),
dcc.Store(id="store-gha2-num"),
dcc.Store(id="store-gha2-stoch"),
dcc.Store(id="store-gha2-approx"),
],
id="pane-gha2",
style={"display": "none"},
)
# HTML-Elemente # HTML-Elemente
app.layout = html.Div( app.layout = html.Div(
@@ -226,23 +386,8 @@ app.layout = html.Div(
], ],
), ),
html.Div(id="tabs-GHA-out", style={"marginBottom": "10px"}), html.Div([pane_gha1, pane_gha2], id="tabs-GHA-out", style={"marginBottom": "10px"}),
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.Loading(html.Div(id="output-gha1-approx")),
dcc.Loading(html.Div(id="output-gha2-num")),
dcc.Loading(html.Div(id="output-gha2-stoch")),
dcc.Loading(html.Div(id="output-gha2-approx")),
dcc.Store(id="store-gha1-ana"),
dcc.Store(id="store-gha1-num"),
dcc.Store(id="store-gha1-stoch"),
dcc.Store(id="store-gha1-approx"),
dcc.Store(id="store-gha2-num"),
dcc.Store(id="store-gha2-stoch"),
dcc.Store(id="store-gha2-approx"),
], ],
), ),
@@ -255,7 +400,7 @@ app.layout = html.Div(
"marginTop": "-50px", "marginTop": "-50px",
}, },
children=[ children=[
html.Label("Koordinatenart wählen:"), html.Label("Koordinatenart wählen:", style={"marginLeft": "80px"},),
dcc.Dropdown( dcc.Dropdown(
id="dropdown-coors-type", id="dropdown-coors-type",
options=[ options=[
@@ -266,7 +411,7 @@ app.layout = html.Div(
], ],
value="ell", value="ell",
clearable=False, clearable=False,
style={"width": "300px"}, style={"width": "200px", "marginLeft": "80px"},
), ),
dcc.Graph( dcc.Graph(
id="ellipsoid-plot", id="ellipsoid-plot",
@@ -302,81 +447,22 @@ def fill_inputs_from_dropdown(selected_ell):
# Funktion zur Generierung der Tab-Inhalte # Funktion zur Generierung der Tab-Inhalte
@app.callback( @app.callback(
Output("tabs-GHA-out", "children"), Output("pane-gha1", "style"),
Output("pane-gha2", "style"),
Input("tabs-GHA", "value"), Input("tabs-GHA", "value"),
) )
def render_content(tab): def switch_tabs(tab):
show1 = {"display": "block"} if tab == "tab-GHA1" else {"display": "none"} show1 = {"display": "block"} if tab == "tab-GHA1" else {"display": "none"}
show2 = {"display": "block"} if tab == "tab-GHA2" else {"display": "none"} show2 = {"display": "block"} if tab == "tab-GHA2" else {"display": "none"}
return show1, show2
pane_gha1 = html.Div( @app.callback(
[ Output("input-approx-ds-1", "disabled"),
inputfeld("β₀", "input-GHA1-beta0", "°", min=-90, max=90), Input("cb-approx-1", "value"),
inputfeld("λ₀", "input-GHA1-lamb0", "°", min=-180, max=180),
inputfeld("s", "input-GHA1-s", "m", min=0),
inputfeld("α₀", "input-GHA1-a", "°", min=0, max=360),
dcc.Checklist(
id="method-checklist-1",
options=[
{"label": "Analytisch", "value": "analytisch"},
{"label": "Numerisch", "value": "numerisch"},
#{"label": "Stochastisch (ES)", "value": "stochastisch"},
{"label": "Approximiert", "value": "approx"},
],
value=[],
style={"marginBottom": "10px", "marginLeft": "10px"},
),
html.Div(
[
html.Button(
"Berechnen",
id="button-calc-gha1",
n_clicks=0,
style={"marginRight": "10px", "marginLeft": "10px"},
),
],
style={"marginBottom": "20px"},
),
],
id="pane-gha1",
style=show1,
) )
def toggle_ds(v):
return "on" not in (v or [])
pane_gha2 = html.Div(
[
inputfeld("β₀", "input-GHA2-beta0", "°", min=-90, max=90),
inputfeld("λ₀", "input-GHA2-lamb0", "°", min=-180, max=180),
inputfeld("β₁", "input-GHA2-beta1", "°", min=-90, max=90),
inputfeld("λ₁", "input-GHA2-lamb1", "°", min=-180, max=180),
dcc.Checklist(
id="method-checklist-2",
options=[
{"label": "Numerisch", "value": "numerisch"},
{"label": "Stochastisch (ES)", "value": "stochastisch"},
{"label": "Approximiert", "value": "approx"},
],
value=[],
style={"marginBottom": "10px", "marginLeft": "10px"},
),
html.Div(
[
html.Button(
"Berechnen",
id="button-calc-gha2",
n_clicks=0,
style={"marginRight": "10px", "marginLeft": "10px"},
),
],
style={"marginBottom": "20px"},
),
],
id="pane-gha2",
style=show2,
)
return html.Div([pane_gha1, pane_gha2])
# -- GHA 1 --- # -- GHA 1 ---
@@ -426,14 +512,14 @@ def compute_gha1_ana(n1, beta0, lamb0, s, a0, ax, ay, b, method1):
html.Br(), html.Br(),
html.Span(f"kartesisch: x₁={P1_ana[0]:.4f} m, y₁={P1_ana[1]:.4f} m, z₁={P1_ana[2]:.4f} m"), html.Span(f"kartesisch: x₁={P1_ana[0]:.4f} m, y₁={P1_ana[1]:.4f} m, z₁={P1_ana[2]:.4f} m"),
html.Br(), html.Br(),
html.Span(f"elliptisch: {aus.gms('β₁', beta2_ana, 4)}, {aus.gms('λ₁', lamb2_ana, 4)}"), html.Span(f"ellipsoidisch: {aus.gms('β₁', beta2_ana, 4)}, {aus.gms('λ₁', lamb2_ana, 4)}"),
html.Br(), html.Br(),
]) ])
store = { store = {
"points": [("P0", P0, "black"), ("P1", P1_ana, "red")], "points": [("P0", P0, "black"), ("P1 (ana)", P1_ana, "red")],
"polyline": None, "polyline": None,
"color": "#d62728" "color": "red"
} }
return out, store return out, store
@@ -473,14 +559,14 @@ def compute_gha1_num(n1, beta0, lamb0, s, a0, ax, ay, b, method1):
html.Br(), html.Br(),
html.Span(f"kartesisch: x₁={P1_num[0]:.4f} m, y₁={P1_num[1]:.4f} m, z₁={P1_num[2]:.4f} m"), html.Span(f"kartesisch: x₁={P1_num[0]:.4f} m, y₁={P1_num[1]:.4f} m, z₁={P1_num[2]:.4f} m"),
html.Br(), html.Br(),
html.Span(f"elliptisch: {aus.gms('β₁', beta2_num, 4)}, {aus.gms('λ₁', lamb2_num, 4)}"), html.Span(f"ellipsoidisch: {aus.gms('β₁', beta2_num, 4)}, {aus.gms('λ₁', lamb2_num, 4)}"),
html.Br(), html.Br(),
]) ])
polyline = [[x1, y1, z1] for x1, _, y1, _, z1, _ in werte] polyline = [[x1, y1, z1] for x1, _, y1, _, z1, _ in werte]
store = { store = {
"points": [("P0", P0, "black"), ("P1", P1_num, "#ff8c00")], "points": [("P0", P0, "black"), ("P1 (num)", P1_num, "#ff8c00")],
"polyline": polyline, "polyline": polyline,
"color": "#ff8c00" "color": "#ff8c00"
} }
@@ -529,11 +615,11 @@ def compute_gha1_stoch(n1, beta0, lamb0, s, a0, ax, ay, b, method1):
html.Br(), html.Br(),
html.Span(f"kartesisch: x₁={P1_stoch[0]:.4f} m, y₁={P1_stoch[1]:.4f} m, z₁={P1_stoch[2]:.4f} m"), html.Span(f"kartesisch: x₁={P1_stoch[0]:.4f} m, y₁={P1_stoch[1]:.4f} m, z₁={P1_stoch[2]:.4f} m"),
html.Br(), html.Br(),
html.Span(f"elliptisch: {aus.gms('β₁', beta1_stoch, 4)}, {aus.gms('λ₁', lamb1_stoch, 4)}"), html.Span(f"ellipsoidisch: {aus.gms('β₁', beta1_stoch, 4)}, {aus.gms('λ₁', lamb1_stoch, 4)}"),
]) ])
store = { store = {
"points": [("P0", P0, "black"), ("P1", P1_stoch, "red")], "points": [("P0", P0, "black"), ("P1 (ES)", P1_stoch, "#d62728")],
"polyline": None, "polyline": None,
"color": "#d62728" "color": "#d62728"
} }
@@ -566,7 +652,7 @@ def compute_gha1_approx(n1, beta0, lamb0, s, a0, ax, ay, b, method1):
s_val = float(s) s_val = float(s)
P0 = ell.ell2cart(beta_rad, lamb_rad) P0 = ell.ell2cart(beta_rad, lamb_rad)
P1_app, alpha1_app, points = gha1_approx(ell, P0, alpha_rad, s_val, ds=5000, all_points=True) P1_app, alpha1_app, points, alphas = gha1_approx(ell, P0, alpha_rad, s_val, ds=5000, all_points=True)
beta1_app, lamb1_app = ell.cart2ell(P1_app) beta1_app, lamb1_app = ell.cart2ell(P1_app)
@@ -575,13 +661,13 @@ def compute_gha1_approx(n1, beta0, lamb0, s, a0, ax, ay, b, method1):
html.Br(), html.Br(),
html.Span(f"kartesisch: x₁={P1_app[0]:.4f} m, y₁={P1_app[1]:.4f} m, z₁={P1_app[2]:.4f} m"), html.Span(f"kartesisch: x₁={P1_app[0]:.4f} m, y₁={P1_app[1]:.4f} m, z₁={P1_app[2]:.4f} m"),
html.Br(), html.Br(),
html.Span(f"elliptisch: {aus.gms('β₁', beta1_app, 4)}, {aus.gms('λ₁', lamb1_app, 4)}"), html.Span(f"ellipsoidisch: {aus.gms('β₁', beta1_app, 4)}, {aus.gms('λ₁', lamb1_app, 4)}"),
]) ])
store = { store = {
"points": [("P0", P0, "black"), ("P1", P1_app, "red")], "points": [("P0", P0, "black"), ("P1 (approx)", P1_app, "#00c2fc")],
"polyline": None, "polyline": points,
"color": "#d62728" "color": "#00c2fc"
} }
return out, store return out, store
@@ -640,9 +726,9 @@ def compute_gha2_num(n2, beta0, lamb0, beta1, lamb1, ax, ay, b, method2):
]) ])
store = { store = {
"points": [("P0", P0, "black"), ("P1", P1, "#1f77b4")], "points": [("P0", P0, "black"), ("P1", P1, "black")],
"polyline": polyline, "polyline": polyline,
"color": "#1f77b4", "color": "#ff8c00",
} }
return out, store return out, store
@@ -683,7 +769,8 @@ def compute_gha2_stoch(n2, beta0, lamb0, beta1, lamb1, ax, ay, b, method2):
html.Span(f"{aus.gms('α₀', a0_stoch, 4)}, α₁ = {a1_stoch}, s = {s_stoch:.4f} m"), html.Span(f"{aus.gms('α₀', a0_stoch, 4)}, α₁ = {a1_stoch}, s = {s_stoch:.4f} m"),
]) ])
return out, {"points": None, "polyline": None, "color": "#9467bd"}
return out, {"points": None, "polyline": None, "color": "#d62728"}
@app.callback( @app.callback(
Output("output-gha2-approx", "children"), Output("output-gha2-approx", "children"),
@@ -715,14 +802,20 @@ def compute_gha2_approx(n2, beta0, lamb0, beta1, lamb1, ax, ay, b, method2):
P0 = ell.ell2cart(beta0_rad, lamb0_rad) P0 = ell.ell2cart(beta0_rad, lamb0_rad)
P1 = ell.ell2cart(beta1_rad, lamb1_rad) P1 = ell.ell2cart(beta1_rad, lamb1_rad)
a0_app, a1_app, s_app, points = gha2_approx(ell, P0, P1, ds=1e-4, all_points=True) a0_app, a1_app, s_app, points = gha2_approx(ell, P0, P1, ds=1000, all_points=True)
out = html.Div([ out = html.Div([
html.Strong("Approximiert: "), html.Strong("Approximiert: "),
html.Span(f"{aus.gms('α₀', a0_app, 4)}, {aus.gms('α₁', a1_app, 4)}, s = {s_app:.4f} m"), html.Span(f"{aus.gms('α₀', a0_app, 4)}, {aus.gms('α₁', a1_app, 4)}, s = {s_app:.4f} m"),
]) ])
return out, {"points": None, "polyline": None, "color": "#94cccc"} store = {
"points": [("P0", P0, "black"), ("P1", P1, "black")],
"polyline": points,
"color": "#00c2fc",
}
return out, store
# --- Plot --- # --- Plot ---
@app.callback( @app.callback(
@@ -764,4 +857,9 @@ def render_all(ax, ay, b, coords_type, store_gha1_ana, store_gha1_num, store_gha
return fig return fig
if __name__ == "__main__": if __name__ == "__main__":
app.run(debug=False) HOST = "127.0.0.1"
PORT = 8050
Timer(1.0, webbrowser.open_new_tab(f"http://{HOST}:{PORT}/")).start
app.run(host=HOST, port=PORT, debug=False)