From 59d53ef59e110d5be1a78f8f4e1b0fc6946dbe89 Mon Sep 17 00:00:00 2001
From: Johannes Junggeburth <johannes.josef.junggeburth@cern.ch>
Date: Thu, 27 Jun 2024 16:09:45 +0200
Subject: [PATCH] GeoModelHelpers - Add subvolume fetch function with selector

---
 .../GeoModelHelpers/getChildNodesWithTrf.h    |  8 +++++--
 .../src/getChildNodesWithTrf.cxx              | 21 +++++++++++++------
 .../GeoModelKernel/GeoDefinitions.h           | 11 +++++++---
 .../GeoModelKernel/src/GeoDefinitions.cxx     | 21 ++++++++++++++++++-
 .../GeoModelKernel/tests/testEulerAngles.cxx  | 11 ++++++++++
 5 files changed, 60 insertions(+), 12 deletions(-)

diff --git a/GeoModelCore/GeoModelHelpers/GeoModelHelpers/getChildNodesWithTrf.h b/GeoModelCore/GeoModelHelpers/GeoModelHelpers/getChildNodesWithTrf.h
index 4e2b2e8e6..f8c3599b2 100644
--- a/GeoModelCore/GeoModelHelpers/GeoModelHelpers/getChildNodesWithTrf.h
+++ b/GeoModelCore/GeoModelHelpers/GeoModelHelpers/getChildNodesWithTrf.h
@@ -39,8 +39,12 @@ std::vector <GeoChildNodeWithTrf> getChildrenWithRef (PVConstLink physVol,
                                                       bool summarizeEqualVol = true);
 /**** @brief Traverses through the GeoVPhysVol tree and returns all sub volumes of this tree.*/
 std::vector<GeoChildNodeWithTrf> getAllSubVolumes(PVConstLink physVol);
