EchoMap 2026-07-25 6d3977c
An experimental cross-platform digital signal processing application for sound-source localisation.
Loading...
Searching...
No Matches
echomap::Project Class Reference
Inheritance diagram for echomap::Project:
[legend]

Public Member Functions

 Project (std::string_view project_name={})
 Creates a new named Project.
const Signaladd_signal (std::shared_ptr< Signal > &&signal)
 Transfers ownership of a Signal into the Project.
const Sensoradd_sensor (std::unique_ptr< Sensor > &&sensor)
 Transfers ownership of a Sensor into the Project.
void add_association (const Signal &signal, const Sensor &sensor)
 Creates a new association between a Signal and Sensor.
void add_association (id_type signal_id, id_type sensor_id)
 Creates a new association between a Signal and Sensor.
auto observe_signals () const noexcept
 Provides a transformed view for stored Signal objects in the Project.
auto share_signals () const noexcept
 Provides a view of Signal objects detained in shared-ownership containers.
size_t get_sensors_count () const noexcept
 Checks if any Sensor objects are owned by the Project.
auto observe_sensors () const noexcept
 Provides a transformed view for stored Sensor objects in the Project.
auto observe_associations () const
 Provides a transformed view for defined channel mappings.
Sensorget_mutable_sensor (id_type sensor_id)
 Retrieve a mutable reference to the Sensor with the given ID.
Public Member Functions inherited from echomap::Object< Project >
 ~Object ()=default
 Non-virtual base destructor.
id_type get_id () const noexcept
bool is_valid () const noexcept
void set_name (const std::string_view new_name)
std::string_view get_name () const noexcept
const char * get_imgui_name () const noexcept
 Object (const Object &)=delete
Object & operator= (const Object &)=delete
bool operator== (const Object &other) const noexcept
 Determine shallow equality between two Object instances.

Static Public Member Functions

static ImPlot3DPoint get_sensor_point (int idx, const void *project_instance) noexcept
Static Public Member Functions inherited from echomap::Object< Project >
static std::string_view get_class_name () noexcept

Private Member Functions

std::optional< std::pair< const Signal &, const Sensor & > > resolve_pair (id_type signal_id, id_type sensor_id) const
 Convenience function to simultaneously resolve observing references to a Signal and a Sensor from the Project storage based on their numerical IDs.

Private Attributes

std::flat_map< id_type, std::shared_ptr< Signal > > signals
std::flat_map< id_type, std::unique_ptr< Sensor > > sensors
BidirectionalUnorderedMapping< id_type, id_type > requested_channel_mapping
 Mapping between Signal objects and Sensor objects (identified by their numerical IDs).

Additional Inherited Members

Protected Member Functions inherited from echomap::Object< Project >
void move_identity_from (Object &&other) noexcept
 Helper for derived classes to provide move-assignment operations.

Detailed Description

Definition at line 25 of file Project.hpp.

Constructor & Destructor Documentation

◆ Project()

echomap::Project::Project ( std::string_view project_name = {})
explicit

Creates a new named Project.

Parameters
project_nameOptional Project display name.

Definition at line 15 of file Project.cpp.

17 :
18 Object(project_name)
19{
20}

Member Function Documentation

◆ add_association() [1/2]

void echomap::Project::add_association ( const Signal & signal,
const Sensor & sensor )

Creates a new association between a Signal and Sensor.

This creates an immediately confirmed mapping: the Signal and Sensor provided must already belong to the Project.

Parameters
signalThe associated Signal
sensorThe associated Sensor
Exceptions
std::runtime_errorThe given Signal was not known to the Project.
std::runtime_errorThe given Sensor was not known to the Project.
std::runtime_errorA component (the Signal or the Sensor) is already mapped.

Definition at line 46 of file Project.cpp.

50{
51 if (!signals.contains(signal.get_id()))
52 throw std::runtime_error(std::format("{} does not exist in the project.", signal.get_name()));
53
54 if (!sensors.contains(sensor.get_id()))
55 throw std::runtime_error(std::format("{} does not exist in the project.", sensor.get_name()));
56
57 if (!requested_channel_mapping.emplace(signal.get_id(), sensor.get_id()).second)
58 throw std::runtime_error(
60 "Could not associate {} with {}: a component is already mapped.",
61 signal.get_name(),
62 sensor.get_name()
63 )
64 );
65}
BidirectionalUnorderedMapping< id_type, id_type > requested_channel_mapping
Mapping between Signal objects and Sensor objects (identified by their numerical IDs).
Definition Project.hpp:215
T format(T... args)
T signal(T... args)

