diff --git a/GeoModelCore/GeoModelHelpers/GeoModelHelpers/GeoDeDuplicator.h b/GeoModelCore/GeoModelHelpers/GeoModelHelpers/GeoDeDuplicator.h index 60a4cfd17b5920de8e7d86f2d349395f8afd72b4..547252a61df4fa8eda1063b0a51b05deff2fcf88 100644 --- a/GeoModelCore/GeoModelHelpers/GeoModelHelpers/GeoDeDuplicator.h +++ b/GeoModelCore/GeoModelHelpers/GeoModelHelpers/GeoDeDuplicator.h @@ -7,8 +7,12 @@ #include "GeoModelKernel/GeoPhysVol.h" #include "GeoModelKernel/GeoShape.h" #include "GeoModelKernel/GeoTransform.h" +#include "GeoModelKernel/GeoAlignableTransform.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoFullPhysVol.h" #include "GeoModelKernel/GeoSerialIdentifier.h" #include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelKernel/GeoIdentifierTag.h" #include "GeoModelHelpers/GeoLogVolSorter.h" #include "GeoModelHelpers/GeoPhysVolSorter.h" @@ -16,7 +20,7 @@ #include "GeoModelHelpers/TransformSorter.h" #include <set> -#include <map> +#include <unordered_map> #include <mutex> #include <thread> /*** @@ -75,6 +79,7 @@ class GeoDeDuplicator { using GeoTrfPtr = GeoIntrusivePtr<GeoTransform>; using GeoPhysVolPtr = GeoIntrusivePtr<GeoPhysVol>; using GeoSerialIdPtr = GeoIntrusivePtr<GeoSerialIdentifier>; + using GeoIdPtr = GeoIntrusivePtr<GeoIdentifierTag>; using GeoNamePtr = GeoIntrusivePtr<GeoNameTag>; /** @brief Standard constructor */ @@ -104,6 +109,12 @@ class GeoDeDuplicator { GeoNamePtr nameTag(const std::string& tagName) const; /** @brief Returns a new GeoSerial Id */ GeoSerialIdPtr serialId(const int id) const; + /** @brief Returns a new GeoIdentifier tag */ + GeoIdPtr geoId(const int id) const; + + /** @brief Clones a physical volume. All components in the tree are + * parsed through the deduplication chain */ + PVLink clone(PVConstLink vol) const; /** @brief Toggles whether shape deduplication shall be enabled */ void setShapeDeDuplication(bool enable); @@ -113,7 +124,6 @@ class GeoDeDuplicator { void setTransformDeDuplication(bool enable); /** @brief Toggles whether physVol node deduplication shall be enabled */ void setPhysVolDeDuplication(bool enable); - /** @brief Clears the shared Shape / Transform / SerialId & NameTag cache */ static void clearSharedCaches(); private: @@ -125,8 +135,9 @@ class GeoDeDuplicator { using LogVolSet = std::set<GeoLogVolPtr, GeoLogVolSorter>; using TrfSet = std::set<GeoTrfPtr, GeoTrf::TransformSorter>; using ShapeSet = std::set<GeoShapePtr, GeoShapeSorter>; - using SerialIdMap = std::map<int, GeoSerialIdPtr>; - using NameTagMap = std::map<std::string, GeoNamePtr>; + using SerialIdMap = std::unordered_map<int, GeoSerialIdPtr>; + using GeoIdMap = std::unordered_map<int, GeoIdPtr>; + using NameTagMap = std::unordered_map<std::string, GeoNamePtr>; mutable PhysVolSet m_physVolStore{}; mutable LogVolSet m_logVolStore{}; @@ -136,6 +147,7 @@ class GeoDeDuplicator { static ShapeSet s_shapeStore; static SerialIdMap s_serialIds; static NameTagMap s_nameTags; + static GeoIdMap s_geoIds; mutable std::mutex m_mutex{}; }; diff --git a/GeoModelCore/GeoModelHelpers/src/GeoDeDuplicator.cxx b/GeoModelCore/GeoModelHelpers/src/GeoDeDuplicator.cxx index 19432f217f40839aadecf876a62f2b4c8f0bce73..e4b88500916956e1915d7b6690815cb073b3bf7d 100644 --- a/GeoModelCore/GeoModelHelpers/src/GeoDeDuplicator.cxx +++ b/GeoModelCore/GeoModelHelpers/src/GeoDeDuplicator.cxx @@ -8,6 +8,7 @@ GeoDeDuplicator::TrfSet GeoDeDuplicator::s_trfStore{}; GeoDeDuplicator::ShapeSet GeoDeDuplicator::s_shapeStore{}; GeoDeDuplicator::SerialIdMap GeoDeDuplicator::s_serialIds{}; GeoDeDuplicator::NameTagMap GeoDeDuplicator::s_nameTags{}; +GeoDeDuplicator::GeoIdMap GeoDeDuplicator::s_geoIds{}; namespace { std::mutex s_mutex{}; @@ -31,6 +32,7 @@ void GeoDeDuplicator::clearSharedCaches() { s_shapeStore.clear(); s_serialIds.clear(); s_nameTags.clear(); + s_geoIds.clear(); } GeoDeDuplicator::GeoTrfPtr @@ -86,7 +88,8 @@ GeoDeDuplicator::GeoNamePtr GeoDeDuplicator::nameTag(const std::string& tagName) s_nameTags.insert(std::make_pair(tagName, newTag)); return newTag; } -GeoDeDuplicator::GeoSerialIdPtr GeoDeDuplicator::serialId(const int id) const { +GeoDeDuplicator::GeoSerialIdPtr + GeoDeDuplicator::serialId(const int id) const { std::lock_guard guard{s_mutex}; SerialIdMap::const_iterator itr = s_serialIds.find(id); if (itr != s_serialIds.end()){ @@ -95,4 +98,59 @@ GeoDeDuplicator::GeoSerialIdPtr GeoDeDuplicator::serialId(const int id) const { GeoSerialIdPtr newId = make_intrusive<GeoSerialIdentifier>(id); s_serialIds.insert(std::make_pair(id, newId)); return newId; +} +GeoDeDuplicator::GeoIdPtr + GeoDeDuplicator::geoId(const int id) const { + std::lock_guard guard{s_mutex}; + GeoIdMap::const_iterator itr = s_geoIds.find(id); + if (itr != s_geoIds.end()){ + return itr->second; + } + GeoIdPtr newId = make_intrusive<GeoIdentifierTag>(id); + s_geoIds.insert(std::make_pair(id, newId)); + return newId; +} + +PVLink GeoDeDuplicator::clone(PVConstLink vol) const { + PVLink newVol{}; + bool tryPhysVolDeDup{m_deDuplicatePhysVol}; + GeoLogVolPtr logVol{const_cast<GeoLogVol*>(vol->getLogVol())}; + if (dynamic_cast<const GeoPhysVol*>(vol.get())) { + newVol = make_intrusive<GeoPhysVol>(cacheVolume(logVol)); + } else { + newVol = make_intrusive<GeoFullPhysVol>(cacheVolume(logVol)); + tryPhysVolDeDup = false; + } + for(unsigned int chNode =0; chNode < newVol->getNChildNodes(); ++chNode) { + GeoIntrusivePtr<const GeoGraphNode>node{*newVol->getChildNode(chNode)}; + /** transform nodes */ + if (typeid(*node) == typeid(GeoAlignableTransform)) { + const auto geoTrf = dynamic_pointer_cast<const GeoAlignableTransform>(node); + newVol->add(make_intrusive<GeoAlignableTransform>(geoTrf->getDefTransform())); + } else if (typeid(*node) == typeid(GeoTransform)) { + const auto geoTrf = dynamic_pointer_cast<const GeoTransform>(node); + auto geoTrfNonConst = const_pointer_cast(geoTrf); + newVol->add(cacheTransform(geoTrfNonConst)); + } + /** physical volumes */ + else if (auto physVol = dynamic_pointer_cast<const GeoVPhysVol>(node); physVol) { + newVol->add(clone(physVol)); + } else if (auto geoId = dynamic_pointer_cast<const GeoIdentifierTag>(node); geoId) { + std::lock_guard guard{s_mutex}; + newVol->add(s_geoIds.insert(std::make_pair(geoId->getIdentifier(), const_pointer_cast(geoId))).first->second); + } else if (auto serialId = dynamic_pointer_cast<const GeoSerialIdentifier>(node); serialId) { + std::lock_guard guard{s_mutex}; + newVol->add(s_serialIds.insert(std::make_pair(serialId->getBaseId(), const_pointer_cast(serialId))).first->second); + } else if (auto nameTag = dynamic_pointer_cast<const GeoNameTag>(node); nameTag) { + std::lock_guard guard{s_mutex}; + newVol->add(s_nameTags.insert(std::make_pair(nameTag->getName(), const_pointer_cast(nameTag))).first->second); + } else { + /// Just copy what's left + newVol->add(const_pointer_cast(node)); + } + } + if (tryPhysVolDeDup){ + newVol = cacheVolume(dynamic_pointer_cast<GeoPhysVol>(newVol)); + } + return newVol; } \ No newline at end of file