File indexing completed on 2025-08-05 08:09:35
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Detector/VolumeStructureBuilder.hpp"
0010
0011 #include "Acts/Detector/PortalGenerators.hpp"
0012 #include "Acts/Geometry/ConeVolumeBounds.hpp"
0013 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0014 #include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp"
0015 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0016 #include "Acts/Geometry/GenericCuboidVolumeBounds.hpp"
0017 #include "Acts/Geometry/TrapezoidVolumeBounds.hpp"
0018 #include "Acts/Utilities/Enumerate.hpp"
0019 #include "Acts/Utilities/Helpers.hpp"
0020 #include "Acts/Utilities/StringHelpers.hpp"
0021
0022 Acts::Experimental::VolumeStructureBuilder::VolumeStructureBuilder(
0023 const Acts::Experimental::VolumeStructureBuilder::Config& cfg,
0024 std::unique_ptr<const Acts::Logger> mlogger)
0025 : IExternalStructureBuilder(), m_cfg(cfg), m_logger(std::move(mlogger)) {
0026
0027 if (m_cfg.boundValues.empty() && !m_cfg.extent.has_value()) {
0028 throw std::invalid_argument(
0029 "VolumeStructureBuilder: no extent nor boundary values given");
0030 }
0031
0032 if (m_cfg.boundsType == VolumeBounds::BoundsType::eOther) {
0033 throw std::invalid_argument(
0034 "VolumeStructureBuilder: no known volume bounds type provided.");
0035 }
0036 }
0037
0038 Acts::Experimental::ExternalStructure
0039 Acts::Experimental::VolumeStructureBuilder::construct(
0040 [[maybe_unused]] const Acts::GeometryContext& gctx) const {
0041
0042 if (!m_cfg.auxiliary.empty()) {
0043 ACTS_DEBUG(m_cfg.auxiliary);
0044 }
0045
0046
0047 std::unique_ptr<VolumeBounds> volumeBounds = nullptr;
0048
0049
0050 auto eTransform = Transform3::Identity();
0051 std::vector<ActsScalar> boundValues = m_cfg.boundValues;
0052
0053
0054 switch (m_cfg.boundsType) {
0055 case VolumeBounds::BoundsType::eCone: {
0056 ACTS_VERBOSE("Building conical volume bounds.");
0057
0058 if (boundValues.size() < 5u) {
0059 throw std::runtime_error(
0060 "VolumeStructureBuilder: parameters for cone volume bounds need to "
0061 "be fully provided, they can not be estimated from an Extent "
0062 "object. It needs at least 5 parameters, while " +
0063 std::to_string(boundValues.size()) + " where given");
0064 }
0065 auto bArray = to_array<ConeVolumeBounds::BoundValues::eSize, ActsScalar>(
0066 boundValues);
0067 volumeBounds = std::make_unique<ConeVolumeBounds>(bArray);
0068 } break;
0069 case VolumeBounds::BoundsType::eCuboid: {
0070 ACTS_VERBOSE("Building cuboid volume bounds.");
0071
0072 if (boundValues.empty() && m_cfg.extent.has_value()) {
0073 ACTS_VERBOSE("Cuboid: estimate parameters from Extent.");
0074 const auto& vExtent = m_cfg.extent.value();
0075 if (vExtent.constrains(binX) && vExtent.constrains(binY) &&
0076 vExtent.constrains(binZ)) {
0077 eTransform.pretranslate(Vector3(vExtent.medium(binX),
0078 vExtent.medium(binY),
0079 vExtent.medium(binZ)));
0080 boundValues = {0.5 * vExtent.interval(binX),
0081 0.5 * vExtent.interval(binY),
0082 0.5 * vExtent.interval(binZ)};
0083
0084 } else {
0085 throw std::runtime_error(
0086 "VolumeStructureBuilder: translation to cuboid does not work as "
0087 "the extent does not constrain all necessary value.");
0088 }
0089 } else if (boundValues.size() < 3u) {
0090 throw std::runtime_error(
0091 "VolumeStructureBuilder: parameters for cuboid volume bounds need "
0092 "to be fully provided, it needs exactly 3 parameters, while " +
0093 std::to_string(boundValues.size()) + " where given");
0094 }
0095 auto bArray =
0096 to_array<CuboidVolumeBounds::BoundValues::eSize>(boundValues);
0097 volumeBounds = std::make_unique<CuboidVolumeBounds>(bArray);
0098 } break;
0099 case VolumeBounds::BoundsType::eCutoutCylinder: {
0100 ACTS_VERBOSE("Building cutout cylindrical volume bounds.");
0101
0102 if (boundValues.size() < 5u) {
0103 throw std::runtime_error(
0104 "VolumeStructureBuilder: parameters for cutout cylinder volume "
0105 "bounds need to be fully provided, they can not be estimated from "
0106 "an Extent object. It needs exactly 3 parameters, while " +
0107 std::to_string(boundValues.size()) + " where given");
0108 }
0109 auto bArray =
0110 to_array<CutoutCylinderVolumeBounds::BoundValues::eSize>(boundValues);
0111 volumeBounds = std::make_unique<CutoutCylinderVolumeBounds>(bArray);
0112 } break;
0113 case VolumeBounds::BoundsType::eCylinder: {
0114 ACTS_VERBOSE("Building cylindrical volume bounds.");
0115
0116 if (boundValues.empty() && m_cfg.extent.has_value()) {
0117 ACTS_VERBOSE("Cylinder: estimate parameters from Extent.");
0118 const auto& vExtent = m_cfg.extent.value();
0119 if (vExtent.constrains(binR) && vExtent.constrains(binZ)) {
0120 eTransform.pretranslate(Vector3(0., 0., vExtent.medium(binZ)));
0121 boundValues = {vExtent.min(binR), vExtent.max(binR),
0122 0.5 * vExtent.interval(binZ)};
0123 if (vExtent.constrains(binPhi)) {
0124 boundValues.push_back(0.5 * vExtent.interval(binPhi));
0125 boundValues.push_back(vExtent.medium(binPhi));
0126 }
0127 } else {
0128 throw std::runtime_error(
0129 "VolumeStructureBuilder: translation to cuboid does not work as "
0130 "the extent does not constrain all necessary values.");
0131 }
0132 } else if (boundValues.size() < 3u) {
0133 throw std::runtime_error(
0134 "VolumeStructureBuilder: parameters for cylinder volume "
0135 "bounds need to be fully provided, it needs at least 3 parameters, "
0136 "while " +
0137 std::to_string(boundValues.size()) + " where given");
0138 }
0139
0140 if (boundValues.size() == 3u) {
0141 boundValues.push_back(M_PI);
0142 boundValues.push_back(0.);
0143 }
0144 ACTS_VERBOSE(" - cylindrical shape with [iR, oR, hZ, sPhi, mPhi] = "
0145 << boundValues[0] << ", " << boundValues[1] << ", "
0146 << boundValues[2] << ", " << boundValues[3] << ", "
0147 << boundValues[4]);
0148 auto bArray =
0149 to_array<CylinderVolumeBounds::BoundValues::eSize>(boundValues);
0150 volumeBounds = std::make_unique<CylinderVolumeBounds>(bArray);
0151 } break;
0152 case VolumeBounds::BoundsType::eGenericCuboid: {
0153 ACTS_VERBOSE("Building generic cuboid volume bounds.");
0154
0155 if (boundValues.size() < GenericCuboidVolumeBounds::BoundValues::eSize) {
0156 throw std::runtime_error(
0157 "VolumeStructureBuilder: parameters for generic cuboid volume "
0158 "bounds need to be provided, they can not be estimated from an "
0159 "Extent object. It needs exactly 24 parameters, while " +
0160 std::to_string(boundValues.size()) + " where given");
0161 }
0162 auto bArray =
0163 to_array<GenericCuboidVolumeBounds::BoundValues::eSize>(boundValues);
0164 volumeBounds = std::make_unique<GenericCuboidVolumeBounds>(bArray);
0165 } break;
0166 case VolumeBounds::BoundsType::eTrapezoid: {
0167 ACTS_VERBOSE("Building trapezoid volume bounds.");
0168
0169 if (boundValues.size() < 4u) {
0170 throw std::runtime_error(
0171 "VolumeStructureBuilder: parameters for trapezoid volume bounds "
0172 "need to be provided, they can not be estimated from an Extent "
0173 "object. It needs at least 4 parameters, while " +
0174 std::to_string(boundValues.size()) + " where given");
0175 }
0176 auto bArray =
0177 to_array<TrapezoidVolumeBounds::BoundValues::eSize>(boundValues);
0178 volumeBounds = std::make_unique<TrapezoidVolumeBounds>(bArray);
0179 } break;
0180 default:
0181 break;
0182 }
0183
0184 Transform3 fTransform = m_cfg.transform * eTransform;
0185 ACTS_VERBOSE(" - translation: " << Acts::toString(fTransform.translation()));
0186 if (!fTransform.rotation().isApprox(
0187 Acts::Transform3::Identity().rotation())) {
0188 ACTS_VERBOSE(" - rotation: " << Acts::toString(fTransform.rotation()));
0189 }
0190
0191
0192 return {fTransform, std::move(volumeBounds), defaultPortalGenerator()};
0193 }