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