projector version

This commit is contained in:
awe
2026-09-15 19:06:05 +03:00
parent 62c0266a6b
commit b3339d101c
33 changed files with 2605 additions and 51 deletions
@@ -59,7 +59,7 @@ def _build_processing_mode_page(parent: QStackedWidget, rows: list[FormRow], *,
def build_processing_group(owner) -> QGroupBox:
"""Create processing mode section with pass-through, B-scan, and GPR pages."""
"""Create processing mode section with pass-through, B-scan, GPR, and 3D SAR pages."""
group = QGroupBox("Processing")
form = QFormLayout(group)
form.setFieldGrowthPolicy(QFormLayout.FieldGrowthPolicy.AllNonFixedFieldsGrow)
@@ -68,9 +68,10 @@ def build_processing_group(owner) -> QGroupBox:
bscan_defaults = processing_defaults.bscan
gpr_live_defaults = processing_defaults.gpr
legacy_gpr_defaults = processing_defaults.legacy_gpr
sar3d_defaults = processing_defaults.sar3d
owner._processing_mode = QComboBox()
owner._processing_mode.addItems(["pass_through", "bscan", "gpr", "legacy_gpr"])
owner._processing_mode.addItems(["pass_through", "bscan", "gpr", "legacy_gpr", "sar3d"])
owner._set_combo_current_text(owner._processing_mode, processing_defaults.selected_mode)
owner._processing_mode_pages = QStackedWidget(group)
@@ -570,6 +571,172 @@ def build_processing_group(owner) -> QGroupBox:
)
owner._processing_mode_pages.addWidget(legacy_gpr_page)
# 3D SAR page: shared gpr_* knobs get their own widget set (like legacy_gpr)
# plus the sar3d-specific aperture/volume knobs consumed by the C++ processor.
owner._sar3d_input_positions_input = QLineEdit(str(sar3d_defaults.input_positions))
owner._sar3d_input_positions_input.setPlaceholderText("0,1,2")
owner._sar3d_output_positions_input = QLineEdit(str(sar3d_defaults.output_positions))
owner._sar3d_output_positions_input.setPlaceholderText("0,1")
owner._sar3d_min_depth_m = QDoubleSpinBox()
owner._sar3d_min_depth_m.setDecimals(2)
owner._sar3d_min_depth_m.setRange(0.0, 50.0)
owner._sar3d_min_depth_m.setSingleStep(0.1)
owner._sar3d_min_depth_m.setValue(float(sar3d_defaults.min_depth_m))
owner._sar3d_max_depth_m = QDoubleSpinBox()
owner._sar3d_max_depth_m.setDecimals(2)
owner._sar3d_max_depth_m.setRange(0.1, 50.0)
owner._sar3d_max_depth_m.setSingleStep(0.1)
owner._sar3d_max_depth_m.setValue(float(sar3d_defaults.max_depth_m))
owner._sar3d_start_freq_mhz = QDoubleSpinBox()
owner._sar3d_start_freq_mhz.setDecimals(1)
owner._sar3d_start_freq_mhz.setRange(100.0, 8800.0)
owner._sar3d_start_freq_mhz.setSingleStep(10.0)
owner._sar3d_start_freq_mhz.setValue(float(sar3d_defaults.start_freq_mhz))
owner._sar3d_stop_freq_mhz = QDoubleSpinBox()
owner._sar3d_stop_freq_mhz.setDecimals(1)
owner._sar3d_stop_freq_mhz.setRange(100.0, 8800.0)
owner._sar3d_stop_freq_mhz.setSingleStep(10.0)
owner._sar3d_stop_freq_mhz.setValue(float(sar3d_defaults.stop_freq_mhz))
owner._sar3d_look_angle_deg = QDoubleSpinBox()
owner._sar3d_look_angle_deg.setDecimals(2)
owner._sar3d_look_angle_deg.setRange(-90.0, 90.0)
owner._sar3d_look_angle_deg.setSingleStep(0.5)
owner._sar3d_look_angle_deg.setValue(float(sar3d_defaults.look_angle_deg))
owner._sar3d_look_angle_deg.setToolTip(
"Radar look angle vs the range axis (deg). Used by intra-sweep motion correction."
)
owner._sar3d_direction_sign = QDoubleSpinBox()
owner._sar3d_direction_sign.setDecimals(0)
owner._sar3d_direction_sign.setRange(-1.0, 1.0)
owner._sar3d_direction_sign.setSingleStep(2.0)
owner._sar3d_direction_sign.setValue(float(sar3d_defaults.direction_sign))
owner._sar3d_direction_sign.setToolTip(
"Motion direction along range: +1 (later frequencies deeper) or -1 (shallower)."
)
owner._sar3d_ignore_socket_speed_enabled = QCheckBox("Ignore socket speed")
owner._sar3d_ignore_socket_speed_enabled.setChecked(bool(sar3d_defaults.ignore_socket_speed_enabled))
owner._sar3d_ignore_socket_speed_enabled.setToolTip(
"When checked, use the speed below for motion correction instead of the "
"value streamed over the locator socket."
)
owner._sar3d_speed_m_s = QDoubleSpinBox()
owner._sar3d_speed_m_s.setDecimals(3)
owner._sar3d_speed_m_s.setRange(-100.0, 100.0)
owner._sar3d_speed_m_s.setSingleStep(0.05)
owner._sar3d_speed_m_s.setValue(float(sar3d_defaults.speed_m_s))
owner._sar3d_speed_m_s.setToolTip(
"Radar speed (m/s) used by intra-sweep motion correction when 'Ignore socket speed' is on."
)
owner._sar3d_apply_freq_phase_correction = QCheckBox("Apply intra-sweep phase correction")
owner._sar3d_apply_freq_phase_correction.setChecked(bool(sar3d_defaults.apply_freq_phase_correction))
owner._sar3d_frame_radius = QSpinBox()
owner._sar3d_frame_radius.setRange(0, 25)
owner._sar3d_frame_radius.setValue(int(sar3d_defaults.frame_radius))
owner._sar3d_frame_radius.setToolTip(
"Synthetic-aperture half width in frames: 2*radius+1 consecutive frames form one aperture."
)
owner._sar3d_edge_frame_weight = QDoubleSpinBox()
owner._sar3d_edge_frame_weight.setDecimals(2)
owner._sar3d_edge_frame_weight.setRange(0.0, 1.0)
owner._sar3d_edge_frame_weight.setSingleStep(0.05)
owner._sar3d_edge_frame_weight.setValue(float(sar3d_defaults.edge_frame_weight))
owner._sar3d_edge_frame_weight.setToolTip(
"Weight of the outermost aperture frames (1 = flat window, 0 = strong taper)."
)
owner._sar3d_pitch_deg = QDoubleSpinBox()
owner._sar3d_pitch_deg.setDecimals(2)
owner._sar3d_pitch_deg.setRange(-90.0, 90.0)
owner._sar3d_pitch_deg.setSingleStep(0.5)
owner._sar3d_pitch_deg.setValue(float(sar3d_defaults.pitch_deg))
owner._sar3d_pitch_deg.setToolTip("Antenna pitch above the horizon (deg); tilts the imaged volume.")
owner._sar3d_center_depth_m = QDoubleSpinBox()
owner._sar3d_center_depth_m.setDecimals(2)
owner._sar3d_center_depth_m.setRange(0.0, 50.0)
owner._sar3d_center_depth_m.setSingleStep(0.1)
owner._sar3d_center_depth_m.setValue(float(sar3d_defaults.center_depth_m))
owner._sar3d_center_depth_m.setToolTip("Range distance to the center of the imaged volume (m).")
owner._sar3d_half_width_x_m = QDoubleSpinBox()
owner._sar3d_half_width_x_m.setDecimals(2)
owner._sar3d_half_width_x_m.setRange(0.01, 50.0)
owner._sar3d_half_width_x_m.setSingleStep(0.1)
owner._sar3d_half_width_x_m.setValue(float(sar3d_defaults.half_width_x_m))
owner._sar3d_half_width_y_m = QDoubleSpinBox()
owner._sar3d_half_width_y_m.setDecimals(2)
owner._sar3d_half_width_y_m.setRange(0.01, 50.0)
owner._sar3d_half_width_y_m.setSingleStep(0.1)
owner._sar3d_half_width_y_m.setValue(float(sar3d_defaults.half_width_y_m))
owner._sar3d_half_width_z_m = QDoubleSpinBox()
owner._sar3d_half_width_z_m.setDecimals(2)
owner._sar3d_half_width_z_m.setRange(0.01, 50.0)
owner._sar3d_half_width_z_m.setSingleStep(0.1)
owner._sar3d_half_width_z_m.setValue(float(sar3d_defaults.half_width_z_m))
owner._sar3d_grid_nx = QSpinBox()
owner._sar3d_grid_nx.setRange(2, 1024)
owner._sar3d_grid_nx.setValue(int(sar3d_defaults.grid_nx))
owner._sar3d_grid_ny = QSpinBox()
owner._sar3d_grid_ny.setRange(2, 1024)
owner._sar3d_grid_ny.setValue(int(sar3d_defaults.grid_ny))
owner._sar3d_grid_nz = QSpinBox()
owner._sar3d_grid_nz.setRange(2, 1024)
owner._sar3d_grid_nz.setValue(int(sar3d_defaults.grid_nz))
owner._sar3d_use_compensation = QCheckBox("Use per-voxel compensation")
owner._sar3d_use_compensation.setChecked(bool(sar3d_defaults.use_compensation))
owner._sar3d_normalize_pairs = QCheckBox("Normalize Tx/Rx pairs")
owner._sar3d_normalize_pairs.setChecked(bool(sar3d_defaults.normalize_pairs))
sar3d_page = _build_processing_mode_page(
owner._processing_mode_pages,
[
("Input positions", owner._sar3d_input_positions_input),
("Output positions", owner._sar3d_output_positions_input),
("Min depth m", owner._sar3d_min_depth_m),
("Max depth m", owner._sar3d_max_depth_m),
("Start MHz", owner._sar3d_start_freq_mhz),
("Stop MHz", owner._sar3d_stop_freq_mhz),
("Look angle deg", owner._sar3d_look_angle_deg),
("Direction sign", owner._sar3d_direction_sign),
owner._sar3d_ignore_socket_speed_enabled,
("Speed m/s", owner._sar3d_speed_m_s),
owner._sar3d_apply_freq_phase_correction,
("Frame radius", owner._sar3d_frame_radius),
("Edge frame weight", owner._sar3d_edge_frame_weight),
("Pitch deg", owner._sar3d_pitch_deg),
("Center depth m", owner._sar3d_center_depth_m),
("Half width X m", owner._sar3d_half_width_x_m),
("Half width Y m", owner._sar3d_half_width_y_m),
("Half width Z m", owner._sar3d_half_width_z_m),
("Grid Nx", owner._sar3d_grid_nx),
("Grid Ny", owner._sar3d_grid_ny),
("Grid Nz", owner._sar3d_grid_nz),
owner._sar3d_use_compensation,
owner._sar3d_normalize_pairs,
],
split_index=11,
)
owner._processing_mode_pages.addWidget(sar3d_page)
owner._processing_mode.currentTextChanged.connect(owner._on_processing_mode_changed)
owner._show_magnitude_checkbox.toggled.connect(owner._on_trace_visibility_changed)
owner._show_phase_checkbox.toggled.connect(owner._on_trace_visibility_changed)
@@ -642,6 +809,29 @@ def build_processing_group(owner) -> QGroupBox:
owner._legacy_gpr_visible_x_max_m.valueChanged.connect(owner._on_gpr_locator_window_changed)
owner._legacy_gpr_visible_z_min_m.valueChanged.connect(owner._on_gpr_locator_window_changed)
owner._legacy_gpr_visible_z_max_m.valueChanged.connect(owner._on_gpr_locator_window_changed)
owner._sar3d_input_positions_input.editingFinished.connect(owner._on_processing_live_settings_changed)
owner._sar3d_output_positions_input.editingFinished.connect(owner._on_processing_live_settings_changed)
owner._sar3d_min_depth_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_max_depth_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_start_freq_mhz.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_stop_freq_mhz.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_look_angle_deg.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_direction_sign.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_ignore_socket_speed_enabled.toggled.connect(owner._on_processing_live_settings_changed)
owner._sar3d_speed_m_s.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_apply_freq_phase_correction.toggled.connect(owner._on_processing_live_settings_changed)
owner._sar3d_frame_radius.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_edge_frame_weight.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_pitch_deg.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_center_depth_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_half_width_x_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_half_width_y_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_half_width_z_m.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_grid_nx.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_grid_ny.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_grid_nz.valueChanged.connect(owner._on_processing_live_settings_changed)
owner._sar3d_use_compensation.toggled.connect(owner._on_processing_live_settings_changed)
owner._sar3d_normalize_pairs.toggled.connect(owner._on_processing_live_settings_changed)
owner._set_processing_mode_page(owner._processing_mode.currentText())
return group