diff --git a/src/ifcgeom/mapping/mapping.cpp b/src/ifcgeom/mapping/mapping.cpp index 0ed5af5396..42c41c1f99 100644 --- a/src/ifcgeom/mapping/mapping.cpp +++ b/src/ifcgeom/mapping/mapping.cpp @@ -1283,26 +1283,59 @@ void mapping::addRepresentationsFromDefaultContexts(std::vector representations; - std::vector of_product; - std::vector intersection; - std::vector intersection_no_box; +void mapping::ensureRepresentationContextCache_() { + const auto has_context_ids = settings_.get().has(); + const auto dimensionality = settings_.get().get(); + const auto context_ids = has_context_ids ? settings_.get().get() : std::set{}; - if (!settings_.get().has()) { + std::lock_guard guard(representation_context_cache_guard_); + + if (representation_context_cache_valid_ && + representation_context_cache_has_context_ids_ == has_context_ids && + representation_context_cache_dimensionality_ == dimensionality && + representation_context_cache_ids_ == context_ids) { + return; + } + + std::vector representations; + if (!has_context_ids) { addRepresentationsFromDefaultContexts(representations); } else { addRepresentationsFromContextIds(representations); } + std::unordered_set representation_ids; + representation_ids.reserve(representations.size()); + for (auto& representation : representations) { + if (representation) { + representation_ids.insert((uint32_t)representation.id()); + } + } + + representation_context_cache_ = std::move(representation_ids); + representation_context_cache_ids_ = std::move(context_ids); + representation_context_cache_dimensionality_ = dimensionality; + representation_context_cache_has_context_ids_ = has_context_ids; + representation_context_cache_valid_ = true; +} + +express::Base mapping::representation_of(const express::Base& product) { + std::vector of_product; + std::vector intersection; + std::vector intersection_no_box; + + ensureRepresentationContextCache_(); + if (product.as().Representation()) { of_product = product.as().Representation().Representations(); } - for (auto& r : of_product) { - if (std::find(representations.begin(), representations.end(), r) != representations.end()) { - intersection.push_back(r); + { + std::lock_guard guard(representation_context_cache_guard_); + for (auto& r : of_product) { + if (representation_context_cache_.find((uint32_t)r.id()) != representation_context_cache_.end()) { + intersection.push_back(r); + } } } diff --git a/src/ifcgeom/mapping/mapping.h b/src/ifcgeom/mapping/mapping.h index 0638fd6dbc..1055fe093b 100644 --- a/src/ifcgeom/mapping/mapping.h +++ b/src/ifcgeom/mapping/mapping.h @@ -7,6 +7,7 @@ #include "../../ifcparse/logger.h" #include +#include #define INCLUDE_SCHEMA(x) STRINGIFY(../../ifcparse/schemas/x.h) #include INCLUDE_SCHEMA(IfcSchema) @@ -36,11 +37,18 @@ namespace geometry { void initialize_units_(); void addRepresentationsFromContextIds(std::vector&); void addRepresentationsFromDefaultContexts(std::vector&); + void ensureRepresentationContextCache_(); // Set of instances to mark failures that are intended, such as representations not // resulting in any items due to dimensionality filters. std::set failed_on_purpose_; std::set not_reusable_maps_; + std::unordered_set representation_context_cache_; + std::set representation_context_cache_ids_; + settings::OutputDimensionalityTypes representation_context_cache_dimensionality_ = settings::SURFACES_AND_SOLIDS; + bool representation_context_cache_has_context_ids_ = false; + bool representation_context_cache_valid_ = false; + std::mutex representation_context_cache_guard_; template void process_mapping(bool& matched, taxonomy::ptr& item, const express::Base& inst) { @@ -152,4 +160,4 @@ namespace geometry { } -#endif \ No newline at end of file +#endif