MayaFlux 0.1.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
RegionGroup.hpp
Go to the documentation of this file.
1#pragma once
2
3#include "Region.hpp"
4
5namespace MayaFlux::Kakshya {
6
7/**
8 * @struct RegionGroup
9 * @brief Organizes related signal regions into a categorized collection.
10 *
11 * RegionGroups provide a way to categorize and organize related regions within
12 * signal data based on algorithmic or analytical criteria. Each group has a name
13 * and can contain multiple Regions, as well as group-level attributes that
14 * apply to the entire collection.
15 *
16 * Common DSP-specific applications include:
17 * - Grouping frequency-domain features (e.g., "formants", "resonances", "harmonics")
18 * - Categorizing time-domain events (e.g., "transients", "steady_states", "decays")
19 * - Organizing analysis results (e.g., "zero_crossings", "spectral_centroids")
20 * - Defining processing boundaries (e.g., "convolution_segments", "filter_regions")
21 * - Storing algorithmic detection results (e.g., "noise_gates", "compression_thresholds")
22 *
23 * This data-driven approach enables sophisticated signal processing workflows
24 * where algorithms can operate on categorized signal segments without requiring
25 * predefined musical or content-specific structures.
26 */
27struct MAYAFLUX_API RegionGroup {
28 /** @brief Descriptive name of the group */
29 std::string name;
30
31 /** @brief Collection of regions belonging to this group */
32 std::vector<Region> regions;
33
34 /** @brief Flexible key-value store for group-specific attributes */
35 std::unordered_map<std::string, std::any> attributes;
36
37 RegionState state = RegionState::IDLE;
38 RegionTransition transition_type = RegionTransition::IMMEDIATE;
39 RegionSelectionPattern region_selection_pattern = RegionSelectionPattern::SEQUENTIAL;
40 double transition_duration_ms = 0.0;
41
42 size_t current_region_index = 0;
43 std::vector<size_t> active_indices;
44
45 // Optional processing callbacks
46 std::function<void(const Region&)> on_region_start;
47 std::function<void(const Region&)> on_region_end;
48 std::function<void(const Region&, const Region&)> on_transition;
49
50 RegionGroup() = default;
51
52 /**
53 * @brief Construct a region group.
54 * @param group_name Name of the group.
55 * @param regions Regions to include.
56 * @param attrs Optional group-level attributes.
57 */
58 RegionGroup(std::string group_name,
59 std::vector<Region> regions = {},
60 std::unordered_map<std::string, std::any> attrs = {})
61 : name(std::move(group_name))
62 , regions(std::move(regions))
63 , attributes(std::move(attrs))
64 {
65 }
66
67 /* static RegionGroup create_sequential_group(std::string group_name,
68 std::vector<Region> regions,
69 std::unordered_map<std::string, std::any> attributes = {})
70 {
71 RegionGroup group(group_name, regions, attributes);
72 group.region_selection_pattern = RegionSelectionPattern::SEQUENTIAL;
73 group.set_attribute("region_selection_pattern", RegionSelectionPattern::SEQUENTIAL);
74 return group;
75 }
76
77 static RegionGroup create_random_pool(std::string group_name,
78 std::vector<Region> regions,
79 std::unordered_map<std::string, std::any> attributes = {})
80 {
81 RegionGroup group(group_name, regions, attributes);
82 group.region_selection_pattern = RegionSelectionPattern::RANDOM;
83 group.set_attribute("region_selection_pattern", RegionSelectionPattern::RANDOM);
84 return group;
85 } */
86
87 void add_region(const Region& region)
88 {
89 regions.push_back(region);
90 }
91
92 /**
93 * @brief Insert a region at a specific index.
94 * @param index Position to insert at.
95 * @param region The Region to insert.
96 */
97 void insert_region(size_t index, const Region& region)
98 {
99 if (index >= regions.size()) {
100 regions.push_back(region);
101 } else {
102 regions.insert(regions.begin() + index, region);
103 }
104 }
105
106 /**
107 * @brief Remove a region by index.
108 * @param index Index of the region to remove.
109 */
110 void remove_region(size_t index)
111 {
112 if (index < regions.size()) {
113 regions.erase(regions.begin() + index);
114 if (current_region_index >= regions.size() && !regions.empty()) {
115 current_region_index = regions.size() - 1;
116 }
117 }
118 }
119
120 /**
121 * @brief Remove all regions from the group.
122 */
124 {
125 regions.clear();
126 current_region_index = 0;
127 active_indices.clear();
128 }
129
130 /**
131 * @brief Sort region by a specific dimension.
132 * @param dimension_index The dimension to sort by.
133 */
134 void sort_by_dimension(size_t dimension_index)
135 {
136 std::ranges::sort(regions,
137 [dimension_index](const Region& a, const Region& b) {
138 if (dimension_index < a.start_coordinates.size() && dimension_index < b.start_coordinates.size()) {
139 return a.start_coordinates[dimension_index] < b.start_coordinates[dimension_index];
140 }
141 return false;
142 });
143 }
144
145 /**
146 * @brief Sort regions by a specific attribute (numeric).
147 * @param attr_name The attribute name.
148 */
149 void sort_by_attribute(const std::string& attr_name)
150 {
151 std::ranges::sort(regions,
152 [&attr_name](const Region& a, const Region& b) {
153 auto a_val = a.get_attribute<double>(attr_name);
154 auto b_val = b.get_attribute<double>(attr_name);
155 if (a_val && b_val)
156 return *a_val < *b_val;
157 return false;
158 });
159 }
160
161 /**
162 * @brief Find all regions with a given label.
163 * @param label The label to search for.
164 * @return Vector of matching Regions.
165 */
166 std::vector<Region> find_regions_with_label(const std::string& label) const
167 {
168 std::vector<Region> result;
169 for (const auto& region : regions) {
170 if (region.get_label() == label) {
171 result.push_back(region);
172 }
173 }
174 return result;
175 }
176
177 /**
178 * @brief Get the bounding region that contains all regions in the group.
179 * @return Region representing the bounding box.
180 */
182 {
183 if (regions.empty())
184 return Region {};
185
186 auto first = regions[0];
187 std::vector<uint64_t> min_coords = first.start_coordinates;
188 std::vector<uint64_t> max_coords = first.end_coordinates;
189
190 for (const auto& region : regions) {
191 for (size_t i = 0; i < min_coords.size(); i++) {
192 if (i < region.start_coordinates.size()) {
193 min_coords[i] = std::min<size_t>(min_coords[i], region.start_coordinates[i]);
194 max_coords[i] = std::max<size_t>(max_coords[i], region.end_coordinates[i]);
195 }
196 }
197 }
198
199 Region bounds(min_coords, max_coords);
200 bounds.set_attribute("type", "bounding_box");
201 bounds.set_attribute("source_group", name);
202 return bounds;
203 }
204
205 /**
206 * @brief Find all regions with a specific attribute value.
207 * @param key Attribute key.
208 * @param value Attribute value to match.
209 * @return Vector of matching Regions.
210 */
211 std::vector<Region> find_regions_with_attribute(const std::string& key, const std::any& value) const
212 {
213 std::vector<Region> result;
214 for (const auto& region : regions) {
215 auto it = region.attributes.find(key);
216 if (it != region.attributes.end()) {
217 try {
218 if (it->second.type() == value.type()) {
219 if (value.type() == typeid(std::string)) {
220 if (std::any_cast<std::string>(it->second) == std::any_cast<std::string>(value)) {
221 result.push_back(region);
222 }
223 } else if (value.type() == typeid(double)) {
224 if (std::any_cast<double>(it->second) == std::any_cast<double>(value)) {
225 result.push_back(region);
226 }
227 } else if (value.type() == typeid(int)) {
228 if (std::any_cast<int>(it->second) == std::any_cast<int>(value)) {
229 result.push_back(region);
230 }
231 } else if (value.type() == typeid(bool)) {
232 if (std::any_cast<bool>(it->second) == std::any_cast<bool>(value)) {
233 result.push_back(region);
234 }
235 }
236 }
237 } catch (const std::bad_any_cast&) {
238 }
239 }
240 }
241 return result;
242 }
243
244 /**
245 * @brief Find all regions containing the given coordinates.
246 * @param coordinates N-dimensional coordinates.
247 * @return Vector of matching Regions.
248 */
249 std::vector<Region> find_regions_containing_coordinates(const std::vector<uint64_t>& coordinates) const
250 {
251 std::vector<Region> result;
252 for (const auto& region : regions) {
253 if (region.contains(coordinates)) {
254 result.push_back(region);
255 }
256 }
257 return result;
258 }
259
260 /**
261 * @brief Set a group-level attribute.
262 * @tparam T Value type.
263 * @param key Attribute key.
264 * @param value Value to set.
265 */
266 template <typename T>
267 void set_attribute(const std::string& key, T value)
268 {
269 attributes[key] = std::move(value);
270 }
271
272 /**
273 * @brief Get a group-level attribute.
274 * @tparam T Value type.
275 * @param key Attribute key.
276 * @return Optional value if present and convertible.
277 */
278 template <typename T>
279 std::optional<T> get_attribute(const std::string& key) const
280 {
281 auto it = attributes.find(key);
282 if (it == attributes.end()) {
283 return std::nullopt;
284 }
285
286 return safe_any_cast<T>(it->second);
287 }
288};
289
290}
RegionSelectionPattern
Describes how regions are selected for processing or playback.
Definition Region.hpp:11
RegionTransition
Describes how transitions between regions are handled.
Definition Region.hpp:26
RegionState
Processing state for regions.
Definition Region.hpp:38
std::unordered_map< std::string, std::any > attributes
Flexible key-value store for group-specific attributes.
void insert_region(size_t index, const Region &region)
Insert a region at a specific index.
std::vector< size_t > active_indices
std::function< void(const Region &, const Region &)> on_transition
void sort_by_attribute(const std::string &attr_name)
Sort regions by a specific attribute (numeric).
std::vector< Region > regions
Collection of regions belonging to this group.
void clear_regions()
Remove all regions from the group.
std::function< void(const Region &)> on_region_end
std::vector< Region > find_regions_containing_coordinates(const std::vector< uint64_t > &coordinates) const
Find all regions containing the given coordinates.
void set_attribute(const std::string &key, T value)
Set a group-level attribute.
void remove_region(size_t index)
Remove a region by index.
std::string name
Descriptive name of the group.
std::optional< T > get_attribute(const std::string &key) const
Get a group-level attribute.
std::vector< Region > find_regions_with_label(const std::string &label) const
Find all regions with a given label.
void add_region(const Region &region)
std::function< void(const Region &)> on_region_start
std::vector< Region > find_regions_with_attribute(const std::string &key, const std::any &value) const
Find all regions with a specific attribute value.
Region get_bounding_region() const
Get the bounding region that contains all regions in the group.
void sort_by_dimension(size_t dimension_index)
Sort region by a specific dimension.
RegionGroup(std::string group_name, std::vector< Region > regions={}, std::unordered_map< std::string, std::any > attrs={})
Construct a region group.
Organizes related signal regions into a categorized collection.
void set_attribute(const std::string &key, std::any value)
Set an attribute value by key.
Definition Region.hpp:339
std::optional< T > get_attribute(const std::string &key) const
Get an attribute value by key, with type conversion support.
Definition Region.hpp:324
std::vector< uint64_t > start_coordinates
Starting frame index (inclusive)
Definition Region.hpp:69
Represents a point or span in N-dimensional space.
Definition Region.hpp:67