-
-
+/*** @brief Traverses thorugh the GeoVPhysVOl tree and returns all subvolumes satisfying an external 
+ *          selection.
+ */
+std::vector<GeoChildNodeWithTrf> getAllSubVolumes(PVConstLink physVol,
+                                                  std::function<bool(const GeoChildNodeWithTrf&)> selector,
+                                                  bool summarizeEqualVol = false);
 
 /**
  *  Returns whether a volume has fullPhysical volume nodes in 
diff --git a/GeoModelCore/GeoModelHelpers/src/getChildNodesWithTrf.cxx b/GeoModelCore/GeoModelHelpers/src/getChildNodesWithTrf.cxx
index 3aa9dd8eb..819473880 100644
--- a/GeoModelCore/GeoModelHelpers/src/getChildNodesWithTrf.cxx
+++ b/GeoModelCore/GeoModelHelpers/src/getChildNodesWithTrf.cxx
@@ -64,14 +64,16 @@ std::vector <GeoChildNodeWithTrf> getChildrenWithRef(PVConstLink physVol,
     }
     return children;
 }
-
-std::vector<GeoChildNodeWithTrf> getAllSubVolumes(PVConstLink physVol) {
-    std::vector<GeoChildNodeWithTrf> children{getChildrenWithRef(physVol, false)}, subVolumes{};
+std::vector<GeoChildNodeWithTrf> getAllSubVolumes(PVConstLink physVol,
+                                                  std::function<bool(const GeoChildNodeWithTrf&)> selector,
+                                                  bool summarizeEqualVol) {
+    std::vector<GeoChildNodeWithTrf> children{getChildrenWithRef(physVol, summarizeEqualVol)}, subVolumes{};
     subVolumes.reserve(children.size());
     for (const GeoChildNodeWithTrf& child : children) {
-        subVolumes.push_back(child);
-        std::vector<GeoChildNodeWithTrf> grandChildren = getAllSubVolumes(child.volume);
-        subVolumes.reserve(grandChildren.size() + subVolumes.size());
+        std::vector<GeoChildNodeWithTrf> grandChildren = getAllSubVolumes(child.volume, selector, summarizeEqualVol);
+        if (selector(child)) subVolumes.push_back(child);
+  
+        subVolumes.reserve(grandChildren.size() + subVolumes.capacity());
         std::transform(std::make_move_iterator(grandChildren.begin()),
                        std::make_move_iterator(grandChildren.end()),
                        std::back_inserter(subVolumes), [&child](GeoChildNodeWithTrf&& grandChild){
@@ -80,6 +82,13 @@ std::vector<GeoChildNodeWithTrf> getAllSubVolumes(PVConstLink physVol) {
                        });
     }
     return subVolumes;
+ }
+
+
+std::vector<GeoChildNodeWithTrf> getAllSubVolumes(PVConstLink physVol) {
+    return getAllSubVolumes(physVol, 
+                            [](const GeoChildNodeWithTrf& child){
+                                        return true;}, false);
 }
 
 bool hasFullPhysVolInTree(PVConstLink physVol) {
diff --git a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoDefinitions.h b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoDefinitions.h
index cbc81fd9d..d1861a649 100644
--- a/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoDefinitions.h
+++ b/GeoModelCore/GeoModelKernel/GeoModelKernel/GeoDefinitions.h
@@ -197,6 +197,8 @@ namespace GeoTrf {
       /// @brief Simple comparison returning -1, 0, 1
       int compare(const EulerAngles& other) const;
       operator bool() const;
+      /// @brief Returns the set of Euler angles to invert the rotation
+      EulerAngles inverse() const;
 
   };
 
@@ -218,6 +220,8 @@ namespace GeoTrf {
     bool operator<(const CoordEulerAngles& other) const;
     /// @brief Simple comparison returning -1, 0, 1
     int compare(const CoordEulerAngles& other) const;
+    /// @brief  Returns the set of CoordEulerAngles to invert the Rotation
+    CoordEulerAngles inverse() const;
     operator bool() const;
   };
   
@@ -250,9 +254,10 @@ namespace GeoTrf {
 
   class GeoTransformRT : public Transform3D {
   public:
-    GeoTransformRT(const GeoRotation& rot, const Vector3D& trans)
-      : Transform3D(Translation3D(trans)*Transform3D(AngleAxis3D(rot)))
-      {}
+    GeoTransformRT(const GeoRotation& rot, const Vector3D& trans);    
+    GeoTransformRT(const EulerAngles& angles, const Vector3D& trans);
+    GeoTransformRT(const CoordEulerAngles&angles, const Vector3D& trans);
+
     virtual ~GeoTransformRT() = default;
   };
 }
diff --git a/GeoModelCore/GeoModelKernel/src/GeoDefinitions.cxx b/GeoModelCore/GeoModelKernel/src/GeoDefinitions.cxx
index 79dd1b7a0..01e49145c 100755
--- a/GeoModelCore/GeoModelKernel/src/GeoDefinitions.cxx
+++ b/GeoModelCore/GeoModelKernel/src/GeoDefinitions.cxx
@@ -7,7 +7,7 @@
 #include <cmath>
 
 namespace {
-  constexpr double rotTolerance = 0.01 * GeoModelKernelUnits::deg;
+  constexpr double rotTolerance = 0.001 * GeoModelKernelUnits::deg;
 
   inline double cutOff(const double val, const double cutOff) {
      return std::abs(val) > cutOff ? val : 0.;
@@ -91,6 +91,10 @@ namespace GeoTrf {
   EulerAngles::operator bool() const {
      return std::abs(phi) > rotTolerance || std::abs(theta) > rotTolerance || std::abs(psi) > rotTolerance;
   }
+  EulerAngles EulerAngles::inverse() const {
+     return getGeoRotationAngles(GeoRotation(*this).inverse());
+  }
+
 
   int CoordEulerAngles::compare(const CoordEulerAngles& other) const {
       if (std::abs(alpha - other.alpha) > rotTolerance) return alpha < other.alpha ? -1 : 1;
@@ -104,6 +108,21 @@ namespace GeoTrf {
   CoordEulerAngles::operator bool() const {
      return std::abs(alpha) > rotTolerance || std::abs(beta) > rotTolerance || std::abs(gamma) > rotTolerance;
   }
+  CoordEulerAngles CoordEulerAngles::inverse() const {
+     return getCoordRotationAngles(GeoRotation(*this).inverse());
+  }
+
+  GeoTransformRT::GeoTransformRT(const EulerAngles& angles, const Vector3D& trans):
+        GeoTransformRT{GeoRotation{angles}, trans}{}
+
+    
+  GeoTransformRT::GeoTransformRT(const CoordEulerAngles&angles, const Vector3D& trans):
+      GeoTransformRT{GeoRotation{angles}, trans} {
+
+  }
+
+  GeoTransformRT::GeoTransformRT(const GeoRotation& rot, const Vector3D& trans): 
+    Transform3D(Translation3D(trans)*Transform3D(AngleAxis3D(rot))){}
 
 }
 
diff --git a/GeoModelCore/GeoModelKernel/tests/testEulerAngles.cxx b/GeoModelCore/GeoModelKernel/tests/testEulerAngles.cxx
index bc3ed0758..541eebc2c 100644
--- a/GeoModelCore/GeoModelKernel/tests/testEulerAngles.cxx
+++ b/GeoModelCore/GeoModelKernel/tests/testEulerAngles.cxx
@@ -80,6 +80,12 @@ int main() {
                                  GeoTrf::get3DRotMatX(coordAngles.alpha *GeoModelKernelUnits::deg)<<std::endl;
 
                 }
+                if (!isIdentity(coordRot * GeoTrf::GeoRotation{coordAngles.inverse()})){
+                    std::cout<<"testEulerAngles() "<<__LINE__<<"The inverse of "<<coordAngles<<" "
+                             <<coordAngles.inverse()<<" does not lead to Identity rotation "<<std::endl;
+                    return EXIT_FAILURE;
+                }
+
                 const GeoTrf::CoordEulerAngles calcCoordAngles = GeoTrf::getCoordRotationAngles(coordRot);
                 const GeoTrf::GeoRotation extCoordRot{calcCoordAngles};
                 if (!isIdentity(extCoordRot.inverse()* coordRot)) {
@@ -90,6 +96,11 @@ int main() {
                              <<calcCoordAngles.beta*toDeg<<"/"<<calcCoordAngles.gamma*toDeg<<std::endl<<extCoordRot<<std::endl;
                     return EXIT_FAILURE;
                 }
+                if (!isIdentity(extCoordRot * GeoTrf::GeoRotation{calcCoordAngles.inverse()})){
+                    std::cout<<"testEulerAngles() "<<__LINE__<<"The inverse of "<<calcCoordAngles<<" "
+                             <<calcCoordAngles.inverse()<<" does not lead to Identity rotation "<<std::endl;
+                    return EXIT_FAILURE;
+                }
             }
         }
     }
-- 
GitLab