2481 friend class Primitive;
2491 [[nodiscard]] Primitive *getPrimitivePointer_private(
uint UUID)
const;
2498 [[nodiscard]] Patch *getPatchPointer_private(
uint UUID)
const;
2506 [[nodiscard]] Triangle *getTrianglePointer_private(
uint UUID)
const;
2513 [[nodiscard]] Voxel *getVoxelPointer_private(
uint UUID)
const;
2527 [[nodiscard]]
Tile *getTileObjectPointer_private(
uint ObjID)
const;
2534 [[nodiscard]]
Sphere *getSphereObjectPointer_private(
uint ObjID)
const;
2541 [[nodiscard]]
Tube *getTubeObjectPointer_private(
uint ObjID)
const;
2548 [[nodiscard]]
Box *getBoxObjectPointer_private(
uint ObjID)
const;
2555 [[nodiscard]]
Disk *getDiskObjectPointer_private(
uint ObjID)
const;
2562 [[nodiscard]]
Polymesh *getPolymeshObjectPointer_private(
uint ObjID)
const;
2569 [[nodiscard]]
Cone *getConeObjectPointer_private(
uint ObjID)
const;
2572 void invalidateAllUUIDsCache()
const {
2573 all_uuids_cache_valid =
false;
2580 std::unordered_map<uint, Primitive *> primitives;
2583 mutable std::vector<uint> cached_all_uuids;
2585 mutable bool all_uuids_cache_valid =
false;
2591 std::vector<uint> dirty_deleted_primitives;
2594 std::unordered_map<uint, CompoundObject *> objects;
2597 std::map<std::string, std::vector<float>> timeseries_data;
2601 std::map<std::string, std::vector<double>> timeseries_datevalue;
2605 std::map<std::string, Texture> textures;
2607 void addTexture(
const char *texture_file);
2610 bool doesTextureFileExist(
const char *texture_file)
const;
2612 bool validateTextureFileExtenstion(
const char *texture_file)
const;
2617 static constexpr const char *DEFAULT_MATERIAL_LABEL =
"__default__";
2620 std::map<uint, Material> materials;
2623 std::map<std::string, uint> material_label_to_id;
2626 uint currentMaterialID;
2636 uint addMaterial_internal(
const std::string &label,
const RGBAcolor &color,
const std::string &texture =
"");
2639 std::string generateMaterialLabel(
const RGBAcolor &color,
const std::string &texture,
bool texture_override)
const;
2642 bool isMaterialShared(
uint materialID)
const;
2645 uint copyMaterialForPrimitive(
uint primitiveUUID);
2649 std::map<std::string, GlobalData> globaldata;
2651 std::unordered_map<std::string, size_t> primitive_data_label_counts;
2652 std::unordered_map<std::string, size_t> object_data_label_counts;
2657 std::unordered_map<std::string, HeliosDataType> primitive_data_type_registry;
2660 std::unordered_map<std::string, HeliosDataType> object_data_type_registry;
2665 std::unordered_map<std::string, std::unordered_map<std::string, size_t>> primitive_string_value_registry;
2666 std::unordered_map<std::string, std::unordered_map<int, size_t>> primitive_int_value_registry;
2667 std::unordered_map<std::string, std::unordered_map<uint, size_t>> primitive_uint_value_registry;
2670 std::unordered_map<std::string, std::unordered_map<std::string, size_t>> object_string_value_registry;
2671 std::unordered_map<std::string, std::unordered_map<int, size_t>> object_int_value_registry;
2672 std::unordered_map<std::string, std::unordered_map<uint, size_t>> object_uint_value_registry;
2675 std::unordered_set<std::string> cached_primitive_data_labels;
2676 std::unordered_set<std::string> cached_object_data_labels;
2682 void incrementPrimitiveDataLabelCounter(
const std::string &primitive_data_label);
2688 void decrementPrimitiveDataLabelCounter(
const std::string &primitive_data_label);
2695 void incrementObjectDataLabelCounter(
const std::string &object_data_label);
2701 void decrementObjectDataLabelCounter(
const std::string &object_data_label);
2727 std::minstd_rand0 generator;
2730 std::uniform_real_distribution<float> unif_distribution;
2733 std::normal_distribution<float> norm_distribution;
2737 std::vector<std::string> XMLfiles;
2739 struct OBJmaterial {
2742 std::string texture;
2744 bool textureHasTransparency =
false;
2745 bool textureColorIsOverridden =
false;
2747 OBJmaterial(
const RGBcolor &a_color, std::string a_texture,
uint a_materialID) : color{a_color}, texture{std::move(a_texture)}, materialID{a_materialID} {};
2750 std::map<std::string, OBJmaterial> loadMTL(
const std::string &filebase,
const std::string &material_file,
const RGBcolor &default_color);
2752 void loadMaterialData(pugi::xml_node mat_node,
const std::string &material_label);
2754 void loadPData(pugi::xml_node p,
uint UUID);
2756 void loadOData(pugi::xml_node p,
uint ID);
2758 void loadOsubPData(pugi::xml_node p,
uint ID);
2760 void writeDataToXMLstream(
const char *data_group,
const std::vector<std::string> &data_labels,
void *ptr, std::ofstream &outfile)
const;
2767 uint currentObjectID;
2776 static void out_of_memory_handler();
2782 static void install_out_of_memory_handler();
2803 static int selfTest(
int argc,
char **argv);
3055 void rotatePrimitive(
const std::vector<uint> &UUIDs,
float rotation_rad,
const char *axis);
3071 void rotatePrimitive(
const std::vector<uint> &UUIDs,
float rotation_rad,
const vec3 &axis);
3177 std::vector<uint>
copyPrimitive(
const std::vector<uint> &UUIDs);
3270 [[nodiscard]]
size_t getPrimitiveCount(
bool include_hidden_primitives =
true)
const;
3277 [[nodiscard]]
size_t getTriangleCount(
bool include_hidden_primitives =
true)
const;
3284 [[nodiscard]]
size_t getPatchCount(
bool include_hidden_primitives =
true)
const;
3287 [[nodiscard]] std::vector<uint>
getAllUUIDs()
const;
3294 [[nodiscard]] std::vector<uint>
getDirtyUUIDs(
bool include_deleted_UUIDs =
false)
const;
3349 void cleanDeletedUUIDs(std::vector<std::vector<std::vector<uint>>> &UUIDs)
const;
3360 template<
typename T>
3363 if (primitives.find(UUID) == primitives.end()) {
3364 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3368 std::string label_str = std::string(label);
3369 bool had_cached_value =
false;
3372 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
3374 T old_cached_value{};
3375 primitives.at(UUID)->getPrimitiveData(label, old_cached_value);
3377 had_cached_value =
true;
3379 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3381 std::string old_cached_value;
3382 primitives.at(UUID)->getPrimitiveData(label, old_cached_value);
3384 had_cached_value =
true;
3388 if (!primitives.at(UUID)->doesPrimitiveDataExist(label)) {
3389 incrementPrimitiveDataLabelCounter(label);
3394 if constexpr (std::is_same_v<T, int>) {
3396 }
else if constexpr (std::is_same_v<T, uint>) {
3398 }
else if constexpr (std::is_same_v<T, float>) {
3400 }
else if constexpr (std::is_same_v<T, double>) {
3402 }
else if constexpr (std::is_same_v<T, vec2>) {
3404 }
else if constexpr (std::is_same_v<T, vec3>) {
3406 }
else if constexpr (std::is_same_v<T, vec4>) {
3408 }
else if constexpr (std::is_same_v<T, int2>) {
3410 }
else if constexpr (std::is_same_v<T, int3>) {
3412 }
else if constexpr (std::is_same_v<T, int4>) {
3414 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3417 HeliosDataType target_type = registerOrValidatePrimitiveDataType<T>(label, data_type);
3420 if (target_type != data_type && isTypeCastingSupported(data_type, target_type)) {
3421 storeDataWithTypeCasting(UUID, label, data, target_type);
3423 primitives.at(UUID)->setPrimitiveData(label, data);
3428 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
3430 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3435 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
3437 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3450 template<
typename T>
3453 if (primitives.find(UUID) == primitives.end()) {
3454 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3457 if (!primitives.at(UUID)->doesPrimitiveDataExist(label)) {
3458 incrementPrimitiveDataLabelCounter(label);
3463 if constexpr (std::is_same_v<T, int>) {
3465 }
else if constexpr (std::is_same_v<T, uint>) {
3467 }
else if constexpr (std::is_same_v<T, float>) {
3469 }
else if constexpr (std::is_same_v<T, double>) {
3471 }
else if constexpr (std::is_same_v<T, vec2>) {
3473 }
else if constexpr (std::is_same_v<T, vec3>) {
3475 }
else if constexpr (std::is_same_v<T, vec4>) {
3477 }
else if constexpr (std::is_same_v<T, int2>) {
3479 }
else if constexpr (std::is_same_v<T, int3>) {
3481 }
else if constexpr (std::is_same_v<T, int4>) {
3483 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3486 registerOrValidatePrimitiveDataType<T>(label, data_type);
3488 primitives.at(UUID)->setPrimitiveData(label, data);
3499 template<
typename T>
3500 void setPrimitiveData(
const std::vector<uint> &UUIDs,
const char *label,
const std::vector<T> &data) {
3502 if (UUIDs.size() != data.size()) {
3503 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUIDs and data vectors must be the same size.");
3509 if (!UUIDs.empty()) {
3511 if constexpr (std::is_same_v<T, int>) {
3513 }
else if constexpr (std::is_same_v<T, uint>) {
3515 }
else if constexpr (std::is_same_v<T, float>) {
3517 }
else if constexpr (std::is_same_v<T, double>) {
3519 }
else if constexpr (std::is_same_v<T, vec2>) {
3521 }
else if constexpr (std::is_same_v<T, vec3>) {
3523 }
else if constexpr (std::is_same_v<T, vec4>) {
3525 }
else if constexpr (std::is_same_v<T, int2>) {
3527 }
else if constexpr (std::is_same_v<T, int3>) {
3529 }
else if constexpr (std::is_same_v<T, int4>) {
3531 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3534 target_type = registerOrValidatePrimitiveDataType<T>(label, data_type);
3537 for (
uint UUID: UUIDs) {
3539 if (primitives.find(UUID) == primitives.end()) {
3540 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3543 if (!primitives.at(UUID)->doesPrimitiveDataExist(label)) {
3544 incrementPrimitiveDataLabelCounter(label);
3549#pragma omp parallel for
3551 for (
int i = 0; i < (int) UUIDs.size(); ++i) {
3552 primitives.at(UUIDs[i])->setPrimitiveData(label, data[i]);
3563 template<
typename T>
3567 if (!UUIDs.empty()) {
3569 if constexpr (std::is_same_v<T, int>) {
3571 }
else if constexpr (std::is_same_v<T, uint>) {
3573 }
else if constexpr (std::is_same_v<T, float>) {
3575 }
else if constexpr (std::is_same_v<T, double>) {
3577 }
else if constexpr (std::is_same_v<T, vec2>) {
3579 }
else if constexpr (std::is_same_v<T, vec3>) {
3581 }
else if constexpr (std::is_same_v<T, vec4>) {
3583 }
else if constexpr (std::is_same_v<T, int2>) {
3585 }
else if constexpr (std::is_same_v<T, int3>) {
3587 }
else if constexpr (std::is_same_v<T, int4>) {
3589 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3592 registerOrValidatePrimitiveDataType<T>(label, data_type);
3595 for (
uint UUID: UUIDs) {
3597 if (primitives.find(UUID) == primitives.end()) {
3598 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3601 if (!primitives.at(UUID)->doesPrimitiveDataExist(label)) {
3602 incrementPrimitiveDataLabelCounter(label);
3607#pragma omp parallel for
3609 for (
int i = 0; i < (int) UUIDs.size(); ++i) {
3610 primitives.at(UUIDs[i])->setPrimitiveData(label, data);
3621 template<
typename T>
3624 if (primitives.find(UUID) == primitives.end()) {
3625 helios_runtime_error(
"ERROR (Context::getPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3628 primitives.at(UUID)->getPrimitiveData(label, data);
3639 template<
typename T>
3642 if (primitives.find(UUID) == primitives.end()) {
3643 helios_runtime_error(
"ERROR (Context::getPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3646 primitives.at(UUID)->getPrimitiveData(label, data);
3826 void hideObject(
const std::vector<uint> &ObjIDs);
3838 void showObject(
const std::vector<uint> &ObjIDs);
4191 void addMaterial(
const std::string &material_label);
4204 [[nodiscard]] std::vector<std::string>
listMaterials()
const;
4218 [[nodiscard]] std::string
getMaterialTexture(
const std::string &material_label)
const;
4241 void setMaterialTexture(
const std::string &material_label,
const std::string &texture_file);
4338 template<
typename T>
4339 void setMaterialData(
const std::string &material_label,
const char *data_label,
const T &data) {
4341 materials[matID].setMaterialData(data_label, data);
4352 template<
typename T>
4353 void setMaterialData(
const std::string &material_label,
const char *data_label,
const std::vector<T> &data) {
4355 materials[matID].setMaterialData(data_label, data);
4365 template<
typename T>
4366 void getMaterialData(
const std::string &material_label,
const char *data_label, T &data)
const {
4368 materials.at(matID).getMaterialData(data_label, data);
4378 template<
typename T>
4379 void getMaterialData(
const std::string &material_label,
const char *data_label, std::vector<T> &data)
const {
4381 materials.at(matID).getMaterialData(data_label, data);
4390 [[nodiscard]]
bool doesMaterialDataExist(
const std::string &material_label,
const char *data_label)
const;
4405 void clearMaterialData(
const std::string &material_label,
const char *data_label);
4418 template<
typename T>
4420 Primitive *prim = getPrimitivePointer_private(UUID);
4421 uint materialID = prim->materialID;
4424 if (materials.find(materialID) != materials.end() && materials.at(materialID).doesMaterialDataExist(data_label)) {
4425 materials.at(materialID).getMaterialData(data_label, data);
4428 else if (prim->doesPrimitiveDataExist(data_label)) {
4429 prim->getPrimitiveData(data_label, data);
4433 helios_runtime_error(
"ERROR (Context::getDataWithMaterialFallback): Data " + std::string(data_label) +
" does not exist for primitive " + std::to_string(UUID) +
" (neither in its material nor as primitive data).");
4473 template<
typename T>
4476 if (objects.find(objID) == objects.end()) {
4477 helios_runtime_error(
"ERROR (Context::setObjectData): Object ID of " + std::to_string(objID) +
" does not exist in the Context.");
4480 static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint> || std::is_same_v<T, float> || std::is_same_v<T, double> || std::is_same_v<T, vec2> || std::is_same_v<T, vec3> || std::is_same_v<T, vec4> || std::is_same_v<T, int2> ||
4481 std::is_same_v<T, int3> || std::is_same_v<T, int4> || std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>,
4482 "Context::setObjectData() was called with an unsupported type.");
4486 if constexpr (std::is_same_v<T, int>) {
4488 }
else if constexpr (std::is_same_v<T, uint>) {
4490 }
else if constexpr (std::is_same_v<T, float>) {
4492 }
else if constexpr (std::is_same_v<T, double>) {
4494 }
else if constexpr (std::is_same_v<T, vec2>) {
4496 }
else if constexpr (std::is_same_v<T, vec3>) {
4498 }
else if constexpr (std::is_same_v<T, vec4>) {
4500 }
else if constexpr (std::is_same_v<T, int2>) {
4502 }
else if constexpr (std::is_same_v<T, int3>) {
4504 }
else if constexpr (std::is_same_v<T, int4>) {
4506 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4509 registerOrValidateObjectDataType<T>(label, data_type);
4512 std::string label_str = std::string(label);
4513 bool had_cached_value =
false;
4516 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4518 T old_cached_value{};
4519 objects.at(objID)->getObjectData(label, old_cached_value);
4521 had_cached_value =
true;
4523 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4525 std::string old_cached_value;
4526 objects.at(objID)->getObjectData(label, old_cached_value);
4528 had_cached_value =
true;
4532 if (!objects.at(objID)->doesObjectDataExist(label)) {
4533 incrementObjectDataLabelCounter(label);
4535 objects.at(objID)->setObjectData(label, data);
4539 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4541 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4546 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4548 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4561 template<
typename T>
4562 void setObjectData(
const std::vector<uint> &objIDs,
const char *label,
const T &data) {
4563 static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint> || std::is_same_v<T, float> || std::is_same_v<T, double> || std::is_same_v<T, vec2> || std::is_same_v<T, vec3> || std::is_same_v<T, vec4> || std::is_same_v<T, int2> ||
4564 std::is_same_v<T, int3> || std::is_same_v<T, int4> || std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>,
4565 "Context::setObjectData() was called with an unsupported type.");
4568 if (!objIDs.empty()) {
4570 if constexpr (std::is_same_v<T, int>) {
4572 }
else if constexpr (std::is_same_v<T, uint>) {
4574 }
else if constexpr (std::is_same_v<T, float>) {
4576 }
else if constexpr (std::is_same_v<T, double>) {
4578 }
else if constexpr (std::is_same_v<T, vec2>) {
4580 }
else if constexpr (std::is_same_v<T, vec3>) {
4582 }
else if constexpr (std::is_same_v<T, vec4>) {
4584 }
else if constexpr (std::is_same_v<T, int2>) {
4586 }
else if constexpr (std::is_same_v<T, int3>) {
4588 }
else if constexpr (std::is_same_v<T, int4>) {
4590 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4593 registerOrValidateObjectDataType<T>(label, data_type);
4597 std::string label_str = std::string(label);
4601 if (caching_enabled) {
4603 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4604 for (
uint objID: objIDs) {
4605 if (objects.at(objID)->doesObjectDataExist(label)) {
4606 T old_cached_value{};
4607 objects.at(objID)->getObjectData(label, old_cached_value);
4611 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4612 for (
uint objID: objIDs) {
4613 if (objects.at(objID)->doesObjectDataExist(label)) {
4614 std::string old_cached_value;
4615 objects.at(objID)->getObjectData(label, old_cached_value);
4623 for (
uint objID: objIDs) {
4624 if (!objects.at(objID)->doesObjectDataExist(label)) {
4625 incrementObjectDataLabelCounter(label);
4630#pragma omp parallel for
4632 for (
int i = 0; i < (int) objIDs.size(); ++i) {
4633 objects.at(objIDs[i])->setObjectData(label, data);
4637 if (caching_enabled) {
4638 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4640 for (
size_t i = 0; i < objIDs.size(); ++i) {
4643 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4645 for (
size_t i = 0; i < objIDs.size(); ++i) {
4659 template<
typename T>
4660 void setObjectData(
const std::vector<std::vector<uint>> &objIDs,
const char *label,
const T &data) {
4661 static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint> || std::is_same_v<T, float> || std::is_same_v<T, double> || std::is_same_v<T, vec2> || std::is_same_v<T, vec3> || std::is_same_v<T, vec4> || std::is_same_v<T, int2> ||
4662 std::is_same_v<T, int3> || std::is_same_v<T, int4> || std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>,
4663 "Context::setObjectData() was called with an unsupported type.");
4666 if (!objIDs.empty() && !objIDs[0].empty()) {
4668 if constexpr (std::is_same_v<T, int>) {
4670 }
else if constexpr (std::is_same_v<T, uint>) {
4672 }
else if constexpr (std::is_same_v<T, float>) {
4674 }
else if constexpr (std::is_same_v<T, double>) {
4676 }
else if constexpr (std::is_same_v<T, vec2>) {
4678 }
else if constexpr (std::is_same_v<T, vec3>) {
4680 }
else if constexpr (std::is_same_v<T, vec4>) {
4682 }
else if constexpr (std::is_same_v<T, int2>) {
4684 }
else if constexpr (std::is_same_v<T, int3>) {
4686 }
else if constexpr (std::is_same_v<T, int4>) {
4688 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4691 registerOrValidateObjectDataType<T>(label, data_type);
4695 std::string label_str = std::string(label);
4697 size_t total_objects = 0;
4700 if (caching_enabled) {
4702 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4703 for (
const auto &j: objIDs) {
4704 for (
uint objID: j) {
4706 if (objects.at(objID)->doesObjectDataExist(label)) {
4707 T old_cached_value{};
4708 objects.at(objID)->getObjectData(label, old_cached_value);
4713 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4714 for (
const auto &j: objIDs) {
4715 for (
uint objID: j) {
4717 if (objects.at(objID)->doesObjectDataExist(label)) {
4718 std::string old_cached_value;
4719 objects.at(objID)->getObjectData(label, old_cached_value);
4727 for (
const auto &j: objIDs) {
4728 total_objects += j.size();
4732 for (
const auto &j: objIDs) {
4733 for (
uint objID: j) {
4734 if (!objects.at(objID)->doesObjectDataExist(label)) {
4735 incrementObjectDataLabelCounter(label);
4741#pragma omp parallel for
4743 for (
int j = 0; j < (int) objIDs.size(); ++j) {
4744 for (
size_t i = 0; i < objIDs[j].size(); ++i) {
4745 objects.at(objIDs[j][i])->setObjectData(label, data);
4750 if (caching_enabled) {
4751 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4753 for (
size_t i = 0; i < total_objects; ++i) {
4756 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4758 for (
size_t i = 0; i < total_objects; ++i) {
4772 template<
typename T>
4773 void setObjectData(
const std::vector<std::vector<std::vector<uint>>> &objIDs,
const char *label,
const T &data) {
4774 static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint> || std::is_same_v<T, float> || std::is_same_v<T, double> || std::is_same_v<T, vec2> || std::is_same_v<T, vec3> || std::is_same_v<T, vec4> || std::is_same_v<T, int2> ||
4775 std::is_same_v<T, int3> || std::is_same_v<T, int4> || std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>,
4776 "Context::setObjectData() was called with an unsupported type.");
4779 if (!objIDs.empty() && !objIDs[0].empty() && !objIDs[0][0].empty()) {
4781 if constexpr (std::is_same_v<T, int>) {
4783 }
else if constexpr (std::is_same_v<T, uint>) {
4785 }
else if constexpr (std::is_same_v<T, float>) {
4787 }
else if constexpr (std::is_same_v<T, double>) {
4789 }
else if constexpr (std::is_same_v<T, vec2>) {
4791 }
else if constexpr (std::is_same_v<T, vec3>) {
4793 }
else if constexpr (std::is_same_v<T, vec4>) {
4795 }
else if constexpr (std::is_same_v<T, int2>) {
4797 }
else if constexpr (std::is_same_v<T, int3>) {
4799 }
else if constexpr (std::is_same_v<T, int4>) {
4801 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4804 registerOrValidateObjectDataType<T>(label, data_type);
4808 std::string label_str = std::string(label);
4810 size_t total_objects = 0;
4813 if (caching_enabled) {
4815 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4816 for (
const auto &k: objIDs) {
4817 for (
const auto &j: k) {
4818 for (
uint objID: j) {
4820 if (objects.at(objID)->doesObjectDataExist(label)) {
4821 T old_cached_value{};
4822 objects.at(objID)->getObjectData(label, old_cached_value);
4828 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4829 for (
const auto &k: objIDs) {
4830 for (
const auto &j: k) {
4831 for (
uint objID: j) {
4833 if (objects.at(objID)->doesObjectDataExist(label)) {
4834 std::string old_cached_value;
4835 objects.at(objID)->getObjectData(label, old_cached_value);
4844 for (
const auto &k: objIDs) {
4845 for (
const auto &j: k) {
4846 total_objects += j.size();
4851 for (
const auto &k: objIDs) {
4852 for (
const auto &j: k) {
4853 for (
uint objID: j) {
4854 if (!objects.at(objID)->doesObjectDataExist(label)) {
4855 incrementObjectDataLabelCounter(label);
4862#pragma omp parallel for
4864 for (
int k = 0; k < (int) objIDs.size(); ++k) {
4865 for (
size_t j = 0; j < objIDs[k].size(); ++j) {
4866 for (
size_t i = 0; i < objIDs[k][j].size(); ++i) {
4867 uint objID = objIDs[k][j][i];
4868 objects.at(objID)->setObjectData(label, data);
4874 if (caching_enabled) {
4875 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4877 for (
size_t i = 0; i < total_objects; ++i) {
4880 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4882 for (
size_t i = 0; i < total_objects; ++i) {
4897 template<
typename T>
4900 if (objects.find(objID) == objects.end()) {
4901 helios_runtime_error(
"ERROR (Context::setObjectData): Object ID of " + std::to_string(objID) +
" does not exist in the Context.");
4904 static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint> || std::is_same_v<T, float> || std::is_same_v<T, double> || std::is_same_v<T, vec2> || std::is_same_v<T, vec3> || std::is_same_v<T, vec4> || std::is_same_v<T, int2> ||
4905 std::is_same_v<T, int3> || std::is_same_v<T, int4> || std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>,
4906 "Context::setObjectData() was called with an unsupported type.");
4910 if constexpr (std::is_same_v<T, int>) {
4912 }
else if constexpr (std::is_same_v<T, uint>) {
4914 }
else if constexpr (std::is_same_v<T, float>) {
4916 }
else if constexpr (std::is_same_v<T, double>) {
4918 }
else if constexpr (std::is_same_v<T, vec2>) {
4920 }
else if constexpr (std::is_same_v<T, vec3>) {
4922 }
else if constexpr (std::is_same_v<T, vec4>) {
4924 }
else if constexpr (std::is_same_v<T, int2>) {
4926 }
else if constexpr (std::is_same_v<T, int3>) {
4928 }
else if constexpr (std::is_same_v<T, int4>) {
4930 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4933 registerOrValidateObjectDataType<T>(label, data_type);
4935 objects.at(objID)->setObjectData(label, data);
4946 template<
typename T>
4947 void setObjectData(
const std::vector<uint> &objIDs,
const char *label,
const std::vector<T> &data) {
4949 if (objIDs.size() != data.size()) {
4950 helios_runtime_error(
"ERROR (Context::setObjectData): Object IDs and data vectors must be the same size.");
4953 static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint> || std::is_same_v<T, float> || std::is_same_v<T, double> || std::is_same_v<T, vec2> || std::is_same_v<T, vec3> || std::is_same_v<T, vec4> || std::is_same_v<T, int2> ||
4954 std::is_same_v<T, int3> || std::is_same_v<T, int4> || std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>,
4955 "Context::setObjectData() was called with an unsupported type.");
4958 if (!objIDs.empty()) {
4960 if constexpr (std::is_same_v<T, int>) {
4962 }
else if constexpr (std::is_same_v<T, uint>) {
4964 }
else if constexpr (std::is_same_v<T, float>) {
4966 }
else if constexpr (std::is_same_v<T, double>) {
4968 }
else if constexpr (std::is_same_v<T, vec2>) {
4970 }
else if constexpr (std::is_same_v<T, vec3>) {
4972 }
else if constexpr (std::is_same_v<T, vec4>) {
4974 }
else if constexpr (std::is_same_v<T, int2>) {
4976 }
else if constexpr (std::is_same_v<T, int3>) {
4978 }
else if constexpr (std::is_same_v<T, int4>) {
4980 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4983 registerOrValidateObjectDataType<T>(label, data_type);
4986 for (
uint objID: objIDs) {
4987 if (!objects.at(objID)->doesObjectDataExist(label)) {
4988 incrementObjectDataLabelCounter(label);
4993#pragma omp parallel for
4995 for (
int i = 0; i < (int) objIDs.size(); ++i) {
4996 objects.at(objIDs[i])->setObjectData(label, data[i]);
5017 template<
typename T>
5020 if (objects.find(objID) == objects.end()) {
5021 helios_runtime_error(
"ERROR (Context::getObjectData): Object ID of " + std::to_string(objID) +
" does not exist in the Context.");
5024 static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint> || std::is_same_v<T, float> || std::is_same_v<T, double> || std::is_same_v<T, vec2> || std::is_same_v<T, vec3> || std::is_same_v<T, vec4> || std::is_same_v<T, int2> ||
5025 std::is_same_v<T, int3> || std::is_same_v<T, int4> || std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>,
5026 "Context::getObjectData() was called with an unsupported type.");
5027 objects.at(objID)->getObjectData(label, data);
5038 template<
typename T>
5041 if (objects.find(objID) == objects.end()) {
5042 helios_runtime_error(
"ERROR (Context::getObjectData): Object ID of " + std::to_string(objID) +
" does not exist in the Context.");
5045 static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint> || std::is_same_v<T, float> || std::is_same_v<T, double> || std::is_same_v<T, vec2> || std::is_same_v<T, vec3> || std::is_same_v<T, vec4> || std::is_same_v<T, int2> ||
5046 std::is_same_v<T, int3> || std::is_same_v<T, int4> || std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>,
5047 "Context::getObjectData() was called with an unsupported type.");
5048 objects.at(objID)->getObjectData(label, data);
5098 void clearObjectData(
const std::vector<uint> &objIDs,
const char *label);
5138 template<
typename T>
5140 static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint> || std::is_same_v<T, float> || std::is_same_v<T, double> || std::is_same_v<T, vec2> || std::is_same_v<T, vec3> || std::is_same_v<T, vec4> || std::is_same_v<T, int2> ||
5141 std::is_same_v<T, int3> || std::is_same_v<T, int4> || std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *> || std::is_same_v<T, bool>,
5142 "Context::setGlobalData() was called with an unsupported type.");
5144 globaldata[label].size = 1;
5145 if constexpr (std::is_same_v<T, int>) {
5146 globaldata[label].global_data_int = {data};
5148 }
else if constexpr (std::is_same_v<T, uint>) {
5149 globaldata[label].global_data_uint = {data};
5151 }
else if constexpr (std::is_same_v<T, float>) {
5152 globaldata[label].global_data_float = {data};
5154 }
else if constexpr (std::is_same_v<T, double>) {
5155 globaldata[label].global_data_double = {data};
5157 }
else if constexpr (std::is_same_v<T, vec2>) {
5158 globaldata[label].global_data_vec2 = {data};
5160 }
else if constexpr (std::is_same_v<T, vec3>) {
5161 globaldata[label].global_data_vec3 = {data};
5163 }
else if constexpr (std::is_same_v<T, vec4>) {
5164 globaldata[label].global_data_vec4 = {data};
5166 }
else if constexpr (std::is_same_v<T, int2>) {
5167 globaldata[label].global_data_int2 = {data};
5169 }
else if constexpr (std::is_same_v<T, int3>) {
5170 globaldata[label].global_data_int3 = {data};
5172 }
else if constexpr (std::is_same_v<T, int4>) {
5173 globaldata[label].global_data_int4 = {data};
5175 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
5176 globaldata[label].global_data_string = {data};
5178 }
else if constexpr (std::is_same_v<T, bool>) {
5179 globaldata[label].global_data_bool = {data};
5182 globaldata[label].version++;
5190 template<
typename T>
5192 static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint> || std::is_same_v<T, float> || std::is_same_v<T, double> || std::is_same_v<T, vec2> || std::is_same_v<T, vec3> || std::is_same_v<T, vec4> || std::is_same_v<T, int2> ||
5193 std::is_same_v<T, int3> || std::is_same_v<T, int4> || std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *> || std::is_same_v<T, bool>,
5194 "Context::setGlobalData() was called with an unsupported type.");
5196 globaldata[label].size = data.size();
5197 if constexpr (std::is_same_v<T, int>) {
5198 globaldata[label].global_data_int = data;
5200 }
else if constexpr (std::is_same_v<T, uint>) {
5201 globaldata[label].global_data_uint = data;
5203 }
else if constexpr (std::is_same_v<T, float>) {
5204 globaldata[label].global_data_float = data;
5206 }
else if constexpr (std::is_same_v<T, double>) {
5207 globaldata[label].global_data_double = data;
5209 }
else if constexpr (std::is_same_v<T, vec2>) {
5210 globaldata[label].global_data_vec2 = data;
5212 }
else if constexpr (std::is_same_v<T, vec3>) {
5213 globaldata[label].global_data_vec3 = data;
5215 }
else if constexpr (std::is_same_v<T, vec4>) {
5216 globaldata[label].global_data_vec4 = data;
5218 }
else if constexpr (std::is_same_v<T, int2>) {
5219 globaldata[label].global_data_int2 = data;
5221 }
else if constexpr (std::is_same_v<T, int3>) {
5222 globaldata[label].global_data_int3 = data;
5224 }
else if constexpr (std::is_same_v<T, int4>) {
5225 globaldata[label].global_data_int4 = data;
5227 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
5228 globaldata[label].global_data_string = data;
5230 }
else if constexpr (std::is_same_v<T, bool>) {
5231 globaldata[label].global_data_bool = data;
5234 globaldata[label].version++;
5242 template<
typename T>
5245 if constexpr (std::is_same_v<T, std::vector<int>>) {
5248 data = globaldata.at(label).global_data_int;
5250 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int, but data " + std::string(label) +
" does not have type int.");
5252 }
else if constexpr (std::is_same_v<T, std::vector<uint>>) {
5255 data = globaldata.at(label).global_data_uint;
5257 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type uint, but data " + std::string(label) +
" does not have type uint.");
5259 }
else if constexpr (std::is_same_v<T, std::vector<float>>) {
5262 data = globaldata.at(label).global_data_float;
5264 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type float, but data " + std::string(label) +
" does not have type float.");
5266 }
else if constexpr (std::is_same_v<T, std::vector<double>>) {
5269 data = globaldata.at(label).global_data_double;
5271 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type double, but data " + std::string(label) +
" does not have type double.");
5273 }
else if constexpr (std::is_same_v<T, std::vector<vec2>>) {
5276 data = globaldata.at(label).global_data_vec2;
5278 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec2, but data " + std::string(label) +
" does not have type vec2.");
5280 }
else if constexpr (std::is_same_v<T, std::vector<vec3>>) {
5283 data = globaldata.at(label).global_data_vec3;
5285 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec3, but data " + std::string(label) +
" does not have type vec3.");
5287 }
else if constexpr (std::is_same_v<T, std::vector<vec4>>) {
5290 data = globaldata.at(label).global_data_vec4;
5292 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec4, but data " + std::string(label) +
" does not have type vec4.");
5294 }
else if constexpr (std::is_same_v<T, std::vector<int2>>) {
5297 data = globaldata.at(label).global_data_int2;
5299 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int2, but data " + std::string(label) +
" does not have type int2.");
5301 }
else if constexpr (std::is_same_v<T, std::vector<int3>>) {
5304 data = globaldata.at(label).global_data_int3;
5306 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int3, but data " + std::string(label) +
" does not have type int3.");
5308 }
else if constexpr (std::is_same_v<T, std::vector<int4>>) {
5311 data = globaldata.at(label).global_data_int4;
5313 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int4, but data " + std::string(label) +
" does not have type int4.");
5315 }
else if constexpr (std::is_same_v<T, std::vector<std::string>>) {
5318 data = globaldata.at(label).global_data_string;
5320 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type string, but data " + std::string(label) +
" does not have type string.");
5322 }
else if constexpr (std::is_same_v<T, int>) {
5325 data = globaldata.at(label).global_data_int.front();
5327 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int, but data " + std::string(label) +
" does not have type int.");
5329 }
else if constexpr (std::is_same_v<T, uint>) {
5332 data = globaldata.at(label).global_data_uint.front();
5334 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type uint, but data " + std::string(label) +
" does not have type uint.");
5336 }
else if constexpr (std::is_same_v<T, float>) {
5339 data = globaldata.at(label).global_data_float.front();
5341 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type float, but data " + std::string(label) +
" does not have type float.");
5343 }
else if constexpr (std::is_same_v<T, double>) {
5346 data = globaldata.at(label).global_data_double.front();
5348 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type double, but data " + std::string(label) +
" does not have type double.");
5350 }
else if constexpr (std::is_same_v<T, vec2>) {
5353 data = globaldata.at(label).global_data_vec2.front();
5355 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec2, but data " + std::string(label) +
" does not have type vec2.");
5357 }
else if constexpr (std::is_same_v<T, vec3>) {
5360 data = globaldata.at(label).global_data_vec3.front();
5362 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec3, but data " + std::string(label) +
" does not have type vec3.");
5364 }
else if constexpr (std::is_same_v<T, vec4>) {
5367 data = globaldata.at(label).global_data_vec4.front();
5369 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec4, but data " + std::string(label) +
" does not have type vec4.");
5371 }
else if constexpr (std::is_same_v<T, int2>) {
5374 data = globaldata.at(label).global_data_int2.front();
5376 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int2, but data " + std::string(label) +
" does not have type int2.");
5378 }
else if constexpr (std::is_same_v<T, int3>) {
5381 data = globaldata.at(label).global_data_int3.front();
5383 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int3, but data " + std::string(label) +
" does not have type int3.");
5385 }
else if constexpr (std::is_same_v<T, int4>) {
5388 data = globaldata.at(label).global_data_int4.front();
5390 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int4, but data " + std::string(label) +
" does not have type int4.");
5392 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
5395 data = globaldata.at(label).global_data_string.front();
5397 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type string, but data " + std::string(label) +
" does not have type string.");
5399 }
else if constexpr (std::is_same_v<T, bool>) {
5402 data = globaldata.at(label).global_data_bool.front();
5404 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type bool, but data " + std::string(label) +
" does not have type bool.");
5407 static_assert(std::is_same_v<T, int> || std::is_same_v<T, uint> || std::is_same_v<T, float> || std::is_same_v<T, double> || std::is_same_v<T, vec2> || std::is_same_v<T, vec3> || std::is_same_v<T, vec4> || std::is_same_v<T, int2> ||
5408 std::is_same_v<T, int3> || std::is_same_v<T, int4> || std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *> ||
5409 std::is_same_v<T, std::vector<int>> || std::is_same_v<T, std::vector<uint>> || std::is_same_v<T, std::vector<float>> || std::is_same_v<T, std::vector<double>> || std::is_same_v<T, std::vector<vec2>> ||
5410 std::is_same_v<T, std::vector<vec3>> || std::is_same_v<T, std::vector<vec4>> || std::is_same_v<T, std::vector<int2>> || std::is_same_v<T, std::vector<int3>> || std::is_same_v<T, std::vector<int4>> ||
5411 std::is_same_v<T, std::vector<std::string>> || std::is_same_v<T, std::vector<bool>>,
5412 "CompoundObject::getGlobalData() was called with an unsupported type.");
5547 std::vector<uint>
copyObject(
const std::vector<uint> &ObjIDs);
5579 std::vector<uint>
filterObjectsByData(
const std::vector<uint> &ObjIDs,
const char *object_data,
float threshold,
const char *comparator)
const;
5601 void rotateObject(
uint ObjID,
float rotation_radians,
const char *rotation_axis_xyz)
const;
5609 void rotateObject(
const std::vector<uint> &ObjIDs,
float rotation_radians,
const char *rotation_axis_xyz)
const;
5625 void rotateObject(
const std::vector<uint> &ObjIDs,
float rotation_radians,
const vec3 &rotation_axis_vector)
const;
5634 void rotateObject(
uint ObjID,
float rotation_radians,
const vec3 &rotation_origin,
const vec3 &rotation_axis_vector)
const;
5643 void rotateObject(
const std::vector<uint> &ObjIDs,
float rotation_radians,
const vec3 &rotation_origin,
const vec3 &rotation_axis_vector)
const;
6168 uint addTubeObject(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius);
6180 uint addTubeObject(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const std::vector<RGBcolor> &color);
6193 uint addTubeObject(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const char *texturefile);
6207 uint addTubeObject(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const char *texturefile,
const std::vector<float> &textureuv_ufrac);
6450 std::vector<uint>
addSphere(
uint Ndivs,
const vec3 ¢er,
float radius,
const char *texturefile);
6511 std::vector<uint>
addTube(
uint Ndivs,
const std::vector<vec3> &nodes,
const std::vector<float> &radius);
6523 std::vector<uint>
addTube(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const std::vector<RGBcolor> &color);
6535 std::vector<uint>
addTube(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const char *texturefile);
6571 std::vector<uint>
addBox(
const vec3 ¢er,
const vec3 &size,
const int3 &subdiv,
const char *texturefile);
6584 std::vector<uint>
addBox(
const vec3 ¢er,
const vec3 &size,
const int3 &subdiv,
const RGBcolor &color,
bool reverse_normals);
6597 std::vector<uint>
addBox(
const vec3 ¢er,
const vec3 &size,
const int3 &subdiv,
const char *texturefile,
bool reverse_normals);
6708 std::vector<uint>
addCone(
uint Ndivs,
const vec3 &node0,
const vec3 &node1,
float radius0,
float radius1);
6734 std::vector<uint>
addCone(
uint Ndivs,
const vec3 &node0,
const vec3 &node1,
float radius0,
float radius1,
const char *texturefile);
6824 void loadTabularTimeseriesData(
const std::string &data_file,
const std::vector<std::string> &column_labels,
const std::string &delimiter,
const std::string &date_string_format =
"YYYYMMDD",
uint headerlines = 0);
6883 void cropDomain(std::vector<uint> &UUIDs,
const vec2 &xbounds,
const vec2 &ybounds,
const vec2 &zbounds);
6911 void colorPrimitiveByDataPseudocolor(
const std::vector<uint> &UUIDs,
const std::string &primitive_data,
const std::string &colormap,
uint Ncolors,
float data_min,
float data_max);
6920 std::vector<uint>
loadXML(
const char *filename,
bool quiet =
false);
6935 static bool scanXMLForTag(
const std::string &filename,
const std::string &tag,
const std::string &label =
"");
6942 void writeXML(
const char *filename,
bool quiet =
false)
const;
6950 void writeXML(
const char *filename,
const std::vector<uint> &UUIDs,
bool quiet =
false)
const;
6958 void writeXML_byobject(
const char *filename,
const std::vector<uint> &UUIDs,
bool quiet =
false)
const;
6966 void writePrimitiveData(
const std::string &filename,
const std::vector<std::string> &column_format,
bool print_header =
false)
const;
6975 void writePrimitiveData(
const std::string &filename,
const std::vector<std::string> &column_format,
const std::vector<uint> &UUIDs,
bool print_header =
false)
const;
6984 std::vector<uint>
loadPLY(
const char *filename,
bool silent =
false);
6996 std::vector<uint>
loadPLY(
const char *filename,
const vec3 &origin,
float height,
const std::string &upaxis =
"YUP",
bool silent =
false);
7009 std::vector<uint>
loadPLY(
const char *filename,
const vec3 &origin,
float height,
const SphericalCoord &rotation,
const std::string &upaxis =
"YUP",
bool silent =
false);
7021 std::vector<uint>
loadPLY(
const char *filename,
const vec3 &origin,
float height,
const RGBcolor &default_color,
const std::string &upaxis =
"YUP",
bool silent =
false);
7034 std::vector<uint>
loadPLY(
const char *filename,
const vec3 &origin,
float height,
const SphericalCoord &rotation,
const RGBcolor &default_color,
const std::string &upaxis =
"YUP",
bool silent =
false);
7040 void writePLY(
const char *filename)
const;
7047 void writePLY(
const char *filename,
const std::vector<uint> &UUIDs)
const;
7056 std::vector<uint>
loadOBJ(
const char *filename,
bool silent =
false);
7068 std::vector<uint>
loadOBJ(
const char *filename,
const vec3 &origin,
float height,
const SphericalCoord &rotation,
const RGBcolor &default_color,
bool silent =
false);
7081 std::vector<uint>
loadOBJ(
const char *filename,
const vec3 &origin,
float height,
const SphericalCoord &rotation,
const RGBcolor &default_color,
const char *upaxis,
bool silent =
false);
7103 void writeOBJ(
const std::string &filename,
bool write_normals =
false,
bool silent =
false)
const;
7112 void writeOBJ(
const std::string &filename,
const std::vector<uint> &UUIDs,
bool write_normals =
false,
bool silent =
false)
const;
7122 void writeOBJ(
const std::string &filename,
const std::vector<uint> &UUIDs,
const std::vector<std::string> &primitive_dat_fields,
bool write_normals =
false,
bool silent =
false)
const;
7132 std::filesystem::path
resolveFilePath(
const std::string &filename)
const;
7141 void setDate(
int day,
int month,
int year);
7156 void setDate(
int Julian_day,
int year);
7186 void setTime(
int minute,
int hour);
7196 void setTime(
int second,
int minute,
int hour);
7435 void scalePrimitiveData(
const std::vector<uint> &UUIDs,
const std::string &label,
float scaling_factor);
7488 void aggregatePrimitiveDataSum(
const std::vector<uint> &UUIDs,
const std::vector<std::string> &primitive_data_labels,
const std::string &result_primitive_data_label);
7497 void aggregatePrimitiveDataProduct(
const std::vector<uint> &UUIDs,
const std::vector<std::string> &primitive_data_labels,
const std::string &result_primitive_data_label);
7515 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
float filter_value,
const std::string &comparator)
const;
7526 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
double filter_value,
const std::string &comparator)
const;
7537 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
int filter_value,
const std::string &comparator)
const;
7548 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
uint filter_value,
const std::string &comparator)
const;
7558 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
const std::string &filter_value)
const;
7569 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
float filter_value,
const std::string &comparator)
const;
7580 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
double filter_value,
const std::string &comparator)
const;
7591 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
int filter_value,
const std::string &comparator)
const;
7602 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
uint filter_value,
const std::string &comparator)
const;
7612 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
const std::string &filter_value)
const;
7643 std::vector<RGBcolor>
generateColormap(
const std::vector<helios::RGBcolor> &ctable,
const std::vector<float> &cfrac,
uint Ncolors);
7647 template<
typename T>
7648 void storeDataWithTypeCasting(
uint UUID,
const char *label,
const T &data,
HeliosDataType target_type) {
7650 if constexpr (std::is_same_v<T, int> || std::is_same_v<T, uint> || std::is_same_v<T, float> || std::is_same_v<T, double>) {
7651 if (target_type == HELIOS_TYPE_INT) {
7652 primitives.at(UUID)->setPrimitiveData(label,
static_cast<int>(data));
7653 }
else if (target_type == HELIOS_TYPE_UINT) {
7654 primitives.at(UUID)->setPrimitiveData(label,
static_cast<uint>(data));
7655 }
else if (target_type == HELIOS_TYPE_FLOAT) {
7656 primitives.at(UUID)->setPrimitiveData(label,
static_cast<float>(data));
7657 }
else if (target_type == HELIOS_TYPE_DOUBLE) {
7658 primitives.at(UUID)->setPrimitiveData(label,
static_cast<double>(data));
7661 primitives.at(UUID)->setPrimitiveData(label, data);
7665 primitives.at(UUID)->setPrimitiveData(label, data);
7669 template<
typename T>
7670 void storeObjectDataWithTypeCasting(
uint objID,
const char *label,
const T &data, HeliosDataType target_type) {
7672 if constexpr (std::is_same_v<T, int> || std::is_same_v<T, uint> || std::is_same_v<T, float> || std::is_same_v<T, double>) {
7673 if (target_type == HELIOS_TYPE_INT) {
7674 objects.at(objID)->setObjectData(label,
static_cast<int>(data));
7675 }
else if (target_type == HELIOS_TYPE_UINT) {
7676 objects.at(objID)->setObjectData(label,
static_cast<uint>(data));
7677 }
else if (target_type == HELIOS_TYPE_FLOAT) {
7678 objects.at(objID)->setObjectData(label,
static_cast<float>(data));
7679 }
else if (target_type == HELIOS_TYPE_DOUBLE) {
7680 objects.at(objID)->setObjectData(label,
static_cast<double>(data));
7683 objects.at(objID)->setObjectData(label, data);
7687 objects.at(objID)->setObjectData(label, data);
7691 template<
typename T>
7692 HeliosDataType registerOrValidatePrimitiveDataType(
const std::string &label, HeliosDataType data_type) {
7693 auto it = primitive_data_type_registry.find(label);
7694 if (it == primitive_data_type_registry.end()) {
7696 primitive_data_type_registry[label] = data_type;
7701 if (expected_type != data_type) {
7703 if (!isTypeCastingSupported(data_type, expected_type)) {
7704 helios_runtime_error(
"ERROR (Context::registerOrValidatePrimitiveDataType): Data type mismatch for label '" + label +
"'. Expected " + dataTypeToString(expected_type) +
" but got " + dataTypeToString(data_type) +
7705 ". Type casting between these types is not supported.");
7707 std::cerr <<
"WARNING (Context::registerOrValidatePrimitiveDataType): Type casting from " + dataTypeToString(data_type) +
" to " + dataTypeToString(expected_type) +
" for label '" + label +
7708 "'. Consider using consistent types."
7712 return expected_type;
7716 template<
typename T>
7717 HeliosDataType registerOrValidateObjectDataType(
const std::string &label, HeliosDataType data_type) {
7718 auto it = object_data_type_registry.find(label);
7719 if (it == object_data_type_registry.end()) {
7721 object_data_type_registry[label] = data_type;
7726 if (expected_type != data_type) {
7728 if (!isTypeCastingSupported(data_type, expected_type)) {
7729 helios_runtime_error(
"ERROR (Context::registerOrValidateObjectDataType): Data type mismatch for label '" + label +
"'. Expected " + dataTypeToString(expected_type) +
" but got " + dataTypeToString(data_type) +
7730 ". Type casting between these types is not supported.");
7732 std::cerr <<
"WARNING (Context::registerOrValidateObjectDataType): Type casting from " + dataTypeToString(data_type) +
" to " + dataTypeToString(expected_type) +
" for label '" + label +
"'. Consider using consistent types."
7736 return expected_type;
7743 template<
typename T>
7745 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
7746 std::string string_value = (std::is_same_v<T, std::string>) ? value : std::string(value);
7747 primitive_string_value_registry[label][string_value]++;
7748 }
else if constexpr (std::is_same_v<T, int>) {
7749 primitive_int_value_registry[label][value]++;
7750 }
else if constexpr (std::is_same_v<T, uint>) {
7751 primitive_uint_value_registry[label][value]++;
7756 template<
typename T>
7758 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
7759 std::string string_value = (std::is_same_v<T, std::string>) ? value : std::string(value);
7760 auto label_it = primitive_string_value_registry.find(label);
7761 if (label_it != primitive_string_value_registry.end()) {
7762 auto value_it = label_it->second.find(string_value);
7763 if (value_it != label_it->second.end() && value_it->second > 0) {
7765 if (value_it->second == 0) {
7766 label_it->second.erase(value_it);
7767 if (label_it->second.empty()) {
7768 primitive_string_value_registry.erase(label_it);
7773 }
else if constexpr (std::is_same_v<T, int>) {
7774 auto label_it = primitive_int_value_registry.find(label);
7775 if (label_it != primitive_int_value_registry.end()) {
7776 auto value_it = label_it->second.find(value);
7777 if (value_it != label_it->second.end() && value_it->second > 0) {
7779 if (value_it->second == 0) {
7780 label_it->second.erase(value_it);
7781 if (label_it->second.empty()) {
7782 primitive_int_value_registry.erase(label_it);
7787 }
else if constexpr (std::is_same_v<T, uint>) {
7788 auto label_it = primitive_uint_value_registry.find(label);
7789 if (label_it != primitive_uint_value_registry.end()) {
7790 auto value_it = label_it->second.find(value);
7791 if (value_it != label_it->second.end() && value_it->second > 0) {
7793 if (value_it->second == 0) {
7794 label_it->second.erase(value_it);
7795 if (label_it->second.empty()) {
7796 primitive_uint_value_registry.erase(label_it);
7805 template<
typename T>
7807 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
7808 std::string string_value = (std::is_same_v<T, std::string>) ? value : std::string(value);
7809 object_string_value_registry[label][string_value]++;
7810 }
else if constexpr (std::is_same_v<T, int>) {
7811 object_int_value_registry[label][value]++;
7812 }
else if constexpr (std::is_same_v<T, uint>) {
7813 object_uint_value_registry[label][value]++;
7818 template<
typename T>
7820 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
7821 std::string string_value = (std::is_same_v<T, std::string>) ? value : std::string(value);
7822 auto label_it = object_string_value_registry.find(label);
7823 if (label_it != object_string_value_registry.end()) {
7824 auto value_it = label_it->second.find(string_value);
7825 if (value_it != label_it->second.end() && value_it->second > 0) {
7827 if (value_it->second == 0) {
7828 label_it->second.erase(value_it);
7829 if (label_it->second.empty()) {
7830 object_string_value_registry.erase(label_it);
7835 }
else if constexpr (std::is_same_v<T, int>) {
7836 auto label_it = object_int_value_registry.find(label);
7837 if (label_it != object_int_value_registry.end()) {
7838 auto value_it = label_it->second.find(value);
7839 if (value_it != label_it->second.end() && value_it->second > 0) {
7841 if (value_it->second == 0) {
7842 label_it->second.erase(value_it);
7843 if (label_it->second.empty()) {
7844 object_int_value_registry.erase(label_it);
7849 }
else if constexpr (std::is_same_v<T, uint>) {
7850 auto label_it = object_uint_value_registry.find(label);
7851 if (label_it != object_uint_value_registry.end()) {
7852 auto value_it = label_it->second.find(value);
7853 if (value_it != label_it->second.end() && value_it->second > 0) {
7855 if (value_it->second == 0) {
7856 label_it->second.erase(value_it);
7857 if (label_it->second.empty()) {
7858 object_uint_value_registry.erase(label_it);
7875 template<
typename T>
7877 static_assert(std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>,
"getUniquePrimitiveDataValues() only supports std::string, int, and uint types.");
7880 helios_runtime_error(
"ERROR (Context::getUniquePrimitiveDataValues): Value-level caching is not enabled for primitive data label '" + label +
"'. Use enablePrimitiveDataValueCaching() first.");
7885 if constexpr (std::is_same_v<T, std::string>) {
7886 auto it = primitive_string_value_registry.find(label);
7887 if (it != primitive_string_value_registry.end()) {
7888 values.reserve(it->second.size());
7889 for (
const auto &[value, count]: it->second) {
7891 values.push_back(value);
7895 }
else if constexpr (std::is_same_v<T, int>) {
7896 auto it = primitive_int_value_registry.find(label);
7897 if (it != primitive_int_value_registry.end()) {
7898 values.reserve(it->second.size());
7899 for (
const auto &[value, count]: it->second) {
7901 values.push_back(value);
7905 }
else if constexpr (std::is_same_v<T, uint>) {
7906 auto it = primitive_uint_value_registry.find(label);
7907 if (it != primitive_uint_value_registry.end()) {
7908 values.reserve(it->second.size());
7909 for (
const auto &[value, count]: it->second) {
7911 values.push_back(value);
7925 template<
typename T>
7927 static_assert(std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>,
"getUniqueObjectDataValues() only supports std::string, int, and uint types.");
7930 helios_runtime_error(
"ERROR (Context::getUniqueObjectDataValues): Value-level caching is not enabled for object data label '" + label +
"'. Use enableObjectDataValueCaching() first.");
7935 if constexpr (std::is_same_v<T, std::string>) {
7936 auto it = object_string_value_registry.find(label);
7937 if (it != object_string_value_registry.end()) {
7938 values.reserve(it->second.size());
7939 for (
const auto &[value, count]: it->second) {
7941 values.push_back(value);
7945 }
else if constexpr (std::is_same_v<T, int>) {
7946 auto it = object_int_value_registry.find(label);
7947 if (it != object_int_value_registry.end()) {
7948 values.reserve(it->second.size());
7949 for (
const auto &[value, count]: it->second) {
7951 values.push_back(value);
7955 }
else if constexpr (std::is_same_v<T, uint>) {
7956 auto it = object_uint_value_registry.find(label);
7957 if (it != object_uint_value_registry.end()) {
7958 values.reserve(it->second.size());
7959 for (
const auto &[value, count]: it->second) {
7961 values.push_back(value);