EchoMap 2026-07-25 6d3977c
An experimental cross-platform digital signal processing application for sound-source localisation.
Loading...
Searching...
No Matches
echomap::SensorGeometryPanel Class Referencefinal

Provides a panel for defining and reviewing (in a 3D plot) positions of loaded Sensor objects in the active Project. More...

#include <SensorGeometryPanel.hpp>

Inheritance diagram for echomap::SensorGeometryPanel:
[legend]

Public Member Functions

 SensorGeometryPanel (EchoMap *app, const Project *initial_project=nullptr)
 Create a new SensorGeometryPanel to plot and control Sensor information.
const char * get_imgui_name () const noexcept override
 Retrieves the name of the IPanel for Dear ImGui API functions.
void draw () noexcept override
 Draw the panel to the active rendering context.
void change_active_project (const Project *new_project) override
 Updates the active Project being described by the IPanel.
Public Member Functions inherited from echomap::IPanel
virtual void update_gpu (const wgpu::CommandEncoder &command_encoder)
 Delegate work to the GPU via the WebGPU platform.

Static Public Member Functions

static const char * get_imgui_stable_name () noexcept

Private Member Functions

void recache_sensor_colours () noexcept
void draw_geometry_summary () noexcept
void draw_geometry_plot () const noexcept

Private Attributes

std::string panel_name
std::vector< ImU32 > sensor_colours
ImPlot3DSpec plotting_spec_3d
const Projectactive_project = nullptr
EchoMapapp
std::vector< sigc::scoped_connection > connections

Additional Inherited Members

Static Protected Attributes inherited from echomap::IPanel
static constexpr ImVec2 button_size {80.0f, 20.0f}
static constexpr auto table_flags

Detailed Description

Provides a panel for defining and reviewing (in a 3D plot) positions of loaded Sensor objects in the active Project.

Definition at line 28 of file SensorGeometryPanel.hpp.

Constructor & Destructor Documentation

◆ SensorGeometryPanel()

echomap::SensorGeometryPanel::SensorGeometryPanel ( EchoMap * app,
const Project * initial_project = nullptr )
explicit

Create a new SensorGeometryPanel to plot and control Sensor information.

Parameters
appThe parent application instance.
initial_projectAn optional initial Project for the IPanel to display.

Definition at line 19 of file SensorGeometryPanel.cpp.

22 :
23 panel_name(std::string("Sensor Geometry") + get_imgui_stable_name()),
24 active_project(initial_project),
25 app(app)
26{
27}

Member Function Documentation

◆ change_active_project()

void echomap::SensorGeometryPanel::change_active_project ( const Project * new_project)
overridevirtual

Updates the active Project being described by the IPanel.

Parameters
new_projectAn observing pointer to the new active Project.

Implements echomap::IProjectPanel.

Definition at line 51 of file SensorGeometryPanel.cpp.

54{
55 active_project = new_project;
56 sensor_colours.clear();
57}

◆ draw()

void echomap::SensorGeometryPanel::draw ( )
overridevirtualnoexcept

Draw the panel to the active rendering context.

Implements echomap::IPanel.

Definition at line 34 of file SensorGeometryPanel.cpp.

35{
36 if (ImGui::Begin(panel_name.c_str())) {
37 if (active_project == nullptr)
38 ImGui::Text("No project is loaded.");
39 else if (active_project->get_sensors_count() == 0u)
40 ImGui::Text("No sensors are loaded.");
41 else {
42 recache_sensor_colours();
43 draw_geometry_summary();
44 draw_geometry_plot();
45 }
46 }
47
48 ImGui::End();
49}

◆ draw_geometry_plot()

void echomap::SensorGeometryPanel::draw_geometry_plot ( ) const
privatenoexcept

Definition at line 163 of file SensorGeometryPanel.cpp.

