7#include <glm/gtc/type_ptr.hpp>
25 std::vector<DataDimension>& dimensions,
28 , m_dimensions(dimensions)
29 , m_modality(modality)
41 requires std::is_arithmetic_v<T>
44 bool replace_existing =
true)
46 validate_scalar_insertion(target_modality);
48 if (replace_existing) {
49 m_variant = std::move(data);
50 m_modality = target_modality;
53 m_dimensions.emplace_back(
54 modality_to_dimension_name(target_modality),
55 static_cast<uint64_t
>(data.size()),
57 modality_to_role(target_modality));
59 append_to_existing(std::move(data));
73 bool replace_existing =
true)
75 validate_structured_insertion<T>(target_modality);
77 if (replace_existing) {
78 m_variant = std::move(data);
79 m_modality = target_modality;
83 m_dimensions.push_back(create_structured_dimension<T>(
84 static_cast<uint64_t
>(data.size()),
87 append_structured_to_existing(std::move(data));
100 std::vector<T> data_copy(data_span.begin(), data_span.end());
102 if constexpr (GlmType<T>) {
103 insert_structured(std::move(data_copy), target_modality);
105 insert_scalar(std::move(data_copy), target_modality);
116 template <
typename From,
typename To>
119 std::vector<To> converted;
120 converted.reserve(source.size());
122 if constexpr (std::is_arithmetic_v<From> && std::is_arithmetic_v<To>) {
123 std::ranges::transform(source, std::back_inserter(converted),
124 [](From val) {
return static_cast<To
>(val); });
125 }
else if constexpr (std::is_same_v<From, std::complex<float>> || std::is_same_v<From, std::complex<double>>) {
126 std::ranges::transform(source, std::back_inserter(converted),
127 [](From val) {
return static_cast<To
>(std::abs(val)); });
129 error<std::invalid_argument>(
130 Journal::Component::Kakshya,
131 Journal::Context::Runtime,
132 std::source_location::current(),
133 "Unsupported conversion from {} to {}",
138 insert_scalar(std::move(converted), target_modality);
150 switch (target_modality) {
151 case DataModality::VERTEX_POSITIONS_3D:
152 case DataModality::VERTEX_NORMALS_3D:
153 case DataModality::VERTEX_TANGENTS_3D:
154 case DataModality::VERTEX_COLORS_RGB:
155 m_variant = std::vector<glm::vec3>();
156 std::get<std::vector<glm::vec3>>(m_variant).reserve(element_count);
159 case DataModality::TEXTURE_COORDS_2D:
160 m_variant = std::vector<glm::vec2>();
161 std::get<std::vector<glm::vec2>>(m_variant).reserve(element_count);
164 case DataModality::VERTEX_COLORS_RGBA:
165 m_variant = std::vector<glm::vec4>();
166 std::get<std::vector<glm::vec4>>(m_variant).reserve(element_count);
169 case DataModality::TRANSFORMATION_MATRIX:
170 m_variant = std::vector<glm::mat4>();
171 std::get<std::vector<glm::mat4>>(m_variant).reserve(element_count);
175 error<std::invalid_argument>(
176 Journal::Component::Kakshya,
177 Journal::Context::Runtime,
178 std::source_location::current(),
179 "Modality {} does not represent structured GLM data",
184 m_variant = std::vector<double>();
185 std::get<std::vector<double>>(m_variant).reserve(element_count);
188 m_modality = target_modality;
196 std::visit([](
auto& vec) { vec.clear(); }, m_variant);
197 m_dimensions.clear();
204 return std::visit([](
const auto& vec) {
return vec.empty(); }, m_variant);
218 error<std::invalid_argument>(
219 Journal::Component::Kakshya,
220 Journal::Context::Runtime,
221 std::source_location::current(),
222 "Modality {} expects structured data (GLM types), not scalars. "
223 "Use insert_structured() or change modality.",
234 constexpr size_t components = glm_component_count<T>();
238 case DataModality::VERTEX_POSITIONS_3D:
239 case DataModality::VERTEX_NORMALS_3D:
240 case DataModality::VERTEX_TANGENTS_3D:
241 case DataModality::VERTEX_COLORS_RGB:
242 valid = (components == 3);
245 case DataModality::TEXTURE_COORDS_2D:
246 valid = (components == 2);
249 case DataModality::VERTEX_COLORS_RGBA:
250 valid = (components == 4);
253 case DataModality::TRANSFORMATION_MATRIX:
254 valid = (components == 16);
258 error<std::invalid_argument>(
259 Journal::Component::Kakshya,
260 Journal::Context::Runtime,
261 std::source_location::current(),
262 "Modality {} does not represent structured GLM data",
267 error<std::invalid_argument>(
268 Journal::Component::Kakshya,
269 Journal::Context::Runtime,
270 std::source_location::current(),
271 "GLM type component count ({}) doesn't match modality {}. "
272 "Suggested type: {}",
275 suggest_glm_type_for_modality(modality));
288 case DataModality::VERTEX_POSITIONS_3D:
289 return DataDimension::vertex_positions(element_count);
291 case DataModality::VERTEX_NORMALS_3D:
292 return DataDimension::vertex_normals(element_count);
294 case DataModality::TEXTURE_COORDS_2D:
295 return DataDimension::texture_coords(element_count);
297 case DataModality::VERTEX_COLORS_RGB:
298 return DataDimension::vertex_colors(element_count,
false);
300 case DataModality::VERTEX_COLORS_RGBA:
301 return DataDimension::vertex_colors(element_count,
true);
303 case DataModality::TRANSFORMATION_MATRIX:
304 case DataModality::VERTEX_TANGENTS_3D:
307 constexpr size_t components = glm_component_count<T>();
308 return DataDimension::grouped(
309 modality_to_dimension_name(modality),
311 static_cast<uint8_t
>(components),
312 modality_to_role(modality));
320 template <
typename T>
323 std::visit([&](
auto& existing_vec) {
324 using ExistingType =
typename std::decay_t<
decltype(existing_vec)>::value_type;
326 if constexpr (std::is_same_v<ExistingType, T>) {
327 existing_vec.insert(existing_vec.end(),
330 }
else if constexpr (std::is_arithmetic_v<ExistingType> && std::is_arithmetic_v<T>) {
332 for (
const auto& val : new_data) {
333 existing_vec.push_back(
static_cast<ExistingType
>(val));
336 error<std::invalid_argument>(
337 Journal::Component::Kakshya,
338 Journal::Context::Runtime,
339 std::source_location::current(),
340 "Cannot append: incompatible types in variant (existing: {}, new: {})",
341 typeid(ExistingType).name(),
348 if (!m_dimensions.empty()) {
349 m_dimensions[0].size = std::visit(
350 [](
const auto& vec) {
return static_cast<uint64_t
>(vec.size()); },
361 if (!std::holds_alternative<std::vector<T>>(m_variant)) {
362 error<std::invalid_argument>(
363 Journal::Component::Kakshya,
364 Journal::Context::Runtime,
365 std::source_location::current(),
366 "Cannot append: existing variant doesn't hold matching GLM type ({})",
370 auto&
existing = std::get<std::vector<T>>(m_variant);
374 if (!m_dimensions.empty()) {
375 m_dimensions[0].size =
existing.size();
385 case DataModality::VERTEX_POSITIONS_3D:
387 case DataModality::VERTEX_NORMALS_3D:
389 case DataModality::VERTEX_TANGENTS_3D:
391 case DataModality::VERTEX_COLORS_RGB:
392 case DataModality::VERTEX_COLORS_RGBA:
394 case DataModality::TEXTURE_COORDS_2D:
396 case DataModality::TRANSFORMATION_MATRIX:
398 case DataModality::AUDIO_1D:
400 case DataModality::AUDIO_MULTICHANNEL:
413 case DataModality::AUDIO_1D:
414 case DataModality::AUDIO_MULTICHANNEL:
415 return DataDimension::Role::TIME;
417 case DataModality::VERTEX_POSITIONS_3D:
418 case DataModality::VERTEX_NORMALS_3D:
419 case DataModality::VERTEX_TANGENTS_3D:
420 case DataModality::TEXTURE_COORDS_2D:
421 return DataDimension::Role::UV;
423 case DataModality::VERTEX_COLORS_RGB:
424 case DataModality::VERTEX_COLORS_RGBA:
425 return DataDimension::Role::CHANNEL;
428 return DataDimension::Role::CUSTOM;
438 case DataModality::VERTEX_POSITIONS_3D:
439 case DataModality::VERTEX_NORMALS_3D:
440 case DataModality::VERTEX_TANGENTS_3D:
441 case DataModality::VERTEX_COLORS_RGB:
444 case DataModality::TEXTURE_COORDS_2D:
447 case DataModality::VERTEX_COLORS_RGBA:
450 case DataModality::TRANSFORMATION_MATRIX:
Cycle Behavior: The for_cycles(N) configuration controls how many times the capture operation execute...
DataModality & m_modality
void append_structured_to_existing(std::vector< T > new_data)
Append structured data to existing storage.
void insert_scalar(std::vector< T > data, DataModality target_modality, bool replace_existing=true)
Insert scalar array data.
void validate_structured_insertion(DataModality modality) const
Validate structured insertion matches GLM component count.
static std::string modality_to_dimension_name(DataModality modality)
Convert modality to appropriate dimension name.
void reserve_space(size_t element_count, DataModality target_modality)
Reserve space without initialization.
std::vector< DataDimension > & m_dimensions
DataInsertion(DataVariant &variant, std::vector< DataDimension > &dimensions, DataModality &modality)
void insert_structured(std::vector< T > data, DataModality target_modality, bool replace_existing=true)
Insert structured GLM data with automatic dimension setup.
void validate_scalar_insertion(DataModality modality) const
Validate scalar insertion matches modality expectations.
void append_to_existing(std::vector< T > new_data)
Append scalar data to existing storage.
static std::string_view suggest_glm_type_for_modality(DataModality modality)
Suggest appropriate GLM type for a modality.
DataModality current_modality() const
DataDimension create_structured_dimension(uint64_t element_count, DataModality modality) const
Create dimension descriptor for structured data.
void insert_converted(const std::vector< From > &source, DataModality target_modality)
Convert and insert from different type.
static DataDimension::Role modality_to_role(DataModality modality)
Convert modality to dimension role.
void clear_data()
Clear all data while preserving modality.
void insert_from_span(std::span< const T > data_span, DataModality target_modality)
Insert data from span (copy operation)
Type-erased writer for NDData with semantic construction.
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
DataModality
Data modality types for cross-modal analysis.
bool is_structured_modality(DataModality modality)
Check if a modality represents structured data (vectors, matrices).
std::string_view modality_to_string(DataModality modality)
Convert DataModality enum to string representation.
Role
Semantic role of the dimension.
Minimal dimension descriptor focusing on structure only.