◆ add_association() [2/2]

void echomap::Project::add_association ( id_type signal_id,
id_type sensor_id )

Creates a new association between a Signal and Sensor.

This requests a mapping: the Signal and Sensor of the given IDs may or may not already belong to the Project. If they do not belong to the Project at the time of insertion, the association will only become observable on the public Project API once both components are loaded; i.e., the prerequisites of add_association(const Signal&, const Sensor&) are met.

Parameters
signal_idThe ID of the associated Signal
sensor_idThe ID of the associated Sensor
Exceptions
std::runtime_errorA component (the Signal or the Sensor) is already mapped.

Definition at line 67 of file Project.cpp.

71{
72 if (!requested_channel_mapping.emplace(signal_id, sensor_id).second)
73 throw std::runtime_error(
75 "Could not associate Signal with ID {} to Sensor with ID {}: a component is already mapped.",
76 signal_id,
77 sensor_id
78 )
79 );
80}

◆ add_sensor()

const Sensor * echomap::Project::add_sensor ( std::unique_ptr< Sensor > && sensor)

Transfers ownership of a Sensor into the Project.

Parameters
sensorThe owning container of the Sensor object to transfer.
Returns
An observing pointer to the inserted Sensor, or nullptr if insertion was de-duplicated.

Definition at line 35 of file Project.cpp.

38{
39 const auto [it, success] = sensors.emplace(sensor->get_id(), std::move(sensor));
40 if (!success)
41 return nullptr;
42
43 return it->second ? it->second.get() : nullptr;
44}

◆ add_signal()

const Signal * echomap::Project::add_signal ( std::shared_ptr< Signal > && signal)

Transfers ownership of a Signal into the Project.

Parameters
signalThe shared-ownership container of the Signal object to transfer.
Returns
An observing pointer to the inserted Signal, or nullptr if insertion was de-duplicated.

Definition at line 24 of file Project.cpp.

27{
28 const auto [it, success] = signals.emplace(signal->get_id(), std::move(signal));
29 if (!success)
30 return nullptr;
31
32 return it->second ? it->second.get() : nullptr;
33}

◆ get_mutable_sensor()

Sensor & echomap::Project::get_mutable_sensor ( id_type sensor_id)
nodiscard

Retrieve a mutable reference to the Sensor with the given ID.

Parameters
sensor_idThe numerical ID of the Sensor to retrieve.
Returns
A mutable reference to the Sensor with the specified ID.
Exceptions
std::runtime_errorA Sensor with the specified ID is not owned by the Project.

Definition at line 98 of file Project.cpp.

101{
102 const auto sensor_it = sensors.find(sensor_id);
103 if (sensor_it == sensors.end())
104 throw std::runtime_error(std::format("No Sensor with ID {} belongs to {}.", sensor_id, get_name()));
105
106 return *sensor_it->second;
107}

◆ get_sensor_point()

ImPlot3DPoint echomap::Project::get_sensor_point ( int idx,
const void * project_instance )
staticnodiscardnoexcept

Definition at line 87 of file Project.cpp.

91{
92 const auto* const project_ptr = static_cast<const Project*>(project_instance);
93 const auto [x, y, z] = project_ptr->sensors.values()[idx]->position;
94
95 return { x, y, z };
96}
Project(std::string_view project_name={})
Creates a new named Project.
Definition Project.cpp:15

◆ get_sensors_count()

std::size_t echomap::Project::get_sensors_count ( ) const
nodiscardnoexcept

Checks if any Sensor objects are owned by the Project.

Returns
Are there any Sensor objects in residence?

Definition at line 82 of file Project.cpp.

83{
84 return sensors.size();
85}

◆ observe_associations()

auto echomap::Project::observe_associations ( ) const
inlinenodiscard

Provides a transformed view for defined channel mappings.

Returns
A view containing observing references to all pairs of stored Signal-Sensor assocations.

Definition at line 151 of file Project.hpp.

152 {
153 return requested_channel_mapping | std::views::transform([this](const auto& association) {
154 return resolve_pair(association.first, association.second);
155 }) |
156 std::views::filter([](const auto& optional) {
157 return optional.has_value();
158 }) |
159 std::views::transform([](const auto& optional) {
160 return *optional;
161 });
162 }
std::optional< std::pair< const Signal &, const Sensor & > > resolve_pair(id_type signal_id, id_type sensor_id) const
Convenience function to simultaneously resolve observing references to a Signal and a Sensor from the...
Definition Project.cpp:112