164{
165 ImGui::SeparatorText("Geometry Plot");
166 ImPlot3D::PushStyleColor(ImPlot3DCol_FrameBg, ImVec4(0.0f, 0.0f, 0.0f, 0.0f));
167
168 const auto avail_size = ImGui::GetContentRegionAvail();
169 const float aspect_ratio = avail_size.x / avail_size.y;
170
171 if (ImPlot3D::BeginPlot("##SensorGeometryPlot", ImVec2(-std::numeric_limits<float>::min(), avail_size.y))) {
172 ImPlot3D::SetupBoxScale(aspect_ratio, 1.0f, 1.0f);
173 ImPlot3D::SetupAxes("X", "Y", "Z");
174 ImPlot3D::PlotScatterG(
175 "",
176 Project::get_sensor_point,
177 active_project,
178 static_cast<int>(active_project->get_sensors_count()),
179 plotting_spec_3d
180 );
181
182 ImPlot3D::EndPlot();
183 }
184
185 ImPlot3D::PopStyleColor();
186}
T min(T... args)

◆ draw_geometry_summary()

void echomap::SensorGeometryPanel::draw_geometry_summary ( )
privatenoexcept

Definition at line 92 of file SensorGeometryPanel.cpp.

93{
94 ImGui::SeparatorText("Geometry Summary");
95 if (ImGui::BeginTable("##GeometrySummary", 5, table_flags)) {
96 ImGui::TableSetupColumn("##SensorColourColumn", ImGuiTableColumnFlags_WidthFixed);
97 ImGui::TableSetupColumn("Sensor", ImGuiTableColumnFlags_WidthFixed);
98 ImGui::TableSetupColumn("X Position", ImGuiTableColumnFlags_WidthStretch);
99 ImGui::TableSetupColumn("Y Position", ImGuiTableColumnFlags_WidthStretch);
100 ImGui::TableSetupColumn("Z Position", ImGuiTableColumnFlags_WidthStretch);
101 ImGui::TableHeadersRow();
102
103 std::size_t row_idx = 0;
104
105 for (const auto& sensor : active_project->observe_sensors()) {
106 ImGui::PushID(static_cast<int>(sensor.get_id()));
107
108 ImGui::TableNextRow();
109 ImGui::TableNextColumn();
110
111 const ImVec4 colour = ImGui::ColorConvertU32ToFloat4(sensor_colours[row_idx]);
112 std::array<float, 4> new_colour = {colour.x, colour.y, colour.z, colour.w};
113 if (ImGui::ColorEdit4("##colour", new_colour.data(), ImGuiColorEditFlags_NoInputs)) {
114 app->notify(ModifySensorColourNotification(
115 active_project->get_id(),
116 sensor.get_id(),
117 {
118 .r = new_colour[0],
119 .g = new_colour[1],
120 .b = new_colour[2],
121 .a = new_colour[3],
122 }
123 ));
124
125 sensor_colours[row_idx] = IM_COL32(
126 static_cast<int>(new_colour[0] * 255.0f),
127 static_cast<int>(new_colour[1] * 255.0f),
128 static_cast<int>(new_colour[2] * 255.0f),
129 static_cast<int>(new_colour[3] * 255.0f)
130 );
131 }
132
133 ImGui::TableNextColumn();
134 ImGui::SetNextItemWidth(-std::numeric_limits<float>::min());
135 ImGui::TextUnformatted(sensor.get_imgui_name());
136
137 Position new_position = sensor.position;
138 bool position_changed = false;
139
140 ImGui::TableNextColumn();
141 ImGui::SetNextItemWidth(-std::numeric_limits<float>::min());
142 position_changed = ImGui::InputFloat("##x", &new_position.x, 0.01f, 1.0f);
143
144 ImGui::TableNextColumn();
145 ImGui::SetNextItemWidth(-std::numeric_limits<float>::min());
146 position_changed = ImGui::InputFloat("##y", &new_position.y, 0.01f, 1.0f) || position_changed;
147
148 ImGui::TableNextColumn();
149 ImGui::SetNextItemWidth(-std::numeric_limits<float>::min());
150 position_changed = ImGui::InputFloat("##z", &new_position.z, 0.01f, 1.0f) || position_changed;
151
152 ImGui::PopID();
153 ++row_idx;
154
155 if (position_changed)
156 app->notify(ModifySensorPositionNotification(active_project->get_id(), sensor.get_id(), new_position));
157 }
158
159 ImGui::EndTable();
160 }
161}
T data(T... args)

