From e9b231341ba594037d367a566d0bb0abdae34cf0 Mon Sep 17 00:00:00 2001
From: Sylvester Joosten <sjoosten@anl.gov>
Date: Mon, 25 Apr 2022 23:30:02 +0000
Subject: [PATCH] Added proper service/support plugin

---
 CMakeLists.txt             |   1 +
 src/TrackerSupport_geo.cpp | 123 +++++++++++++++++++++++++++++++++++++
 2 files changed, 124 insertions(+)
 create mode 100644 src/TrackerSupport_geo.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ab176a0..21a36e6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -45,6 +45,7 @@ dd4hep_add_plugin(${a_lib_name} SOURCES
   src/SimpleDiskDetector_geo.cpp
   src/Solenoid_geo.cpp
   src/TrapEndcapTracker_geo.cpp
+  src/TrackerSupport_geo.cpp
   USES ActsCore ActsPluginDD4hep
   )
 target_link_libraries(${a_lib_name}
diff --git a/src/TrackerSupport_geo.cpp b/src/TrackerSupport_geo.cpp
new file mode 100644
index 0000000..8afcd9e
--- /dev/null
+++ b/src/TrackerSupport_geo.cpp
@@ -0,0 +1,123 @@
+/** \addtogroup Trackers Trackers
+ * \brief Type: **BarrelTrackerWithFrame**.
+ * \author W. Armstrong
+ *
+ * \ingroup trackers
+ *
+ * @{
+ */
+#include <DD4hep/DetFactoryHelper.h>
+#include <DD4hep/Printout.h>
+#include <DD4hep/Shapes.h>
+#include <XML/Layering.h>
+#include <XML/Utilities.h>
+
+#include <cassert>
+
+using namespace std;
+using namespace dd4hep;
+
+namespace {
+  std::pair<Volume, Transform3D> build_shape(const Detector& descr, const xml_det_t& x_det, const xml_comp_t& x_support,
+                                             const xml_comp_t& x_child, const double offset = 0)
+  {
+    // Get rotation/translation info
+    xml_dim_t  x_pos(x_child.child(_U(position), false));
+    xml_dim_t  x_rot(x_child.child(_U(rotation), false));
+    Position   pos3D{0, 0, 0};
+    Rotation3D rot3D;
+
+    if (x_rot) {
+      rot3D = RotationZYX(x_rot.z(0), x_rot.y(0), x_rot.x(0));
+    }
+    if (x_pos) {
+      pos3D = Position(x_pos.x(0), x_pos.y(0), x_pos.z(0));
+    }
+    Transform3D tr(rot3D, pos3D);
+
+    // handle different known shapes and create solids
+    Solid             solid;
+    const std::string type = x_support.attr<std::string>(_U(type));
+    if (type == "Tube") {
+      const double thickness = getAttrOrDefault(x_child, _U(thickness), x_support.thickness());
+      const double length    = getAttrOrDefault(x_child, _U(length), x_support.length());
+      const double rmin      = getAttrOrDefault(x_child, _U(rmin), x_support.rmin());
+      solid                  = Tube(rmin + offset, rmin + thickness + offset, length / 2);
+    }
+    if (type == "Cone") {
+      const double thickness = getAttrOrDefault(x_child, _U(thickness), x_support.thickness());
+      const double length    = getAttrOrDefault(x_child, _U(length), x_support.length());
+      const double rmin1     = getAttrOrDefault(x_child, _U(rmin1), x_support.rmin2());
+      const double rmin2     = getAttrOrDefault(x_child, _U(rmin2), x_support.rmin2());
+      // Account for the fact that the distance between rmin1 and rmax2 is the projection
+      // of the thickness on the transverse direction
+      const double transverse_thickness = thickness / cos(atan2(fabs(rmin2 - rmin1), length));
+      const double rmax1                = rmin1 + transverse_thickness;
+      const double rmax2                = rmin2 + transverse_thickness;
+      solid                             = Cone(length / 2, rmin1, rmax1, rmin2, rmax2);
+    } else {
+      printout(ERROR, x_det.nameStr(), "Unknown support type: %s", type);
+      std::exit(1);
+    }
+    // Materials
+    Material mat = descr.material(getAttrOrDefault<std::string>(x_child, _U(material), "Air"));
+    // Create our volume
+    Volume vol{getAttrOrDefault<std::string>(x_child, _U(name), "support_vol"), solid, mat};
+
+    // visualization?
+    if (x_child.hasAttr(_U(vis))) {
+      vol.setVisAttributes(descr.visAttributes(x_child.visStr()));
+    }
+    return {vol, tr};
+  }
+  std::pair<Volume, Transform3D> build_shape(const Detector& descr, const xml_det_t& x_det, const xml_comp_t& x_support,
+                                             const double offset = 0)
+  {
+    return build_shape(descr, x_det, x_support, x_support, offset);
+  }
+} // namespace
+
+/** Generic tracker support implementation, can consist of arbitrary shapes
+ *
+ * @author Sylvester Joosten
+ */
+static Ref_t create_TrackerSupport(Detector& description, xml_h e, SensitiveDetector sens)
+{
+  const xml_det_t x_det    = e;
+  const Material  air      = description.air();
+  const int       det_id   = x_det.id();
+  const string    det_name = x_det.nameStr();
+
+  // global z-offset for the entire support assembly
+  const double offset = getAttrOrDefault(x_det, _U(offset), 0.);
+
+  DetElement det(det_name, det_id);
+  Assembly   assembly(det_name + "_assembly");
+
+  // Loop over the supports
+  for (xml_coll_t su{x_det, _U(support)}; su; ++su) {
+    xml_comp_t x_sup = su;
+    auto [vol, tr]   = build_shape(description, x_det, x_sup);
+    auto pv          = assembly.placeVolume(vol, tr);
+    // Loop over support components, if any
+    double cumulative_thickness = 0;
+    for (xml_coll_t com{x_sup, _U(component)}; com; ++com) {
+      xml_comp_t x_com = com;
+      auto [cvol, ctr] = build_shape(description, x_det, x_sup, x_com, cumulative_thickness);
+      vol.placeVolume(cvol, ctr);
+      cumulative_thickness += x_com.thickness();
+    }
+  }
+
+  // final placement
+  Volume       motherVol = description.pickMotherVolume(det);
+  Position     pos(0, 0, offset);
+  PlacedVolume pv = motherVol.placeVolume(assembly, pos);
+  pv.addPhysVolID("system", det.id());
+  det.setPlacement(pv);
+
+  return det;
+}
+
+// clang-format off
+DECLARE_DETELEMENT(eic_TrackerSupport, create_TrackerSupport)
-- 
GitLab