File indexing completed on 2026-09-14 08:18:16
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0010
0011 #include "Acts/Definitions/Direction.hpp"
0012 #include "Acts/Surfaces/LineSurface.hpp"
0013 #include "Acts/Surfaces/PlaneSurface.hpp"
0014 #include "Acts/Surfaces/RectangleBounds.hpp"
0015 #include "Acts/Surfaces/Surface.hpp"
0016 #include "Acts/Utilities/BoundingBox.hpp"
0017 #include "Acts/Utilities/detail/OstreamStateGuard.hpp"
0018
0019 #include <algorithm>
0020 #include <array>
0021 #include <iomanip>
0022 #include <stdexcept>
0023 #include <utility>
0024
0025 namespace Acts {
0026
0027 CuboidVolumeBounds::CuboidVolumeBounds(double halex, double haley, double halez)
0028 : VolumeBounds(), m_values({halex, haley, halez}) {
0029 checkConsistency();
0030 buildSurfaceBounds();
0031 }
0032
0033 CuboidVolumeBounds::CuboidVolumeBounds(const std::array<double, eSize>& values)
0034 : m_values(values) {
0035 checkConsistency();
0036 buildSurfaceBounds();
0037 }
0038
0039 CuboidVolumeBounds::CuboidVolumeBounds(
0040 std::initializer_list<std::pair<BoundValues, double>> keyValues)
0041 : m_values({-1, -1, -1}) {
0042 for (const auto& [key, value] : keyValues) {
0043 m_values[key] = value;
0044 }
0045
0046 if (std::ranges::any_of(m_values,
0047 [](const auto& val) { return val == -1; })) {
0048 throw std::logic_error("Missing bound values");
0049 }
0050 checkConsistency();
0051 buildSurfaceBounds();
0052 }
0053
0054 std::vector<double> CuboidVolumeBounds::values() const {
0055 return {m_values.begin(), m_values.end()};
0056 }
0057
0058 std::vector<Acts::OrientedSurface> Acts::CuboidVolumeBounds::orientedSurfaces(
0059 const Transform3& transform) const {
0060 std::vector<OrientedSurface> oSurfaces;
0061 oSurfaces.reserve(6);
0062
0063
0064 auto sf = Surface::makeShared<PlaneSurface>(
0065 transform * Translation3(0., 0., -get(eHalfLengthZ)), m_xyBounds);
0066 oSurfaces.emplace_back(std::move(sf), Direction::AlongNormal());
0067
0068 sf = Surface::makeShared<PlaneSurface>(
0069 transform * Translation3(0., 0., get(eHalfLengthZ)), m_xyBounds);
0070 oSurfaces.emplace_back(std::move(sf), Direction::OppositeNormal());
0071
0072
0073 sf = Surface::makeShared<PlaneSurface>(
0074 transform * Translation3(-get(eHalfLengthX), 0., 0.) * s_planeYZ,
0075 m_yzBounds);
0076 oSurfaces.emplace_back(std::move(sf), Direction::AlongNormal());
0077
0078 sf = Surface::makeShared<PlaneSurface>(
0079 transform * Translation3(get(eHalfLengthX), 0., 0.) * s_planeYZ,
0080 m_yzBounds);
0081 oSurfaces.emplace_back(std::move(sf), Direction::OppositeNormal());
0082
0083
0084 sf = Surface::makeShared<PlaneSurface>(
0085 transform * Translation3(0., -get(eHalfLengthY), 0.) * s_planeZX,
0086 m_zxBounds);
0087 oSurfaces.emplace_back(std::move(sf), Direction::AlongNormal());
0088
0089 sf = Surface::makeShared<PlaneSurface>(
0090 transform * Translation3(0., get(eHalfLengthY), 0.) * s_planeZX,
0091 m_zxBounds);
0092 oSurfaces.emplace_back(std::move(sf), Direction::OppositeNormal());
0093
0094 return oSurfaces;
0095 }
0096
0097 std::ostream& CuboidVolumeBounds::toStream(std::ostream& os) const {
0098 detail::OstreamStateGuard guard{os};
0099 os << std::fixed << std::setprecision(5);
0100 os << "Acts::CuboidVolumeBounds: (halfLengthX, halfLengthY, halfLengthZ) = ";
0101 os << "(" << get(eHalfLengthX) << ", " << get(eHalfLengthY) << ", "
0102 << get(eHalfLengthZ) << ")";
0103 return os;
0104 }
0105
0106 Volume::BoundingBox CuboidVolumeBounds::boundingBox(
0107 const Transform3* trf, const Vector3& envelope,
0108 const Volume* entity) const {
0109 Vector3 vmin(-get(eHalfLengthX), -get(eHalfLengthY), -get(eHalfLengthZ));
0110 Vector3 vmax(get(eHalfLengthX), get(eHalfLengthY), get(eHalfLengthZ));
0111
0112 Volume::BoundingBox box(entity, vmin - envelope, vmax + envelope);
0113 return trf == nullptr ? box : box.transformed(*trf);
0114 }
0115
0116 void CuboidVolumeBounds::buildSurfaceBounds() {
0117 m_xyBounds = std::make_shared<const RectangleBounds>(get(eHalfLengthX),
0118 get(eHalfLengthY));
0119 m_yzBounds = std::make_shared<const RectangleBounds>(get(eHalfLengthY),
0120 get(eHalfLengthZ));
0121 m_zxBounds = std::make_shared<const RectangleBounds>(get(eHalfLengthZ),
0122 get(eHalfLengthX));
0123 }
0124
0125 double CuboidVolumeBounds::referenceBorder(AxisDirection aDir) const {
0126 if (aDir <= AxisDirection::AxisZ) {
0127 return m_values[toUnderlying(aDir)];
0128 }
0129 if (aDir == AxisDirection::AxisR) {
0130 return std::sqrt(m_values[toUnderlying(AxisDirection::AxisX)] *
0131 m_values[toUnderlying(AxisDirection::AxisX)] +
0132 m_values[toUnderlying(AxisDirection::AxisY)] *
0133 m_values[toUnderlying(AxisDirection::AxisY)]);
0134 }
0135 return 0.0;
0136 }
0137
0138 bool CuboidVolumeBounds::inside(const Vector3& pos, double tol) const {
0139 return (std::abs(pos.x()) <= get(eHalfLengthX) + tol &&
0140 std::abs(pos.y()) <= get(eHalfLengthY) + tol &&
0141 std::abs(pos.z()) <= get(eHalfLengthZ) + tol);
0142 }
0143
0144 void CuboidVolumeBounds::checkConsistency() noexcept(false) {
0145 if (get(eHalfLengthX) <= 0 || get(eHalfLengthY) <= 0 ||
0146 get(eHalfLengthZ) <= 0.) {
0147 throw std::invalid_argument(
0148 "CuboidVolumeBounds: invalid input, zero or negative.");
0149 }
0150 }
0151
0152 void CuboidVolumeBounds::set(BoundValues bValue, double value) {
0153 set({{bValue, value}});
0154 }
0155
0156 void CuboidVolumeBounds::set(
0157 std::initializer_list<std::pair<BoundValues, double>> keyValues) {
0158 std::array<double, eSize> previous = m_values;
0159 for (const auto& [key, value] : keyValues) {
0160 m_values[key] = value;
0161 }
0162 try {
0163 checkConsistency();
0164 buildSurfaceBounds();
0165 } catch (std::invalid_argument& e) {
0166 m_values = previous;
0167 throw e;
0168 }
0169 }
0170
0171 CuboidVolumeBounds::BoundValues CuboidVolumeBounds::boundsFromAxisDirection(
0172 AxisDirection direction) {
0173 using enum AxisDirection;
0174 switch (direction) {
0175 case AxisX:
0176 return BoundValues::eHalfLengthX;
0177 case AxisY:
0178 return BoundValues::eHalfLengthY;
0179 case AxisZ:
0180 return BoundValues::eHalfLengthZ;
0181 default:
0182 throw std::invalid_argument("Invalid axis direction");
0183 }
0184 }
0185
0186 std::tuple<CuboidVolumeBounds::Face, CuboidVolumeBounds::Face,
0187 std::array<CuboidVolumeBounds::Face, 4>>
0188 CuboidVolumeBounds::facesFromAxisDirection(AxisDirection direction) {
0189 using enum AxisDirection;
0190 using enum CuboidVolumeBounds::Face;
0191 if (direction == AxisX) {
0192 return {NegativeXFace,
0193 PositiveXFace,
0194 {NegativeZFace, PositiveZFace, NegativeYFace, PositiveYFace}};
0195 } else if (direction == AxisY) {
0196 return {NegativeYFace,
0197 PositiveYFace,
0198 {NegativeZFace, PositiveZFace, NegativeXFace, PositiveXFace}};
0199 } else if (direction == AxisZ) {
0200 return {NegativeZFace,
0201 PositiveZFace,
0202 {NegativeXFace, PositiveXFace, NegativeYFace, PositiveYFace}};
0203 } else {
0204 throw std::invalid_argument("Invalid axis direction");
0205 }
0206 }
0207
0208 }
0209
0210
0211 std::ostream& operator<<(std::ostream& os,
0212 Acts::CuboidVolumeBounds::Face face) {
0213 using enum Acts::CuboidVolumeBounds::Face;
0214 switch (face) {
0215 case NegativeXFace:
0216 return os << "NegativeXFace";
0217 case PositiveXFace:
0218 return os << "PositiveXFace";
0219 case NegativeYFace:
0220 return os << "NegativeYFace";
0221 case PositiveYFace:
0222 return os << "PositiveYFace";
0223 case NegativeZFace:
0224 return os << "NegativeZFace";
0225 case PositiveZFace:
0226 return os << "PositiveZFace";
0227 default:
0228 return os << "UnknownFace";
0229 }
0230 }