File indexing completed on 2025-09-12 08:13:59
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Plugins/GeoModel/GeoModelToDetectorVolume.hpp"
0010
0011 #include "Acts/Detector/GeometryIdGenerator.hpp"
0012 #include "Acts/Detector/PortalGenerators.hpp"
0013 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0014 #include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp"
0015 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0016 #include "Acts/Geometry/GeometryIdentifier.hpp"
0017 #include "Acts/Geometry/TrapezoidVolumeBounds.hpp"
0018 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0019 #include "Acts/Navigation/InternalNavigation.hpp"
0020
0021 #include <numbers>
0022
0023 #include <GeoModelHelpers/GeoShapeUtils.h>
0024 #include <GeoModelKernel/GeoBox.h>
0025 #include <GeoModelKernel/GeoPcon.h>
0026 #include <GeoModelKernel/GeoShapeShift.h>
0027 #include <GeoModelKernel/GeoShapeSubtraction.h>
0028 #include <GeoModelKernel/GeoShapeUnion.h>
0029 #include <GeoModelKernel/GeoSimplePolygonBrep.h>
0030 #include <GeoModelKernel/GeoTrd.h>
0031 #include <GeoModelKernel/GeoTube.h>
0032 #include <GeoModelKernel/GeoTubs.h>
0033 #include <GeoModelKernel/GeoVFullPhysVol.h>
0034
0035 namespace Acts::GeoModel {
0036
0037 Acts::Transform3 volumePosInSpace(const PVConstLink& physVol) {
0038 if (auto fullPhys = dynamic_pointer_cast<const GeoVFullPhysVol>(physVol);
0039 fullPhys != nullptr) {
0040 return fullPhys->getAbsoluteTransform();
0041 }
0042
0043
0044
0045 class GeoVolumePositioner : public GeoNodePositioning {
0046 public:
0047 explicit GeoVolumePositioner(const GeoVPhysVol* physVol)
0048 : GeoNodePositioning{physVol} {}
0049 };
0050
0051 GeoVolumePositioner positioner{physVol};
0052 return positioner.getAbsoluteTransform();
0053 }
0054 std::shared_ptr<Volume> convertVolume(const Transform3& trf,
0055 const GeoShape* shape,
0056 VolumeBoundFactory& boundFactory) {
0057 assert(shape);
0058 std::shared_ptr<VolumeBounds> bounds{};
0059 GeoTrf::Transform3D newTrf = trf;
0060 const ShapeType id = shape->typeID();
0061 if (id == GeoTube::getClassTypeID()) {
0062 const auto* tube = dynamic_cast<const GeoTube*>(shape);
0063 bounds = boundFactory.makeBounds<CylinderVolumeBounds>(
0064 tube->getRMin(), tube->getRMax(), tube->getZHalfLength());
0065 } else if (id == GeoTubs::getClassTypeID()) {
0066 const auto* tubs = dynamic_cast<const GeoTubs*>(shape);
0067 bounds = boundFactory.makeBounds<CylinderVolumeBounds>(
0068 tubs->getRMin(), tubs->getRMax(), tubs->getZHalfLength(),
0069 tubs->getDPhi() / 2);
0070 newTrf = trf * GeoTrf::RotateZ3D(tubs->getSPhi() + 0.5 * tubs->getDPhi());
0071 } else if (id == GeoBox::getClassTypeID()) {
0072 const auto* box = dynamic_cast<const GeoBox*>(shape);
0073 bounds = boundFactory.makeBounds<CuboidVolumeBounds>(
0074 box->getXHalfLength(), box->getYHalfLength(), box->getZHalfLength());
0075 } else if (id == GeoSimplePolygonBrep::getClassTypeID() ||
0076
0077 id == GeoShapeUnion::getClassTypeID() ||
0078
0079 id == GeoPcon::getClassTypeID()) {
0080 double xmin{0}, xmax{0}, ymin{0}, ymax{0}, zmin{0}, zmax{0};
0081 shape->extent(xmin, ymin, zmin, xmax, ymax, zmax);
0082 bounds = boundFactory.makeBounds<CuboidVolumeBounds>(
0083 (xmax - xmin) / 2, (ymax - ymin) / 2, (zmax - zmin) / 2);
0084 } else if (id == GeoTrd::getClassTypeID()) {
0085 const auto* trd = dynamic_cast<const GeoTrd*>(shape);
0086 double x1 = trd->getXHalfLength1();
0087 double x2 = trd->getXHalfLength2();
0088 double y1 = trd->getYHalfLength1();
0089 double y2 = trd->getYHalfLength2();
0090 double z = trd->getZHalfLength();
0091 if (y1 == y2) {
0092 if (x1 <= x2) {
0093
0094 bounds = boundFactory.makeBounds<TrapezoidVolumeBounds>(x1, x2, z, y1);
0095 constexpr double rotationAngle = std::numbers::pi / 2.;
0096 newTrf = trf * GeoTrf::RotateX3D(rotationAngle);
0097 } else {
0098 bounds = boundFactory.makeBounds<TrapezoidVolumeBounds>(x2, x1, z, y1);
0099 constexpr double rotationAngle = std::numbers::pi;
0100 newTrf = trf * GeoTrf::RotateY3D(rotationAngle) *
0101 GeoTrf::RotateZ3D(rotationAngle);
0102 }
0103 } else if (x1 == x2) {
0104 if (y1 < y2) {
0105 bounds = boundFactory.makeBounds<TrapezoidVolumeBounds>(y1, y2, z, x1);
0106 auto rotationAngle = std::numbers::pi / 2.;
0107 newTrf = trf * GeoTrf::RotateZ3D(rotationAngle) *
0108 GeoTrf::RotateX3D(rotationAngle);
0109 } else {
0110 bounds = boundFactory.makeBounds<TrapezoidVolumeBounds>(y2, y1, z, x1);
0111 auto rotationAngle = std::numbers::pi;
0112 newTrf = trf * GeoTrf::RotateX3D(rotationAngle) *
0113 GeoTrf::RotateZ3D(rotationAngle / 2) *
0114 GeoTrf::RotateX3D(rotationAngle / 2);
0115 }
0116 } else {
0117 throw std::runtime_error("convertVolume() - Translating the GeoTrd " +
0118 printGeoShape(shape) + " to ACTS failed");
0119 }
0120
0121 } else if (id == GeoShapeSubtraction::getClassTypeID()) {
0122 return convertVolume(newTrf, getOps(shape).first, boundFactory);
0123 } else if (id == GeoShapeShift::getClassTypeID()) {
0124 auto compressed = compressShift(shape);
0125 if (compressed->typeID() != GeoShapeShift::getClassTypeID()) {
0126 return convertVolume(newTrf, compressed, boundFactory);
0127 }
0128 const auto shiftShape =
0129 dynamic_pointer_cast<const GeoShapeShift>(compressed);
0130 const GeoShape* shapeOp = shiftShape->getOp();
0131 return convertVolume(newTrf * shiftShape->getX(), shapeOp, boundFactory);
0132 } else {
0133 throw std::runtime_error("Cannot convert " + printGeoShape(shape));
0134 }
0135 return std::make_shared<Volume>(newTrf, bounds);
0136 }
0137
0138 std::shared_ptr<Experimental::DetectorVolume> convertDetectorVolume(
0139 const GeometryContext& context, Volume& vol, const std::string& name,
0140 const std::vector<std::shared_ptr<Surface>>& sensitives) {
0141 auto portalGenerator = Experimental::defaultPortalAndSubPortalGenerator();
0142 return Experimental::DetectorVolumeFactory::construct(
0143 portalGenerator, context, name, vol.transform(), vol.volumeBoundsPtr(),
0144 sensitives,
0145 std::vector<std::shared_ptr<Acts::Experimental::DetectorVolume>>{},
0146 Experimental::tryNoVolumes(), Experimental::tryAllPortalsAndSurfaces());
0147 }
0148
0149 }