2483 friend class Primitive;
2493 [[nodiscard]] Primitive *getPrimitivePointer_private(
uint UUID)
const;
2500 [[nodiscard]] Patch *getPatchPointer_private(
uint UUID)
const;
2508 [[nodiscard]] Triangle *getTrianglePointer_private(
uint UUID)
const;
2515 [[nodiscard]] Voxel *getVoxelPointer_private(
uint UUID)
const;
2529 [[nodiscard]]
Tile *getTileObjectPointer_private(
uint ObjID)
const;
2544 void regenerateTileObjectSubpatches(
uint ObjID,
const int2 &new_subdiv);
2551 [[nodiscard]]
Sphere *getSphereObjectPointer_private(
uint ObjID)
const;
2558 [[nodiscard]]
Tube *getTubeObjectPointer_private(
uint ObjID)
const;
2565 [[nodiscard]]
Box *getBoxObjectPointer_private(
uint ObjID)
const;
2572 [[nodiscard]]
Disk *getDiskObjectPointer_private(
uint ObjID)
const;
2579 [[nodiscard]]
Polymesh *getPolymeshObjectPointer_private(
uint ObjID)
const;
2586 [[nodiscard]]
Cone *getConeObjectPointer_private(
uint ObjID)
const;
2589 void invalidateAllUUIDsCache()
const {
2590 all_uuids_cache_valid =
false;
2597 std::unordered_map<uint, Primitive *> primitives;
2600 mutable std::vector<uint> cached_all_uuids;
2602 mutable bool all_uuids_cache_valid =
false;
2608 std::vector<uint> dirty_deleted_primitives;
2611 std::unordered_map<uint, CompoundObject *> objects;
2614 std::map<std::string, std::vector<float>> timeseries_data;
2618 std::map<std::string, std::vector<double>> timeseries_datevalue;
2622 std::map<std::string, Texture> textures;
2624 void addTexture(
const char *texture_file);
2627 bool doesTextureFileExist(
const char *texture_file)
const;
2629 bool validateTextureFileExtenstion(
const char *texture_file)
const;
2634 static constexpr const char *DEFAULT_MATERIAL_LABEL =
"__default__";
2637 std::map<uint, Material> materials;
2640 std::map<std::string, uint> material_label_to_id;
2643 uint currentMaterialID;
2653 uint addMaterial_internal(
const std::string &label,
const RGBAcolor &color,
const std::string &texture =
"");
2656 std::string generateMaterialLabel(
const RGBAcolor &color,
const std::string &texture,
bool texture_override)
const;
2659 bool isMaterialShared(
uint materialID)
const;
2662 uint copyMaterialForPrimitive(
uint primitiveUUID);
2666 std::map<std::string, GlobalData> globaldata;
2668 std::unordered_map<std::string, size_t> primitive_data_label_counts;
2669 std::unordered_map<std::string, size_t> object_data_label_counts;
2674 std::unordered_map<std::string, HeliosDataType> primitive_data_type_registry;
2677 std::unordered_map<std::string, HeliosDataType> object_data_type_registry;
2682 std::unordered_map<std::string, std::unordered_map<std::string, size_t>> primitive_string_value_registry;
2683 std::unordered_map<std::string, std::unordered_map<int, size_t>> primitive_int_value_registry;
2684 std::unordered_map<std::string, std::unordered_map<uint, size_t>> primitive_uint_value_registry;
2687 std::unordered_map<std::string, std::unordered_map<std::string, size_t>> object_string_value_registry;
2688 std::unordered_map<std::string, std::unordered_map<int, size_t>> object_int_value_registry;
2689 std::unordered_map<std::string, std::unordered_map<uint, size_t>> object_uint_value_registry;
2692 std::unordered_set<std::string> cached_primitive_data_labels;
2693 std::unordered_set<std::string> cached_object_data_labels;
2699 void incrementPrimitiveDataLabelCounter(
const std::string &primitive_data_label);
2705 void decrementPrimitiveDataLabelCounter(
const std::string &primitive_data_label);
2712 void incrementObjectDataLabelCounter(
const std::string &object_data_label);
2718 void decrementObjectDataLabelCounter(
const std::string &object_data_label);
2744 std::minstd_rand0 generator;
2747 std::uniform_real_distribution<float> unif_distribution;
2750 std::normal_distribution<float> norm_distribution;
2754 std::vector<std::string> XMLfiles;
2756 struct OBJmaterial {
2759 std::string texture;
2761 bool textureHasTransparency =
false;
2762 bool textureColorIsOverridden =
false;
2764 OBJmaterial(
const RGBcolor &a_color, std::string a_texture,
uint a_materialID) : color{a_color}, texture{std::move(a_texture)}, materialID{a_materialID} {};
2767 std::map<std::string, OBJmaterial> loadMTL(
const std::string &filebase,
const std::string &material_file,
const RGBcolor &default_color);
2769 void loadMaterialData(pugi::xml_node mat_node,
const std::string &material_label);
2771 void loadPData(pugi::xml_node p,
uint UUID);
2773 void loadOData(pugi::xml_node p,
uint ID);
2777 void writeDataToXMLstream(
const char *data_group,
const std::vector<std::string> &data_labels,
void *ptr, std::ofstream &outfile)
const;
2784 uint currentObjectID;
2793 static void out_of_memory_handler();
2799 static void install_out_of_memory_handler();
2820 static int selfTest(
int argc,
char **argv);
3072 void rotatePrimitive(
const std::vector<uint> &UUIDs,
float rotation_rad,
const char *axis);
3088 void rotatePrimitive(
const std::vector<uint> &UUIDs,
float rotation_rad,
const vec3 &axis);
3194 std::vector<uint>
copyPrimitive(
const std::vector<uint> &UUIDs);
3287 [[nodiscard]]
size_t getPrimitiveCount(
bool include_hidden_primitives =
true)
const;
3294 [[nodiscard]]
size_t getTriangleCount(
bool include_hidden_primitives =
true)
const;
3301 [[nodiscard]]
size_t getPatchCount(
bool include_hidden_primitives =
true)
const;
3304 [[nodiscard]] std::vector<uint>
getAllUUIDs()
const;
3311 [[nodiscard]] std::vector<uint>
getDirtyUUIDs(
bool include_deleted_UUIDs =
false)
const;
3366 void cleanDeletedUUIDs(std::vector<std::vector<std::vector<uint>>> &UUIDs)
const;
3377 template<
typename T>
3380 if (primitives.find(UUID) == primitives.end()) {
3381 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3385 std::string label_str = std::string(label);
3386 bool had_cached_value =
false;
3389 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
3391 T old_cached_value{};
3392 primitives.at(UUID)->getPrimitiveData(label, old_cached_value);
3394 had_cached_value =
true;
3396 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3398 std::string old_cached_value;
3399 primitives.at(UUID)->getPrimitiveData(label, old_cached_value);
3401 had_cached_value =
true;
3405 if (!primitives.at(UUID)->doesPrimitiveDataExist(label)) {
3406 incrementPrimitiveDataLabelCounter(label);
3411 if constexpr (std::is_same_v<T, int>) {
3413 }
else if constexpr (std::is_same_v<T, uint>) {
3415 }
else if constexpr (std::is_same_v<T, float>) {
3417 }
else if constexpr (std::is_same_v<T, double>) {
3419 }
else if constexpr (std::is_same_v<T, vec2>) {
3421 }
else if constexpr (std::is_same_v<T, vec3>) {
3423 }
else if constexpr (std::is_same_v<T, vec4>) {
3425 }
else if constexpr (std::is_same_v<T, int2>) {
3427 }
else if constexpr (std::is_same_v<T, int3>) {
3429 }
else if constexpr (std::is_same_v<T, int4>) {
3431 }
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 *>) {
3434 HeliosDataType target_type = registerOrValidatePrimitiveDataType<T>(label, data_type);
3437 if (target_type != data_type && isTypeCastingSupported(data_type, target_type)) {
3438 storeDataWithTypeCasting(UUID, label, data, target_type);
3440 primitives.at(UUID)->setPrimitiveData(label, data);
3445 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
3447 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3452 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
3454 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3467 template<
typename T>
3470 if (primitives.find(UUID) == primitives.end()) {
3471 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3474 if (!primitives.at(UUID)->doesPrimitiveDataExist(label)) {
3475 incrementPrimitiveDataLabelCounter(label);
3480 if constexpr (std::is_same_v<T, int>) {
3482 }
else if constexpr (std::is_same_v<T, uint>) {
3484 }
else if constexpr (std::is_same_v<T, float>) {
3486 }
else if constexpr (std::is_same_v<T, double>) {
3488 }
else if constexpr (std::is_same_v<T, vec2>) {
3490 }
else if constexpr (std::is_same_v<T, vec3>) {
3492 }
else if constexpr (std::is_same_v<T, vec4>) {
3494 }
else if constexpr (std::is_same_v<T, int2>) {
3496 }
else if constexpr (std::is_same_v<T, int3>) {
3498 }
else if constexpr (std::is_same_v<T, int4>) {
3500 }
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 *>) {
3503 registerOrValidatePrimitiveDataType<T>(label, data_type);
3505 primitives.at(UUID)->setPrimitiveData(label, data);
3516 template<
typename T>
3517 void setPrimitiveData(
const std::vector<uint> &UUIDs,
const char *label,
const std::vector<T> &data) {
3519 if (UUIDs.size() != data.size()) {
3520 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUIDs and data vectors must be the same size.");
3526 if (!UUIDs.empty()) {
3528 if constexpr (std::is_same_v<T, int>) {
3530 }
else if constexpr (std::is_same_v<T, uint>) {
3532 }
else if constexpr (std::is_same_v<T, float>) {
3534 }
else if constexpr (std::is_same_v<T, double>) {
3536 }
else if constexpr (std::is_same_v<T, vec2>) {
3538 }
else if constexpr (std::is_same_v<T, vec3>) {
3540 }
else if constexpr (std::is_same_v<T, vec4>) {
3542 }
else if constexpr (std::is_same_v<T, int2>) {
3544 }
else if constexpr (std::is_same_v<T, int3>) {
3546 }
else if constexpr (std::is_same_v<T, int4>) {
3548 }
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 *>) {
3551 target_type = registerOrValidatePrimitiveDataType<T>(label, data_type);
3554 for (
uint UUID: UUIDs) {
3556 if (primitives.find(UUID) == primitives.end()) {
3557 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3560 if (!primitives.at(UUID)->doesPrimitiveDataExist(label)) {
3561 incrementPrimitiveDataLabelCounter(label);
3566#pragma omp parallel for
3568 for (
int i = 0; i < (int) UUIDs.size(); ++i) {
3569 primitives.at(UUIDs[i])->setPrimitiveData(label, data[i]);
3580 template<
typename T>
3584 if (!UUIDs.empty()) {
3586 if constexpr (std::is_same_v<T, int>) {
3588 }
else if constexpr (std::is_same_v<T, uint>) {
3590 }
else if constexpr (std::is_same_v<T, float>) {
3592 }
else if constexpr (std::is_same_v<T, double>) {
3594 }
else if constexpr (std::is_same_v<T, vec2>) {
3596 }
else if constexpr (std::is_same_v<T, vec3>) {
3598 }
else if constexpr (std::is_same_v<T, vec4>) {
3600 }
else if constexpr (std::is_same_v<T, int2>) {
3602 }
else if constexpr (std::is_same_v<T, int3>) {
3604 }
else if constexpr (std::is_same_v<T, int4>) {
3606 }
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 *>) {
3609 registerOrValidatePrimitiveDataType<T>(label, data_type);
3612 for (
uint UUID: UUIDs) {
3614 if (primitives.find(UUID) == primitives.end()) {
3615 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3618 if (!primitives.at(UUID)->doesPrimitiveDataExist(label)) {
3619 incrementPrimitiveDataLabelCounter(label);
3624#pragma omp parallel for
3626 for (
int i = 0; i < (int) UUIDs.size(); ++i) {
3627 primitives.at(UUIDs[i])->setPrimitiveData(label, data);
3638 template<
typename T>
3641 if (primitives.find(UUID) == primitives.end()) {
3642 helios_runtime_error(
"ERROR (Context::getPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3645 primitives.at(UUID)->getPrimitiveData(label, data);
3656 template<
typename T>
3659 if (primitives.find(UUID) == primitives.end()) {
3660 helios_runtime_error(
"ERROR (Context::getPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3663 primitives.at(UUID)->getPrimitiveData(label, data);
3850 void hideObject(
const std::vector<uint> &ObjIDs);
3862 void showObject(
const std::vector<uint> &ObjIDs);
4215 void addMaterial(
const std::string &material_label);
4223 void renameMaterial(
const std::string &old_label,
const std::string &new_label);
4236 [[nodiscard]] std::vector<std::string>
listMaterials()
const;
4250 [[nodiscard]] std::string
getMaterialTexture(
const std::string &material_label)
const;
4273 void setMaterialTexture(
const std::string &material_label,
const std::string &texture_file);
4296 void setMaterialTwosidedFlag(
const std::string &material_label,
uint twosided_flag);
4314 void assignMaterialToPrimitive(
uint UUID,
const std::string &material_label);
4322 void assignMaterialToPrimitive(
const std::vector<uint> &UUIDs,
const std::string &material_label);
4370 template<
typename T>
4371 void setMaterialData(
const std::string &material_label,
const char *data_label,
const T &data) {
4373 materials[matID].setMaterialData(data_label, data);
4384 template<
typename T>
4385 void setMaterialData(
const std::string &material_label,
const char *data_label,
const std::vector<T> &data) {
4387 materials[matID].setMaterialData(data_label, data);
4397 template<
typename T>
4398 void getMaterialData(
const std::string &material_label,
const char *data_label, T &data)
const {
4400 materials.at(matID).getMaterialData(data_label, data);
4410 template<
typename T>
4411 void getMaterialData(
const std::string &material_label,
const char *data_label, std::vector<T> &data)
const {
4413 materials.at(matID).getMaterialData(data_label, data);
4422 [[nodiscard]]
bool doesMaterialDataExist(
const std::string &material_label,
const char *data_label)
const;
4437 void clearMaterialData(
const std::string &material_label,
const char *data_label);
4450 template<
typename T>
4452 Primitive *prim = getPrimitivePointer_private(UUID);
4453 uint materialID = prim->materialID;
4456 if (materials.find(materialID) != materials.end() && materials.at(materialID).doesMaterialDataExist(data_label)) {
4457 materials.at(materialID).getMaterialData(data_label, data);
4460 else if (prim->doesPrimitiveDataExist(data_label)) {
4461 prim->getPrimitiveData(data_label, data);
4465 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).");
4505 template<
typename T>
4508 if (objects.find(objID) == objects.end()) {
4509 helios_runtime_error(
"ERROR (Context::setObjectData): Object ID of " + std::to_string(objID) +
" does not exist in the Context.");
4512 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> ||
4513 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 *>,
4514 "Context::setObjectData() was called with an unsupported type.");
4518 if constexpr (std::is_same_v<T, int>) {
4520 }
else if constexpr (std::is_same_v<T, uint>) {
4522 }
else if constexpr (std::is_same_v<T, float>) {
4524 }
else if constexpr (std::is_same_v<T, double>) {
4526 }
else if constexpr (std::is_same_v<T, vec2>) {
4528 }
else if constexpr (std::is_same_v<T, vec3>) {
4530 }
else if constexpr (std::is_same_v<T, vec4>) {
4532 }
else if constexpr (std::is_same_v<T, int2>) {
4534 }
else if constexpr (std::is_same_v<T, int3>) {
4536 }
else if constexpr (std::is_same_v<T, int4>) {
4538 }
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 *>) {
4541 registerOrValidateObjectDataType<T>(label, data_type);
4544 std::string label_str = std::string(label);
4545 bool had_cached_value =
false;
4548 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4550 T old_cached_value{};
4551 objects.at(objID)->getObjectData(label, old_cached_value);
4553 had_cached_value =
true;
4555 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4557 std::string old_cached_value;
4558 objects.at(objID)->getObjectData(label, old_cached_value);
4560 had_cached_value =
true;
4564 if (!objects.at(objID)->doesObjectDataExist(label)) {
4565 incrementObjectDataLabelCounter(label);
4567 objects.at(objID)->setObjectData(label, data);
4571 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4573 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4578 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4580 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4593 template<
typename T>
4594 void setObjectData(
const std::vector<uint> &objIDs,
const char *label,
const T &data) {
4595 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> ||
4596 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 *>,
4597 "Context::setObjectData() was called with an unsupported type.");
4600 if (!objIDs.empty()) {
4602 if constexpr (std::is_same_v<T, int>) {
4604 }
else if constexpr (std::is_same_v<T, uint>) {
4606 }
else if constexpr (std::is_same_v<T, float>) {
4608 }
else if constexpr (std::is_same_v<T, double>) {
4610 }
else if constexpr (std::is_same_v<T, vec2>) {
4612 }
else if constexpr (std::is_same_v<T, vec3>) {
4614 }
else if constexpr (std::is_same_v<T, vec4>) {
4616 }
else if constexpr (std::is_same_v<T, int2>) {
4618 }
else if constexpr (std::is_same_v<T, int3>) {
4620 }
else if constexpr (std::is_same_v<T, int4>) {
4622 }
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 *>) {
4625 registerOrValidateObjectDataType<T>(label, data_type);
4629 std::string label_str = std::string(label);
4633 if (caching_enabled) {
4635 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4636 for (
uint objID: objIDs) {
4637 if (objects.at(objID)->doesObjectDataExist(label)) {
4638 T old_cached_value{};
4639 objects.at(objID)->getObjectData(label, old_cached_value);
4643 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4644 for (
uint objID: objIDs) {
4645 if (objects.at(objID)->doesObjectDataExist(label)) {
4646 std::string old_cached_value;
4647 objects.at(objID)->getObjectData(label, old_cached_value);
4655 for (
uint objID: objIDs) {
4656 if (!objects.at(objID)->doesObjectDataExist(label)) {
4657 incrementObjectDataLabelCounter(label);
4662#pragma omp parallel for
4664 for (
int i = 0; i < (int) objIDs.size(); ++i) {
4665 objects.at(objIDs[i])->setObjectData(label, data);
4669 if (caching_enabled) {
4670 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4672 for (
size_t i = 0; i < objIDs.size(); ++i) {
4675 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4677 for (
size_t i = 0; i < objIDs.size(); ++i) {
4691 template<
typename T>
4692 void setObjectData(
const std::vector<std::vector<uint>> &objIDs,
const char *label,
const T &data) {
4693 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> ||
4694 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 *>,
4695 "Context::setObjectData() was called with an unsupported type.");
4698 if (!objIDs.empty() && !objIDs[0].empty()) {
4700 if constexpr (std::is_same_v<T, int>) {
4702 }
else if constexpr (std::is_same_v<T, uint>) {
4704 }
else if constexpr (std::is_same_v<T, float>) {
4706 }
else if constexpr (std::is_same_v<T, double>) {
4708 }
else if constexpr (std::is_same_v<T, vec2>) {
4710 }
else if constexpr (std::is_same_v<T, vec3>) {
4712 }
else if constexpr (std::is_same_v<T, vec4>) {
4714 }
else if constexpr (std::is_same_v<T, int2>) {
4716 }
else if constexpr (std::is_same_v<T, int3>) {
4718 }
else if constexpr (std::is_same_v<T, int4>) {
4720 }
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 *>) {
4723 registerOrValidateObjectDataType<T>(label, data_type);
4727 std::string label_str = std::string(label);
4729 size_t total_objects = 0;
4732 if (caching_enabled) {
4734 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4735 for (
const auto &j: objIDs) {
4736 for (
uint objID: j) {
4738 if (objects.at(objID)->doesObjectDataExist(label)) {
4739 T old_cached_value{};
4740 objects.at(objID)->getObjectData(label, old_cached_value);
4745 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4746 for (
const auto &j: objIDs) {
4747 for (
uint objID: j) {
4749 if (objects.at(objID)->doesObjectDataExist(label)) {
4750 std::string old_cached_value;
4751 objects.at(objID)->getObjectData(label, old_cached_value);
4759 for (
const auto &j: objIDs) {
4760 total_objects += j.size();
4764 for (
const auto &j: objIDs) {
4765 for (
uint objID: j) {
4766 if (!objects.at(objID)->doesObjectDataExist(label)) {
4767 incrementObjectDataLabelCounter(label);
4773#pragma omp parallel for
4775 for (
int j = 0; j < (int) objIDs.size(); ++j) {
4776 for (
size_t i = 0; i < objIDs[j].size(); ++i) {
4777 objects.at(objIDs[j][i])->setObjectData(label, data);
4782 if (caching_enabled) {
4783 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4785 for (
size_t i = 0; i < total_objects; ++i) {
4788 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4790 for (
size_t i = 0; i < total_objects; ++i) {
4804 template<
typename T>
4805 void setObjectData(
const std::vector<std::vector<std::vector<uint>>> &objIDs,
const char *label,
const T &data) {
4806 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> ||
4807 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 *>,
4808 "Context::setObjectData() was called with an unsupported type.");
4811 if (!objIDs.empty() && !objIDs[0].empty() && !objIDs[0][0].empty()) {
4813 if constexpr (std::is_same_v<T, int>) {
4815 }
else if constexpr (std::is_same_v<T, uint>) {
4817 }
else if constexpr (std::is_same_v<T, float>) {
4819 }
else if constexpr (std::is_same_v<T, double>) {
4821 }
else if constexpr (std::is_same_v<T, vec2>) {
4823 }
else if constexpr (std::is_same_v<T, vec3>) {
4825 }
else if constexpr (std::is_same_v<T, vec4>) {
4827 }
else if constexpr (std::is_same_v<T, int2>) {
4829 }
else if constexpr (std::is_same_v<T, int3>) {
4831 }
else if constexpr (std::is_same_v<T, int4>) {
4833 }
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 *>) {
4836 registerOrValidateObjectDataType<T>(label, data_type);
4840 std::string label_str = std::string(label);
4842 size_t total_objects = 0;
4845 if (caching_enabled) {
4847 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4848 for (
const auto &k: objIDs) {
4849 for (
const auto &j: k) {
4850 for (
uint objID: j) {
4852 if (objects.at(objID)->doesObjectDataExist(label)) {
4853 T old_cached_value{};
4854 objects.at(objID)->getObjectData(label, old_cached_value);
4860 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4861 for (
const auto &k: objIDs) {
4862 for (
const auto &j: k) {
4863 for (
uint objID: j) {
4865 if (objects.at(objID)->doesObjectDataExist(label)) {
4866 std::string old_cached_value;
4867 objects.at(objID)->getObjectData(label, old_cached_value);
4876 for (
const auto &k: objIDs) {
4877 for (
const auto &j: k) {
4878 total_objects += j.size();
4883 for (
const auto &k: objIDs) {
4884 for (
const auto &j: k) {
4885 for (
uint objID: j) {
4886 if (!objects.at(objID)->doesObjectDataExist(label)) {
4887 incrementObjectDataLabelCounter(label);
4894#pragma omp parallel for
4896 for (
int k = 0; k < (int) objIDs.size(); ++k) {
4897 for (
size_t j = 0; j < objIDs[k].size(); ++j) {
4898 for (
size_t i = 0; i < objIDs[k][j].size(); ++i) {
4899 uint objID = objIDs[k][j][i];
4900 objects.at(objID)->setObjectData(label, data);
4906 if (caching_enabled) {
4907 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4909 for (
size_t i = 0; i < total_objects; ++i) {
4912 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4914 for (
size_t i = 0; i < total_objects; ++i) {
4929 template<
typename T>
4932 if (objects.find(objID) == objects.end()) {
4933 helios_runtime_error(
"ERROR (Context::setObjectData): Object ID of " + std::to_string(objID) +
" does not exist in the Context.");
4936 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> ||
4937 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 *>,
4938 "Context::setObjectData() was called with an unsupported type.");
4942 if constexpr (std::is_same_v<T, int>) {
4944 }
else if constexpr (std::is_same_v<T, uint>) {
4946 }
else if constexpr (std::is_same_v<T, float>) {
4948 }
else if constexpr (std::is_same_v<T, double>) {
4950 }
else if constexpr (std::is_same_v<T, vec2>) {
4952 }
else if constexpr (std::is_same_v<T, vec3>) {
4954 }
else if constexpr (std::is_same_v<T, vec4>) {
4956 }
else if constexpr (std::is_same_v<T, int2>) {
4958 }
else if constexpr (std::is_same_v<T, int3>) {
4960 }
else if constexpr (std::is_same_v<T, int4>) {
4962 }
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 *>) {
4965 registerOrValidateObjectDataType<T>(label, data_type);
4967 objects.at(objID)->setObjectData(label, data);
4978 template<
typename T>
4979 void setObjectData(
const std::vector<uint> &objIDs,
const char *label,
const std::vector<T> &data) {
4981 if (objIDs.size() != data.size()) {
4982 helios_runtime_error(
"ERROR (Context::setObjectData): Object IDs and data vectors must be the same size.");
4985 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> ||
4986 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 *>,
4987 "Context::setObjectData() was called with an unsupported type.");
4990 if (!objIDs.empty()) {
4992 if constexpr (std::is_same_v<T, int>) {
4994 }
else if constexpr (std::is_same_v<T, uint>) {
4996 }
else if constexpr (std::is_same_v<T, float>) {
4998 }
else if constexpr (std::is_same_v<T, double>) {
5000 }
else if constexpr (std::is_same_v<T, vec2>) {
5002 }
else if constexpr (std::is_same_v<T, vec3>) {
5004 }
else if constexpr (std::is_same_v<T, vec4>) {
5006 }
else if constexpr (std::is_same_v<T, int2>) {
5008 }
else if constexpr (std::is_same_v<T, int3>) {
5010 }
else if constexpr (std::is_same_v<T, int4>) {
5012 }
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 *>) {
5015 registerOrValidateObjectDataType<T>(label, data_type);
5018 for (
uint objID: objIDs) {
5019 if (!objects.at(objID)->doesObjectDataExist(label)) {
5020 incrementObjectDataLabelCounter(label);
5025#pragma omp parallel for
5027 for (
int i = 0; i < (int) objIDs.size(); ++i) {
5028 objects.at(objIDs[i])->setObjectData(label, data[i]);
5049 template<
typename T>
5052 if (objects.find(objID) == objects.end()) {
5053 helios_runtime_error(
"ERROR (Context::getObjectData): Object ID of " + std::to_string(objID) +
" does not exist in the Context.");
5056 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> ||
5057 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 *>,
5058 "Context::getObjectData() was called with an unsupported type.");
5059 objects.at(objID)->getObjectData(label, data);
5070 template<
typename T>
5073 if (objects.find(objID) == objects.end()) {
5074 helios_runtime_error(
"ERROR (Context::getObjectData): Object ID of " + std::to_string(objID) +
" does not exist in the Context.");
5077 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> ||
5078 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 *>,
5079 "Context::getObjectData() was called with an unsupported type.");
5080 objects.at(objID)->getObjectData(label, data);
5130 void clearObjectData(
const std::vector<uint> &objIDs,
const char *label);
5177 template<
typename T>
5179 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> ||
5180 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>,
5181 "Context::setGlobalData() was called with an unsupported type.");
5183 globaldata[label].size = 1;
5184 if constexpr (std::is_same_v<T, int>) {
5185 globaldata[label].global_data_int = {data};
5187 }
else if constexpr (std::is_same_v<T, uint>) {
5188 globaldata[label].global_data_uint = {data};
5190 }
else if constexpr (std::is_same_v<T, float>) {
5191 globaldata[label].global_data_float = {data};
5193 }
else if constexpr (std::is_same_v<T, double>) {
5194 globaldata[label].global_data_double = {data};
5196 }
else if constexpr (std::is_same_v<T, vec2>) {
5197 globaldata[label].global_data_vec2 = {data};
5199 }
else if constexpr (std::is_same_v<T, vec3>) {
5200 globaldata[label].global_data_vec3 = {data};
5202 }
else if constexpr (std::is_same_v<T, vec4>) {
5203 globaldata[label].global_data_vec4 = {data};
5205 }
else if constexpr (std::is_same_v<T, int2>) {
5206 globaldata[label].global_data_int2 = {data};
5208 }
else if constexpr (std::is_same_v<T, int3>) {
5209 globaldata[label].global_data_int3 = {data};
5211 }
else if constexpr (std::is_same_v<T, int4>) {
5212 globaldata[label].global_data_int4 = {data};
5214 }
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 *>) {
5215 globaldata[label].global_data_string = {data};
5217 }
else if constexpr (std::is_same_v<T, bool>) {
5218 globaldata[label].global_data_bool = {data};
5221 globaldata[label].version++;
5229 template<
typename T>
5231 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> ||
5232 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>,
5233 "Context::setGlobalData() was called with an unsupported type.");
5235 globaldata[label].size = data.size();
5236 if constexpr (std::is_same_v<T, int>) {
5237 globaldata[label].global_data_int = data;
5239 }
else if constexpr (std::is_same_v<T, uint>) {
5240 globaldata[label].global_data_uint = data;
5242 }
else if constexpr (std::is_same_v<T, float>) {
5243 globaldata[label].global_data_float = data;
5245 }
else if constexpr (std::is_same_v<T, double>) {
5246 globaldata[label].global_data_double = data;
5248 }
else if constexpr (std::is_same_v<T, vec2>) {
5249 globaldata[label].global_data_vec2 = data;
5251 }
else if constexpr (std::is_same_v<T, vec3>) {
5252 globaldata[label].global_data_vec3 = data;
5254 }
else if constexpr (std::is_same_v<T, vec4>) {
5255 globaldata[label].global_data_vec4 = data;
5257 }
else if constexpr (std::is_same_v<T, int2>) {
5258 globaldata[label].global_data_int2 = data;
5260 }
else if constexpr (std::is_same_v<T, int3>) {
5261 globaldata[label].global_data_int3 = data;
5263 }
else if constexpr (std::is_same_v<T, int4>) {
5264 globaldata[label].global_data_int4 = data;
5266 }
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 *>) {
5267 globaldata[label].global_data_string = data;
5269 }
else if constexpr (std::is_same_v<T, bool>) {
5270 globaldata[label].global_data_bool = data;
5273 globaldata[label].version++;
5281 template<
typename T>
5284 if constexpr (std::is_same_v<T, std::vector<int>>) {
5287 data = globaldata.at(label).global_data_int;
5289 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int, but data " + std::string(label) +
" does not have type int.");
5291 }
else if constexpr (std::is_same_v<T, std::vector<uint>>) {
5294 data = globaldata.at(label).global_data_uint;
5296 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type uint, but data " + std::string(label) +
" does not have type uint.");
5298 }
else if constexpr (std::is_same_v<T, std::vector<float>>) {
5301 data = globaldata.at(label).global_data_float;
5303 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type float, but data " + std::string(label) +
" does not have type float.");
5305 }
else if constexpr (std::is_same_v<T, std::vector<double>>) {
5308 data = globaldata.at(label).global_data_double;
5310 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type double, but data " + std::string(label) +
" does not have type double.");
5312 }
else if constexpr (std::is_same_v<T, std::vector<vec2>>) {
5315 data = globaldata.at(label).global_data_vec2;
5317 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec2, but data " + std::string(label) +
" does not have type vec2.");
5319 }
else if constexpr (std::is_same_v<T, std::vector<vec3>>) {
5322 data = globaldata.at(label).global_data_vec3;
5324 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec3, but data " + std::string(label) +
" does not have type vec3.");
5326 }
else if constexpr (std::is_same_v<T, std::vector<vec4>>) {
5329 data = globaldata.at(label).global_data_vec4;
5331 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec4, but data " + std::string(label) +
" does not have type vec4.");
5333 }
else if constexpr (std::is_same_v<T, std::vector<int2>>) {
5336 data = globaldata.at(label).global_data_int2;
5338 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int2, but data " + std::string(label) +
" does not have type int2.");
5340 }
else if constexpr (std::is_same_v<T, std::vector<int3>>) {
5343 data = globaldata.at(label).global_data_int3;
5345 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int3, but data " + std::string(label) +
" does not have type int3.");
5347 }
else if constexpr (std::is_same_v<T, std::vector<int4>>) {
5350 data = globaldata.at(label).global_data_int4;
5352 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int4, but data " + std::string(label) +
" does not have type int4.");
5354 }
else if constexpr (std::is_same_v<T, std::vector<std::string>>) {
5357 data = globaldata.at(label).global_data_string;
5359 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type string, but data " + std::string(label) +
" does not have type string.");
5361 }
else if constexpr (std::is_same_v<T, int>) {
5364 data = globaldata.at(label).global_data_int.front();
5366 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int, but data " + std::string(label) +
" does not have type int.");
5368 }
else if constexpr (std::is_same_v<T, uint>) {
5371 data = globaldata.at(label).global_data_uint.front();
5373 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type uint, but data " + std::string(label) +
" does not have type uint.");
5375 }
else if constexpr (std::is_same_v<T, float>) {
5378 data = globaldata.at(label).global_data_float.front();
5380 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type float, but data " + std::string(label) +
" does not have type float.");
5382 }
else if constexpr (std::is_same_v<T, double>) {
5385 data = globaldata.at(label).global_data_double.front();
5387 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type double, but data " + std::string(label) +
" does not have type double.");
5389 }
else if constexpr (std::is_same_v<T, vec2>) {
5392 data = globaldata.at(label).global_data_vec2.front();
5394 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec2, but data " + std::string(label) +
" does not have type vec2.");
5396 }
else if constexpr (std::is_same_v<T, vec3>) {
5399 data = globaldata.at(label).global_data_vec3.front();
5401 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec3, but data " + std::string(label) +
" does not have type vec3.");
5403 }
else if constexpr (std::is_same_v<T, vec4>) {
5406 data = globaldata.at(label).global_data_vec4.front();
5408 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec4, but data " + std::string(label) +
" does not have type vec4.");
5410 }
else if constexpr (std::is_same_v<T, int2>) {
5413 data = globaldata.at(label).global_data_int2.front();
5415 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int2, but data " + std::string(label) +
" does not have type int2.");
5417 }
else if constexpr (std::is_same_v<T, int3>) {
5420 data = globaldata.at(label).global_data_int3.front();
5422 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int3, but data " + std::string(label) +
" does not have type int3.");
5424 }
else if constexpr (std::is_same_v<T, int4>) {
5427 data = globaldata.at(label).global_data_int4.front();
5429 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int4, but data " + std::string(label) +
" does not have type int4.");
5431 }
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 *>) {
5434 data = globaldata.at(label).global_data_string.front();
5436 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type string, but data " + std::string(label) +
" does not have type string.");
5438 }
else if constexpr (std::is_same_v<T, bool>) {
5441 data = globaldata.at(label).global_data_bool.front();
5443 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type bool, but data " + std::string(label) +
" does not have type bool.");
5446 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> ||
5447 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 *> ||
5448 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>> ||
5449 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>> ||
5450 std::is_same_v<T, std::vector<std::string>> || std::is_same_v<T, std::vector<bool>>,
5451 "CompoundObject::getGlobalData() was called with an unsupported type.");
5586 std::vector<uint>
copyObject(
const std::vector<uint> &ObjIDs);
5618 std::vector<uint>
filterObjectsByData(
const std::vector<uint> &ObjIDs,
const char *object_data,
float threshold,
const char *comparator)
const;
5640 void rotateObject(
uint ObjID,
float rotation_radians,
const char *rotation_axis_xyz)
const;
5648 void rotateObject(
const std::vector<uint> &ObjIDs,
float rotation_radians,
const char *rotation_axis_xyz)
const;
5664 void rotateObject(
const std::vector<uint> &ObjIDs,
float rotation_radians,
const vec3 &rotation_axis_vector)
const;
5673 void rotateObject(
uint ObjID,
float rotation_radians,
const vec3 &rotation_origin,
const vec3 &rotation_axis_vector)
const;
5682 void rotateObject(
const std::vector<uint> &ObjIDs,
float rotation_radians,
const vec3 &rotation_origin,
const vec3 &rotation_axis_vector)
const;
6209 uint addTubeObject(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius);
6221 uint addTubeObject(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const std::vector<RGBcolor> &color);
6234 uint addTubeObject(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const char *texturefile);
6248 uint addTubeObject(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const char *texturefile,
const std::vector<float> &textureuv_ufrac);
6491 std::vector<uint>
addSphere(
uint Ndivs,
const vec3 ¢er,
float radius,
const char *texturefile);
6552 std::vector<uint>
addTube(
uint Ndivs,
const std::vector<vec3> &nodes,
const std::vector<float> &radius);
6564 std::vector<uint>
addTube(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const std::vector<RGBcolor> &color);
6576 std::vector<uint>
addTube(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const char *texturefile);
6612 std::vector<uint>
addBox(
const vec3 ¢er,
const vec3 &size,
const int3 &subdiv,
const char *texturefile);
6625 std::vector<uint>
addBox(
const vec3 ¢er,
const vec3 &size,
const int3 &subdiv,
const RGBcolor &color,
bool reverse_normals);
6638 std::vector<uint>
addBox(
const vec3 ¢er,
const vec3 &size,
const int3 &subdiv,
const char *texturefile,
bool reverse_normals);
6749 std::vector<uint>
addCone(
uint Ndivs,
const vec3 &node0,
const vec3 &node1,
float radius0,
float radius1);
6775 std::vector<uint>
addCone(
uint Ndivs,
const vec3 &node0,
const vec3 &node1,
float radius0,
float radius1,
const char *texturefile);
6925 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);
6984 void cropDomain(std::vector<uint> &UUIDs,
const vec2 &xbounds,
const vec2 &ybounds,
const vec2 &zbounds);
7012 void colorPrimitiveByDataPseudocolor(
const std::vector<uint> &UUIDs,
const std::string &primitive_data,
const std::string &colormap,
uint Ncolors,
float data_min,
float data_max);
7021 std::vector<uint> loadXML(
const char *filename,
bool quiet =
false);
7036 static bool scanXMLForTag(
const std::string &filename,
const std::string &tag,
const std::string &label =
"");
7043 void writeXML(
const char *filename,
bool quiet =
false)
const;
7051 void writeXML(
const char *filename,
const std::vector<uint> &UUIDs,
bool quiet =
false)
const;
7059 void writeXML_byobject(
const char *filename,
const std::vector<uint> &UUIDs,
bool quiet =
false)
const;
7067 void writePrimitiveData(
const std::string &filename,
const std::vector<std::string> &column_format,
bool print_header =
false)
const;
7076 void writePrimitiveData(
const std::string &filename,
const std::vector<std::string> &column_format,
const std::vector<uint> &UUIDs,
bool print_header =
false)
const;
7085 std::vector<uint>
loadPLY(
const char *filename,
bool silent =
false);
7097 std::vector<uint>
loadPLY(
const char *filename,
const vec3 &origin,
float height,
const std::string &upaxis =
"YUP",
bool silent =
false);
7110 std::vector<uint>
loadPLY(
const char *filename,
const vec3 &origin,
float height,
const SphericalCoord &rotation,
const std::string &upaxis =
"YUP",
bool silent =
false);
7122 std::vector<uint>
loadPLY(
const char *filename,
const vec3 &origin,
float height,
const RGBcolor &default_color,
const std::string &upaxis =
"YUP",
bool silent =
false);
7135 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);
7141 void writePLY(
const char *filename)
const;
7148 void writePLY(
const char *filename,
const std::vector<uint> &UUIDs)
const;
7157 std::vector<uint>
loadOBJ(
const char *filename,
bool silent =
false);
7169 std::vector<uint>
loadOBJ(
const char *filename,
const vec3 &origin,
float height,
const SphericalCoord &rotation,
const RGBcolor &default_color,
bool silent =
false);
7182 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);
7204 void writeOBJ(
const std::string &filename,
bool write_normals =
false,
bool silent =
false)
const;
7213 void writeOBJ(
const std::string &filename,
const std::vector<uint> &UUIDs,
bool write_normals =
false,
bool silent =
false)
const;
7223 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;
7233 std::filesystem::path
resolveFilePath(
const std::string &filename)
const;
7242 void setDate(
int day,
int month,
int year);
7257 void setDate(
int Julian_day,
int year);
7287 void setTime(
int minute,
int hour);
7297 void setTime(
int second,
int minute,
int hour);
7495 void calculatePrimitiveDataAreaWeightedSum(
const std::vector<uint> &UUIDs,
const std::string &label,
float &awt_sum)
const;
7503 void calculatePrimitiveDataAreaWeightedSum(
const std::vector<uint> &UUIDs,
const std::string &label,
double &
sum)
const;
7511 void calculatePrimitiveDataAreaWeightedSum(
const std::vector<uint> &UUIDs,
const std::string &label,
helios::vec2 &
sum)
const;
7519 void calculatePrimitiveDataAreaWeightedSum(
const std::vector<uint> &UUIDs,
const std::string &label,
helios::vec3 &
sum)
const;
7527 void calculatePrimitiveDataAreaWeightedSum(
const std::vector<uint> &UUIDs,
const std::string &label,
helios::vec4 &
sum)
const;
7536 void scalePrimitiveData(
const std::vector<uint> &UUIDs,
const std::string &label,
float scaling_factor);
7589 void aggregatePrimitiveDataSum(
const std::vector<uint> &UUIDs,
const std::vector<std::string> &primitive_data_labels,
const std::string &result_primitive_data_label);
7598 void aggregatePrimitiveDataProduct(
const std::vector<uint> &UUIDs,
const std::vector<std::string> &primitive_data_labels,
const std::string &result_primitive_data_label);
7616 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
float filter_value,
const std::string &comparator)
const;
7627 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
double filter_value,
const std::string &comparator)
const;
7638 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
int filter_value,
const std::string &comparator)
const;
7649 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
uint filter_value,
const std::string &comparator)
const;
7659 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
const std::string &filter_value)
const;
7670 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
float filter_value,
const std::string &comparator)
const;
7681 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
double filter_value,
const std::string &comparator)
const;
7692 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
int filter_value,
const std::string &comparator)
const;
7703 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
uint filter_value,
const std::string &comparator)
const;
7713 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
const std::string &filter_value)
const;
7744 std::vector<RGBcolor>
generateColormap(
const std::vector<helios::RGBcolor> &ctable,
const std::vector<float> &cfrac,
uint Ncolors);
7748 template<
typename T>
7749 void storeDataWithTypeCasting(
uint UUID,
const char *label,
const T &data,
HeliosDataType target_type) {
7751 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>) {
7752 if (target_type == HELIOS_TYPE_INT) {
7753 primitives.at(UUID)->setPrimitiveData(label,
static_cast<int>(data));
7754 }
else if (target_type == HELIOS_TYPE_UINT) {
7755 primitives.at(UUID)->setPrimitiveData(label,
static_cast<uint>(data));
7756 }
else if (target_type == HELIOS_TYPE_FLOAT) {
7757 primitives.at(UUID)->setPrimitiveData(label,
static_cast<float>(data));
7758 }
else if (target_type == HELIOS_TYPE_DOUBLE) {
7759 primitives.at(UUID)->setPrimitiveData(label,
static_cast<double>(data));
7762 primitives.at(UUID)->setPrimitiveData(label, data);
7766 primitives.at(UUID)->setPrimitiveData(label, data);
7770 template<
typename T>
7771 void storeObjectDataWithTypeCasting(
uint objID,
const char *label,
const T &data, HeliosDataType target_type) {
7773 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>) {
7774 if (target_type == HELIOS_TYPE_INT) {
7775 objects.at(objID)->setObjectData(label,
static_cast<int>(data));
7776 }
else if (target_type == HELIOS_TYPE_UINT) {
7777 objects.at(objID)->setObjectData(label,
static_cast<uint>(data));
7778 }
else if (target_type == HELIOS_TYPE_FLOAT) {
7779 objects.at(objID)->setObjectData(label,
static_cast<float>(data));
7780 }
else if (target_type == HELIOS_TYPE_DOUBLE) {
7781 objects.at(objID)->setObjectData(label,
static_cast<double>(data));
7784 objects.at(objID)->setObjectData(label, data);
7788 objects.at(objID)->setObjectData(label, data);
7792 template<
typename T>
7793 HeliosDataType registerOrValidatePrimitiveDataType(
const std::string &label, HeliosDataType data_type) {
7794 auto it = primitive_data_type_registry.find(label);
7795 if (it == primitive_data_type_registry.end()) {
7797 primitive_data_type_registry[label] = data_type;
7802 if (expected_type != data_type) {
7804 if (!isTypeCastingSupported(data_type, expected_type)) {
7805 helios_runtime_error(
"ERROR (Context::setPrimitiveData): Primitive data '" + label +
"' already exists with type '" + dataTypeToString(expected_type) +
"', so it cannot be assigned a value with type '" +
7806 dataTypeToString(data_type) +
"'. To assign a value of a different type, first remove the existing data from every primitive by calling Context::clearPrimitiveData(\"" + label +
"\").");
7808 std::cerr <<
"WARNING (Context::setPrimitiveData): Primitive data '" + label +
"' already exists with type '" + dataTypeToString(expected_type) +
"'; the assigned value of type '" + dataTypeToString(data_type) +
7809 "' will be cast to '" + dataTypeToString(expected_type) +
"'. Consider using consistent types."
7813 return expected_type;
7817 template<
typename T>
7818 HeliosDataType registerOrValidateObjectDataType(
const std::string &label, HeliosDataType data_type) {
7819 auto it = object_data_type_registry.find(label);
7820 if (it == object_data_type_registry.end()) {
7822 object_data_type_registry[label] = data_type;
7827 if (expected_type != data_type) {
7829 if (!isTypeCastingSupported(data_type, expected_type)) {
7830 helios_runtime_error(
"ERROR (Context::setObjectData): Object data '" + label +
"' already exists with type '" + dataTypeToString(expected_type) +
"', so it cannot be assigned a value with type '" +
7831 dataTypeToString(data_type) +
"'. To assign a value of a different type, first remove the existing data from every object by calling Context::clearObjectData(\"" + label +
"\").");
7833 std::cerr <<
"WARNING (Context::setObjectData): Object data '" + label +
"' already exists with type '" + dataTypeToString(expected_type) +
"'; the assigned value of type '" + dataTypeToString(data_type) +
7834 "' will be cast to '" + dataTypeToString(expected_type) +
"'. Consider using consistent types."
7838 return expected_type;
7845 template<
typename T>
7847 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 *>) {
7848 std::string string_value = (std::is_same_v<T, std::string>) ? value : std::string(value);
7849 primitive_string_value_registry[label][string_value]++;
7850 }
else if constexpr (std::is_same_v<T, int>) {
7851 primitive_int_value_registry[label][value]++;
7852 }
else if constexpr (std::is_same_v<T, uint>) {
7853 primitive_uint_value_registry[label][value]++;
7858 template<
typename T>
7860 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 *>) {
7861 std::string string_value = (std::is_same_v<T, std::string>) ? value : std::string(value);
7862 auto label_it = primitive_string_value_registry.find(label);
7863 if (label_it != primitive_string_value_registry.end()) {
7864 auto value_it = label_it->second.find(string_value);
7865 if (value_it != label_it->second.end() && value_it->second > 0) {
7867 if (value_it->second == 0) {
7868 label_it->second.erase(value_it);
7869 if (label_it->second.empty()) {
7870 primitive_string_value_registry.erase(label_it);
7875 }
else if constexpr (std::is_same_v<T, int>) {
7876 auto label_it = primitive_int_value_registry.find(label);
7877 if (label_it != primitive_int_value_registry.end()) {
7878 auto value_it = label_it->second.find(value);
7879 if (value_it != label_it->second.end() && value_it->second > 0) {
7881 if (value_it->second == 0) {
7882 label_it->second.erase(value_it);
7883 if (label_it->second.empty()) {
7884 primitive_int_value_registry.erase(label_it);
7889 }
else if constexpr (std::is_same_v<T, uint>) {
7890 auto label_it = primitive_uint_value_registry.find(label);
7891 if (label_it != primitive_uint_value_registry.end()) {
7892 auto value_it = label_it->second.find(value);
7893 if (value_it != label_it->second.end() && value_it->second > 0) {
7895 if (value_it->second == 0) {
7896 label_it->second.erase(value_it);
7897 if (label_it->second.empty()) {
7898 primitive_uint_value_registry.erase(label_it);
7907 template<
typename T>
7909 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 *>) {
7910 std::string string_value = (std::is_same_v<T, std::string>) ? value : std::string(value);
7911 object_string_value_registry[label][string_value]++;
7912 }
else if constexpr (std::is_same_v<T, int>) {
7913 object_int_value_registry[label][value]++;
7914 }
else if constexpr (std::is_same_v<T, uint>) {
7915 object_uint_value_registry[label][value]++;
7920 template<
typename T>
7922 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 *>) {
7923 std::string string_value = (std::is_same_v<T, std::string>) ? value : std::string(value);
7924 auto label_it = object_string_value_registry.find(label);
7925 if (label_it != object_string_value_registry.end()) {
7926 auto value_it = label_it->second.find(string_value);
7927 if (value_it != label_it->second.end() && value_it->second > 0) {
7929 if (value_it->second == 0) {
7930 label_it->second.erase(value_it);
7931 if (label_it->second.empty()) {
7932 object_string_value_registry.erase(label_it);
7937 }
else if constexpr (std::is_same_v<T, int>) {
7938 auto label_it = object_int_value_registry.find(label);
7939 if (label_it != object_int_value_registry.end()) {
7940 auto value_it = label_it->second.find(value);
7941 if (value_it != label_it->second.end() && value_it->second > 0) {
7943 if (value_it->second == 0) {
7944 label_it->second.erase(value_it);
7945 if (label_it->second.empty()) {
7946 object_int_value_registry.erase(label_it);
7951 }
else if constexpr (std::is_same_v<T, uint>) {
7952 auto label_it = object_uint_value_registry.find(label);
7953 if (label_it != object_uint_value_registry.end()) {
7954 auto value_it = label_it->second.find(value);
7955 if (value_it != label_it->second.end() && value_it->second > 0) {
7957 if (value_it->second == 0) {
7958 label_it->second.erase(value_it);
7959 if (label_it->second.empty()) {
7960 object_uint_value_registry.erase(label_it);
7977 template<
typename T>
7979 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.");
7982 helios_runtime_error(
"ERROR (Context::getUniquePrimitiveDataValues): Value-level caching is not enabled for primitive data label '" + label +
"'. Use enablePrimitiveDataValueCaching() first.");
7987 if constexpr (std::is_same_v<T, std::string>) {
7988 auto it = primitive_string_value_registry.find(label);
7989 if (it != primitive_string_value_registry.end()) {
7990 values.reserve(it->second.size());
7991 for (
const auto &[value, count]: it->second) {
7993 values.push_back(value);
7997 }
else if constexpr (std::is_same_v<T, int>) {
7998 auto it = primitive_int_value_registry.find(label);
7999 if (it != primitive_int_value_registry.end()) {
8000 values.reserve(it->second.size());
8001 for (
const auto &[value, count]: it->second) {
8003 values.push_back(value);
8007 }
else if constexpr (std::is_same_v<T, uint>) {
8008 auto it = primitive_uint_value_registry.find(label);
8009 if (it != primitive_uint_value_registry.end()) {
8010 values.reserve(it->second.size());
8011 for (
const auto &[value, count]: it->second) {
8013 values.push_back(value);
8027 template<
typename T>
8029 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.");
8032 helios_runtime_error(
"ERROR (Context::getUniqueObjectDataValues): Value-level caching is not enabled for object data label '" + label +
"'. Use enableObjectDataValueCaching() first.");
8037 if constexpr (std::is_same_v<T, std::string>) {
8038 auto it = object_string_value_registry.find(label);
8039 if (it != object_string_value_registry.end()) {
8040 values.reserve(it->second.size());
8041 for (
const auto &[value, count]: it->second) {
8043 values.push_back(value);
8047 }
else if constexpr (std::is_same_v<T, int>) {
8048 auto it = object_int_value_registry.find(label);
8049 if (it != object_int_value_registry.end()) {
8050 values.reserve(it->second.size());
8051 for (
const auto &[value, count]: it->second) {
8053 values.push_back(value);
8057 }
else if constexpr (std::is_same_v<T, uint>) {
8058 auto it = object_uint_value_registry.find(label);
8059 if (it != object_uint_value_registry.end()) {
8060 values.reserve(it->second.size());
8061 for (
const auto &[value, count]: it->second) {
8063 values.push_back(value);