Source code for opengnc.visualization.orbit

import numpy as np
import plotly.graph_objects as go


[docs] def plot_orbit_3d( r_eci: np.ndarray | list[list[float]], r_earth: bool = True, title: str = "3D Orbit Visualization" ) -> go.Figure: """ Standard 3D Orbit Visualization. Renders flight path relative to a spherical Earth ($R_e = 6378.137$ km). Parameters ---------- r_eci : np.ndarray | list[list[float]] Sequence of ECI positions $(N, 3)$ (m). r_earth : bool, optional Render Earth sphere. Default True. title : str, optional Plot heading. Returns ------- go.Figure Plotly 3D scatter object. """ r_val = np.asarray(r_eci) if r_val.ndim != 2 or r_val.shape[1] != 3: raise ValueError("r_eci must be a 2D array of shape (N, 3)") fig = go.Figure() # 1. Earth Sphere if r_earth: R_Earth = 6378137.0 u = np.linspace(0, 2 * np.pi, 60) v = np.linspace(0, np.pi, 60) x = R_Earth * np.outer(np.cos(u), np.sin(v)) y = R_Earth * np.outer(np.sin(u), np.sin(v)) z = R_Earth * np.outer(np.ones(np.size(u)), np.cos(v)) fig.add_trace( go.Surface( x=x, y=y, z=z, colorscale="Blues", opacity=0.3, showscale=False, name="Earth", hoverinfo="skip", ) ) # 2. Flight Path fig.add_trace( go.Scatter3d( x=r_val[:, 0], y=r_val[:, 1], z=r_val[:, 2], mode="lines", line=dict(color="darkred", width=4), name="Orbit Path", ) ) # 3. Markers fig.add_trace( go.Scatter3d( x=[r_val[0, 0]], y=[r_val[0, 1]], z=[r_val[0, 2]], mode="markers", marker=dict(size=6, color="green", symbol="circle"), name="Start", ) ) fig.add_trace( go.Scatter3d( x=[r_val[-1, 0]], y=[r_val[-1, 1]], z=[r_val[-1, 2]], mode="markers", marker=dict(size=6, color="orange", symbol="circle"), name="Current Position", ) ) # 4. Global Scene Format fig.update_layout( title=title, scene=dict( xaxis=dict(title="X [m]", gridcolor="gray", showbackground=False), yaxis=dict(title="Y [m]", gridcolor="gray", showbackground=False), zaxis=dict(title="Z [m]", gridcolor="gray", showbackground=False), aspectmode="data", ), margin=dict(r=10, l=10, b=10, t=40), ) return fig