1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright (c) 2025-present FERS Contributors (see AUTHORS.md).
17} from '@mui/material';
18import { useState } from 'react';
19import { GlobalParameters, useScenarioStore } from '@/stores/scenarioStore';
20import { NumberField, Section } from './InspectorControls';
22interface GlobalParametersInspectorProps {
23 item: GlobalParameters;
26export function GlobalParametersInspector({
28}: GlobalParametersInspectorProps) {
29 const updateItem = useScenarioStore((s) => s.updateItem);
30 const setRotationAngleUnit = useScenarioStore(
31 (s) => s.setRotationAngleUnit
33 const platforms = useScenarioStore((s) => s.platforms);
34 const handleChange = (path: string, value: unknown) =>
35 updateItem(item.id, path, value);
36 const [pendingRotationUnit, setPendingRotationUnit] = useState<
37 GlobalParameters['rotationAngleUnit'] | null
40 const hasExistingRotationValues = platforms.some((platform) => {
41 if (platform.rotation.type === 'fixed') {
43 platform.rotation.startAzimuth,
44 platform.rotation.startElevation,
45 platform.rotation.azimuthRate,
46 platform.rotation.elevationRate,
47 ].some((value) => value !== 0);
49 return platform.rotation.waypoints.some(
50 (waypoint) => waypoint.azimuth !== 0 || waypoint.elevation !== 0
54 const handleRotationUnitChange = (
55 nextUnit: GlobalParameters['rotationAngleUnit']
57 if (nextUnit === item.rotationAngleUnit) {
60 if (hasExistingRotationValues) {
61 setPendingRotationUnit(nextUnit);
64 setRotationAngleUnit(nextUnit, false);
68 <Box sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
69 <FormControl fullWidth size="small">
70 <InputLabel>Rotation Angle Unit</InputLabel>
72 label="Rotation Angle Unit"
73 value={item.rotationAngleUnit}
75 handleRotationUnitChange(
77 .value as GlobalParameters['rotationAngleUnit']
81 <MenuItem value="deg">Degrees</MenuItem>
82 <MenuItem value="rad">Radians</MenuItem>
86 label="Simulation Name"
90 value={item.simulation_name}
92 handleChange('simulation_name', e.target.value)
96 label="Start Time (s)"
98 onChange={(v) => handleChange('start', v)}
103 onChange={(v) => handleChange('end', v)}
106 label="Output Sampling Rate (Hz)"
108 onChange={(v) => handleChange('rate', v)}
111 label="Internal Sim Sampling Rate (Hz)"
112 value={item.simSamplingRate}
113 onChange={(v) => handleChange('simSamplingRate', v)}
116 label="Speed of Light (m/s)"
118 onChange={(v) => handleChange('c', v)}
122 value={item.random_seed}
123 onChange={(v) => handleChange('random_seed', v)}
127 value={item.adc_bits}
128 onChange={(v) => handleChange('adc_bits', v)}
131 label="Oversample Ratio"
132 value={item.oversample_ratio}
133 onChange={(v) => handleChange('oversample_ratio', v)}
136 <Section title="Georeference">
138 label="Origin Latitude (deg)"
139 value={item.origin.latitude}
140 onChange={(v) => handleChange('origin.latitude', v)}
143 label="Origin Longitude (deg)"
144 value={item.origin.longitude}
145 onChange={(v) => handleChange('origin.longitude', v)}
148 label="Origin Altitude (m)"
149 value={item.origin.altitude}
150 onChange={(v) => handleChange('origin.altitude', v)}
152 <FormControl fullWidth size="small">
153 <InputLabel>Coordinate System</InputLabel>
155 label="Coordinate System"
156 value={item.coordinateSystem.frame}
159 'coordinateSystem.frame',
164 <MenuItem value="ENU">ENU (East-North-Up)</MenuItem>
165 <MenuItem value="UTM">UTM</MenuItem>
166 <MenuItem value="ECEF">ECEF</MenuItem>
169 {item.coordinateSystem.frame === 'UTM' && (
173 value={item.coordinateSystem.zone ?? null}
175 handleChange('coordinateSystem.zone', v)
178 <FormControl fullWidth size="small">
179 <InputLabel>UTM Hemisphere</InputLabel>
181 label="UTM Hemisphere"
182 value={item.coordinateSystem.hemisphere ?? 'N'}
185 'coordinateSystem.hemisphere',
190 <MenuItem value="N">North</MenuItem>
191 <MenuItem value="S">South</MenuItem>
198 open={pendingRotationUnit !== null}
199 onClose={() => setPendingRotationUnit(null)}
201 <DialogTitle>Change Rotation Angle Unit</DialogTitle>
204 Existing rotation values are present. Convert them to
205 keep the same physical orientation and rates, or keep
206 the numeric values as they are.
210 <Button onClick={() => setPendingRotationUnit(null)}>
215 if (pendingRotationUnit) {
216 setRotationAngleUnit(
221 setPendingRotationUnit(null);
229 if (pendingRotationUnit) {
230 setRotationAngleUnit(pendingRotationUnit, true);
232 setPendingRotationUnit(null);
235 Convert Existing Values