1.3.64
 
Loading...
Searching...
No Matches
Context_data.cpp
Go to the documentation of this file.
1
16#include "Context.h"
17
18using namespace helios;
19
20void Context::incrementPrimitiveDataLabelCounter(const std::string &primitive_data_label) {
21 primitive_data_label_counts[primitive_data_label]++;
22}
23
24void Context::decrementPrimitiveDataLabelCounter(const std::string &primitive_data_label) {
25 auto it = primitive_data_label_counts.find(primitive_data_label);
26 if (it != primitive_data_label_counts.end() && it->second > 0) {
27 it->second--;
28 if (it->second == 0) {
29 primitive_data_label_counts.erase(it);
30 }
31 }
32}
33
34//----------- VALUE-LEVEL CACHING CONFIGURATION ----------//
35
36void Context::enablePrimitiveDataValueCaching(const std::string &label) {
37 cached_primitive_data_labels.insert(label);
38}
39
40void Context::disablePrimitiveDataValueCaching(const std::string &label) {
41 cached_primitive_data_labels.erase(label);
42 // Clear cached values for this label
43 primitive_string_value_registry.erase(label);
44 primitive_int_value_registry.erase(label);
45 primitive_uint_value_registry.erase(label);
46}
47
48bool Context::isPrimitiveDataValueCachingEnabled(const std::string &label) const {
49 return cached_primitive_data_labels.find(label) != cached_primitive_data_labels.end();
50}
51
52void Context::enableObjectDataValueCaching(const std::string &label) {
53 cached_object_data_labels.insert(label);
54}
55
56void Context::disableObjectDataValueCaching(const std::string &label) {
57 cached_object_data_labels.erase(label);
58 // Clear cached values for this label
59 object_string_value_registry.erase(label);
60 object_int_value_registry.erase(label);
61 object_uint_value_registry.erase(label);
62}
63
64bool Context::isObjectDataValueCachingEnabled(const std::string &label) const {
65 return cached_object_data_labels.find(label) != cached_object_data_labels.end();
66}
67
68
69void Context::incrementObjectDataLabelCounter(const std::string &object_data_label) {
70 object_data_label_counts[object_data_label]++;
71}
72
73void Context::decrementObjectDataLabelCounter(const std::string &object_data_label) {
74 auto it = object_data_label_counts.find(object_data_label);
75 if (it != object_data_label_counts.end() && it->second > 0) {
76 it->second--;
77 if (it->second == 0) {
78 object_data_label_counts.erase(it);
79 }
80 }
81}
82
83// ------ Primitive Data -------- //
84
85HeliosDataType Primitive::getPrimitiveDataType(const char *label) const {
86
87#ifdef HELIOS_DEBUG
88 if (!doesPrimitiveDataExist(label)) {
89 helios_runtime_error("ERROR (Primitive::getPrimitiveDataType): Primitive data " + std::string(label) + " does not exist for primitive " + std::to_string(UUID));
90 }
91#endif
92
93 return primitive_data_types.at(label);
94}
95
97 const auto it = primitive_data_type_registry.find(label);
98 if (it != primitive_data_type_registry.end()) {
99 return it->second;
100 }
101 helios_runtime_error("ERROR (Context::getPrimitiveDataType): Primitive data " + std::string(label) + " does not exist.");
102 return HELIOS_TYPE_UNKNOWN; // Should never reach here, but added to avoid compiler warning
103}
104
105uint Primitive::getPrimitiveDataSize(const char *label) const {
106
107#ifdef HELIOS_DEBUG
108 if (!doesPrimitiveDataExist(label)) {
109 helios_runtime_error("ERROR (Primitive::getPrimitiveDataSize): Primitive data " + std::string(label) + " does not exist for primitive " + std::to_string(UUID));
110 }
111#endif
112
113 const HeliosDataType &type = primitive_data_types.at(label);
114
115 if (type == HELIOS_TYPE_INT) {
116 return primitive_data_int.at(label).size();
117 } else if (type == HELIOS_TYPE_UINT) {
118 return primitive_data_uint.at(label).size();
119 } else if (type == HELIOS_TYPE_FLOAT) {
120 return primitive_data_float.at(label).size();
121 } else if (type == HELIOS_TYPE_DOUBLE) {
122 return primitive_data_double.at(label).size();
123 } else if (type == HELIOS_TYPE_VEC2) {
124 return primitive_data_vec2.at(label).size();
125 } else if (type == HELIOS_TYPE_VEC3) {
126 return primitive_data_vec3.at(label).size();
127 } else if (type == HELIOS_TYPE_VEC4) {
128 return primitive_data_vec4.at(label).size();
129 } else if (type == HELIOS_TYPE_INT2) {
130 return primitive_data_int2.at(label).size();
131 } else if (type == HELIOS_TYPE_INT3) {
132 return primitive_data_int3.at(label).size();
133 } else if (type == HELIOS_TYPE_INT4) {
134 return primitive_data_int4.at(label).size();
135 } else if (type == HELIOS_TYPE_STRING) {
136 return primitive_data_string.at(label).size();
137 } else {
138 assert(false);
139 }
140
141 return 0;
142}
143
144void Primitive::clearPrimitiveData(const char *label) {
145
146 if (!doesPrimitiveDataExist(label)) {
147 return;
148 }
149
150 HeliosDataType type = primitive_data_types.at(label);
151
152 if (type == HELIOS_TYPE_INT) {
153 primitive_data_int.erase(label);
154 primitive_data_types.erase(label);
155 } else if (type == HELIOS_TYPE_UINT) {
156 primitive_data_uint.erase(label);
157 primitive_data_types.erase(label);
158 } else if (type == HELIOS_TYPE_FLOAT) {
159 primitive_data_float.erase(label);
160 primitive_data_types.erase(label);
161 } else if (type == HELIOS_TYPE_DOUBLE) {
162 primitive_data_double.erase(label);
163 primitive_data_types.erase(label);
164 } else if (type == HELIOS_TYPE_VEC2) {
165 primitive_data_vec2.erase(label);
166 primitive_data_types.erase(label);
167 } else if (type == HELIOS_TYPE_VEC3) {
168 primitive_data_vec3.erase(label);
169 primitive_data_types.erase(label);
170 } else if (type == HELIOS_TYPE_VEC4) {
171 primitive_data_vec4.erase(label);
172 primitive_data_types.erase(label);
173 } else if (type == HELIOS_TYPE_INT2) {
174 primitive_data_int2.erase(label);
175 primitive_data_types.erase(label);
176 } else if (type == HELIOS_TYPE_INT3) {
177 primitive_data_int3.erase(label);
178 primitive_data_types.erase(label);
179 } else if (type == HELIOS_TYPE_INT4) {
180 primitive_data_int4.erase(label);
181 primitive_data_types.erase(label);
182 } else if (type == HELIOS_TYPE_STRING) {
183 primitive_data_string.erase(label);
184 primitive_data_types.erase(label);
185 } else {
186 assert(false);
187 }
188 dirty_flag = true;
189}
190
191bool Primitive::doesPrimitiveDataExist(const char *label) const {
192 if (primitive_data_types.find(std::string(label)) == primitive_data_types.end()) {
193 return false;
194 }
195 return true;
196}
197
198std::vector<std::string> Primitive::listPrimitiveData() const {
199
200 std::vector<std::string> labels;
201 labels.reserve(primitive_data_types.size());
202
203 for (const auto &[label, type]: primitive_data_types) {
204 labels.push_back(label);
205 }
206
207 return labels;
208}
209
210HeliosDataType Context::getPrimitiveDataType(uint UUID, const char *label) const {
211#ifdef HELIOS_DEBUG
212 if (primitives.find(UUID) == primitives.end()) {
213 helios_runtime_error("ERROR (Context::getPrimitiveDataType): UUID of " + std::to_string(UUID) + " does not exist in the Context.");
214 }
215#endif
216 return primitives.at(UUID)->getPrimitiveDataType(label);
217}
218
219uint Context::getPrimitiveDataSize(uint UUID, const char *label) const {
220#ifdef HELIOS_DEBUG
221 if (primitives.find(UUID) == primitives.end()) {
222 helios_runtime_error("ERROR (Context::getPrimitiveDataSize): UUID of " + std::to_string(UUID) + " does not exist in the Context.");
223 }
224#endif
225 return primitives.at(UUID)->getPrimitiveDataSize(label);
226}
227
228bool Context::doesPrimitiveDataExist(uint UUID, const char *label) const {
229#ifdef HELIOS_DEBUG
230 if (primitives.find(UUID) == primitives.end()) {
231 helios_runtime_error("ERROR (Context::doesPrimitiveDataExist): UUID of " + std::to_string(UUID) + " does not exist in the Context.");
232 }
233#endif
234 return primitives.at(UUID)->doesPrimitiveDataExist(label);
235}
236
237void Context::clearPrimitiveData(uint UUID, const char *label) {
238#ifdef HELIOS_DEBUG
239 if (primitives.find(UUID) == primitives.end()) {
240 helios_runtime_error("ERROR (Context::getPrimitiveData): UUID of " + std::to_string(UUID) + " does not exist in the Context.");
241 }
242#endif
243 // Handle value registry before clearing if caching is enabled
244 std::string label_str = std::string(label);
245 if (isPrimitiveDataValueCachingEnabled(label_str) && primitives.at(UUID)->doesPrimitiveDataExist(label)) {
246 HeliosDataType data_type = primitives.at(UUID)->getPrimitiveDataType(label);
247 if (data_type == HELIOS_TYPE_STRING) {
248 std::string cached_value;
249 primitives.at(UUID)->getPrimitiveData(label, cached_value);
250 decrementPrimitiveValueRegistry(label_str, cached_value);
251 } else if (data_type == HELIOS_TYPE_INT) {
252 int cached_value;
253 primitives.at(UUID)->getPrimitiveData(label, cached_value);
254 decrementPrimitiveValueRegistry(label_str, cached_value);
255 } else if (data_type == HELIOS_TYPE_UINT) {
256 uint cached_value;
257 primitives.at(UUID)->getPrimitiveData(label, cached_value);
258 decrementPrimitiveValueRegistry(label_str, cached_value);
259 }
260 }
261
262 if (primitives.at(UUID)->doesPrimitiveDataExist(label)) {
263 decrementPrimitiveDataLabelCounter(label);
264 }
265 primitives.at(UUID)->clearPrimitiveData(label);
266}
267
268void Context::clearPrimitiveData(const std::vector<uint> &UUIDs, const char *label) {
269 for (unsigned int UUID: UUIDs) {
270#ifdef HELIOS_DEBUG
271 if (primitives.find(UUID) == primitives.end()) {
272 helios_runtime_error("ERROR (Context::getPrimitiveData): UUID of " + std::to_string(UUID) + " does not exist in the Context.");
273 }
274#endif
275 // Handle value registry before clearing if caching is enabled
276 std::string label_str = std::string(label);
277 if (isPrimitiveDataValueCachingEnabled(label_str) && primitives.at(UUID)->doesPrimitiveDataExist(label)) {
278 HeliosDataType data_type = primitives.at(UUID)->getPrimitiveDataType(label);
279 if (data_type == HELIOS_TYPE_STRING) {
280 std::string cached_value;
281 primitives.at(UUID)->getPrimitiveData(label, cached_value);
282 decrementPrimitiveValueRegistry(label_str, cached_value);
283 } else if (data_type == HELIOS_TYPE_INT) {
284 int cached_value;
285 primitives.at(UUID)->getPrimitiveData(label, cached_value);
286 decrementPrimitiveValueRegistry(label_str, cached_value);
287 } else if (data_type == HELIOS_TYPE_UINT) {
288 uint cached_value;
289 primitives.at(UUID)->getPrimitiveData(label, cached_value);
290 decrementPrimitiveValueRegistry(label_str, cached_value);
291 }
292 }
293
294 if (primitives.at(UUID)->doesPrimitiveDataExist(label)) {
295 decrementPrimitiveDataLabelCounter(label);
296 }
297 primitives.at(UUID)->clearPrimitiveData(label);
298 }
299}
300
301void Context::copyPrimitiveData(uint sourceUUID, uint destinationUUID) {
302
303#ifdef HELIOS_DEBUG
304 if (primitives.find(sourceUUID) == primitives.end()) {
305 helios_runtime_error("ERROR (Context::copyPrimitiveData): Source UUID of " + std::to_string(sourceUUID) + " does not exist in the Context.");
306 } else if (primitives.find(destinationUUID) == primitives.end()) {
307 helios_runtime_error("ERROR (Context::copyPrimitiveData): Destination UUID of " + std::to_string(destinationUUID) + " does not exist in the Context.");
308 }
309#endif
310
311 const auto &dest_labels = primitives.at(destinationUUID)->primitive_data_types;
312 for (const auto &[label, type]: dest_labels) {
313 decrementPrimitiveDataLabelCounter(label);
314 }
315
316 primitives.at(destinationUUID)->primitive_data_types = primitives.at(sourceUUID)->primitive_data_types;
317
318 primitives.at(destinationUUID)->primitive_data_int = primitives.at(sourceUUID)->primitive_data_int;
319 primitives.at(destinationUUID)->primitive_data_uint = primitives.at(sourceUUID)->primitive_data_uint;
320 primitives.at(destinationUUID)->primitive_data_float = primitives.at(sourceUUID)->primitive_data_float;
321 primitives.at(destinationUUID)->primitive_data_double = primitives.at(sourceUUID)->primitive_data_double;
322 primitives.at(destinationUUID)->primitive_data_vec2 = primitives.at(sourceUUID)->primitive_data_vec2;
323 primitives.at(destinationUUID)->primitive_data_vec3 = primitives.at(sourceUUID)->primitive_data_vec3;
324 primitives.at(destinationUUID)->primitive_data_vec4 = primitives.at(sourceUUID)->primitive_data_vec4;
325 primitives.at(destinationUUID)->primitive_data_int2 = primitives.at(sourceUUID)->primitive_data_int2;
326 primitives.at(destinationUUID)->primitive_data_int3 = primitives.at(sourceUUID)->primitive_data_int3;
327 primitives.at(destinationUUID)->primitive_data_int4 = primitives.at(sourceUUID)->primitive_data_int4;
328 primitives.at(destinationUUID)->primitive_data_string = primitives.at(sourceUUID)->primitive_data_string;
329
330 for (const auto &[label, type]: primitives.at(destinationUUID)->primitive_data_types) {
331 incrementPrimitiveDataLabelCounter(label);
332 }
333
334 primitives.at(destinationUUID)->dirty_flag = true;
335}
336
337void Context::renamePrimitiveData(uint UUID, const char *old_label, const char *new_label) {
338
339#ifdef HELIOS_DEBUG
340 if (primitives.find(UUID) == primitives.end()) {
341 helios_runtime_error("ERROR (Context::renamePrimitiveData): UUID of " + std::to_string(UUID) + " does not exist in the Context.");
342 } else if (!primitives.at(UUID)->doesPrimitiveDataExist(old_label)) {
343 helios_runtime_error("ERROR (Context::renamePrimitiveData): Primitive data of " + std::string(old_label) + " does not exist for primitive " + std::to_string(UUID) + ".");
344 }
345#endif
346
347 duplicatePrimitiveData(UUID, old_label, new_label);
348 clearPrimitiveData(UUID, old_label);
349 primitives.at(UUID)->dirty_flag = true;
350}
351
352void Context::duplicatePrimitiveData(uint UUID, const char *old_label, const char *new_label) {
353
354#ifdef HELIOS_DEBUG
355 if (primitives.find(UUID) == primitives.end()) {
356 helios_runtime_error("ERROR (Context::duplicatePrimitiveData): UUID of " + std::to_string(UUID) + " does not exist in the Context.");
357 } else if (!primitives.at(UUID)->doesPrimitiveDataExist(old_label)) {
358 helios_runtime_error("ERROR (Context::duplicatePrimitiveData): Primitive data of " + std::string(old_label) + " does not exist for primitive " + std::to_string(UUID) + ".");
359 }
360#endif
361
362 HeliosDataType type = getPrimitiveDataType(old_label);
363
364 if (!primitives.at(UUID)->doesPrimitiveDataExist(new_label)) {
365 incrementPrimitiveDataLabelCounter(new_label);
366 }
367 primitives.at(UUID)->primitive_data_types[new_label] = type;
368 if (type == HELIOS_TYPE_INT) {
369 primitives.at(UUID)->primitive_data_int[new_label] = primitives.at(UUID)->primitive_data_int.at(old_label);
370 } else if (type == HELIOS_TYPE_UINT) {
371 primitives.at(UUID)->primitive_data_uint[new_label] = primitives.at(UUID)->primitive_data_uint.at(old_label);
372 } else if (type == HELIOS_TYPE_FLOAT) {
373 primitives.at(UUID)->primitive_data_float[new_label] = primitives.at(UUID)->primitive_data_float.at(old_label);
374 } else if (type == HELIOS_TYPE_DOUBLE) {
375 primitives.at(UUID)->primitive_data_double[new_label] = primitives.at(UUID)->primitive_data_double.at(old_label);
376 } else if (type == HELIOS_TYPE_VEC2) {
377 primitives.at(UUID)->primitive_data_vec2[new_label] = primitives.at(UUID)->primitive_data_vec2.at(old_label);
378 } else if (type == HELIOS_TYPE_VEC3) {
379 primitives.at(UUID)->primitive_data_vec3[new_label] = primitives.at(UUID)->primitive_data_vec3.at(old_label);
380 } else if (type == HELIOS_TYPE_VEC4) {
381 primitives.at(UUID)->primitive_data_vec4[new_label] = primitives.at(UUID)->primitive_data_vec4.at(old_label);
382 } else if (type == HELIOS_TYPE_INT2) {
383 primitives.at(UUID)->primitive_data_int2[new_label] = primitives.at(UUID)->primitive_data_int2.at(old_label);
384 } else if (type == HELIOS_TYPE_INT3) {
385 primitives.at(UUID)->primitive_data_int3[new_label] = primitives.at(UUID)->primitive_data_int3.at(old_label);
386 } else if (type == HELIOS_TYPE_INT4) {
387 primitives.at(UUID)->primitive_data_int4[new_label] = primitives.at(UUID)->primitive_data_int4.at(old_label);
388 } else if (type == HELIOS_TYPE_STRING) {
389 primitives.at(UUID)->primitive_data_string[new_label] = primitives.at(UUID)->primitive_data_string.at(old_label);
390 } else {
391 assert(false);
392 }
393
394 primitives.at(UUID)->dirty_flag = true;
395}
396
397std::vector<std::string> Context::listPrimitiveData(uint UUID) const {
398 return getPrimitivePointer_private(UUID)->listPrimitiveData();
399}
400
401void Context::duplicatePrimitiveData(const char *existing_data_label, const char *copy_data_label) {
402 for (auto &[UUID, primitive]: primitives) {
403 if (primitive->doesPrimitiveDataExist(existing_data_label)) {
404 const HeliosDataType type = primitive->getPrimitiveDataType(existing_data_label);
405 if (!primitive->doesPrimitiveDataExist(copy_data_label)) {
406 incrementPrimitiveDataLabelCounter(copy_data_label);
407 }
408 primitive->primitive_data_types[copy_data_label] = type;
409 if (type == HELIOS_TYPE_FLOAT) {
410 primitive->primitive_data_float[copy_data_label] = primitive->primitive_data_float.at(existing_data_label);
411 } else if (type == HELIOS_TYPE_DOUBLE) {
412 primitive->primitive_data_double[copy_data_label] = primitive->primitive_data_double.at(existing_data_label);
413 } else if (type == HELIOS_TYPE_INT) {
414 primitive->primitive_data_int[copy_data_label] = primitive->primitive_data_int.at(existing_data_label);
415 } else if (type == HELIOS_TYPE_UINT) {
416 primitive->primitive_data_uint[copy_data_label] = primitive->primitive_data_uint.at(existing_data_label);
417 } else if (type == HELIOS_TYPE_VEC2) {
418 primitive->primitive_data_vec2[copy_data_label] = primitive->primitive_data_vec2.at(existing_data_label);
419 } else if (type == HELIOS_TYPE_VEC3) {
420 primitive->primitive_data_vec3[copy_data_label] = primitive->primitive_data_vec3.at(existing_data_label);
421 } else if (type == HELIOS_TYPE_VEC4) {
422 primitive->primitive_data_vec4[copy_data_label] = primitive->primitive_data_vec4.at(existing_data_label);
423 } else if (type == HELIOS_TYPE_INT2) {
424 primitive->primitive_data_int2[copy_data_label] = primitive->primitive_data_int2.at(existing_data_label);
425 } else if (type == HELIOS_TYPE_INT3) {
426 primitive->primitive_data_int3[copy_data_label] = primitive->primitive_data_int3.at(existing_data_label);
427 } else if (type == HELIOS_TYPE_STRING) {
428 primitive->primitive_data_string[copy_data_label] = primitive->primitive_data_string.at(existing_data_label);
429 }
430 primitive->dirty_flag = true;
431 }
432 }
433}
434
435void Context::calculatePrimitiveDataMean(const std::vector<uint> &UUIDs, const std::string &label, float &mean) const {
436 float value;
437 float sum = 0.f;
438 size_t count = 0;
439 for (uint UUID: UUIDs) {
440
441 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_FLOAT) {
442 getPrimitiveData(UUID, label.c_str(), value);
443 sum += value;
444 count++;
445 }
446 }
447
448 if (count == 0) {
449 std::cerr << "WARNING (Context::calculatePrimitiveDataMean): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
450 mean = 0;
451 } else {
452 mean = sum / float(count);
453 }
454}
455
456void Context::calculatePrimitiveDataMean(const std::vector<uint> &UUIDs, const std::string &label, double &mean) const {
457 double value;
458 double sum = 0.f;
459 size_t count = 0;
460 for (uint UUID: UUIDs) {
461
462 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_DOUBLE) {
463 getPrimitiveData(UUID, label.c_str(), value);
464 sum += value;
465 count++;
466 }
467 }
468
469 if (count == 0) {
470 std::cerr << "WARNING (Context::calculatePrimitiveDataMean): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
471 mean = 0;
472 } else {
473 mean = sum / float(count);
474 }
475}
476
477void Context::calculatePrimitiveDataMean(const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &mean) const {
478 vec2 value;
479 vec2 sum(0.f, 0.f);
480 size_t count = 0;
481 for (uint UUID: UUIDs) {
482
483 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_VEC2) {
484 getPrimitiveData(UUID, label.c_str(), value);
485 sum = sum + value;
486 count++;
487 }
488 }
489
490 if (count == 0) {
491 std::cerr << "WARNING (Context::calculatePrimitiveDataMean): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
492 mean = make_vec2(0, 0);
493 } else {
494 mean = sum / float(count);
495 }
496}
497
498void Context::calculatePrimitiveDataMean(const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &mean) const {
499 vec3 value;
500 vec3 sum(0.f, 0.f, 0.f);
501 size_t count = 0;
502 for (uint UUID: UUIDs) {
503
504 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_VEC3) {
505 getPrimitiveData(UUID, label.c_str(), value);
506 sum = sum + value;
507 count++;
508 }
509 }
510
511 if (count == 0) {
512 std::cerr << "WARNING (Context::calculatePrimitiveDataMean): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
513 mean = make_vec3(0, 0, 0);
514 } else {
515 mean = sum / float(count);
516 }
517}
518
519void Context::calculatePrimitiveDataMean(const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &mean) const {
520 vec4 value;
521 vec4 sum(0.f, 0.f, 0.f, 0.f);
522 size_t count = 0;
523 for (uint UUID: UUIDs) {
524
525 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_VEC4) {
526 getPrimitiveData(UUID, label.c_str(), value);
527 sum = sum + value;
528 count++;
529 }
530 }
531
532 if (count == 0) {
533 std::cerr << "WARNING (Context::calculatePrimitiveDataMean): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
534 mean = make_vec4(0, 0, 0, 0);
535 } else {
536 mean = sum / float(count);
537 }
538}
539
540void Context::setObjectDataFromPrimitiveDataMean(uint objID, const std::string &label) {
541#ifdef HELIOS_DEBUG
542 if (!doesObjectExist(objID)) {
543 helios_runtime_error("ERROR (Context::setObjectDataFromPrimitiveDataMean): Object ID of " + std::to_string(objID) + " does not exist in the Context.");
544 }
545#endif
546
547 // Get primitive UUIDs for this object
548 std::vector<uint> UUIDs = getObjectPrimitiveUUIDs(objID);
549
550 if (UUIDs.empty()) {
551 helios_runtime_error("ERROR (Context::setObjectDataFromPrimitiveDataMean): Object ID " + std::to_string(objID) + " has no primitive children.");
552 }
553
554 // Determine the data type by checking the first primitive that has this data
556 for (uint UUID: UUIDs) {
557 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str())) {
558 data_type = getPrimitiveDataType(label.c_str());
559 break;
560 }
561 }
562
563 if (data_type == HELIOS_TYPE_UNKNOWN) {
564 helios_runtime_error("ERROR (Context::setObjectDataFromPrimitiveDataMean): Primitive data '" + label + "' does not exist for any primitives in object " + std::to_string(objID) + ".");
565 }
566
567 // Validate data type is supported for mean calculation
568 if (data_type != HELIOS_TYPE_FLOAT && data_type != HELIOS_TYPE_DOUBLE && data_type != HELIOS_TYPE_VEC2 && data_type != HELIOS_TYPE_VEC3 && data_type != HELIOS_TYPE_VEC4) {
569 helios_runtime_error("ERROR (Context::setObjectDataFromPrimitiveDataMean): Cannot calculate mean for primitive data type. Only float, double, vec2, vec3, and vec4 are supported.");
570 }
571
572 // Calculate mean based on data type
573 if (data_type == HELIOS_TYPE_FLOAT) {
574 float value;
575 float sum = 0.f;
576 size_t count = 0;
577 for (uint UUID: UUIDs) {
578 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str())) {
579 getPrimitiveData(UUID, label.c_str(), value);
580 sum += value;
581 count++;
582 }
583 }
584 if (count == 0) {
585 helios_runtime_error("ERROR (Context::setObjectDataFromPrimitiveDataMean): No primitives in object " + std::to_string(objID) + " have primitive data '" + label + "'.");
586 }
587 float mean = sum / float(count);
588 setObjectData(objID, label.c_str(), mean);
589
590 } else if (data_type == HELIOS_TYPE_DOUBLE) {
591 double value;
592 double sum = 0.0;
593 size_t count = 0;
594 for (uint UUID: UUIDs) {
595 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str())) {
596 getPrimitiveData(UUID, label.c_str(), value);
597 sum += value;
598 count++;
599 }
600 }
601 if (count == 0) {
602 helios_runtime_error("ERROR (Context::setObjectDataFromPrimitiveDataMean): No primitives in object " + std::to_string(objID) + " have primitive data '" + label + "'.");
603 }
604 double mean = sum / double(count);
605 setObjectData(objID, label.c_str(), mean);
606
607 } else if (data_type == HELIOS_TYPE_VEC2) {
608 vec2 value;
609 vec2 sum(0.f, 0.f);
610 size_t count = 0;
611 for (uint UUID: UUIDs) {
612 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str())) {
613 getPrimitiveData(UUID, label.c_str(), value);
614 sum = sum + value;
615 count++;
616 }
617 }
618 if (count == 0) {
619 helios_runtime_error("ERROR (Context::setObjectDataFromPrimitiveDataMean): No primitives in object " + std::to_string(objID) + " have primitive data '" + label + "'.");
620 }
621 vec2 mean = sum / float(count);
622 setObjectData(objID, label.c_str(), mean);
623
624 } else if (data_type == HELIOS_TYPE_VEC3) {
625 vec3 value;
626 vec3 sum(0.f, 0.f, 0.f);
627 size_t count = 0;
628 for (uint UUID: UUIDs) {
629 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str())) {
630 getPrimitiveData(UUID, label.c_str(), value);
631 sum = sum + value;
632 count++;
633 }
634 }
635 if (count == 0) {
636 helios_runtime_error("ERROR (Context::setObjectDataFromPrimitiveDataMean): No primitives in object " + std::to_string(objID) + " have primitive data '" + label + "'.");
637 }
638 vec3 mean = sum / float(count);
639 setObjectData(objID, label.c_str(), mean);
640
641 } else if (data_type == HELIOS_TYPE_VEC4) {
642 vec4 value;
643 vec4 sum(0.f, 0.f, 0.f, 0.f);
644 size_t count = 0;
645 for (uint UUID: UUIDs) {
646 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str())) {
647 getPrimitiveData(UUID, label.c_str(), value);
648 sum = sum + value;
649 count++;
650 }
651 }
652 if (count == 0) {
653 helios_runtime_error("ERROR (Context::setObjectDataFromPrimitiveDataMean): No primitives in object " + std::to_string(objID) + " have primitive data '" + label + "'.");
654 }
655 vec4 mean = sum / float(count);
656 setObjectData(objID, label.c_str(), mean);
657 }
658}
659
660void Context::calculatePrimitiveDataAreaWeightedMean(const std::vector<uint> &UUIDs, const std::string &label, float &awt_mean) const {
661 float value, A;
662 float sum = 0.f;
663 float area = 0;
664 bool nan_warning = false;
665 for (uint UUID: UUIDs) {
666
667 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_FLOAT) {
668 getPrimitiveData(UUID, label.c_str(), value);
669 A = getPrimitiveArea(UUID);
670 if (std::isnan(A)) {
671 nan_warning = true;
672 }
673 sum += value * A;
674 area += A;
675 }
676 }
677
678 if (area == 0) {
679 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedMean): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
680 awt_mean = 0;
681 } else if (nan_warning) {
682 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedMean): At least one primitive has an area of NaN and was excluded from calculations" << std::endl;
683 } else {
684 awt_mean = sum / area;
685 }
686}
687
688void Context::calculatePrimitiveDataAreaWeightedMean(const std::vector<uint> &UUIDs, const std::string &label, double &awt_mean) const {
689 double value;
690 float A;
691 double sum = 0.f;
692 double area = 0;
693 bool nan_warning = false;
694 for (uint UUID: UUIDs) {
695
696 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_DOUBLE) {
697 getPrimitiveData(UUID, label.c_str(), value);
698 A = getPrimitiveArea(UUID);
699 if (std::isnan(A)) {
700 nan_warning = true;
701 }
702 sum += value * double(A);
703 area += A;
704 }
705 }
706
707 if (area == 0) {
708 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedMean): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
709 awt_mean = 0;
710 } else if (nan_warning) {
711 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedMean): At least one primitive has an area of NaN and was excluded from calculations" << std::endl;
712 } else {
713 awt_mean = sum / area;
714 }
715}
716
717void Context::calculatePrimitiveDataAreaWeightedMean(const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &awt_mean) const {
718 vec2 value;
719 vec2 sum(0.f, 0.f);
720 float area = 0;
721 bool nan_warning = false;
722 for (uint UUID: UUIDs) {
723
724 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_VEC2) {
725 getPrimitiveData(UUID, label.c_str(), value);
726 float A = getPrimitiveArea(UUID);
727 if (std::isnan(A)) {
728 nan_warning = true;
729 }
730 sum = sum + (value * A);
731 area += A;
732 }
733 }
734
735 if (area == 0) {
736 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedMean): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
737 awt_mean = make_vec2(0, 0);
738 } else if (nan_warning) {
739 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedMean): At least one primitive has an area of NaN and was excluded from calculations" << std::endl;
740 } else {
741 awt_mean = sum / area;
742 }
743}
744
745void Context::calculatePrimitiveDataAreaWeightedMean(const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &awt_mean) const {
746 vec3 value;
747 vec3 sum(0.f, 0.f, 0.f);
748 float area = 0;
749 bool nan_warning = false;
750 for (uint UUID: UUIDs) {
751
752 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_VEC3) {
753 getPrimitiveData(UUID, label.c_str(), value);
754 float A = getPrimitiveArea(UUID);
755 if (std::isnan(A)) {
756 nan_warning = true;
757 }
758 sum = sum + (value * A);
759 area += A;
760 }
761 }
762
763 if (area == 0) {
764 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedMean): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
765 awt_mean = make_vec3(0, 0, 0);
766 } else if (nan_warning) {
767 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedMean): At least one primitive has an area of NaN and was excluded from calculations" << std::endl;
768 } else {
769 awt_mean = sum / area;
770 }
771}
772
773void Context::calculatePrimitiveDataAreaWeightedMean(const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &awt_mean) const {
774 vec4 value;
775 vec4 sum(0.f, 0.f, 0.f, 0.f);
776 float area = 0;
777 bool nan_warning = false;
778 for (uint UUID: UUIDs) {
779
780 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_VEC4) {
781 getPrimitiveData(UUID, label.c_str(), value);
782 float A = getPrimitiveArea(UUID);
783 if (std::isnan(A)) {
784 nan_warning = true;
785 }
786 sum = sum + (value * A);
787 area += A;
788 }
789 }
790
791 if (area == 0) {
792 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedMean): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
793 awt_mean = make_vec4(0, 0, 0, 0);
794 } else if (nan_warning) {
795 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedMean): At least one primitive has an area of NaN and was excluded from calculations" << std::endl;
796 } else {
797 awt_mean = sum / area;
798 }
799}
800
801void Context::calculatePrimitiveDataSum(const std::vector<uint> &UUIDs, const std::string &label, float &sum) const {
802
803 float value;
804 sum = 0.f;
805 bool added_to_sum = false;
806 for (uint UUID: UUIDs) {
807
808 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_FLOAT) {
809 getPrimitiveData(UUID, label.c_str(), value);
810 sum += value;
811 added_to_sum = true;
812 }
813 }
814
815 if (!added_to_sum) {
816 std::cerr << "WARNING (Context::calculatePrimitiveDataSum): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
817 }
818}
819
820void Context::calculatePrimitiveDataSum(const std::vector<uint> &UUIDs, const std::string &label, double &sum) const {
821
822 double value;
823 sum = 0.f;
824 bool added_to_sum = false;
825 for (uint UUID: UUIDs) {
826
827 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_DOUBLE) {
828 getPrimitiveData(UUID, label.c_str(), value);
829 sum += value;
830 added_to_sum = true;
831 }
832 }
833
834 if (!added_to_sum) {
835 std::cerr << "WARNING (Context::calculatePrimitiveDataSum): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
836 }
837}
838
839void Context::calculatePrimitiveDataSum(const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &sum) const {
840
841 vec2 value;
842 sum = make_vec2(0.f, 0.f);
843 bool added_to_sum = false;
844 for (uint UUID: UUIDs) {
845
846 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_VEC2) {
847 getPrimitiveData(UUID, label.c_str(), value);
848 sum = sum + value;
849 added_to_sum = true;
850 }
851 }
852
853 if (!added_to_sum) {
854 std::cerr << "WARNING (Context::calculatePrimitiveDataSum): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
855 }
856}
857
858void Context::calculatePrimitiveDataSum(const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &sum) const {
859
860 vec3 value;
861 sum = make_vec3(0.f, 0.f, 0.f);
862 bool added_to_sum = false;
863 for (uint UUID: UUIDs) {
864
865 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_VEC3) {
866 getPrimitiveData(UUID, label.c_str(), value);
867 sum = sum + value;
868 added_to_sum = true;
869 }
870 }
871
872 if (!added_to_sum) {
873 std::cerr << "WARNING (Context::calculatePrimitiveDataSum): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
874 }
875}
876
877void Context::calculatePrimitiveDataSum(const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &sum) const {
878
879 vec4 value;
880 sum = make_vec4(0.f, 0.f, 0.f, 0.f);
881 bool added_to_sum = false;
882 for (uint UUID: UUIDs) {
883
884 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_VEC4) {
885 getPrimitiveData(UUID, label.c_str(), value);
886 sum = sum + value;
887 added_to_sum = true;
888 }
889 }
890
891 if (!added_to_sum) {
892 std::cerr << "WARNING (Context::calculatePrimitiveDataSum): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
893 }
894}
895
896void Context::calculatePrimitiveDataAreaWeightedSum(const std::vector<uint> &UUIDs, const std::string &label, float &awt_sum) const {
897
898 float value;
899 awt_sum = 0.f;
900 bool added_to_sum = false;
901 bool nan_warning = false;
902 for (uint UUID: UUIDs) {
903
904 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_FLOAT) {
905 float area = getPrimitiveArea(UUID);
906 if (std::isnan(area)) {
907 nan_warning = true;
908 continue;
909 }
910 getPrimitiveData(UUID, label.c_str(), value);
911 awt_sum += value * area;
912 added_to_sum = true;
913 }
914 }
915
916 if (!added_to_sum) {
917 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedSum): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
918 } else if (nan_warning) {
919 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedSum): At least one primitive has an area of NaN and was excluded from calculations" << std::endl;
920 }
921}
922
923void Context::calculatePrimitiveDataAreaWeightedSum(const std::vector<uint> &UUIDs, const std::string &label, double &awt_sum) const {
924
925 double value;
926 awt_sum = 0.f;
927 bool added_to_sum = false;
928 bool nan_warning = false;
929 for (uint UUID: UUIDs) {
930
931 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_DOUBLE) {
932 float area = getPrimitiveArea(UUID);
933 if (std::isnan(area)) {
934 nan_warning = true;
935 continue;
936 }
937 getPrimitiveData(UUID, label.c_str(), value);
938 awt_sum += value * area;
939 added_to_sum = true;
940 }
941 }
942
943 if (!added_to_sum) {
944 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedSum): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
945 } else if (nan_warning) {
946 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedSum): At least one primitive has an area of NaN and was excluded from calculations" << std::endl;
947 }
948}
949
950void Context::calculatePrimitiveDataAreaWeightedSum(const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &awt_sum) const {
951
952 vec2 value;
953 awt_sum = make_vec2(0.f, 0.f);
954 bool added_to_sum = false;
955 bool nan_warning = false;
956 for (uint UUID: UUIDs) {
957
958 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_VEC2) {
959 float area = getPrimitiveArea(UUID);
960 if (std::isnan(area)) {
961 nan_warning = true;
962 continue;
963 }
964 getPrimitiveData(UUID, label.c_str(), value);
965 awt_sum = awt_sum + value * area;
966 added_to_sum = true;
967 }
968 }
969
970 if (!added_to_sum) {
971 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedSum): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
972 } else if (nan_warning) {
973 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedSum): At least one primitive has an area of NaN and was excluded from calculations" << std::endl;
974 }
975}
976
977void Context::calculatePrimitiveDataAreaWeightedSum(const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &awt_sum) const {
978
979 vec3 value;
980 awt_sum = make_vec3(0.f, 0.f, 0.f);
981 bool added_to_sum = false;
982 bool nan_warning = false;
983 for (uint UUID: UUIDs) {
984
985 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_VEC3) {
986 float area = getPrimitiveArea(UUID);
987 if (std::isnan(area)) {
988 nan_warning = true;
989 continue;
990 }
991 getPrimitiveData(UUID, label.c_str(), value);
992 awt_sum = awt_sum + value * area;
993 added_to_sum = true;
994 }
995 }
996
997 if (!added_to_sum) {
998 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedSum): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
999 } else if (nan_warning) {
1000 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedSum): At least one primitive has an area of NaN and was excluded from calculations" << std::endl;
1001 }
1002}
1003
1004void Context::calculatePrimitiveDataAreaWeightedSum(const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &awt_sum) const {
1005
1006 vec4 value;
1007 awt_sum = make_vec4(0.f, 0.f, 0.f, 0.F);
1008 bool added_to_sum = false;
1009 bool nan_warning = false;
1010 for (uint UUID: UUIDs) {
1011
1012 if (doesPrimitiveExist(UUID) && doesPrimitiveDataExist(UUID, label.c_str()) && getPrimitiveDataType(label.c_str()) == HELIOS_TYPE_VEC4) {
1013 float area = getPrimitiveArea(UUID);
1014 if (std::isnan(area)) {
1015 nan_warning = true;
1016 continue;
1017 }
1018 getPrimitiveData(UUID, label.c_str(), value);
1019 awt_sum = awt_sum + value * area;
1020 added_to_sum = true;
1021 }
1022 }
1023
1024 if (!added_to_sum) {
1025 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedSum): No primitives found with primitive data of '" << label << "'. Returning a value of 0." << std::endl;
1026 } else if (nan_warning) {
1027 std::cerr << "WARNING (Context::calculatePrimitiveDataAreaWeightedSum): At least one primitive has an area of NaN and was excluded from calculations" << std::endl;
1028 }
1029}
1030
1031void Context::scalePrimitiveData(const std::vector<uint> &UUIDs, const std::string &label, float scaling_factor) {
1032
1033 uint primitives_not_exist = 0;
1034 uint primitive_data_not_exist = 0;
1035 for (uint UUID: UUIDs) {
1036 if (!doesPrimitiveExist(UUID)) {
1037 primitives_not_exist++;
1038 continue;
1039 }
1040 if (!doesPrimitiveDataExist(UUID, label.c_str())) {
1041 primitive_data_not_exist++;
1042 continue;
1043 }
1044 HeliosDataType data_type = getPrimitiveDataType(label.c_str());
1045 if (data_type == HELIOS_TYPE_FLOAT) {
1046 for (float &data: primitives.at(UUID)->primitive_data_float[label]) {
1047 data *= scaling_factor;
1048 }
1049 } else if (data_type == HELIOS_TYPE_DOUBLE) {
1050 for (double &data: primitives.at(UUID)->primitive_data_double[label]) {
1051 data *= scaling_factor;
1052 }
1053 } else if (data_type == HELIOS_TYPE_VEC2) {
1054 for (auto &data: primitives.at(UUID)->primitive_data_vec2[label]) {
1055 data.x *= scaling_factor;
1056 data.y *= scaling_factor;
1057 }
1058 } else if (data_type == HELIOS_TYPE_VEC3) {
1059 for (auto &data: primitives.at(UUID)->primitive_data_vec3[label]) {
1060 data.x *= scaling_factor;
1061 data.y *= scaling_factor;
1062 data.z *= scaling_factor;
1063 }
1064 } else if (data_type == HELIOS_TYPE_VEC4) {
1065 for (auto &data: primitives.at(UUID)->primitive_data_vec4[label]) {
1066 data.x *= scaling_factor;
1067 data.y *= scaling_factor;
1068 data.z *= scaling_factor;
1069 data.w *= scaling_factor;
1070 }
1071 } else {
1072 helios_runtime_error("ERROR (Context::scalePrimitiveData): This operation only supports primitive data of type float, double, vec2, vec3, and vec4.");
1073 }
1074 primitives.at(UUID)->dirty_flag = true;
1075 }
1076
1077 if (primitives_not_exist > 0) {
1078 std::cerr << "WARNING (Context::scalePrimitiveData): " << primitives_not_exist << " of " << UUIDs.size() << " from the input UUID vector did not exist." << std::endl;
1079 }
1080 if (primitive_data_not_exist > 0) {
1081 std::cerr << "WARNING (Context::scalePrimitiveData): Primitive data did not exist for " << primitive_data_not_exist << " primitives, and thus no scaling was applied." << std::endl;
1082 }
1083}
1084
1085void Context::scalePrimitiveData(const std::string &label, float scaling_factor) {
1086 scalePrimitiveData(getAllUUIDs(), label, scaling_factor);
1087}
1088
1089void Context::incrementPrimitiveData(const std::vector<uint> &UUIDs, const char *label, int increment) {
1090
1091 WarningAggregator warnings;
1092
1093 for (uint UUID: UUIDs) {
1094
1095 if (!doesPrimitiveDataExist(UUID, label)) {
1096 helios_runtime_error("ERROR (Context::incrementPrimitiveData): Primitive data " + std::string(label) + " does not exist in the Context for primitive " + std::to_string(UUID) + ".");
1097 }
1098
1099 uint size = getPrimitiveDataSize(UUID, label);
1100
1101 if (primitives.at(UUID)->primitive_data_types.at(label) == HELIOS_TYPE_INT) {
1102 for (uint i = 0; i < size; i++) {
1103 primitives.at(UUID)->primitive_data_int.at(label).at(i) += increment;
1104 }
1105 primitives.at(UUID)->dirty_flag = true;
1106 } else {
1107 warnings.addWarning("increment_type_mismatch", "Attempted to increment primitive data for type int, but data '" + std::string(label) + "' does not have type int.");
1108 }
1109 }
1110
1111 warnings.report(std::cerr);
1112}
1113
1114void Context::incrementPrimitiveData(const std::vector<uint> &UUIDs, const char *label, uint increment) {
1115
1116 WarningAggregator warnings;
1117
1118 for (uint UUID: UUIDs) {
1119
1120 if (!doesPrimitiveDataExist(UUID, label)) {
1121 helios_runtime_error("ERROR (Context::incrementPrimitiveData): Primitive data " + std::string(label) + " does not exist in the Context for primitive " + std::to_string(UUID) + ".");
1122 }
1123
1124 uint size = getPrimitiveDataSize(UUID, label);
1125
1126 if (primitives.at(UUID)->primitive_data_types.at(label) == HELIOS_TYPE_UINT) {
1127 for (uint i = 0; i < size; i++) {
1128 primitives.at(UUID)->primitive_data_uint.at(label).at(i) += increment;
1129 }
1130 primitives.at(UUID)->dirty_flag = true;
1131 } else {
1132 warnings.addWarning("increment_type_mismatch", "Attempted to increment Primitive data for type uint, but data '" + std::string(label) + "' does not have type uint.");
1133 }
1134 }
1135
1136 warnings.report(std::cerr);
1137}
1138
1139void Context::incrementPrimitiveData(const std::vector<uint> &UUIDs, const char *label, float increment) {
1140
1141 WarningAggregator warnings;
1142
1143 for (uint UUID: UUIDs) {
1144
1145 if (!doesPrimitiveDataExist(UUID, label)) {
1146 helios_runtime_error("ERROR (Context::incrementPrimitiveData): Primitive data " + std::string(label) + " does not exist in the Context for primitive " + std::to_string(UUID) + ".");
1147 }
1148
1149 uint size = getPrimitiveDataSize(UUID, label);
1150
1151 if (primitives.at(UUID)->primitive_data_types.at(label) == HELIOS_TYPE_FLOAT) {
1152 for (uint i = 0; i < size; i++) {
1153 primitives.at(UUID)->primitive_data_float.at(label).at(i) += increment;
1154 }
1155 primitives.at(UUID)->dirty_flag = true;
1156 } else {
1157 warnings.addWarning("increment_type_mismatch", "Attempted to increment Primitive data for type float, but data '" + std::string(label) + "' does not have type float.");
1158 }
1159 }
1160
1161 warnings.report(std::cerr);
1162}
1163
1164void Context::incrementPrimitiveData(const std::vector<uint> &UUIDs, const char *label, double increment) {
1165
1166 WarningAggregator warnings;
1167
1168 for (uint UUID: UUIDs) {
1169
1170 if (!doesPrimitiveDataExist(UUID, label)) {
1171 helios_runtime_error("ERROR (Context::incrementPrimitiveData): Primitive data " + std::string(label) + " does not exist in the Context for primitive " + std::to_string(UUID) + ".");
1172 }
1173
1174 uint size = getPrimitiveDataSize(UUID, label);
1175
1176 if (primitives.at(UUID)->primitive_data_types.at(label) == HELIOS_TYPE_DOUBLE) {
1177 for (uint i = 0; i < size; i++) {
1178 primitives.at(UUID)->primitive_data_double.at(label).at(i) += increment;
1179 }
1180 primitives.at(UUID)->dirty_flag = true;
1181 } else {
1182 warnings.addWarning("increment_type_mismatch", "Attempted to increment Primitive data for type double, but data '" + std::string(label) + "' does not have type double.");
1183 }
1184 }
1185
1186 warnings.report(std::cerr);
1187}
1188
1189void Context::aggregatePrimitiveDataSum(const std::vector<uint> &UUIDs, const std::vector<std::string> &primitive_data_labels, const std::string &result_primitive_data_label) {
1190
1191 uint primitives_not_exist = 0;
1192 uint primitive_data_not_exist = 0;
1193
1194 float data_float = 0;
1195 double data_double = 0;
1196 uint data_uint = 0;
1197 int data_int = 0;
1198 int2 data_int2;
1199 int3 data_int3;
1200 int4 data_int4;
1201 vec2 data_vec2;
1202 vec3 data_vec3;
1203 vec4 data_vec4;
1204
1205 for (uint UUID: UUIDs) {
1206 if (!doesPrimitiveExist(UUID)) {
1207 primitives_not_exist++;
1208 continue;
1209 }
1210
1211 HeliosDataType data_type;
1212
1213 bool init_type = false;
1214 for (const auto &label: primitive_data_labels) {
1215
1216 if (!doesPrimitiveDataExist(UUID, label.c_str())) {
1217 continue;
1218 }
1219
1220 HeliosDataType data_type_current = getPrimitiveDataType(label.c_str());
1221 if (!init_type) {
1222 data_type = data_type_current;
1223 init_type = true;
1224 } else {
1225 if (data_type != data_type_current) {
1226 helios_runtime_error("ERROR (Context::aggregatePrimitiveDataSum): Primitive data types are not consistent for UUID " + std::to_string(UUID));
1227 }
1228 }
1229
1230 if (data_type_current == HELIOS_TYPE_FLOAT) {
1231 float data;
1232 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1233 data_float += data;
1234 } else if (data_type_current == HELIOS_TYPE_DOUBLE) {
1235 double data;
1236 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1237 data_double += data;
1238 } else if (data_type_current == HELIOS_TYPE_VEC2) {
1239 vec2 data;
1240 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1241 data_vec2 = data_vec2 + data;
1242 } else if (data_type_current == HELIOS_TYPE_VEC3) {
1243 vec3 data;
1244 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1245 data_vec3 = data_vec3 + data;
1246 } else if (data_type_current == HELIOS_TYPE_VEC4) {
1247 vec4 data;
1248 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1249 data_vec4 = data_vec4 + data;
1250 } else if (data_type_current == HELIOS_TYPE_INT) {
1251 int data;
1252 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1253 data_int = data_int + data;
1254 } else if (data_type_current == HELIOS_TYPE_UINT) {
1255 uint data;
1256 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1257 data_uint = data_uint + data;
1258 } else if (data_type_current == HELIOS_TYPE_INT2) {
1259 int2 data;
1260 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1261 data_int2 = data_int2 + data;
1262 } else if (data_type_current == HELIOS_TYPE_INT3) {
1263 int3 data;
1264 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1265 data_int3 = data_int3 + data;
1266 } else if (data_type_current == HELIOS_TYPE_INT4) {
1267 int4 data;
1268 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1269 data_int4 = data_int4 + data;
1270 } else {
1271 helios_runtime_error("ERROR (Context::aggregatePrimitiveDataSum): This operation is not supported for string primitive data types.");
1272 }
1273 }
1274
1275 if (!init_type) {
1276 primitive_data_not_exist++;
1277 continue;
1278 } else if (data_type == HELIOS_TYPE_FLOAT) {
1279 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_float);
1280 data_float = 0;
1281 } else if (data_type == HELIOS_TYPE_DOUBLE) {
1282 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_double);
1283 data_double = 0;
1284 } else if (data_type == HELIOS_TYPE_VEC2) {
1285 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_vec2);
1286 data_vec2 = make_vec2(0, 0);
1287 } else if (data_type == HELIOS_TYPE_VEC3) {
1288 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_vec3);
1289 data_vec3 = make_vec3(0, 0, 0);
1290 } else if (data_type == HELIOS_TYPE_VEC4) {
1291 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_vec4);
1292 data_vec4 = make_vec4(0, 0, 0, 0);
1293 } else if (data_type == HELIOS_TYPE_INT) {
1294 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_int);
1295 data_int = 0;
1296 } else if (data_type == HELIOS_TYPE_UINT) {
1297 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_uint);
1298 data_uint = 0;
1299 } else if (data_type == HELIOS_TYPE_INT2) {
1300 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_int2);
1301 data_int2 = make_int2(0, 0);
1302 } else if (data_type == HELIOS_TYPE_INT3) {
1303 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_int3);
1304 data_int3 = make_int3(0, 0, 0);
1305 } else if (data_type == HELIOS_TYPE_INT4) {
1306 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_int4);
1307 data_int4 = make_int4(0, 0, 0, 0);
1308 }
1309 }
1310
1311 if (primitives_not_exist > 0) {
1312 std::cerr << "WARNING (Context::aggregatePrimitiveDataSum): " << primitives_not_exist << " of " << UUIDs.size() << " from the input UUID vector did not exist." << std::endl;
1313 }
1314 if (primitive_data_not_exist > 0) {
1315 std::cerr << "WARNING (Context::aggregatePrimitiveDataSum): Primitive data did not exist for " << primitive_data_not_exist
1316 << " primitives, and thus no scaling summation was performed and new primitive data was not created for this primitive." << std::endl;
1317 }
1318}
1319
1320void Context::aggregatePrimitiveDataProduct(const std::vector<uint> &UUIDs, const std::vector<std::string> &primitive_data_labels, const std::string &result_primitive_data_label) {
1321
1322 uint primitives_not_exist = 0;
1323 uint primitive_data_not_exist = 0;
1324
1325 float data_float = 0;
1326 double data_double = 0;
1327 uint data_uint = 0;
1328 int data_int = 0;
1329 int2 data_int2;
1330 int3 data_int3;
1331 int4 data_int4;
1332 vec2 data_vec2;
1333 vec3 data_vec3;
1334 vec4 data_vec4;
1335
1336 for (uint UUID: UUIDs) {
1337 if (!doesPrimitiveExist(UUID)) {
1338 primitives_not_exist++;
1339 continue;
1340 }
1341
1342 HeliosDataType data_type;
1343
1344 bool init_type = false;
1345 int i = 0;
1346 for (const auto &label: primitive_data_labels) {
1347
1348 if (!doesPrimitiveDataExist(UUID, label.c_str())) {
1349 continue;
1350 }
1351
1352 HeliosDataType data_type_current = getPrimitiveDataType(label.c_str());
1353 if (!init_type) {
1354 data_type = data_type_current;
1355 init_type = true;
1356 } else {
1357 if (data_type != data_type_current) {
1358 helios_runtime_error("ERROR (Context::aggregatePrimitiveDataProduct): Primitive data types are not consistent for UUID " + std::to_string(UUID));
1359 }
1360 }
1361
1362 if (data_type_current == HELIOS_TYPE_FLOAT) {
1363 float data;
1364 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1365 if (i == 0) {
1366 data_float = data;
1367 } else {
1368 data_float *= data;
1369 }
1370 } else if (data_type_current == HELIOS_TYPE_DOUBLE) {
1371 double data;
1372 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1373 if (i == 0) {
1374 data_double *= data;
1375 } else {
1376 data_double = data;
1377 }
1378 } else if (data_type_current == HELIOS_TYPE_VEC2) {
1379 vec2 data;
1380 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1381 if (i == 0) {
1382 data_vec2.x *= data.x;
1383 data_vec2.y *= data.y;
1384 } else {
1385 data_vec2 = data;
1386 }
1387 } else if (data_type_current == HELIOS_TYPE_VEC3) {
1388 vec3 data;
1389 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1390 if (i == 0) {
1391 data_vec3.x *= data.x;
1392 data_vec3.y *= data.y;
1393 data_vec3.z *= data.z;
1394 } else {
1395 data_vec3 = data;
1396 }
1397 } else if (data_type_current == HELIOS_TYPE_VEC4) {
1398 vec4 data;
1399 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1400 if (i == 0) {
1401 data_vec4.x *= data.x;
1402 data_vec4.y *= data.y;
1403 data_vec4.z *= data.z;
1404 data_vec4.w *= data.w;
1405 } else {
1406 data_vec4 = data;
1407 }
1408 } else if (data_type_current == HELIOS_TYPE_INT) {
1409 int data;
1410 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1411 if (i == 0) {
1412 data_int = data_int * data;
1413 } else {
1414 data_int = data;
1415 }
1416 } else if (data_type_current == HELIOS_TYPE_UINT) {
1417 uint data;
1418 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1419 if (i == 0) {
1420 data_uint = data_uint * data;
1421 } else {
1422 data_uint = data;
1423 }
1424 } else if (data_type_current == HELIOS_TYPE_INT2) {
1425 int2 data;
1426 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1427 if (i == 0) {
1428 data_int2.x *= data.x;
1429 data_int2.y *= data.y;
1430 } else {
1431 data_int2 = data;
1432 }
1433 } else if (data_type_current == HELIOS_TYPE_INT3) {
1434 int3 data;
1435 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1436 if (i == 0) {
1437 data_int3.x *= data.x;
1438 data_int3.y *= data.y;
1439 data_int3.z *= data.z;
1440 } else {
1441 data_int3 = data;
1442 }
1443 } else if (data_type_current == HELIOS_TYPE_INT4) {
1444 int4 data;
1445 primitives.at(UUID)->getPrimitiveData(label.c_str(), data);
1446 if (i == 0) {
1447 data_int4.x *= data.x;
1448 data_int4.y *= data.y;
1449 data_int4.z *= data.z;
1450 data_int4.w *= data.w;
1451 } else {
1452 data_int4 = data;
1453 }
1454 } else {
1455 helios_runtime_error("ERROR (Context::aggregatePrimitiveDataProduct): This operation is not supported for string primitive data types.");
1456 }
1457 i++;
1458 }
1459
1460 if (!init_type) {
1461 primitive_data_not_exist++;
1462 continue;
1463 } else if (data_type == HELIOS_TYPE_FLOAT) {
1464 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_float);
1465 } else if (data_type == HELIOS_TYPE_DOUBLE) {
1466 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_double);
1467 } else if (data_type == HELIOS_TYPE_VEC2) {
1468 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_vec2);
1469 } else if (data_type == HELIOS_TYPE_VEC3) {
1470 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_vec3);
1471 } else if (data_type == HELIOS_TYPE_VEC4) {
1472 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_vec4);
1473 } else if (data_type == HELIOS_TYPE_INT) {
1474 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_int);
1475 } else if (data_type == HELIOS_TYPE_UINT) {
1476 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_uint);
1477 } else if (data_type == HELIOS_TYPE_INT2) {
1478 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_int2);
1479 } else if (data_type == HELIOS_TYPE_INT3) {
1480 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_int3);
1481 } else if (data_type == HELIOS_TYPE_INT4) {
1482 setPrimitiveData(UUID, result_primitive_data_label.c_str(), data_int4);
1483 }
1484 }
1485
1486 if (primitives_not_exist > 0) {
1487 std::cerr << "WARNING (Context::aggregatePrimitiveDataProduct): " << primitives_not_exist << " of " << UUIDs.size() << " from the input UUID vector did not exist." << std::endl;
1488 }
1489 if (primitive_data_not_exist > 0) {
1490 std::cerr << "WARNING (Context::aggregatePrimitiveDataProduct): Primitive data did not exist for " << primitive_data_not_exist
1491 << " primitives, and thus no multiplication was performed and new primitive data was not created for this primitive." << std::endl;
1492 }
1493}
1494
1495
1496float Context::sumPrimitiveSurfaceArea(const std::vector<uint> &UUIDs) const {
1497
1498 bool primitive_warning = false;
1499 bool nan_warning = false;
1500 float area = 0;
1501 for (uint UUID: UUIDs) {
1502
1503 float A = getPrimitiveArea(UUID);
1504
1505 if (std::isnan(A)) {
1506 nan_warning = true;
1507 continue;
1508 }
1509
1510 if (doesPrimitiveExist(UUID)) {
1511 area += A;
1512 } else {
1513 primitive_warning = true;
1514 }
1515 }
1516
1517 if (primitive_warning) {
1518 std::cerr << "WARNING (Context::sumPrimitiveSurfaceArea): One or more primitives reference in the UUID vector did not exist." << std::endl;
1519 } else if (nan_warning) {
1520 std::cerr << "WARNING (Context::sumPrimitiveSurfaceArea): One or more primitives had an area of NaN." << std::endl;
1521 }
1522
1523 return area;
1524}
1525
1526std::vector<uint> Context::filterPrimitivesByData(const std::vector<uint> &UUIDs, const std::string &primitive_data_label, float filter_value, const std::string &comparator) const {
1527
1528 if (comparator != "==" && comparator != ">" && comparator != "<" && comparator != ">=" && comparator != "<=") {
1529 helios_runtime_error("ERROR (Context::filterPrimitivesByData): Invalid comparator. Must be one of '==', '>', '<', '>=', or '<='.");
1530 }
1531
1532 std::vector<uint> UUIDs_out = UUIDs;
1533 for (std::size_t p = UUIDs.size(); p-- > 0;) {
1534 uint UUID = UUIDs_out.at(p);
1535 if (doesPrimitiveDataExist(UUID, primitive_data_label.c_str()) && getPrimitiveDataType(primitive_data_label.c_str()) == HELIOS_TYPE_FLOAT) {
1536 float data;
1537 getPrimitiveData(UUID, primitive_data_label.c_str(), data);
1538 if (comparator == "==" && data == filter_value) {
1539 continue;
1540 }
1541 if (comparator == ">" && data > filter_value) {
1542 continue;
1543 }
1544 if (comparator == "<" && data < filter_value) {
1545 continue;
1546 }
1547 if (comparator == ">=" && data >= filter_value) {
1548 continue;
1549 }
1550 if (comparator == "<=" && data <= filter_value) {
1551 continue;
1552 }
1553
1554 std::swap(UUIDs_out.at(p), UUIDs_out.back());
1555 UUIDs_out.pop_back();
1556 } else {
1557 std::swap(UUIDs_out.at(p), UUIDs_out.back());
1558 UUIDs_out.pop_back();
1559 }
1560 }
1561
1562 return UUIDs_out;
1563}
1564
1565std::vector<uint> Context::filterPrimitivesByData(const std::vector<uint> &UUIDs, const std::string &primitive_data_label, double filter_value, const std::string &comparator) const {
1566
1567 if (comparator != "==" && comparator != ">" && comparator != "<" && comparator != ">=" && comparator != "<=") {
1568 helios_runtime_error("ERROR (Context::filterPrimitivesByData): Invalid comparator. Must be one of '==', '>', '<', '>=', or '<='.");
1569 }
1570
1571 std::vector<uint> UUIDs_out = UUIDs;
1572 for (std::size_t p = UUIDs.size(); p-- > 0;) {
1573 uint UUID = UUIDs_out.at(p);
1574 if (doesPrimitiveDataExist(UUID, primitive_data_label.c_str()) && getPrimitiveDataType(primitive_data_label.c_str()) == HELIOS_TYPE_DOUBLE) {
1575 double data;
1576 getPrimitiveData(UUID, primitive_data_label.c_str(), data);
1577 if (comparator == "==" && data == filter_value) {
1578 continue;
1579 }
1580 if (comparator == ">" && data > filter_value) {
1581 continue;
1582 }
1583 if (comparator == "<" && data < filter_value) {
1584 continue;
1585 }
1586 if (comparator == ">=" && data >= filter_value) {
1587 continue;
1588 }
1589 if (comparator == "<=" && data <= filter_value) {
1590 continue;
1591 }
1592
1593 std::swap(UUIDs_out.at(p), UUIDs_out.back());
1594 UUIDs_out.pop_back();
1595 } else {
1596 std::swap(UUIDs_out.at(p), UUIDs_out.back());
1597 UUIDs_out.pop_back();
1598 }
1599 }
1600
1601 return UUIDs_out;
1602}
1603
1604std::vector<uint> Context::filterPrimitivesByData(const std::vector<uint> &UUIDs, const std::string &primitive_data_label, int filter_value, const std::string &comparator) const {
1605
1606 if (comparator != "==" && comparator != ">" && comparator != "<" && comparator != ">=" && comparator != "<=") {
1607 helios_runtime_error("ERROR (Context::filterPrimitivesByData): Invalid comparator. Must be one of '==', '>', '<', '>=', or '<='.");
1608 }
1609
1610 std::vector<uint> UUIDs_out = UUIDs;
1611 for (std::size_t p = UUIDs.size(); p-- > 0;) {
1612 uint UUID = UUIDs_out.at(p);
1613 if (doesPrimitiveDataExist(UUID, primitive_data_label.c_str()) && getPrimitiveDataType(primitive_data_label.c_str()) == HELIOS_TYPE_INT) {
1614 int data;
1615 getPrimitiveData(UUID, primitive_data_label.c_str(), data);
1616 if (comparator == "==" && data == filter_value) {
1617 continue;
1618 }
1619 if (comparator == ">" && data > filter_value) {
1620 continue;
1621 }
1622 if (comparator == "<" && data < filter_value) {
1623 continue;
1624 }
1625 if (comparator == ">=" && data >= filter_value) {
1626 continue;
1627 }
1628 if (comparator == "<=" && data <= filter_value) {
1629 continue;
1630 }
1631
1632 std::swap(UUIDs_out.at(p), UUIDs_out.back());
1633 UUIDs_out.pop_back();
1634 } else {
1635 std::swap(UUIDs_out.at(p), UUIDs_out.back());
1636 UUIDs_out.pop_back();
1637 }
1638 }
1639
1640 return UUIDs_out;
1641}
1642
1643std::vector<uint> Context::filterPrimitivesByData(const std::vector<uint> &UUIDs, const std::string &primitive_data_label, uint filter_value, const std::string &comparator) const {
1644
1645 if (comparator != "==" && comparator != ">" && comparator != "<" && comparator != ">=" && comparator != "<=") {
1646 helios_runtime_error("ERROR (Context::filterPrimitivesByData): Invalid comparator. Must be one of '==', '>', '<', '>=', or '<='.");
1647 }
1648
1649 std::vector<uint> UUIDs_out = UUIDs;
1650 for (std::size_t p = UUIDs.size(); p-- > 0;) {
1651 uint UUID = UUIDs_out.at(p);
1652 if (doesPrimitiveDataExist(UUID, primitive_data_label.c_str()) && getPrimitiveDataType(primitive_data_label.c_str()) == HELIOS_TYPE_UINT) {
1653 uint data;
1654 getPrimitiveData(UUID, primitive_data_label.c_str(), data);
1655 if (comparator == "==" && data == filter_value) {
1656 continue;
1657 }
1658 if (comparator == ">" && data > filter_value) {
1659 continue;
1660 }
1661 if (comparator == "<" && data < filter_value) {
1662 continue;
1663 }
1664 if (comparator == ">=" && data >= filter_value) {
1665 continue;
1666 }
1667 if (comparator == "<=" && data <= filter_value) {
1668 continue;
1669 }
1670
1671 std::swap(UUIDs_out.at(p), UUIDs_out.back());
1672 UUIDs_out.pop_back();
1673 } else {
1674 std::swap(UUIDs_out.at(p), UUIDs_out.back());
1675 UUIDs_out.pop_back();
1676 }
1677 }
1678
1679 return UUIDs_out;
1680}
1681
1682std::vector<uint> Context::filterPrimitivesByData(const std::vector<uint> &UUIDs, const std::string &primitive_data_label, const std::string &filter_value) const {
1683
1684 std::vector<uint> UUIDs_out = UUIDs;
1685 for (std::size_t p = UUIDs.size(); p-- > 0;) {
1686 uint UUID = UUIDs_out.at(p);
1687 if (doesPrimitiveDataExist(UUID, primitive_data_label.c_str()) && getPrimitiveDataType(primitive_data_label.c_str()) == HELIOS_TYPE_STRING) {
1688 std::string data;
1689 getPrimitiveData(UUID, primitive_data_label.c_str(), data);
1690 if (data != filter_value) {
1691 std::swap(UUIDs_out.at(p), UUIDs_out.back());
1692 UUIDs_out.pop_back();
1693 }
1694 } else {
1695 std::swap(UUIDs_out.at(p), UUIDs_out.back());
1696 UUIDs_out.pop_back();
1697 }
1698 }
1699
1700 return UUIDs_out;
1701}
1702
1703//------ Object Data ------- //
1704
1705HeliosDataType Context::getObjectDataType(uint objID, const char *label) const {
1706#ifdef HELIOS_DEBUG
1707 if (objects.find(objID) == objects.end()) {
1708 helios_runtime_error("ERROR (Context::getObjectDataType): objID of " + std::to_string(objID) + " does not exist in the Context.");
1709 }
1710#endif
1711 return objects.at(objID)->getObjectDataType(label);
1712}
1713
1715 const auto it = object_data_type_registry.find(label);
1716 if (it != object_data_type_registry.end()) {
1717 return it->second;
1718 }
1719 helios_runtime_error("ERROR (Context::getObjectDataType): Object data " + std::string(label) + " does not exist.");
1720 return HELIOS_TYPE_UNKNOWN; // This line will never be reached, but is needed to avoid compiler warnings.
1721}
1722
1723uint Context::getObjectDataSize(uint objID, const char *label) const {
1724#ifdef HELIOS_DEBUG
1725 if (objects.find(objID) == objects.end()) {
1726 helios_runtime_error("ERROR (Context::getObjectDataSize): objID of " + std::to_string(objID) + " does not exist in the Context.");
1727 }
1728#endif
1729 return objects.at(objID)->getObjectDataSize(label);
1730}
1731
1732bool Context::doesObjectDataExist(uint objID, const char *label) const {
1733#ifdef HELIOS_DEBUG
1734 if (objects.find(objID) == objects.end()) {
1735 helios_runtime_error("ERROR (Context::doesObjectDataExist): objID of " + std::to_string(objID) + " does not exist in the Context.");
1736 }
1737#endif
1738 return objects.at(objID)->doesObjectDataExist(label);
1739}
1740
1741void Context::copyObjectData(uint source_objID, uint destination_objID) {
1742
1743#ifdef HELIOS_DEBUG
1744 if (objects.find(source_objID) == objects.end()) {
1745 helios_runtime_error("ERROR (Context::copyObjectData): Source object ID of " + std::to_string(source_objID) + " does not exist in the Context.");
1746 } else if (objects.find(destination_objID) == objects.end()) {
1747 helios_runtime_error("ERROR (Context::copyObjectData): Destination object ID of " + std::to_string(destination_objID) + " does not exist in the Context.");
1748 }
1749#endif
1750
1751 const auto &dest_labels = objects.at(destination_objID)->object_data_types;
1752 for (const auto &[label, type]: dest_labels) {
1753 decrementObjectDataLabelCounter(label);
1754 }
1755
1756 objects.at(destination_objID)->object_data_types = objects.at(source_objID)->object_data_types;
1757
1758 objects.at(destination_objID)->object_data_int = objects.at(source_objID)->object_data_int;
1759 objects.at(destination_objID)->object_data_uint = objects.at(source_objID)->object_data_uint;
1760 objects.at(destination_objID)->object_data_float = objects.at(source_objID)->object_data_float;
1761 objects.at(destination_objID)->object_data_double = objects.at(source_objID)->object_data_double;
1762 objects.at(destination_objID)->object_data_vec2 = objects.at(source_objID)->object_data_vec2;
1763 objects.at(destination_objID)->object_data_vec3 = objects.at(source_objID)->object_data_vec3;
1764 objects.at(destination_objID)->object_data_vec4 = objects.at(source_objID)->object_data_vec4;
1765 objects.at(destination_objID)->object_data_int2 = objects.at(source_objID)->object_data_int2;
1766 objects.at(destination_objID)->object_data_int3 = objects.at(source_objID)->object_data_int3;
1767 objects.at(destination_objID)->object_data_int4 = objects.at(source_objID)->object_data_int4;
1768 objects.at(destination_objID)->object_data_string = objects.at(source_objID)->object_data_string;
1769
1770 for (const auto &[lbl, type]: objects.at(destination_objID)->object_data_types) {
1771 incrementObjectDataLabelCounter(lbl);
1772 }
1773}
1774
1775void Context::duplicateObjectData(uint objID, const char *old_label, const char *new_label) {
1776
1777#ifdef HELIOS_DEBUG
1778 if (objects.find(objID) == objects.end()) {
1779 helios_runtime_error("ERROR (Context::duplicateObjectData): Object ID of " + std::to_string(objID) + " does not exist in the Context.");
1780 } else if (!doesObjectDataExist(objID, old_label)) {
1781 helios_runtime_error("ERROR (Context::duplicateObjectData): Object ID of " + std::to_string(objID) + " does not have data with label " + std::string(old_label) + ".");
1782 }
1783#endif
1784
1785 HeliosDataType type = getObjectDataType(old_label);
1786
1787 if (!objects.at(objID)->doesObjectDataExist(new_label)) {
1788 incrementObjectDataLabelCounter(new_label);
1789 }
1790 objects.at(objID)->object_data_types[new_label] = type;
1791 if (type == HELIOS_TYPE_INT) {
1792 objects.at(objID)->object_data_int[new_label] = objects.at(objID)->object_data_int.at(old_label);
1793 } else if (type == HELIOS_TYPE_UINT) {
1794 objects.at(objID)->object_data_uint[new_label] = objects.at(objID)->object_data_uint.at(old_label);
1795 } else if (type == HELIOS_TYPE_FLOAT) {
1796 objects.at(objID)->object_data_float[new_label] = objects.at(objID)->object_data_float.at(old_label);
1797 } else if (type == HELIOS_TYPE_DOUBLE) {
1798 objects.at(objID)->object_data_double[new_label] = objects.at(objID)->object_data_double.at(old_label);
1799 } else if (type == HELIOS_TYPE_VEC2) {
1800 objects.at(objID)->object_data_vec2[new_label] = objects.at(objID)->object_data_vec2.at(old_label);
1801 } else if (type == HELIOS_TYPE_VEC3) {
1802 objects.at(objID)->object_data_vec3[new_label] = objects.at(objID)->object_data_vec3.at(old_label);
1803 } else if (type == HELIOS_TYPE_VEC4) {
1804 objects.at(objID)->object_data_vec4[new_label] = objects.at(objID)->object_data_vec4.at(old_label);
1805 } else if (type == HELIOS_TYPE_INT2) {
1806 objects.at(objID)->object_data_int2[new_label] = objects.at(objID)->object_data_int2.at(old_label);
1807 } else if (type == HELIOS_TYPE_INT3) {
1808 objects.at(objID)->object_data_int3[new_label] = objects.at(objID)->object_data_int3.at(old_label);
1809 } else if (type == HELIOS_TYPE_INT4) {
1810 objects.at(objID)->object_data_int4[new_label] = objects.at(objID)->object_data_int4.at(old_label);
1811 } else if (type == HELIOS_TYPE_STRING) {
1812 objects.at(objID)->object_data_string[new_label] = objects.at(objID)->object_data_string.at(old_label);
1813 } else {
1814 assert(false);
1815 }
1816}
1817
1818
1819void Context::renameObjectData(uint objID, const char *old_label, const char *new_label) {
1820
1821#ifdef HELIOS_DEBUG
1822 if (objects.find(objID) == objects.end()) {
1823 helios_runtime_error("ERROR (Context::renameObjectData): Object ID of " + std::to_string(objID) + " does not exist in the Context.");
1824 } else if (!doesObjectDataExist(objID, old_label)) {
1825 helios_runtime_error("ERROR (Context::renameObjectData): Object ID of " + std::to_string(objID) + " does not have data with label " + std::string(old_label) + ".");
1826 }
1827#endif
1828
1829 duplicateObjectData(objID, old_label, new_label);
1830 clearObjectData(objID, old_label);
1831}
1832
1833void Context::clearObjectData(uint objID, const char *label) {
1834#ifdef HELIOS_DEBUG
1835 if (objects.find(objID) == objects.end()) {
1836 helios_runtime_error("ERROR (Context::clearObjectData): objID of " + std::to_string(objID) + " does not exist in the Context.");
1837 }
1838#endif
1839 // Handle value registry before clearing if caching is enabled
1840 std::string label_str = std::string(label);
1841 if (isObjectDataValueCachingEnabled(label_str) && objects.at(objID)->doesObjectDataExist(label)) {
1842 HeliosDataType data_type = objects.at(objID)->getObjectDataType(label);
1843 if (data_type == HELIOS_TYPE_STRING) {
1844 std::string cached_value;
1845 objects.at(objID)->getObjectData(label, cached_value);
1846 decrementObjectValueRegistry(label_str, cached_value);
1847 } else if (data_type == HELIOS_TYPE_INT) {
1848 int cached_value;
1849 objects.at(objID)->getObjectData(label, cached_value);
1850 decrementObjectValueRegistry(label_str, cached_value);
1851 } else if (data_type == HELIOS_TYPE_UINT) {
1852 uint cached_value;
1853 objects.at(objID)->getObjectData(label, cached_value);
1854 decrementObjectValueRegistry(label_str, cached_value);
1855 }
1856 }
1857
1858 if (objects.at(objID)->doesObjectDataExist(label)) {
1859 decrementObjectDataLabelCounter(label);
1860 }
1861 objects.at(objID)->clearObjectData(label);
1862}
1863
1864void Context::clearObjectData(const std::vector<uint> &objIDs, const char *label) {
1865 std::string label_str = std::string(label);
1866 for (uint objID: objIDs) {
1867#ifdef HELIOS_DEBUG
1868 if (objects.find(objID) == objects.end()) {
1869 helios_runtime_error("ERROR (Context::clearObjectData): objID of " + std::to_string(objID) + " does not exist in the Context.");
1870 }
1871#endif
1872 // Handle value registry before clearing if caching is enabled
1873 if (isObjectDataValueCachingEnabled(label_str) && objects.at(objID)->doesObjectDataExist(label)) {
1874 HeliosDataType data_type = objects.at(objID)->getObjectDataType(label);
1875 if (data_type == HELIOS_TYPE_STRING) {
1876 std::string cached_value;
1877 objects.at(objID)->getObjectData(label, cached_value);
1878 decrementObjectValueRegistry(label_str, cached_value);
1879 } else if (data_type == HELIOS_TYPE_INT) {
1880 int cached_value;
1881 objects.at(objID)->getObjectData(label, cached_value);
1882 decrementObjectValueRegistry(label_str, cached_value);
1883 } else if (data_type == HELIOS_TYPE_UINT) {
1884 uint cached_value;
1885 objects.at(objID)->getObjectData(label, cached_value);
1886 decrementObjectValueRegistry(label_str, cached_value);
1887 }
1888 }
1889
1890 if (objects.at(objID)->doesObjectDataExist(label)) {
1891 decrementObjectDataLabelCounter(label);
1892 }
1893 objects.at(objID)->clearObjectData(label);
1894 }
1895}
1896
1897std::vector<std::string> Context::listObjectData(uint ObjID) const {
1898 return getObjectPointer_private(ObjID)->listObjectData();
1899}
1900
1902
1903#ifdef HELIOS_DEBUG
1904 if (!doesObjectDataExist(label)) {
1905 helios_runtime_error("ERROR (CompoundObject::getObjectDataType): Object data " + std::string(label) + " does not exist for object " + std::to_string(OID));
1906 }
1907#endif
1908
1909 return object_data_types.at(label);
1910}
1911
1912uint CompoundObject::getObjectDataSize(const char *label) const {
1913
1914#ifdef HELIOS_DEBUG
1915 if (!doesObjectDataExist(label)) {
1916 helios_runtime_error("ERROR (CompoundObject::getObjectDataSize): Object data " + std::string(label) + " does not exist for object " + std::to_string(OID));
1917 }
1918#endif
1919
1920 HeliosDataType qtype = object_data_types.at(label);
1921
1922 if (qtype == HELIOS_TYPE_INT) {
1923 return object_data_int.at(label).size();
1924 } else if (qtype == HELIOS_TYPE_UINT) {
1925 return object_data_uint.at(label).size();
1926 } else if (qtype == HELIOS_TYPE_FLOAT) {
1927 return object_data_float.at(label).size();
1928 } else if (qtype == HELIOS_TYPE_DOUBLE) {
1929 return object_data_double.at(label).size();
1930 } else if (qtype == HELIOS_TYPE_VEC2) {
1931 return object_data_vec2.at(label).size();
1932 } else if (qtype == HELIOS_TYPE_VEC3) {
1933 return object_data_vec3.at(label).size();
1934 } else if (qtype == HELIOS_TYPE_VEC4) {
1935 return object_data_vec4.at(label).size();
1936 } else if (qtype == HELIOS_TYPE_INT2) {
1937 return object_data_int2.at(label).size();
1938 } else if (qtype == HELIOS_TYPE_INT3) {
1939 return object_data_int3.at(label).size();
1940 } else if (qtype == HELIOS_TYPE_INT4) {
1941 return object_data_int4.at(label).size();
1942 } else if (qtype == HELIOS_TYPE_STRING) {
1943 return object_data_string.at(label).size();
1944 } else {
1945 assert(false);
1946 }
1947
1948 return 0;
1949}
1950
1951void CompoundObject::clearObjectData(const char *label) {
1952
1953 if (!doesObjectDataExist(label)) {
1954 return;
1955 }
1956
1957 const HeliosDataType &qtype = object_data_types.at(label);
1958
1959 if (qtype == HELIOS_TYPE_INT) {
1960 object_data_int.erase(label);
1961 object_data_types.erase(label);
1962 } else if (qtype == HELIOS_TYPE_UINT) {
1963 object_data_uint.erase(label);
1964 object_data_types.erase(label);
1965 } else if (qtype == HELIOS_TYPE_FLOAT) {
1966 object_data_float.erase(label);
1967 object_data_types.erase(label);
1968 } else if (qtype == HELIOS_TYPE_DOUBLE) {
1969 object_data_double.erase(label);
1970 object_data_types.erase(label);
1971 } else if (qtype == HELIOS_TYPE_VEC2) {
1972 object_data_vec2.erase(label);
1973 object_data_types.erase(label);
1974 } else if (qtype == HELIOS_TYPE_VEC3) {
1975 object_data_vec3.erase(label);
1976 object_data_types.erase(label);
1977 } else if (qtype == HELIOS_TYPE_VEC4) {
1978 object_data_vec4.erase(label);
1979 object_data_types.erase(label);
1980 } else if (qtype == HELIOS_TYPE_INT2) {
1981 object_data_int2.erase(label);
1982 object_data_types.erase(label);
1983 } else if (qtype == HELIOS_TYPE_INT3) {
1984 object_data_int3.erase(label);
1985 object_data_types.erase(label);
1986 } else if (qtype == HELIOS_TYPE_INT4) {
1987 object_data_int4.erase(label);
1988 object_data_types.erase(label);
1989 } else if (qtype == HELIOS_TYPE_STRING) {
1990 object_data_string.erase(label);
1991 object_data_types.erase(label);
1992 } else {
1993 assert(false);
1994 }
1995}
1996
1997bool CompoundObject::doesObjectDataExist(const char *label) const {
1998
1999 if (object_data_types.find(std::string(label)) == object_data_types.end()) {
2000 return false;
2001 } else {
2002 return true;
2003 }
2004}
2005
2006std::vector<std::string> CompoundObject::listObjectData() const {
2007
2008 std::vector<std::string> labels;
2009 labels.reserve(object_data_types.size());
2010
2011 for (const auto &[label, type]: object_data_types) {
2012 labels.push_back(label);
2013 }
2014
2015 return labels;
2016}
2017
2018std::vector<uint> Context::filterObjectsByData(const std::vector<uint> &objIDs, const std::string &object_data_label, float filter_value, const std::string &comparator) const {
2019
2020 if (comparator != "==" && comparator != ">" && comparator != "<" && comparator != ">=" && comparator != "<=") {
2021 helios_runtime_error("ERROR (Context::filterObjectsByData): Invalid comparator. Must be one of '==', '>', '<', '>=', or '<='.");
2022 }
2023
2024 std::vector<uint> objIDs_out = objIDs;
2025 for (std::size_t p = objIDs.size(); p-- > 0;) {
2026 uint objID = objIDs_out.at(p);
2027 if (doesObjectDataExist(objID, object_data_label.c_str()) && getObjectDataType(object_data_label.c_str()) == HELIOS_TYPE_FLOAT) {
2028 float data;
2029 getObjectData(objID, object_data_label.c_str(), data);
2030 if (comparator == "==" && data == filter_value) {
2031 continue;
2032 } else if (comparator == ">" && data > filter_value) {
2033 continue;
2034 } else if (comparator == "<" && data < filter_value) {
2035 continue;
2036 } else if (comparator == ">=" && data >= filter_value) {
2037 continue;
2038 } else if (comparator == "<=" && data <= filter_value) {
2039 continue;
2040 }
2041
2042 std::swap(objIDs_out.at(p), objIDs_out.back());
2043 objIDs_out.pop_back();
2044 } else {
2045 std::swap(objIDs_out.at(p), objIDs_out.back());
2046 objIDs_out.pop_back();
2047 }
2048 }
2049
2050 return objIDs_out;
2051}
2052
2053std::vector<uint> Context::filterObjectsByData(const std::vector<uint> &objIDs, const std::string &object_data_label, double filter_value, const std::string &comparator) const {
2054
2055 if (comparator != "==" && comparator != ">" && comparator != "<" && comparator != ">=" && comparator != "<=") {
2056 helios_runtime_error("ERROR (Context::filterObjectsByData): Invalid comparator. Must be one of '==', '>', '<', '>=', or '<='.");
2057 }
2058
2059 std::vector<uint> objIDs_out = objIDs;
2060 for (std::size_t p = objIDs.size(); p-- > 0;) {
2061 uint objID = objIDs_out.at(p);
2062 if (doesObjectDataExist(objID, object_data_label.c_str()) && getObjectDataType(object_data_label.c_str()) == HELIOS_TYPE_DOUBLE) {
2063 double data;
2064 getObjectData(objID, object_data_label.c_str(), data);
2065 if (comparator == "==" && data == filter_value) {
2066 continue;
2067 } else if (comparator == ">" && data > filter_value) {
2068 continue;
2069 } else if (comparator == "<" && data < filter_value) {
2070 continue;
2071 } else if (comparator == ">=" && data >= filter_value) {
2072 continue;
2073 } else if (comparator == "<=" && data <= filter_value) {
2074 continue;
2075 }
2076
2077 std::swap(objIDs_out.at(p), objIDs_out.back());
2078 objIDs_out.pop_back();
2079 } else {
2080 std::swap(objIDs_out.at(p), objIDs_out.back());
2081 objIDs_out.pop_back();
2082 }
2083 }
2084
2085 return objIDs_out;
2086}
2087
2088std::vector<uint> Context::filterObjectsByData(const std::vector<uint> &objIDs, const std::string &object_data_label, int filter_value, const std::string &comparator) const {
2089
2090 if (comparator != "==" && comparator != ">" && comparator != "<" && comparator != ">=" && comparator != "<=") {
2091 helios_runtime_error("ERROR (Context::filterObjectsByData): Invalid comparator. Must be one of '==', '>', '<', '>=', or '<='.");
2092 }
2093
2094 std::vector<uint> objIDs_out = objIDs;
2095 for (std::size_t p = objIDs.size(); p-- > 0;) {
2096 uint objID = objIDs_out.at(p);
2097 if (doesObjectDataExist(objID, object_data_label.c_str()) && getObjectDataType(object_data_label.c_str()) == HELIOS_TYPE_INT) {
2098 int data;
2099 getObjectData(objID, object_data_label.c_str(), data);
2100 if (comparator == "==" && data == filter_value) {
2101 continue;
2102 } else if (comparator == ">" && data > filter_value) {
2103 continue;
2104 } else if (comparator == "<" && data < filter_value) {
2105 continue;
2106 } else if (comparator == ">=" && data >= filter_value) {
2107 continue;
2108 } else if (comparator == "<=" && data <= filter_value) {
2109 continue;
2110 }
2111
2112 std::swap(objIDs_out.at(p), objIDs_out.back());
2113 objIDs_out.pop_back();
2114 } else {
2115 std::swap(objIDs_out.at(p), objIDs_out.back());
2116 objIDs_out.pop_back();
2117 }
2118 }
2119
2120 return objIDs_out;
2121}
2122
2123std::vector<uint> Context::filterObjectsByData(const std::vector<uint> &objIDs, const std::string &object_data_label, uint filter_value, const std::string &comparator) const {
2124
2125 if (comparator != "==" && comparator != ">" && comparator != "<" && comparator != ">=" && comparator != "<=") {
2126 helios_runtime_error("ERROR (Context::filterObjectsByData): Invalid comparator. Must be one of '==', '>', '<', '>=', or '<='.");
2127 }
2128
2129 std::vector<uint> objIDs_out = objIDs;
2130 for (std::size_t p = objIDs.size(); p-- > 0;) {
2131 uint objID = objIDs_out.at(p);
2132 if (doesObjectDataExist(objID, object_data_label.c_str()) && getObjectDataType(object_data_label.c_str()) == HELIOS_TYPE_UINT) {
2133 uint data;
2134 getObjectData(objID, object_data_label.c_str(), data);
2135 if (comparator == "==" && data == filter_value) {
2136 continue;
2137 } else if (comparator == ">" && data > filter_value) {
2138 continue;
2139 } else if (comparator == "<" && data < filter_value) {
2140 continue;
2141 } else if (comparator == ">=" && data >= filter_value) {
2142 continue;
2143 } else if (comparator == "<=" && data <= filter_value) {
2144 continue;
2145 }
2146
2147 std::swap(objIDs_out.at(p), objIDs_out.back());
2148 objIDs_out.pop_back();
2149 } else {
2150 std::swap(objIDs_out.at(p), objIDs_out.back());
2151 objIDs_out.pop_back();
2152 }
2153 }
2154
2155 return objIDs_out;
2156}
2157
2158std::vector<uint> Context::filterObjectsByData(const std::vector<uint> &objIDs, const std::string &object_data_label, const std::string &filter_value) const {
2159
2160 std::vector<uint> objIDs_out = objIDs;
2161 for (std::size_t p = objIDs.size(); p-- > 0;) {
2162 uint objID = objIDs_out.at(p);
2163 if (doesObjectDataExist(objID, object_data_label.c_str()) && getObjectDataType(object_data_label.c_str()) == HELIOS_TYPE_STRING) {
2164 std::string data;
2165 getObjectData(objID, object_data_label.c_str(), data);
2166 if (data != filter_value) {
2167 std::swap(objIDs_out.at(p), objIDs_out.back());
2168 objIDs_out.pop_back();
2169 }
2170 } else {
2171 std::swap(objIDs_out.at(p), objIDs_out.back());
2172 objIDs_out.pop_back();
2173 }
2174 }
2175
2176 return objIDs_out;
2177}
2178
2179// -------- Global Data ---------- //
2180
2181void Context::renameGlobalData(const char *old_label, const char *new_label) {
2182
2183 if (!doesGlobalDataExist(old_label)) {
2184 helios_runtime_error("ERROR (Context::duplicateGlobalData): Global data " + std::string(old_label) + " does not exist in the Context.");
2185 }
2186
2187 duplicateGlobalData(old_label, new_label);
2188 clearGlobalData(old_label);
2189}
2190
2191void Context::duplicateGlobalData(const char *old_label, const char *new_label) {
2192
2193 if (!doesGlobalDataExist(old_label)) {
2194 helios_runtime_error("ERROR (Context::duplicateGlobalData): Global data " + std::string(old_label) + " does not exist in the Context.");
2195 }
2196
2197 HeliosDataType type = getGlobalDataType(old_label);
2198
2199 if (type == HELIOS_TYPE_INT) {
2200 std::vector<int> gdata;
2201 getGlobalData(old_label, gdata);
2202 setGlobalData(new_label, gdata);
2203 } else if (type == HELIOS_TYPE_UINT) {
2204 std::vector<uint> gdata;
2205 getGlobalData(old_label, gdata);
2206 setGlobalData(new_label, gdata);
2207 } else if (type == HELIOS_TYPE_FLOAT) {
2208 std::vector<float> gdata;
2209 getGlobalData(old_label, gdata);
2210 setGlobalData(new_label, gdata);
2211 } else if (type == HELIOS_TYPE_DOUBLE) {
2212 std::vector<double> gdata;
2213 getGlobalData(old_label, gdata);
2214 setGlobalData(new_label, gdata);
2215 } else if (type == HELIOS_TYPE_VEC2) {
2216 std::vector<vec2> gdata;
2217 getGlobalData(old_label, gdata);
2218 setGlobalData(new_label, gdata);
2219 } else if (type == HELIOS_TYPE_VEC3) {
2220 std::vector<vec3> gdata;
2221 getGlobalData(old_label, gdata);
2222 setGlobalData(new_label, gdata);
2223 } else if (type == HELIOS_TYPE_VEC4) {
2224 std::vector<vec4> gdata;
2225 getGlobalData(old_label, gdata);
2226 setGlobalData(new_label, gdata);
2227 } else if (type == HELIOS_TYPE_INT2) {
2228 std::vector<int2> gdata;
2229 getGlobalData(old_label, gdata);
2230 setGlobalData(new_label, gdata);
2231 } else if (type == HELIOS_TYPE_INT3) {
2232 std::vector<int3> gdata;
2233 getGlobalData(old_label, gdata);
2234 setGlobalData(new_label, gdata);
2235 } else if (type == HELIOS_TYPE_INT4) {
2236 std::vector<int4> gdata;
2237 getGlobalData(old_label, gdata);
2238 setGlobalData(new_label, gdata);
2239 } else if (type == HELIOS_TYPE_STRING) {
2240 std::vector<std::string> gdata;
2241 getGlobalData(old_label, gdata);
2242 setGlobalData(new_label, gdata);
2243 } else {
2244 assert(false);
2245 }
2246}
2247
2248void Context::clearGlobalData(const char *label) {
2249
2250 if (doesGlobalDataExist(label)) {
2251 globaldata.erase(label);
2252 }
2253}
2254
2256
2257 if (!doesGlobalDataExist(label)) {
2258 helios_runtime_error("ERROR (Context::getGlobalDataType): Global data " + std::string(label) + " does not exist in the Context.");
2259 }
2260
2261 return globaldata.at(label).type;
2262}
2263
2264size_t Context::getGlobalDataSize(const char *label) const {
2265
2266 if (!doesGlobalDataExist(label)) {
2267 helios_runtime_error("ERROR (Context::getGlobalDataSize): Global data " + std::string(label) + " does not exist in the Context.");
2268 }
2269
2270 return globaldata.at(label).size;
2271}
2272
2273uint64_t Context::getGlobalDataVersion(const char *label) const {
2274
2275 if (!doesGlobalDataExist(label)) {
2276 return 0; // Return 0 for non-existent data (consistent with version = 0 initialization)
2277 }
2278
2279 return globaldata.at(label).version;
2280}
2281
2282std::vector<std::string> Context::listGlobalData() const {
2283
2284 std::vector<std::string> labels;
2285 labels.reserve(globaldata.size());
2286 for (const auto &[label, data]: globaldata) {
2287 labels.push_back(label);
2288 }
2289
2290 return labels;
2291}
2292
2293std::vector<std::string> Context::listAllPrimitiveDataLabels() const {
2294 std::vector<std::string> labels;
2295 labels.reserve(primitive_data_label_counts.size());
2296 for (const auto &[label, count]: primitive_data_label_counts) {
2297 if (count > 0) {
2298 labels.push_back(label);
2299 }
2300 }
2301 return labels;
2302}
2303
2304
2305std::vector<std::string> Context::listAllObjectDataLabels() const {
2306 std::vector<std::string> labels;
2307 labels.reserve(object_data_label_counts.size());
2308 for (const auto &[label, count]: object_data_label_counts) {
2309 if (count > 0) {
2310 labels.push_back(label);
2311 }
2312 }
2313 return labels;
2314}
2315
2316bool Context::doesGlobalDataExist(const char *label) const {
2317 return globaldata.find(std::string(label)) != globaldata.end();
2318}
2319
2320void Context::incrementGlobalData(const char *label, int increment) {
2321
2322 if (!doesGlobalDataExist(label)) {
2323 helios_runtime_error("ERROR (Context::incrementGlobalData): Global data " + std::string(label) + " does not exist in the Context.");
2324 }
2325
2326 uint size = getGlobalDataSize(label);
2327
2328 if (globaldata.at(label).type == HELIOS_TYPE_INT) {
2329 for (uint i = 0; i < size; i++) {
2330 globaldata.at(label).global_data_int.at(i) += increment;
2331 }
2332 } else {
2333 std::cerr << "WARNING (Context::incrementGlobalData): Attempted to increment global data for type int, but data '" << label << "' does not have type int." << std::endl;
2334 }
2335}
2336
2337void Context::incrementGlobalData(const char *label, uint increment) {
2338
2339 if (!doesGlobalDataExist(label)) {
2340 helios_runtime_error("ERROR (Context::incrementGlobalData): Global data " + std::string(label) + " does not exist in the Context.");
2341 }
2342
2343 uint size = getGlobalDataSize(label);
2344
2345 if (globaldata.at(label).type == HELIOS_TYPE_UINT) {
2346 for (uint i = 0; i < size; i++) {
2347 globaldata.at(label).global_data_uint.at(i) += increment;
2348 }
2349 } else {
2350 std::cerr << "WARNING (Context::incrementGlobalData): Attempted to increment global data for type uint, but data '" << label << "' does not have type uint." << std::endl;
2351 }
2352}
2353
2354void Context::incrementGlobalData(const char *label, float increment) {
2355
2356 if (!doesGlobalDataExist(label)) {
2357 helios_runtime_error("ERROR (Context::incrementGlobalData): Global data " + std::string(label) + " does not exist in the Context.");
2358 }
2359
2360 uint size = getGlobalDataSize(label);
2361
2362 if (globaldata.at(label).type == HELIOS_TYPE_FLOAT) {
2363 for (uint i = 0; i < size; i++) {
2364 globaldata.at(label).global_data_float.at(i) += increment;
2365 }
2366 } else {
2367 std::cerr << "WARNING (Context::incrementGlobalData): Attempted to increment global data for type float, but data '" << label << "' does not have type float." << std::endl;
2368 }
2369}
2370
2371void Context::incrementGlobalData(const char *label, double increment) {
2372
2373 if (!doesGlobalDataExist(label)) {
2374 helios_runtime_error("ERROR (Context::incrementGlobalData): Global data " + std::string(label) + " does not exist in the Context.");
2375 }
2376
2377 uint size = getGlobalDataSize(label);
2378
2379 if (globaldata.at(label).type == HELIOS_TYPE_DOUBLE) {
2380 for (uint i = 0; i < size; i++) {
2381 globaldata.at(label).global_data_double.at(i) += increment;
2382 }
2383 } else {
2384 std::cerr << "WARNING (Context::incrementGlobalData): Attempted to increment global data for type double, but data '" << label << "' does not have type double." << std::endl;
2385 }
2386}
2387
2388std::string Context::dataTypeToString(HeliosDataType type) const {
2389 switch (type) {
2390 case HELIOS_TYPE_INT:
2391 return "int";
2392 case HELIOS_TYPE_UINT:
2393 return "uint";
2394 case HELIOS_TYPE_FLOAT:
2395 return "float";
2396 case HELIOS_TYPE_DOUBLE:
2397 return "double";
2398 case HELIOS_TYPE_VEC2:
2399 return "vec2";
2400 case HELIOS_TYPE_VEC3:
2401 return "vec3";
2402 case HELIOS_TYPE_VEC4:
2403 return "vec4";
2404 case HELIOS_TYPE_INT2:
2405 return "int2";
2406 case HELIOS_TYPE_INT3:
2407 return "int3";
2408 case HELIOS_TYPE_INT4:
2409 return "int4";
2410 case HELIOS_TYPE_STRING:
2411 return "string";
2412 case HELIOS_TYPE_BOOL:
2413 return "bool";
2415 return "unknown";
2416 default:
2417 return "undefined";
2418 }
2419}
2420
2421bool Context::isTypeCastingSupported(HeliosDataType from_type, HeliosDataType to_type) const {
2422 // Support casting between numeric types only
2423 const std::set<HeliosDataType> numeric_types = {HELIOS_TYPE_INT, HELIOS_TYPE_UINT, HELIOS_TYPE_FLOAT, HELIOS_TYPE_DOUBLE};
2424
2425 return (numeric_types.count(from_type) > 0 && numeric_types.count(to_type) > 0);
2426}