◆ get_imgui_name()

const char * echomap::SensorGeometryPanel::get_imgui_name ( ) const
nodiscardoverridevirtualnoexcept

Retrieves the name of the IPanel for Dear ImGui API functions.

Returns
The human-readable name of the window as a NULL-terminated C string.

Implements echomap::IPanel.

Definition at line 29 of file SensorGeometryPanel.cpp.

30{
31 return panel_name.c_str();
32}

◆ get_imgui_stable_name()

const char * echomap::SensorGeometryPanel::get_imgui_stable_name ( )
staticnoexcept

Definition at line 59 of file SensorGeometryPanel.cpp.

60{
61 return "###SensorGeometryPanel";
62}

◆ recache_sensor_colours()

void echomap::SensorGeometryPanel::recache_sensor_colours ( )
privatenoexcept

Definition at line 64 of file SensorGeometryPanel.cpp.

65{
66 if (active_project->get_sensors_count() != sensor_colours.size()) {
67 // Ensure that we maintain the correct number of colours for the current number of sensors.
68 try {
69 sensor_colours.resize(active_project->get_sensors_count());
70 for (auto [src, dst] : std::views::zip(active_project->observe_sensors(), sensor_colours))
71 dst = IM_COL32(
72 static_cast<int>(src.colour.r * 255.0f),
73 static_cast<int>(src.colour.g * 255.0f),
74 static_cast<int>(src.colour.b * 255.0f),
75 static_cast<int>(src.colour.a * 255.0f)
76 );
77 } catch (const std::exception& exception) {
78 LOG_F_ERROR("Could not store the sensor colouring: {}", exception.what());
79 plotting_spec_3d.MarkerFillColors = nullptr;
80 plotting_spec_3d.MarkerLineColors = nullptr;
81 plotting_spec_3d.MarkerFillColor = ImVec4(255.0f, 255.0f, 255.0f, 255.0f);
82 plotting_spec_3d.MarkerLineColor = IMPLOT_AUTO_COL;
83 return;
84 }
85
86 // ... and update the plotting specification in case the resize invalidated pointers.
87 plotting_spec_3d.MarkerFillColors = &*sensor_colours.begin();
88 plotting_spec_3d.MarkerLineColors = plotting_spec_3d.MarkerFillColors;
89 }
90}
#define LOG_F_ERROR(msg,...)
Logs a formatted error-level message using echomap::Logger::log_f.
Definition Logger.hpp:125
T what(T... args)

Member Data Documentation

◆ active_project

const Project* echomap::SensorGeometryPanel::active_project = nullptr
private

Definition at line 59 of file SensorGeometryPanel.hpp.

◆ app

EchoMap* echomap::SensorGeometryPanel::app
private

Definition at line 60 of file SensorGeometryPanel.hpp.

◆ connections

std::vector<sigc::scoped_connection> echomap::SensorGeometryPanel::connections
private

Definition at line 61 of file SensorGeometryPanel.hpp.

◆ panel_name

std::string echomap::SensorGeometryPanel::panel_name
private

Definition at line 55 of file SensorGeometryPanel.hpp.

◆ plotting_spec_3d

ImPlot3DSpec echomap::SensorGeometryPanel::plotting_spec_3d
private

Definition at line 58 of file SensorGeometryPanel.hpp.

◆ sensor_colours

std::vector<ImU32> echomap::SensorGeometryPanel::sensor_colours
private

Definition at line 57 of file SensorGeometryPanel.hpp.


The documentation for this class was generated from the following files: