2042 [[nodiscard]] Primitive *getPrimitivePointer_private(
uint UUID)
const;
2049 [[nodiscard]] Patch *getPatchPointer_private(
uint UUID)
const;
2057 [[nodiscard]] Triangle *getTrianglePointer_private(
uint UUID)
const;
2064 [[nodiscard]] Voxel *getVoxelPointer_private(
uint UUID)
const;
2078 [[nodiscard]]
Tile *getTileObjectPointer_private(
uint ObjID)
const;
2085 [[nodiscard]]
Sphere *getSphereObjectPointer_private(
uint ObjID)
const;
2092 [[nodiscard]]
Tube *getTubeObjectPointer_private(
uint ObjID)
const;
2099 [[nodiscard]]
Box *getBoxObjectPointer_private(
uint ObjID)
const;
2106 [[nodiscard]]
Disk *getDiskObjectPointer_private(
uint ObjID)
const;
2113 [[nodiscard]]
Polymesh *getPolymeshObjectPointer_private(
uint ObjID)
const;
2120 [[nodiscard]]
Cone *getConeObjectPointer_private(
uint ObjID)
const;
2123 void invalidateAllUUIDsCache()
const {
2124 all_uuids_cache_valid =
false;
2131 std::unordered_map<uint, Primitive *> primitives;
2134 mutable std::vector<uint> cached_all_uuids;
2136 mutable bool all_uuids_cache_valid =
false;
2139 std::vector<uint> dirty_deleted_primitives;
2142 std::unordered_map<uint, CompoundObject *> objects;
2145 std::map<std::string, std::vector<float>> timeseries_data;
2149 std::map<std::string, std::vector<double>> timeseries_datevalue;
2153 std::map<std::string, Texture> textures;
2155 void addTexture(
const char *texture_file);
2158 bool doesTextureFileExist(
const char *texture_file)
const;
2160 bool validateTextureFileExtenstion(
const char *texture_file)
const;
2164 std::map<std::string, GlobalData> globaldata;
2166 std::unordered_map<std::string, size_t> primitive_data_label_counts;
2167 std::unordered_map<std::string, size_t> object_data_label_counts;
2172 std::unordered_map<std::string, HeliosDataType> primitive_data_type_registry;
2175 std::unordered_map<std::string, HeliosDataType> object_data_type_registry;
2180 std::unordered_map<std::string, std::unordered_map<std::string, size_t>> primitive_string_value_registry;
2181 std::unordered_map<std::string, std::unordered_map<int, size_t>> primitive_int_value_registry;
2182 std::unordered_map<std::string, std::unordered_map<uint, size_t>> primitive_uint_value_registry;
2185 std::unordered_map<std::string, std::unordered_map<std::string, size_t>> object_string_value_registry;
2186 std::unordered_map<std::string, std::unordered_map<int, size_t>> object_int_value_registry;
2187 std::unordered_map<std::string, std::unordered_map<uint, size_t>> object_uint_value_registry;
2190 std::unordered_set<std::string> cached_primitive_data_labels;
2191 std::unordered_set<std::string> cached_object_data_labels;
2197 void incrementPrimitiveDataLabelCounter(
const std::string &primitive_data_label);
2203 void decrementPrimitiveDataLabelCounter(
const std::string &primitive_data_label);
2210 void incrementObjectDataLabelCounter(
const std::string &object_data_label);
2216 void decrementObjectDataLabelCounter(
const std::string &object_data_label);
2242 std::minstd_rand0 generator;
2245 std::uniform_real_distribution<float> unif_distribution;
2248 std::normal_distribution<float> norm_distribution;
2252 std::vector<std::string> XMLfiles;
2254 struct OBJmaterial {
2257 std::string texture;
2259 bool textureHasTransparency =
false;
2260 bool textureColorIsOverridden =
false;
2262 OBJmaterial(
const RGBcolor &a_color, std::string a_texture,
uint a_materialID) : color{a_color}, texture{std::move(a_texture)}, materialID{a_materialID} {};
2265 std::map<std::string, OBJmaterial> loadMTL(
const std::string &filebase,
const std::string &material_file);
2267 void loadPData(pugi::xml_node p,
uint UUID);
2269 void loadOData(pugi::xml_node p,
uint ID);
2271 void loadOsubPData(pugi::xml_node p,
uint ID);
2273 void writeDataToXMLstream(
const char *data_group,
const std::vector<std::string> &data_labels,
void *ptr, std::ofstream &outfile)
const;
2280 uint currentObjectID;
2289 static void out_of_memory_handler();
2295 static void install_out_of_memory_handler();
2316 static int selfTest(
int argc,
char **argv);
2568 void rotatePrimitive(
const std::vector<uint> &UUIDs,
float rotation_rad,
const char *axis);
2584 void rotatePrimitive(
const std::vector<uint> &UUIDs,
float rotation_rad,
const vec3 &axis);
2690 std::vector<uint>
copyPrimitive(
const std::vector<uint> &UUIDs);
2783 [[nodiscard]]
size_t getPrimitiveCount(
bool include_hidden_primitives =
true)
const;
2790 [[nodiscard]]
size_t getTriangleCount(
bool include_hidden_primitives =
true)
const;
2797 [[nodiscard]]
size_t getPatchCount(
bool include_hidden_primitives =
true)
const;
2800 [[nodiscard]] std::vector<uint>
getAllUUIDs()
const;
2807 [[nodiscard]] std::vector<uint>
getDirtyUUIDs(
bool include_deleted_UUIDs =
false)
const;
2862 void cleanDeletedUUIDs(std::vector<std::vector<std::vector<uint>>> &UUIDs)
const;
2873 template<
typename T>
2876 if (primitives.find(UUID) == primitives.end()) {
2877 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
2881 std::string label_str = std::string(label);
2882 bool had_cached_value =
false;
2885 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
2887 T old_cached_value{};
2888 primitives.at(UUID)->getPrimitiveData(label, old_cached_value);
2890 had_cached_value =
true;
2892 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
2894 std::string old_cached_value;
2895 primitives.at(UUID)->getPrimitiveData(label, old_cached_value);
2897 had_cached_value =
true;
2901 if (!primitives.at(UUID)->doesPrimitiveDataExist(label)) {
2902 incrementPrimitiveDataLabelCounter(label);
2907 if constexpr (std::is_same_v<T, int>) {
2909 }
else if constexpr (std::is_same_v<T, uint>) {
2911 }
else if constexpr (std::is_same_v<T, float>) {
2913 }
else if constexpr (std::is_same_v<T, double>) {
2915 }
else if constexpr (std::is_same_v<T, vec2>) {
2917 }
else if constexpr (std::is_same_v<T, vec3>) {
2919 }
else if constexpr (std::is_same_v<T, vec4>) {
2921 }
else if constexpr (std::is_same_v<T, int2>) {
2923 }
else if constexpr (std::is_same_v<T, int3>) {
2925 }
else if constexpr (std::is_same_v<T, int4>) {
2927 }
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 *>) {
2930 HeliosDataType target_type = registerOrValidatePrimitiveDataType<T>(label, data_type);
2933 if (target_type != data_type && isTypeCastingSupported(data_type, target_type)) {
2934 storeDataWithTypeCasting(UUID, label, data, target_type);
2936 primitives.at(UUID)->setPrimitiveData(label, data);
2941 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
2943 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
2948 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
2950 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
2963 template<
typename T>
2966 if (primitives.find(UUID) == primitives.end()) {
2967 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
2970 if (!primitives.at(UUID)->doesPrimitiveDataExist(label)) {
2971 incrementPrimitiveDataLabelCounter(label);
2976 if constexpr (std::is_same_v<T, int>) {
2978 }
else if constexpr (std::is_same_v<T, uint>) {
2980 }
else if constexpr (std::is_same_v<T, float>) {
2982 }
else if constexpr (std::is_same_v<T, double>) {
2984 }
else if constexpr (std::is_same_v<T, vec2>) {
2986 }
else if constexpr (std::is_same_v<T, vec3>) {
2988 }
else if constexpr (std::is_same_v<T, vec4>) {
2990 }
else if constexpr (std::is_same_v<T, int2>) {
2992 }
else if constexpr (std::is_same_v<T, int3>) {
2994 }
else if constexpr (std::is_same_v<T, int4>) {
2996 }
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 *>) {
2999 registerOrValidatePrimitiveDataType<T>(label, data_type);
3001 primitives.at(UUID)->setPrimitiveData(label, data);
3012 template<
typename T>
3013 void setPrimitiveData(
const std::vector<uint> &UUIDs,
const char *label,
const std::vector<T> &data) {
3015 if (UUIDs.size() != data.size()) {
3016 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUIDs and data vectors must be the same size.");
3022 if (!UUIDs.empty()) {
3024 if constexpr (std::is_same_v<T, int>) {
3026 }
else if constexpr (std::is_same_v<T, uint>) {
3028 }
else if constexpr (std::is_same_v<T, float>) {
3030 }
else if constexpr (std::is_same_v<T, double>) {
3032 }
else if constexpr (std::is_same_v<T, vec2>) {
3034 }
else if constexpr (std::is_same_v<T, vec3>) {
3036 }
else if constexpr (std::is_same_v<T, vec4>) {
3038 }
else if constexpr (std::is_same_v<T, int2>) {
3040 }
else if constexpr (std::is_same_v<T, int3>) {
3042 }
else if constexpr (std::is_same_v<T, int4>) {
3044 }
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 *>) {
3047 target_type = registerOrValidatePrimitiveDataType<T>(label, data_type);
3050 for (
uint UUID: UUIDs) {
3052 if (primitives.find(UUID) == primitives.end()) {
3053 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3056 if (!primitives.at(UUID)->doesPrimitiveDataExist(label)) {
3057 incrementPrimitiveDataLabelCounter(label);
3062#pragma omp parallel for
3064 for (
int i = 0; i < (int) UUIDs.size(); ++i) {
3065 primitives.at(UUIDs[i])->setPrimitiveData(label, data[i]);
3076 template<
typename T>
3080 if (!UUIDs.empty()) {
3082 if constexpr (std::is_same_v<T, int>) {
3084 }
else if constexpr (std::is_same_v<T, uint>) {
3086 }
else if constexpr (std::is_same_v<T, float>) {
3088 }
else if constexpr (std::is_same_v<T, double>) {
3090 }
else if constexpr (std::is_same_v<T, vec2>) {
3092 }
else if constexpr (std::is_same_v<T, vec3>) {
3094 }
else if constexpr (std::is_same_v<T, vec4>) {
3096 }
else if constexpr (std::is_same_v<T, int2>) {
3098 }
else if constexpr (std::is_same_v<T, int3>) {
3100 }
else if constexpr (std::is_same_v<T, int4>) {
3102 }
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 *>) {
3105 registerOrValidatePrimitiveDataType<T>(label, data_type);
3108 for (
uint UUID: UUIDs) {
3110 if (primitives.find(UUID) == primitives.end()) {
3111 helios_runtime_error(
"ERROR (Context::setPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3114 if (!primitives.at(UUID)->doesPrimitiveDataExist(label)) {
3115 incrementPrimitiveDataLabelCounter(label);
3120#pragma omp parallel for
3122 for (
int i = 0; i < (int) UUIDs.size(); ++i) {
3123 primitives.at(UUIDs[i])->setPrimitiveData(label, data);
3134 template<
typename T>
3137 if (primitives.find(UUID) == primitives.end()) {
3138 helios_runtime_error(
"ERROR (Context::getPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3141 primitives.at(UUID)->getPrimitiveData(label, data);
3152 template<
typename T>
3155 if (primitives.find(UUID) == primitives.end()) {
3156 helios_runtime_error(
"ERROR (Context::getPrimitiveData): UUID of " + std::to_string(UUID) +
" does not exist in the Context.");
3159 primitives.at(UUID)->getPrimitiveData(label, data);
3338 void hideObject(
const std::vector<uint> &ObjIDs);
3350 void showObject(
const std::vector<uint> &ObjIDs);
3697 template<
typename T>
3700 if (objects.find(objID) == objects.end()) {
3701 helios_runtime_error(
"ERROR (Context::setObjectData): Object ID of " + std::to_string(objID) +
" does not exist in the Context.");
3704 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> ||
3705 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 *>,
3706 "Context::setObjectData() was called with an unsupported type.");
3710 if constexpr (std::is_same_v<T, int>) {
3712 }
else if constexpr (std::is_same_v<T, uint>) {
3714 }
else if constexpr (std::is_same_v<T, float>) {
3716 }
else if constexpr (std::is_same_v<T, double>) {
3718 }
else if constexpr (std::is_same_v<T, vec2>) {
3720 }
else if constexpr (std::is_same_v<T, vec3>) {
3722 }
else if constexpr (std::is_same_v<T, vec4>) {
3724 }
else if constexpr (std::is_same_v<T, int2>) {
3726 }
else if constexpr (std::is_same_v<T, int3>) {
3728 }
else if constexpr (std::is_same_v<T, int4>) {
3730 }
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 *>) {
3733 registerOrValidateObjectDataType<T>(label, data_type);
3736 std::string label_str = std::string(label);
3737 bool had_cached_value =
false;
3740 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
3742 T old_cached_value{};
3743 objects.at(objID)->getObjectData(label, old_cached_value);
3745 had_cached_value =
true;
3747 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3749 std::string old_cached_value;
3750 objects.at(objID)->getObjectData(label, old_cached_value);
3752 had_cached_value =
true;
3756 if (!objects.at(objID)->doesObjectDataExist(label)) {
3757 incrementObjectDataLabelCounter(label);
3759 objects.at(objID)->setObjectData(label, data);
3763 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
3765 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3770 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
3772 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3785 template<
typename T>
3786 void setObjectData(
const std::vector<uint> &objIDs,
const char *label,
const T &data) {
3787 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> ||
3788 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 *>,
3789 "Context::setObjectData() was called with an unsupported type.");
3792 if (!objIDs.empty()) {
3794 if constexpr (std::is_same_v<T, int>) {
3796 }
else if constexpr (std::is_same_v<T, uint>) {
3798 }
else if constexpr (std::is_same_v<T, float>) {
3800 }
else if constexpr (std::is_same_v<T, double>) {
3802 }
else if constexpr (std::is_same_v<T, vec2>) {
3804 }
else if constexpr (std::is_same_v<T, vec3>) {
3806 }
else if constexpr (std::is_same_v<T, vec4>) {
3808 }
else if constexpr (std::is_same_v<T, int2>) {
3810 }
else if constexpr (std::is_same_v<T, int3>) {
3812 }
else if constexpr (std::is_same_v<T, int4>) {
3814 }
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 *>) {
3817 registerOrValidateObjectDataType<T>(label, data_type);
3821 std::string label_str = std::string(label);
3825 if (caching_enabled) {
3827 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
3828 for (
uint objID: objIDs) {
3829 if (objects.at(objID)->doesObjectDataExist(label)) {
3830 T old_cached_value{};
3831 objects.at(objID)->getObjectData(label, old_cached_value);
3835 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3836 for (
uint objID: objIDs) {
3837 if (objects.at(objID)->doesObjectDataExist(label)) {
3838 std::string old_cached_value;
3839 objects.at(objID)->getObjectData(label, old_cached_value);
3847 for (
uint objID: objIDs) {
3848 if (!objects.at(objID)->doesObjectDataExist(label)) {
3849 incrementObjectDataLabelCounter(label);
3854#pragma omp parallel for
3856 for (
int i = 0; i < (int) objIDs.size(); ++i) {
3857 objects.at(objIDs[i])->setObjectData(label, data);
3861 if (caching_enabled) {
3862 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
3864 for (
size_t i = 0; i < objIDs.size(); ++i) {
3867 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3869 for (
size_t i = 0; i < objIDs.size(); ++i) {
3883 template<
typename T>
3884 void setObjectData(
const std::vector<std::vector<uint>> &objIDs,
const char *label,
const T &data) {
3885 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> ||
3886 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 *>,
3887 "Context::setObjectData() was called with an unsupported type.");
3890 if (!objIDs.empty() && !objIDs[0].empty()) {
3892 if constexpr (std::is_same_v<T, int>) {
3894 }
else if constexpr (std::is_same_v<T, uint>) {
3896 }
else if constexpr (std::is_same_v<T, float>) {
3898 }
else if constexpr (std::is_same_v<T, double>) {
3900 }
else if constexpr (std::is_same_v<T, vec2>) {
3902 }
else if constexpr (std::is_same_v<T, vec3>) {
3904 }
else if constexpr (std::is_same_v<T, vec4>) {
3906 }
else if constexpr (std::is_same_v<T, int2>) {
3908 }
else if constexpr (std::is_same_v<T, int3>) {
3910 }
else if constexpr (std::is_same_v<T, int4>) {
3912 }
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 *>) {
3915 registerOrValidateObjectDataType<T>(label, data_type);
3919 std::string label_str = std::string(label);
3921 size_t total_objects = 0;
3924 if (caching_enabled) {
3926 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
3927 for (
const auto &j: objIDs) {
3928 for (
uint objID: j) {
3930 if (objects.at(objID)->doesObjectDataExist(label)) {
3931 T old_cached_value{};
3932 objects.at(objID)->getObjectData(label, old_cached_value);
3937 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3938 for (
const auto &j: objIDs) {
3939 for (
uint objID: j) {
3941 if (objects.at(objID)->doesObjectDataExist(label)) {
3942 std::string old_cached_value;
3943 objects.at(objID)->getObjectData(label, old_cached_value);
3951 for (
const auto &j: objIDs) {
3952 total_objects += j.size();
3956 for (
const auto &j: objIDs) {
3957 for (
uint objID: j) {
3958 if (!objects.at(objID)->doesObjectDataExist(label)) {
3959 incrementObjectDataLabelCounter(label);
3965#pragma omp parallel for
3967 for (
int j = 0; j < (int) objIDs.size(); ++j) {
3968 for (
size_t i = 0; i < objIDs[j].size(); ++i) {
3969 objects.at(objIDs[j][i])->setObjectData(label, data);
3974 if (caching_enabled) {
3975 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
3977 for (
size_t i = 0; i < total_objects; ++i) {
3980 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
3982 for (
size_t i = 0; i < total_objects; ++i) {
3996 template<
typename T>
3997 void setObjectData(
const std::vector<std::vector<std::vector<uint>>> &objIDs,
const char *label,
const T &data) {
3998 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> ||
3999 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 *>,
4000 "Context::setObjectData() was called with an unsupported type.");
4003 if (!objIDs.empty() && !objIDs[0].empty() && !objIDs[0][0].empty()) {
4005 if constexpr (std::is_same_v<T, int>) {
4007 }
else if constexpr (std::is_same_v<T, uint>) {
4009 }
else if constexpr (std::is_same_v<T, float>) {
4011 }
else if constexpr (std::is_same_v<T, double>) {
4013 }
else if constexpr (std::is_same_v<T, vec2>) {
4015 }
else if constexpr (std::is_same_v<T, vec3>) {
4017 }
else if constexpr (std::is_same_v<T, vec4>) {
4019 }
else if constexpr (std::is_same_v<T, int2>) {
4021 }
else if constexpr (std::is_same_v<T, int3>) {
4023 }
else if constexpr (std::is_same_v<T, int4>) {
4025 }
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 *>) {
4028 registerOrValidateObjectDataType<T>(label, data_type);
4032 std::string label_str = std::string(label);
4034 size_t total_objects = 0;
4037 if (caching_enabled) {
4039 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4040 for (
const auto &k: objIDs) {
4041 for (
const auto &j: k) {
4042 for (
uint objID: j) {
4044 if (objects.at(objID)->doesObjectDataExist(label)) {
4045 T old_cached_value{};
4046 objects.at(objID)->getObjectData(label, old_cached_value);
4052 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4053 for (
const auto &k: objIDs) {
4054 for (
const auto &j: k) {
4055 for (
uint objID: j) {
4057 if (objects.at(objID)->doesObjectDataExist(label)) {
4058 std::string old_cached_value;
4059 objects.at(objID)->getObjectData(label, old_cached_value);
4068 for (
const auto &k: objIDs) {
4069 for (
const auto &j: k) {
4070 total_objects += j.size();
4075 for (
const auto &k: objIDs) {
4076 for (
const auto &j: k) {
4077 for (
uint objID: j) {
4078 if (!objects.at(objID)->doesObjectDataExist(label)) {
4079 incrementObjectDataLabelCounter(label);
4086#pragma omp parallel for
4088 for (
int k = 0; k < (int) objIDs.size(); ++k) {
4089 for (
size_t j = 0; j < objIDs[k].size(); ++j) {
4090 for (
size_t i = 0; i < objIDs[k][j].size(); ++i) {
4091 uint objID = objIDs[k][j][i];
4092 objects.at(objID)->setObjectData(label, data);
4098 if (caching_enabled) {
4099 if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, int> || std::is_same_v<T, uint>) {
4101 for (
size_t i = 0; i < total_objects; ++i) {
4104 }
else if constexpr (std::is_same_v<std::decay_t<T>,
const char *> || std::is_same_v<std::decay_t<T>,
char *>) {
4106 for (
size_t i = 0; i < total_objects; ++i) {
4121 template<
typename T>
4124 if (objects.find(objID) == objects.end()) {
4125 helios_runtime_error(
"ERROR (Context::setObjectData): Object ID of " + std::to_string(objID) +
" does not exist in the Context.");
4128 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> ||
4129 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 *>,
4130 "Context::setObjectData() was called with an unsupported type.");
4134 if constexpr (std::is_same_v<T, int>) {
4136 }
else if constexpr (std::is_same_v<T, uint>) {
4138 }
else if constexpr (std::is_same_v<T, float>) {
4140 }
else if constexpr (std::is_same_v<T, double>) {
4142 }
else if constexpr (std::is_same_v<T, vec2>) {
4144 }
else if constexpr (std::is_same_v<T, vec3>) {
4146 }
else if constexpr (std::is_same_v<T, vec4>) {
4148 }
else if constexpr (std::is_same_v<T, int2>) {
4150 }
else if constexpr (std::is_same_v<T, int3>) {
4152 }
else if constexpr (std::is_same_v<T, int4>) {
4154 }
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 *>) {
4157 registerOrValidateObjectDataType<T>(label, data_type);
4159 objects.at(objID)->setObjectData(label, data);
4170 template<
typename T>
4171 void setObjectData(
const std::vector<uint> &objIDs,
const char *label,
const std::vector<T> &data) {
4173 if (objIDs.size() != data.size()) {
4174 helios_runtime_error(
"ERROR (Context::setObjectData): Object IDs and data vectors must be the same size.");
4177 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> ||
4178 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 *>,
4179 "Context::setObjectData() was called with an unsupported type.");
4182 if (!objIDs.empty()) {
4184 if constexpr (std::is_same_v<T, int>) {
4186 }
else if constexpr (std::is_same_v<T, uint>) {
4188 }
else if constexpr (std::is_same_v<T, float>) {
4190 }
else if constexpr (std::is_same_v<T, double>) {
4192 }
else if constexpr (std::is_same_v<T, vec2>) {
4194 }
else if constexpr (std::is_same_v<T, vec3>) {
4196 }
else if constexpr (std::is_same_v<T, vec4>) {
4198 }
else if constexpr (std::is_same_v<T, int2>) {
4200 }
else if constexpr (std::is_same_v<T, int3>) {
4202 }
else if constexpr (std::is_same_v<T, int4>) {
4204 }
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 *>) {
4207 registerOrValidateObjectDataType<T>(label, data_type);
4210 for (
uint objID: objIDs) {
4211 if (!objects.at(objID)->doesObjectDataExist(label)) {
4212 incrementObjectDataLabelCounter(label);
4217#pragma omp parallel for
4219 for (
int i = 0; i < (int) objIDs.size(); ++i) {
4220 objects.at(objIDs[i])->setObjectData(label, data[i]);
4231 template<
typename T>
4234 if (objects.find(objID) == objects.end()) {
4235 helios_runtime_error(
"ERROR (Context::getObjectData): Object ID of " + std::to_string(objID) +
" does not exist in the Context.");
4238 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> ||
4239 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 *>,
4240 "Context::getObjectData() was called with an unsupported type.");
4241 objects.at(objID)->getObjectData(label, data);
4252 template<
typename T>
4255 if (objects.find(objID) == objects.end()) {
4256 helios_runtime_error(
"ERROR (Context::getObjectData): Object ID of " + std::to_string(objID) +
" does not exist in the Context.");
4259 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> ||
4260 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 *>,
4261 "Context::getObjectData() was called with an unsupported type.");
4262 objects.at(objID)->getObjectData(label, data);
4311 void clearObjectData(
const std::vector<uint> &objIDs,
const char *label);
4351 template<
typename T>
4353 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> ||
4354 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>,
4355 "Context::setGlobalData() was called with an unsupported type.");
4357 globaldata[label].size = 1;
4358 if constexpr (std::is_same_v<T, int>) {
4359 globaldata[label].global_data_int = {data};
4361 }
else if constexpr (std::is_same_v<T, uint>) {
4362 globaldata[label].global_data_uint = {data};
4364 }
else if constexpr (std::is_same_v<T, float>) {
4365 globaldata[label].global_data_float = {data};
4367 }
else if constexpr (std::is_same_v<T, double>) {
4368 globaldata[label].global_data_double = {data};
4370 }
else if constexpr (std::is_same_v<T, vec2>) {
4371 globaldata[label].global_data_vec2 = {data};
4373 }
else if constexpr (std::is_same_v<T, vec3>) {
4374 globaldata[label].global_data_vec3 = {data};
4376 }
else if constexpr (std::is_same_v<T, vec4>) {
4377 globaldata[label].global_data_vec4 = {data};
4379 }
else if constexpr (std::is_same_v<T, int2>) {
4380 globaldata[label].global_data_int2 = {data};
4382 }
else if constexpr (std::is_same_v<T, int3>) {
4383 globaldata[label].global_data_int3 = {data};
4385 }
else if constexpr (std::is_same_v<T, int4>) {
4386 globaldata[label].global_data_int4 = {data};
4388 }
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 *>) {
4389 globaldata[label].global_data_string = {data};
4391 }
else if constexpr (std::is_same_v<T, bool>) {
4392 globaldata[label].global_data_bool = {data};
4402 template<
typename T>
4404 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> ||
4405 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>,
4406 "Context::setGlobalData() was called with an unsupported type.");
4408 globaldata[label].size = data.size();
4409 if constexpr (std::is_same_v<T, int>) {
4410 globaldata[label].global_data_int = data;
4412 }
else if constexpr (std::is_same_v<T, uint>) {
4413 globaldata[label].global_data_uint = data;
4415 }
else if constexpr (std::is_same_v<T, float>) {
4416 globaldata[label].global_data_float = data;
4418 }
else if constexpr (std::is_same_v<T, double>) {
4419 globaldata[label].global_data_double = data;
4421 }
else if constexpr (std::is_same_v<T, vec2>) {
4422 globaldata[label].global_data_vec2 = data;
4424 }
else if constexpr (std::is_same_v<T, vec3>) {
4425 globaldata[label].global_data_vec3 = data;
4427 }
else if constexpr (std::is_same_v<T, vec4>) {
4428 globaldata[label].global_data_vec4 = data;
4430 }
else if constexpr (std::is_same_v<T, int2>) {
4431 globaldata[label].global_data_int2 = data;
4433 }
else if constexpr (std::is_same_v<T, int3>) {
4434 globaldata[label].global_data_int3 = data;
4436 }
else if constexpr (std::is_same_v<T, int4>) {
4437 globaldata[label].global_data_int4 = data;
4439 }
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 *>) {
4440 globaldata[label].global_data_string = data;
4442 }
else if constexpr (std::is_same_v<T, bool>) {
4443 globaldata[label].global_data_bool = data;
4453 template<
typename T>
4456 if constexpr (std::is_same_v<T, std::vector<int>>) {
4459 data = globaldata.at(label).global_data_int;
4461 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int, but data " + std::string(label) +
" does not have type int.");
4463 }
else if constexpr (std::is_same_v<T, std::vector<uint>>) {
4466 data = globaldata.at(label).global_data_uint;
4468 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type uint, but data " + std::string(label) +
" does not have type uint.");
4470 }
else if constexpr (std::is_same_v<T, std::vector<float>>) {
4473 data = globaldata.at(label).global_data_float;
4475 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type float, but data " + std::string(label) +
" does not have type float.");
4477 }
else if constexpr (std::is_same_v<T, std::vector<double>>) {
4480 data = globaldata.at(label).global_data_double;
4482 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type double, but data " + std::string(label) +
" does not have type double.");
4484 }
else if constexpr (std::is_same_v<T, std::vector<vec2>>) {
4487 data = globaldata.at(label).global_data_vec2;
4489 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec2, but data " + std::string(label) +
" does not have type vec2.");
4491 }
else if constexpr (std::is_same_v<T, std::vector<vec3>>) {
4494 data = globaldata.at(label).global_data_vec3;
4496 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec3, but data " + std::string(label) +
" does not have type vec3.");
4498 }
else if constexpr (std::is_same_v<T, std::vector<vec4>>) {
4501 data = globaldata.at(label).global_data_vec4;
4503 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec4, but data " + std::string(label) +
" does not have type vec4.");
4505 }
else if constexpr (std::is_same_v<T, std::vector<int2>>) {
4508 data = globaldata.at(label).global_data_int2;
4510 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int2, but data " + std::string(label) +
" does not have type int2.");
4512 }
else if constexpr (std::is_same_v<T, std::vector<int3>>) {
4515 data = globaldata.at(label).global_data_int3;
4517 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int3, but data " + std::string(label) +
" does not have type int3.");
4519 }
else if constexpr (std::is_same_v<T, std::vector<int4>>) {
4522 data = globaldata.at(label).global_data_int4;
4524 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int4, but data " + std::string(label) +
" does not have type int4.");
4526 }
else if constexpr (std::is_same_v<T, std::vector<std::string>>) {
4529 data = globaldata.at(label).global_data_string;
4531 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type string, but data " + std::string(label) +
" does not have type string.");
4533 }
else if constexpr (std::is_same_v<T, int>) {
4536 data = globaldata.at(label).global_data_int.front();
4538 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int, but data " + std::string(label) +
" does not have type int.");
4540 }
else if constexpr (std::is_same_v<T, uint>) {
4543 data = globaldata.at(label).global_data_uint.front();
4545 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type uint, but data " + std::string(label) +
" does not have type uint.");
4547 }
else if constexpr (std::is_same_v<T, float>) {
4550 data = globaldata.at(label).global_data_float.front();
4552 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type float, but data " + std::string(label) +
" does not have type float.");
4554 }
else if constexpr (std::is_same_v<T, double>) {
4557 data = globaldata.at(label).global_data_double.front();
4559 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type double, but data " + std::string(label) +
" does not have type double.");
4561 }
else if constexpr (std::is_same_v<T, vec2>) {
4564 data = globaldata.at(label).global_data_vec2.front();
4566 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec2, but data " + std::string(label) +
" does not have type vec2.");
4568 }
else if constexpr (std::is_same_v<T, vec3>) {
4571 data = globaldata.at(label).global_data_vec3.front();
4573 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec3, but data " + std::string(label) +
" does not have type vec3.");
4575 }
else if constexpr (std::is_same_v<T, vec4>) {
4578 data = globaldata.at(label).global_data_vec4.front();
4580 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type vec4, but data " + std::string(label) +
" does not have type vec4.");
4582 }
else if constexpr (std::is_same_v<T, int2>) {
4585 data = globaldata.at(label).global_data_int2.front();
4587 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int2, but data " + std::string(label) +
" does not have type int2.");
4589 }
else if constexpr (std::is_same_v<T, int3>) {
4592 data = globaldata.at(label).global_data_int3.front();
4594 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int3, but data " + std::string(label) +
" does not have type int3.");
4596 }
else if constexpr (std::is_same_v<T, int4>) {
4599 data = globaldata.at(label).global_data_int4.front();
4601 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type int4, but data " + std::string(label) +
" does not have type int4.");
4603 }
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 *>) {
4606 data = globaldata.at(label).global_data_string.front();
4608 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type string, but data " + std::string(label) +
" does not have type string.");
4610 }
else if constexpr (std::is_same_v<T, bool>) {
4613 data = globaldata.at(label).global_data_bool.front();
4615 helios_runtime_error(
"ERROR (Context::getGlobalData): Attempted to get data for type bool, but data " + std::string(label) +
" does not have type bool.");
4618 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> ||
4619 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 *> ||
4620 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>> ||
4621 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>> ||
4622 std::is_same_v<T, std::vector<std::string>> || std::is_same_v<T, std::vector<bool>>,
4623 "CompoundObject::getGlobalData() was called with an unsupported type.");
4756 std::vector<uint>
copyObject(
const std::vector<uint> &ObjIDs);
4788 std::vector<uint>
filterObjectsByData(
const std::vector<uint> &ObjIDs,
const char *object_data,
float threshold,
const char *comparator)
const;
4810 void rotateObject(
uint ObjID,
float rotation_radians,
const char *rotation_axis_xyz)
const;
4818 void rotateObject(
const std::vector<uint> &ObjIDs,
float rotation_radians,
const char *rotation_axis_xyz)
const;
4834 void rotateObject(
const std::vector<uint> &ObjIDs,
float rotation_radians,
const vec3 &rotation_axis_vector)
const;
4843 void rotateObject(
uint ObjID,
float rotation_radians,
const vec3 &rotation_origin,
const vec3 &rotation_axis_vector)
const;
4852 void rotateObject(
const std::vector<uint> &ObjIDs,
float rotation_radians,
const vec3 &rotation_origin,
const vec3 &rotation_axis_vector)
const;
5405 uint addTubeObject(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius);
5417 uint addTubeObject(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const std::vector<RGBcolor> &color);
5430 uint addTubeObject(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const char *texturefile);
5444 uint addTubeObject(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const char *texturefile,
const std::vector<float> &textureuv_ufrac);
5687 std::vector<uint>
addSphere(
uint Ndivs,
const vec3 ¢er,
float radius,
const char *texturefile);
5748 std::vector<uint>
addTube(
uint Ndivs,
const std::vector<vec3> &nodes,
const std::vector<float> &radius);
5760 std::vector<uint>
addTube(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const std::vector<RGBcolor> &color);
5772 std::vector<uint>
addTube(
uint radial_subdivisions,
const std::vector<vec3> &nodes,
const std::vector<float> &radius,
const char *texturefile);
5808 std::vector<uint>
addBox(
const vec3 ¢er,
const vec3 &size,
const int3 &subdiv,
const char *texturefile);
5821 std::vector<uint>
addBox(
const vec3 ¢er,
const vec3 &size,
const int3 &subdiv,
const RGBcolor &color,
bool reverse_normals);
5834 std::vector<uint>
addBox(
const vec3 ¢er,
const vec3 &size,
const int3 &subdiv,
const char *texturefile,
bool reverse_normals);
5945 std::vector<uint>
addCone(
uint Ndivs,
const vec3 &node0,
const vec3 &node1,
float radius0,
float radius1);
5971 std::vector<uint>
addCone(
uint Ndivs,
const vec3 &node0,
const vec3 &node1,
float radius0,
float radius1,
const char *texturefile);
6061 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);
6120 void cropDomain(std::vector<uint> &UUIDs,
const vec2 &xbounds,
const vec2 &ybounds,
const vec2 &zbounds);
6148 void colorPrimitiveByDataPseudocolor(
const std::vector<uint> &UUIDs,
const std::string &primitive_data,
const std::string &colormap,
uint Ncolors,
float data_min,
float data_max);
6157 std::vector<uint>
loadXML(
const char *filename,
bool quiet =
false);
6172 static bool scanXMLForTag(
const std::string &filename,
const std::string &tag,
const std::string &label =
"");
6179 void writeXML(
const char *filename,
bool quiet =
false)
const;
6187 void writeXML(
const char *filename,
const std::vector<uint> &UUIDs,
bool quiet =
false)
const;
6195 void writeXML_byobject(
const char *filename,
const std::vector<uint> &UUIDs,
bool quiet =
false)
const;
6203 void writePrimitiveData(
const std::string &filename,
const std::vector<std::string> &column_format,
bool print_header =
false)
const;
6212 void writePrimitiveData(
const std::string &filename,
const std::vector<std::string> &column_format,
const std::vector<uint> &UUIDs,
bool print_header =
false)
const;
6221 std::vector<uint>
loadPLY(
const char *filename,
bool silent =
false);
6233 std::vector<uint>
loadPLY(
const char *filename,
const vec3 &origin,
float height,
const std::string &upaxis =
"YUP",
bool silent =
false);
6246 std::vector<uint>
loadPLY(
const char *filename,
const vec3 &origin,
float height,
const SphericalCoord &rotation,
const std::string &upaxis =
"YUP",
bool silent =
false);
6258 std::vector<uint>
loadPLY(
const char *filename,
const vec3 &origin,
float height,
const RGBcolor &default_color,
const std::string &upaxis =
"YUP",
bool silent =
false);
6271 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);
6277 void writePLY(
const char *filename)
const;
6284 void writePLY(
const char *filename,
const std::vector<uint> &UUIDs)
const;
6293 std::vector<uint>
loadOBJ(
const char *filename,
bool silent =
false);
6305 std::vector<uint>
loadOBJ(
const char *filename,
const vec3 &origin,
float height,
const SphericalCoord &rotation,
const RGBcolor &default_color,
bool silent =
false);
6318 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);
6340 void writeOBJ(
const std::string &filename,
bool write_normals =
false,
bool silent =
false)
const;
6349 void writeOBJ(
const std::string &filename,
const std::vector<uint> &UUIDs,
bool write_normals =
false,
bool silent =
false)
const;
6359 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;
6369 std::filesystem::path
resolveFilePath(
const std::string &filename)
const;
6378 void setDate(
int day,
int month,
int year);
6393 void setDate(
int Julian_day,
int year);
6423 void setTime(
int minute,
int hour);
6433 void setTime(
int second,
int minute,
int hour);
6672 void scalePrimitiveData(
const std::vector<uint> &UUIDs,
const std::string &label,
float scaling_factor);
6725 void aggregatePrimitiveDataSum(
const std::vector<uint> &UUIDs,
const std::vector<std::string> &primitive_data_labels,
const std::string &result_primitive_data_label);
6734 void aggregatePrimitiveDataProduct(
const std::vector<uint> &UUIDs,
const std::vector<std::string> &primitive_data_labels,
const std::string &result_primitive_data_label);
6752 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
float filter_value,
const std::string &comparator)
const;
6763 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
double filter_value,
const std::string &comparator)
const;
6774 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
int filter_value,
const std::string &comparator)
const;
6785 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
uint filter_value,
const std::string &comparator)
const;
6795 [[nodiscard]] std::vector<uint>
filterPrimitivesByData(
const std::vector<uint> &UUIDs,
const std::string &primitive_data_label,
const std::string &filter_value)
const;
6806 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
float filter_value,
const std::string &comparator)
const;
6817 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
double filter_value,
const std::string &comparator)
const;
6828 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
int filter_value,
const std::string &comparator)
const;
6839 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
uint filter_value,
const std::string &comparator)
const;
6849 [[nodiscard]] std::vector<uint>
filterObjectsByData(
const std::vector<uint> &objIDs,
const std::string &object_data_label,
const std::string &filter_value)
const;
6880 std::vector<RGBcolor>
generateColormap(
const std::vector<helios::RGBcolor> &ctable,
const std::vector<float> &cfrac,
uint Ncolors);
6884 template<
typename T>
6885 void storeDataWithTypeCasting(
uint UUID,
const char *label,
const T &data,
HeliosDataType target_type) {
6887 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>) {
6888 if (target_type == HELIOS_TYPE_INT) {
6889 primitives.at(UUID)->setPrimitiveData(label,
static_cast<int>(data));
6890 }
else if (target_type == HELIOS_TYPE_UINT) {
6891 primitives.at(UUID)->setPrimitiveData(label,
static_cast<uint>(data));
6892 }
else if (target_type == HELIOS_TYPE_FLOAT) {
6893 primitives.at(UUID)->setPrimitiveData(label,
static_cast<float>(data));
6894 }
else if (target_type == HELIOS_TYPE_DOUBLE) {
6895 primitives.at(UUID)->setPrimitiveData(label,
static_cast<double>(data));
6898 primitives.at(UUID)->setPrimitiveData(label, data);
6902 primitives.at(UUID)->setPrimitiveData(label, data);
6906 template<
typename T>
6907 void storeObjectDataWithTypeCasting(
uint objID,
const char *label,
const T &data, HeliosDataType target_type) {
6909 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>) {
6910 if (target_type == HELIOS_TYPE_INT) {
6911 objects.at(objID)->setObjectData(label,
static_cast<int>(data));
6912 }
else if (target_type == HELIOS_TYPE_UINT) {
6913 objects.at(objID)->setObjectData(label,
static_cast<uint>(data));
6914 }
else if (target_type == HELIOS_TYPE_FLOAT) {
6915 objects.at(objID)->setObjectData(label,
static_cast<float>(data));
6916 }
else if (target_type == HELIOS_TYPE_DOUBLE) {
6917 objects.at(objID)->setObjectData(label,
static_cast<double>(data));
6920 objects.at(objID)->setObjectData(label, data);
6924 objects.at(objID)->setObjectData(label, data);
6928 template<
typename T>
6929 HeliosDataType registerOrValidatePrimitiveDataType(
const std::string &label, HeliosDataType data_type) {
6930 auto it = primitive_data_type_registry.find(label);
6931 if (it == primitive_data_type_registry.end()) {
6933 primitive_data_type_registry[label] = data_type;
6938 if (expected_type != data_type) {
6940 if (!isTypeCastingSupported(data_type, expected_type)) {
6941 helios_runtime_error(
"ERROR (Context::registerOrValidatePrimitiveDataType): Data type mismatch for label '" + label +
"'. Expected " + dataTypeToString(expected_type) +
" but got " + dataTypeToString(data_type) +
6942 ". Type casting between these types is not supported.");
6944 std::cerr <<
"WARNING (Context::registerOrValidatePrimitiveDataType): Type casting from " + dataTypeToString(data_type) +
" to " + dataTypeToString(expected_type) +
" for label '" + label +
6945 "'. Consider using consistent types."
6949 return expected_type;
6953 template<
typename T>
6954 HeliosDataType registerOrValidateObjectDataType(
const std::string &label, HeliosDataType data_type) {
6955 auto it = object_data_type_registry.find(label);
6956 if (it == object_data_type_registry.end()) {
6958 object_data_type_registry[label] = data_type;
6963 if (expected_type != data_type) {
6965 if (!isTypeCastingSupported(data_type, expected_type)) {
6966 helios_runtime_error(
"ERROR (Context::registerOrValidateObjectDataType): Data type mismatch for label '" + label +
"'. Expected " + dataTypeToString(expected_type) +
" but got " + dataTypeToString(data_type) +
6967 ". Type casting between these types is not supported.");
6969 std::cerr <<
"WARNING (Context::registerOrValidateObjectDataType): Type casting from " + dataTypeToString(data_type) +
" to " + dataTypeToString(expected_type) +
" for label '" + label +
"'. Consider using consistent types."
6973 return expected_type;
6980 template<
typename T>
6982 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 *>) {
6983 std::string string_value = (std::is_same_v<T, std::string>) ? value : std::string(value);
6984 primitive_string_value_registry[label][string_value]++;
6985 }
else if constexpr (std::is_same_v<T, int>) {
6986 primitive_int_value_registry[label][value]++;
6987 }
else if constexpr (std::is_same_v<T, uint>) {
6988 primitive_uint_value_registry[label][value]++;
6993 template<
typename T>
6995 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 *>) {
6996 std::string string_value = (std::is_same_v<T, std::string>) ? value : std::string(value);
6997 auto label_it = primitive_string_value_registry.find(label);
6998 if (label_it != primitive_string_value_registry.end()) {
6999 auto value_it = label_it->second.find(string_value);
7000 if (value_it != label_it->second.end() && value_it->second > 0) {
7002 if (value_it->second == 0) {
7003 label_it->second.erase(value_it);
7004 if (label_it->second.empty()) {
7005 primitive_string_value_registry.erase(label_it);
7010 }
else if constexpr (std::is_same_v<T, int>) {
7011 auto label_it = primitive_int_value_registry.find(label);
7012 if (label_it != primitive_int_value_registry.end()) {
7013 auto value_it = label_it->second.find(value);
7014 if (value_it != label_it->second.end() && value_it->second > 0) {
7016 if (value_it->second == 0) {
7017 label_it->second.erase(value_it);
7018 if (label_it->second.empty()) {
7019 primitive_int_value_registry.erase(label_it);
7024 }
else if constexpr (std::is_same_v<T, uint>) {
7025 auto label_it = primitive_uint_value_registry.find(label);
7026 if (label_it != primitive_uint_value_registry.end()) {
7027 auto value_it = label_it->second.find(value);
7028 if (value_it != label_it->second.end() && value_it->second > 0) {
7030 if (value_it->second == 0) {
7031 label_it->second.erase(value_it);
7032 if (label_it->second.empty()) {
7033 primitive_uint_value_registry.erase(label_it);
7042 template<
typename T>
7044 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 *>) {
7045 std::string string_value = (std::is_same_v<T, std::string>) ? value : std::string(value);
7046 object_string_value_registry[label][string_value]++;
7047 }
else if constexpr (std::is_same_v<T, int>) {
7048 object_int_value_registry[label][value]++;
7049 }
else if constexpr (std::is_same_v<T, uint>) {
7050 object_uint_value_registry[label][value]++;
7055 template<
typename T>
7057 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 *>) {
7058 std::string string_value = (std::is_same_v<T, std::string>) ? value : std::string(value);
7059 auto label_it = object_string_value_registry.find(label);
7060 if (label_it != object_string_value_registry.end()) {
7061 auto value_it = label_it->second.find(string_value);
7062 if (value_it != label_it->second.end() && value_it->second > 0) {
7064 if (value_it->second == 0) {
7065 label_it->second.erase(value_it);
7066 if (label_it->second.empty()) {
7067 object_string_value_registry.erase(label_it);
7072 }
else if constexpr (std::is_same_v<T, int>) {
7073 auto label_it = object_int_value_registry.find(label);
7074 if (label_it != object_int_value_registry.end()) {
7075 auto value_it = label_it->second.find(value);
7076 if (value_it != label_it->second.end() && value_it->second > 0) {
7078 if (value_it->second == 0) {
7079 label_it->second.erase(value_it);
7080 if (label_it->second.empty()) {
7081 object_int_value_registry.erase(label_it);
7086 }
else if constexpr (std::is_same_v<T, uint>) {
7087 auto label_it = object_uint_value_registry.find(label);
7088 if (label_it != object_uint_value_registry.end()) {
7089 auto value_it = label_it->second.find(value);
7090 if (value_it != label_it->second.end() && value_it->second > 0) {
7092 if (value_it->second == 0) {
7093 label_it->second.erase(value_it);
7094 if (label_it->second.empty()) {
7095 object_uint_value_registry.erase(label_it);
7112 template<
typename T>
7114 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.");
7117 helios_runtime_error(
"ERROR (Context::getUniquePrimitiveDataValues): Value-level caching is not enabled for primitive data label '" + label +
"'. Use enablePrimitiveDataValueCaching() first.");
7122 if constexpr (std::is_same_v<T, std::string>) {
7123 auto it = primitive_string_value_registry.find(label);
7124 if (it != primitive_string_value_registry.end()) {
7125 values.reserve(it->second.size());
7126 for (
const auto &[value, count]: it->second) {
7128 values.push_back(value);
7132 }
else if constexpr (std::is_same_v<T, int>) {
7133 auto it = primitive_int_value_registry.find(label);
7134 if (it != primitive_int_value_registry.end()) {
7135 values.reserve(it->second.size());
7136 for (
const auto &[value, count]: it->second) {
7138 values.push_back(value);
7142 }
else if constexpr (std::is_same_v<T, uint>) {
7143 auto it = primitive_uint_value_registry.find(label);
7144 if (it != primitive_uint_value_registry.end()) {
7145 values.reserve(it->second.size());
7146 for (
const auto &[value, count]: it->second) {
7148 values.push_back(value);
7162 template<
typename T>
7164 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.");
7167 helios_runtime_error(
"ERROR (Context::getUniqueObjectDataValues): Value-level caching is not enabled for object data label '" + label +
"'. Use enableObjectDataValueCaching() first.");
7172 if constexpr (std::is_same_v<T, std::string>) {
7173 auto it = object_string_value_registry.find(label);
7174 if (it != object_string_value_registry.end()) {
7175 values.reserve(it->second.size());
7176 for (
const auto &[value, count]: it->second) {
7178 values.push_back(value);
7182 }
else if constexpr (std::is_same_v<T, int>) {
7183 auto it = object_int_value_registry.find(label);
7184 if (it != object_int_value_registry.end()) {
7185 values.reserve(it->second.size());
7186 for (
const auto &[value, count]: it->second) {
7188 values.push_back(value);
7192 }
else if constexpr (std::is_same_v<T, uint>) {
7193 auto it = object_uint_value_registry.find(label);
7194 if (it != object_uint_value_registry.end()) {
7195 values.reserve(it->second.size());
7196 for (
const auto &[value, count]: it->second) {
7198 values.push_back(value);