diff --git a/GeoModelCore/GeoModelHelpers/GeoModelHelpers/GeoDeDuplicator.h b/GeoModelCore/GeoModelHelpers/GeoModelHelpers/GeoDeDuplicator.h index 1e0dbd8c182b8e2a46f30157b0bf16d793753535..547252a61df4fa8eda1063b0a51b05deff2fcf88 100644 --- a/GeoModelCore/GeoModelHelpers/GeoModelHelpers/GeoDeDuplicator.h +++ b/GeoModelCore/GeoModelHelpers/GeoModelHelpers/GeoDeDuplicator.h @@ -7,6 +7,9 @@ #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" @@ -109,6 +112,10 @@ class GeoDeDuplicator { /** @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); /** @brief Toggles whether logVol deduplication shall be enabled */ @@ -117,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: diff --git a/GeoModelCore/GeoModelHelpers/src/GeoDeDuplicator.cxx b/GeoModelCore/GeoModelHelpers/src/GeoDeDuplicator.cxx index f8ecad113ac900d4c0343f0dcb3439cf14548a92..e4b88500916956e1915d7b6690815cb073b3bf7d 100644 --- a/GeoModelCore/GeoModelHelpers/src/GeoDeDuplicator.cxx +++ b/GeoModelCore/GeoModelHelpers/src/GeoDeDuplicator.cxx @@ -109,4 +109,48 @@ GeoDeDuplicator::GeoIdPtr 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