From 505aee6de7a488e69024755847ae2932066d795d Mon Sep 17 00:00:00 2001 From: "Tammo.Weber" Date: Tue, 13 Jan 2026 20:46:15 +0100 Subject: [PATCH] Kleinere Anpassungen --- dashboard.py | 281 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 192 insertions(+), 89 deletions(-) diff --git a/dashboard.py b/dashboard.py index 8b1e9f9..7caa4b5 100644 --- a/dashboard.py +++ b/dashboard.py @@ -1,5 +1,4 @@ from dash import Dash, html, dcc, Input, Output, State, no_update -import dash import plotly.graph_objects as go import numpy as np @@ -14,13 +13,13 @@ from GHA_triaxial.approx_gha1 import gha1_approx from GHA_triaxial.panou_2013_2GHA_num import gha2_num from GHA_triaxial.ES_gha2 import gha2_ES -from GHA_triaxial.approx_gha2 import gha2_approx - +from GHA_triaxial.approx_gha2 import gha2 app = Dash(__name__, suppress_callback_exceptions=True) app.title = "Geodätische Hauptaufgaben" + def inputfeld(left_text, input_id, right_text="", width=200, min=None, max=None): return html.Div( [ @@ -221,14 +220,18 @@ app.layout = html.Div( 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"), ], ), @@ -251,7 +254,7 @@ app.layout = html.Div( ], ), - html.P("© 2026", style={"fontSize": "10px", "color": "gray", "textAlign": "center", "marginTop": "16px"}), + #html.P("© 2026", style={"fontSize": "10px", "color": "gray", "textAlign": "center", "marginTop": "16px"}), ], ) @@ -284,8 +287,8 @@ def render_content(tab): pane_gha1 = html.Div( [ - inputfeld("β₀", "input-GHA1-beta1", "°", min=-90, max=90), - inputfeld("λ₀", "input-GHA1-lamb1", "°", min=-180, max=180), + 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), @@ -318,10 +321,10 @@ def render_content(tab): pane_gha2 = html.Div( [ - inputfeld("β₀", "input-GHA2-beta1", "°", min=-90, max=90), - inputfeld("λ₀", "input-GHA2-lamb1", "°", min=-180, max=180), - inputfeld("β₁", "input-GHA2-beta2", "°", min=-90, max=90), - inputfeld("λ₁", "input-GHA2-lamb2", "°", min=-180, max=180), + 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", @@ -357,8 +360,8 @@ def render_content(tab): 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-beta0", "value"), + State("input-GHA1-lamb0", "value"), State("input-GHA1-s", "value"), State("input-GHA1-a", "value"), State("input-ax", "value"), @@ -367,7 +370,7 @@ def render_content(tab): State("method-checklist-1", "value"), prevent_initial_call=True, ) -def compute_gha1_ana(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1): +def compute_gha1_ana(n1, beta0, lamb0, s, a0, ax, ay, b, method1): out = html.Div([ html.H4("Erste Hauptaufgabe"), ]) @@ -375,7 +378,7 @@ def compute_gha1_ana(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1): 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): + if None in (beta0, lamb0, s, a0): 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 @@ -384,28 +387,27 @@ def compute_gha1_ana(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1): ell = EllipsoidTriaxial(ax, ay, b) - beta_rad = wu.deg2rad(float(beta11)) - lamb_rad = wu.deg2rad(float(lamb11)) - alpha_rad = wu.deg2rad(float(a_deg)) + beta_rad = wu.deg2rad(float(beta0)) + lamb_rad = wu.deg2rad(float(lamb0)) + alpha_rad = wu.deg2rad(float(a0)) s_val = float(s) - p1 = ell.ell2cart(beta_rad, lamb_rad) - p2_ana, alpha2 = gha1_ana(ell, p1, alpha_rad, s_val, 70) - x2, y2, z2 = p2_ana - beta2, lamb2 = ell.cart2ell(p2_ana) + P0 = ell.ell2cart(beta_rad, lamb_rad) + P1_ana, alpha2 = gha1_ana(ell, P0, alpha_rad, s_val, 70) + beta2_ana, lamb2_ana = ell.cart2ell(P1_ana) out = html.Div([ html.H4("Erste Hauptaufgabe"), html.Strong("Analytisch: "), html.Br(), - html.Span(f"kartesisch: x₁={x2:.4f} m, y₁={y2:.4f} m, z₁={z2:.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.Span(f"elliptisch: {aus.gms('β₁', beta2, 4)}, {aus.gms('λ₁', lamb2, 4)}"), + html.Span(f"elliptisch: {aus.gms('β₁', beta2_ana, 4)}, {aus.gms('λ₁', lamb2_ana, 4)}"), html.Br(), ]) store = { - "points": [("P1", p1, "black"), ("P2", p2_ana, "red")], + "points": [("P0", P0, "black"), ("P1", P1_ana, "red")], "polyline": None, "color": "#d62728" } @@ -415,8 +417,8 @@ def compute_gha1_ana(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1): 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-beta0", "value"), + State("input-GHA1-lamb0", "value"), State("input-GHA1-s", "value"), State("input-GHA1-a", "value"), State("input-ax", "value"), @@ -425,27 +427,27 @@ def compute_gha1_ana(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1): State("method-checklist-1", "value"), prevent_initial_call=True, ) -def compute_gha1_num(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1): +def compute_gha1_num(n1, beta0, lamb0, s, a0, 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)) + beta_rad = wu.deg2rad(float(beta0)) + lamb_rad = wu.deg2rad(float(lamb0)) + alpha_rad = wu.deg2rad(float(a0)) s_val = float(s) - p1 = ell.ell2cart(beta_rad, lamb_rad) + P0 = ell.ell2cart(beta_rad, lamb_rad) - p2_num, alpha1, werte = gha1_num(ell, p1, alpha_rad, s_val, 10000, all_points=True) - beta2_num, lamb2_num = ell.cart2ell(p2_num) + P1_num, alpha1, werte = gha1_num(ell, P0, alpha_rad, s_val, 10000, all_points=True) + beta2_num, lamb2_num = ell.cart2ell(P1_num) out = 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.Span(f"kartesisch: x₁={P1_num[0]:.4f} m, y₁={P1_num[1]:.4f} m, z₁={P1_num[2]:.4f} m"), html.Br(), html.Span(f"elliptisch: {aus.gms('β₁', beta2_num, 4)}, {aus.gms('λ₁', lamb2_num, 4)}"), html.Br(), @@ -454,7 +456,7 @@ def compute_gha1_num(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1): polyline = [[x1, y1, z1] for x1, _, y1, _, z1, _ in werte] store = { - "points": [("P1", p1, "black"), ("P2", p2_num, "#ff8c00")], + "points": [("P0", P0, "black"), ("P1", P1_num, "#ff8c00")], "polyline": polyline, "color": "#ff8c00" } @@ -464,8 +466,8 @@ def compute_gha1_num(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1): 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-beta0", "value"), + State("input-GHA1-lamb0", "value"), State("input-GHA1-s", "value"), State("input-GHA1-a", "value"), State("input-ax", "value"), @@ -474,16 +476,16 @@ def compute_gha1_num(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1): State("method-checklist-1", "value"), prevent_initial_call=True, ) -def compute_gha1_stoch(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1): +def compute_gha1_stoch(n1, beta0, lamb0, s, a0, 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)) + beta_rad = wu.deg2rad(float(beta0)) + lamb_rad = wu.deg2rad(float(lamb0)) + alpha_rad = wu.deg2rad(float(a0)) s_val = float(s) betas, lambs, alphas, S_real = gha1_es( @@ -492,24 +494,68 @@ def compute_gha1_stoch(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1): 10000, ell ) - beta2 = betas[-1] - lamb2 = lambs[-1] - alpha2 = alphas[-1] + beta1_stoch = betas[-1] + lamb1_stoch = lambs[-1] - p1 = ell.ell2cart(beta_rad, lamb_rad) - p2 = ell.ell2cart(beta2, lamb2) - x2, y2, z2 = p2[0], p2[1], p2[2] + P0 = ell.ell2cart(beta_rad, lamb_rad) + P1_stoch = ell.ell2cart(beta1_stoch, lamb1_stoch) 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.Span(f"kartesisch: x₁={P1_stoch[0]:.4f} m, y₁={P1_stoch[1]:.4f} m, z₁={P1_stoch[2]:.4f} m"), html.Br(), - html.Span(f"elliptisch: {aus.gms('β₁', beta2, 4)}, {aus.gms('λ₁', lamb2, 4)}"), + html.Span(f"elliptisch: {aus.gms('β₁', beta1_stoch, 4)}, {aus.gms('λ₁', lamb1_stoch, 4)}"), ]) store = { - "points": [("P1", p1, "black"), ("P2", p2, "red")], + "points": [("P0", P0, "black"), ("P1", P1_stoch, "red")], + "polyline": None, + "color": "#d62728" + } + return out, store + +@app.callback( + Output("output-gha1-approx", "children"), + Output("store-gha1-approx", "data"), + Input("button-calc-gha1", "n_clicks"), + State("input-GHA1-beta0", "value"), + State("input-GHA1-lamb0", "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_approx(n1, beta0, lamb0, s, a0, ax, ay, b, method1): + if not n1: + return no_update, no_update + if "approx" not in (method1 or []): + return no_update, no_update + + ell = EllipsoidTriaxial(ax, ay, b) + beta_rad = wu.deg2rad(float(beta0)) + lamb_rad = wu.deg2rad(float(lamb0)) + alpha_rad = wu.deg2rad(float(a0)) + s_val = float(s) + + 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) + + beta1_app, lamb1_app = ell.cart2ell(P1_app) + + out = html.Div([ + html.Strong("Approximiert: "), + 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.Br(), + html.Span(f"elliptisch: {aus.gms('β₁', beta1_app, 4)}, {aus.gms('λ₁', lamb1_app, 4)}"), + ]) + + store = { + "points": [("P0", P0, "black"), ("P1", P1_app, "red")], "polyline": None, "color": "#d62728" } @@ -521,17 +567,17 @@ def compute_gha1_stoch(n1, beta11, lamb11, s, a_deg, ax, ay, b, method1): Output("output-gha2-num", "children"), Output("store-gha2-num", "data"), Input("button-calc-gha2", "n_clicks"), + State("input-GHA2-beta0", "value"), + State("input-GHA2-lamb0", "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-2", "value"), prevent_initial_call=True, ) -def compute_gha2_num(n2, beta1, lamb1, beta2, lamb2, ax, ay, b, method2): +def compute_gha2_num(n2, beta0, lamb0, beta1, lamb1, ax, ay, b, method2): out = html.Div([ html.H4("Zweite Hauptaufgabe"), ]) @@ -539,7 +585,7 @@ def compute_gha2_num(n2, beta1, lamb1, beta2, lamb2, ax, ay, b, method2): 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): + if None in (beta0, lamb0, beta1, lamb1): return html.Span("Bitte β₀, λ₀, β₁ und λ₁ eingeben.", style={"color": "red"}), None if not method2: return html.Span("Bitte Berechnungsverfahren wählen.", style={"color": "red"}), None @@ -548,13 +594,15 @@ def compute_gha2_num(n2, beta1, lamb1, beta2, lamb2, ax, ay, b, method2): 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)) + beta0_rad = wu.deg2rad(float(beta0)) + lamb0_rad = wu.deg2rad(float(lamb0)) + beta1_rad = wu.deg2rad(float(beta1)) + lamb1_rad = wu.deg2rad(float(lamb1)) - p1 = tuple(map(float, ell.ell2cart(b1, l1))) - p2 = tuple(map(float, ell.ell2cart(b2, l2))) + P0 = ell.ell2cart(beta0_rad, lamb0_rad) + P1 = ell.ell2cart(beta1_rad, lamb1_rad) - alpha_1, alpha_2, s12, beta_arr, lamb_arr = gha2_num(ell, b1, l1, b2, l2) + a0_num, a1_num, s_num, beta_arr, lamb_arr = gha2_num(ell, beta0_rad, lamb0_rad, beta1_rad, lamb1_rad, all_points=True) polyline = [] for b_rad, l_rad in zip(beta_arr, lamb_arr): @@ -564,43 +612,95 @@ def compute_gha2_num(n2, beta1, lamb1, beta2, lamb2, ax, ay, b, method2): out = html.Div([ html.H4("Zweite Hauptaufgabe"), html.Strong("Numerisch: "), - html.Span(f"{aus.gms('α₀', alpha_1, 4)}, {aus.gms('α₁', alpha_2, 4)}, s = {s12:.4f} m"), + html.Span(f"{aus.gms('α₀', a0_num, 4)}, {aus.gms('α₁', a1_num, 4)}, s = {s_num:.4f} m"), ]) store = { - "points": [("P1", p1, "black"), ("P2", p2, "#1f77b4")], + "points": [("P0", P0, "black"), ("P1", P1, "#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("Stochastisch (ES): "), -# html.Span("noch nicht implementiert...") -# ]) -# -# return out, {"points": None, "polyline": None, "color": "#9467bd"} +@app.callback( + Output("output-gha2-stoch", "children"), + Output("store-gha2-stoch", "data"), + Input("button-calc-gha2", "n_clicks"), + State("input-GHA2-beta0", "value"), + State("input-GHA2-lamb0", "value"), + State("input-GHA2-beta1", "value"), + State("input-GHA2-lamb1", "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, beta0, lamb0, beta1, lamb1, ax, ay, b, method2): + if not n2: + return no_update, no_update + if "stochastisch" not in (method2 or []): + return no_update, no_update + ell = EllipsoidTriaxial(ax, ay, b) + + beta0_rad = wu.deg2rad(float(beta0)) + lamb0_rad = wu.deg2rad(float(lamb0)) + beta1_rad = wu.deg2rad(float(beta1)) + lamb1_rad = wu.deg2rad(float(lamb1)) + + P0 = ell.ell2cart(beta0_rad, lamb0_rad) + P1 = ell.ell2cart(beta1_rad, lamb1_rad) + + a0_stoch, a1_stoch, s_stoch, points = gha2_ES(ell, P0, P1, all_points=True, sigmaStep=1e-5) + + out = html.Div([ + html.Strong("Stochastisch (ES): "), + html.Span(f"{aus.gms('α₀', a0_stoch, 4)}, α₁ = {a1_stoch}, s = {s_stoch:.4f} m"), + ]) + + return out, {"points": None, "polyline": None, "color": "#9467bd"} + +@app.callback( + Output("output-gha2-approx", "children"), + Output("store-gha2-approx", "data"), + Input("button-calc-gha2", "n_clicks"), + State("input-GHA2-beta0", "value"), + State("input-GHA2-lamb0", "value"), + State("input-GHA2-beta1", "value"), + State("input-GHA2-lamb1", "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_approx(n2, beta0, lamb0, beta1, lamb1, ax, ay, b, method2): + if not n2: + return no_update, no_update + if "approx" not in (method2 or []): + return no_update, no_update + + ell = EllipsoidTriaxial(ax, ay, b) + + beta0_rad = wu.deg2rad(float(beta0)) + lamb0_rad = wu.deg2rad(float(lamb0)) + beta1_rad = wu.deg2rad(float(beta1)) + lamb1_rad = wu.deg2rad(float(lamb1)) + + P0 = ell.ell2cart(beta0_rad, lamb0_rad) + P1 = ell.ell2cart(beta1_rad, lamb1_rad) + + a0_app, a1_app, s_app, points = gha2(ell, P0, P1, ds=1e-4, all_points=True) + + out = html.Div([ + html.Strong("Approximiert: "), + 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"} + +# --- Plot --- @app.callback( Output("ellipsoid-plot", "figure"), Input("input-ax", "value"), @@ -608,10 +708,13 @@ def compute_gha2_num(n2, beta1, lamb1, beta2, lamb2, ax, ay, b, method2): Input("input-b", "value"), Input("store-gha1-ana", "data"), Input("store-gha1-num", "data"), + Input("store-gha1-stoch", "data"), + Input("store-gha1-approx", "data"), Input("store-gha2-num", "data"), Input("store-gha2-stoch", "data"), + Input("store-gha2-approx", "data"), ) -def render_all(ax, ay, b, store_gha1_ana, store_gha1_num, store_gha2_num, store_gha2_stoch): +def render_all(ax, ay, b, store_gha1_ana, store_gha1_num, store_gha1_stoch, store_gha1_approx, store_gha2_num, store_gha2_stoch, store_gha2_approx): if None in (ax, ay, b): return go.Figure() @@ -630,7 +733,7 @@ def render_all(ax, ay, b, store_gha1_ana, store_gha1_num, store_gha2_num, store_ 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): + for st in (store_gha1_ana, store_gha1_num, store_gha1_stoch, store_gha1_approx, store_gha2_num, store_gha2_stoch, store_gha2_approx): fig = add_from_store(fig, st) return fig