◆ observe_sensors()

auto echomap::Project::observe_sensors ( ) const
inlinenodiscardnoexcept

Provides a transformed view for stored Sensor objects in the Project.

Returns
A view containing observing references to all stored Sensor objects.

Definition at line 137 of file Project.hpp.

138 {
139 return sensors | std::views::values |
140 std::views::transform([](const std::unique_ptr<Sensor>& container) -> const Sensor& {
141 assert(container);
142 return *container;
143 });
144 }

◆ observe_signals()

auto echomap::Project::observe_signals ( ) const
inlinenodiscardnoexcept

Provides a transformed view for stored Signal objects in the Project.

Returns
A view containing observing references to all stored Signal objects.

Definition at line 97 of file Project.hpp.

98 {
99 return signals | std::views::values |
100 std::views::transform([](const std::shared_ptr<Signal>& container) -> const Signal& {
101 /*
102 * N.B. for this functor and all similar ones: this is an assertion, not an exception. If the Project
103 * possesses a container for something, but that container is empty, it's definitely violated an
104 * invariant. Failing on a name-based lookup would be exceptional, but this assertion failing
105 * indicates a bug.
106 *
107 * We intentionally produce references (as opposed to raw pointers) to indicate the non-optionality
108 * of these containers.
109 */
110 assert(container);
111 return *container;
112 });
113 }

◆ resolve_pair()

std::optional< std::pair< const Signal &, const Sensor & > > echomap::Project::resolve_pair ( id_type signal_id,
id_type sensor_id ) const
nodiscardprivate

Convenience function to simultaneously resolve observing references to a Signal and a Sensor from the Project storage based on their numerical IDs.

Note that the returned Signal and Sensor needn't be associated in a channel mapping or any other way, besides being owned by the current Project.

Parameters
signal_idThe numerical ID of the desired Signal.
sensor_idThe numerical ID of the desired Sensor.
Returns
A pair of observing references to the associated Signal and Sensor objects, owned by the Project.
Postcondition
The Signal owned by the Project references a non-empty container.
The Sensor owned by the Project references a non-empty container.
Exceptions
std::runtime_errorA Signal with the given ID is not owned by the Project.
std::runtime_errorA Sensor with the given ID is not owned by the Project.

Definition at line 112 of file Project.cpp.

116{
117 /*
118 * For the exception messages here, the best we can manage is the ID. Logging the display names would require
119 * resolving the full Object, which we can't do if we can't find the thing!
120 */
121
122 const auto signal_it = signals.find(signal_id);
123 if (signal_it == signals.end())
124 return {};
125
126 const auto sensor_it = sensors.find(sensor_id);
127 if (sensor_it == sensors.end())
128 return {};
129
130 assert(signal_it->second != nullptr);
131 assert(sensor_it->second != nullptr);
132
133 return {{*signal_it->second, *sensor_it->second}};
134}

◆ share_signals()

auto echomap::Project::share_signals ( ) const
inlinenodiscardnoexcept

Provides a view of Signal objects detained in shared-ownership containers.

Returns
A view containing mutable sharable references to all stored Signal objects.

Definition at line 120 of file Project.hpp.

121 {
122 return signals | std::views::values;
123 }

Member Data Documentation

◆ requested_channel_mapping

BidirectionalUnorderedMapping<id_type, id_type> echomap::Project::requested_channel_mapping
private

Mapping between Signal objects and Sensor objects (identified by their numerical IDs).

The structure stores all "requested" mappings, a non-strict subset of which are "confirmed". A mapping request is caused by an external caller, such as a factory, invoking add_association(id_type, id_type), which does not require that the corresponding Signal or Sensor is owned by the Project at the time of the request.

Mappings become confirmed once both the relevant Signal and Sensor have been loaded and are owned by the Project.

Only confirmed mappings may be observed on the public API.

Definition at line 215 of file Project.hpp.

◆ sensors

std::flat_map<id_type, std::unique_ptr<Sensor> > echomap::Project::sensors
private

Definition at line 28 of file Project.hpp.

◆ signals

std::flat_map<id_type, std::shared_ptr<Signal> > echomap::Project::signals
private

Definition at line 27 of file Project.hpp.


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