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;
82 m_dimensions.push_back(create_structured_dimension<T>(
83 static_cast<uint64_t
>(data.size()),
86 append_structured_to_existing(std::move(data));
99 std::vector<T> data_copy(data_span.begin(), data_span.end());
101 if constexpr (GlmType<T>) {
102 insert_structured(std::move(data_copy), target_modality);
104 insert_scalar(std::move(data_copy), target_modality);
115 template <
typename From,
typename To>
118 std::vector<To> converted;
119 converted.reserve(source.size());
121 if constexpr (std::is_arithmetic_v<From> && std::is_arithmetic_v<To>) {
122 std::ranges::transform(source, std::back_inserter(converted),
123 [](From val) {
return static_cast<To
>(val); });
124 }
else if constexpr (std::is_same_v<From, std::complex<float>> || std::is_same_v<From, std::complex<double>>) {
125 std::ranges::transform(source, std::back_inserter(converted),
126 [](From val) {
return static_cast<To
>(std::abs(val)); });
128 error<std::invalid_argument>(
129 Journal::Component::Kakshya,
130 Journal::Context::Runtime,
131 std::source_location::current(),
132 "Unsupported conversion from {} to {}",
137 insert_scalar(std::move(converted), target_modality);
148 switch (target_modality) {
149 case DataModality::VERTEX_POSITIONS_3D:
150 case DataModality::VERTEX_NORMALS_3D:
151 case DataModality::VERTEX_TANGENTS_3D:
152 case DataModality::VERTEX_COLORS_RGB:
153 m_variant = std::vector<glm::vec3>();
154 std::get<std::vector<glm::vec3>>(m_variant).reserve(element_count);
157 case DataModality::TEXTURE_COORDS_2D:
158 m_variant = std::vector<glm::vec2>();
159 std::get<std::vector<glm::vec2>>(m_variant).reserve(element_count);
162 case DataModality::VERTEX_COLORS_RGBA:
163 m_variant = std::vector<glm::vec4>();
164 std::get<std::vector<glm::vec4>>(m_variant).reserve(element_count);
167 case DataModality::TRANSFORMATION_MATRIX:
168 m_variant = std::vector<glm::mat4>();
169 std::get<std::vector<glm::mat4>>(m_variant).reserve(element_count);
173 error<std::invalid_argument>(
174 Journal::Component::Kakshya,
175 Journal::Context::Runtime,
176 std::source_location::current(),
177 "Modality {} does not represent structured GLM data",
181 m_variant = std::vector<double>();
182 std::get<std::vector<double>>(m_variant).reserve(element_count);
185 m_modality = target_modality;
193 std::visit([](
auto& vec) { vec.clear(); }, m_variant);
194 m_dimensions.clear();
201 return std::visit([](
const auto& vec) {
return vec.empty(); }, m_variant);
215 error<std::invalid_argument>(
216 Journal::Component::Kakshya,
217 Journal::Context::Runtime,
218 std::source_location::current(),
219 "Modality {} expects structured data (GLM types), not scalars. "
220 "Use insert_structured() or change modality.",
231 constexpr size_t components = glm_component_count<T>();
235 case DataModality::VERTEX_POSITIONS_3D:
236 case DataModality::VERTEX_NORMALS_3D:
237 case DataModality::VERTEX_TANGENTS_3D:
238 case DataModality::VERTEX_COLORS_RGB:
239 valid = (components == 3);
242 case DataModality::TEXTURE_COORDS_2D:
243 valid = (components == 2);
246 case DataModality::VERTEX_COLORS_RGBA:
247 valid = (components == 4);
250 case DataModality::TRANSFORMATION_MATRIX:
251 valid = (components == 16);
255 error<std::invalid_argument>(
256 Journal::Component::Kakshya,
257 Journal::Context::Runtime,
258 std::source_location::current(),
259 "Modality {} does not represent structured GLM data",
264 error<std::invalid_argument>(
265 Journal::Component::Kakshya,
266 Journal::Context::Runtime,
267 std::source_location::current(),
268 "GLM type component count ({}) doesn't match modality {}. "
269 "Suggested type: {}",
272 suggest_glm_type_for_modality(modality));
284 case DataModality::VERTEX_POSITIONS_3D:
285 return DataDimension::vertex_positions(element_count);
287 case DataModality::VERTEX_NORMALS_3D:
288 return DataDimension::vertex_normals(element_count);
290 case DataModality::TEXTURE_COORDS_2D:
291 return DataDimension::texture_coords(element_count);
293 case DataModality::VERTEX_COLORS_RGB:
294 return DataDimension::vertex_colors(element_count,
false);
296 case DataModality::VERTEX_COLORS_RGBA:
297 return DataDimension::vertex_colors(element_count,
true);
299 case DataModality::TRANSFORMATION_MATRIX:
300 case DataModality::VERTEX_TANGENTS_3D:
302 constexpr size_t components = glm_component_count<T>();
303 return DataDimension::grouped(
304 modality_to_dimension_name(modality),
306 static_cast<uint8_t
>(components),
307 modality_to_role(modality));
315 template <
typename T>
318 std::visit([&](
auto& existing_vec) {
319 using ExistingType =
typename std::decay_t<
decltype(existing_vec)>::value_type;
321 if constexpr (std::is_same_v<ExistingType, T>) {
322 existing_vec.insert(existing_vec.end(),
325 }
else if constexpr (std::is_arithmetic_v<ExistingType> && std::is_arithmetic_v<T>) {
326 for (
const auto& val : new_data) {
327 existing_vec.push_back(
static_cast<ExistingType
>(val));
330 error<std::invalid_argument>(
331 Journal::Component::Kakshya,
332 Journal::Context::Runtime,
333 std::source_location::current(),
334 "Cannot append: incompatible types in variant (existing: {}, new: {})",
335 typeid(ExistingType).name(),
341 if (!m_dimensions.empty()) {
342 m_dimensions[0].size = std::visit(
343 [](
const auto& vec) {
return static_cast<uint64_t
>(vec.size()); },
354 if (!std::holds_alternative<std::vector<T>>(m_variant)) {
355 error<std::invalid_argument>(
356 Journal::Component::Kakshya,
357 Journal::Context::Runtime,
358 std::source_location::current(),
359 "Cannot append: existing variant doesn't hold matching GLM type ({})",
363 auto&
existing = std::get<std::vector<T>>(m_variant);
366 if (!m_dimensions.empty()) {
367 m_dimensions[0].size =
existing.size();
377 case DataModality::VERTEX_POSITIONS_3D:
379 case DataModality::VERTEX_NORMALS_3D:
381 case DataModality::VERTEX_TANGENTS_3D:
383 case DataModality::VERTEX_COLORS_RGB:
384 case DataModality::VERTEX_COLORS_RGBA:
386 case DataModality::TEXTURE_COORDS_2D:
388 case DataModality::TRANSFORMATION_MATRIX:
390 case DataModality::AUDIO_1D:
392 case DataModality::AUDIO_MULTICHANNEL:
405 case DataModality::AUDIO_1D:
406 case DataModality::AUDIO_MULTICHANNEL:
407 return DataDimension::Role::TIME;
409 case DataModality::VERTEX_POSITIONS_3D:
410 case DataModality::VERTEX_NORMALS_3D:
411 case DataModality::VERTEX_TANGENTS_3D:
412 case DataModality::TEXTURE_COORDS_2D:
413 return DataDimension::Role::UV;
415 case DataModality::VERTEX_COLORS_RGB:
416 case DataModality::VERTEX_COLORS_RGBA:
417 return DataDimension::Role::CHANNEL;
420 return DataDimension::Role::CUSTOM;
430 case DataModality::VERTEX_POSITIONS_3D:
431 case DataModality::VERTEX_NORMALS_3D:
432 case DataModality::VERTEX_TANGENTS_3D:
433 case DataModality::VERTEX_COLORS_RGB:
436 case DataModality::TEXTURE_COORDS_2D:
439 case DataModality::VERTEX_COLORS_RGBA:
442 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.