File indexing completed on 2026-09-18 08:21:37
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Geometry/TrapezoidVolumeBounds.hpp"
0010
0011 #include "Acts/Definitions/Direction.hpp"
0012 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0013 #include "Acts/Surfaces/PlaneSurface.hpp"
0014 #include "Acts/Surfaces/RectangleBounds.hpp"
0015 #include "Acts/Surfaces/Surface.hpp"
0016 #include "Acts/Surfaces/TrapezoidBounds.hpp"
0017 #include "Acts/Utilities/BoundingBox.hpp"
0018 #include "Acts/Utilities/detail/OstreamStateGuard.hpp"
0019
0020 #include <cmath>
0021 #include <cstddef>
0022 #include <iomanip>
0023 #include <numbers>
0024 #include <utility>
0025
0026 namespace Acts {
0027
0028 TrapezoidVolumeBounds::TrapezoidVolumeBounds(double minhalex, double maxhalex,
0029 double haley, double halez)
0030 : VolumeBounds() {
0031 m_values[eHalfLengthXnegY] = minhalex;
0032 m_values[eHalfLengthXposY] = maxhalex;
0033 m_values[eHalfLengthY] = haley;
0034 m_values[eHalfLengthZ] = halez;
0035 m_values[eAlpha] = std::atan2(2 * haley, (maxhalex - minhalex));
0036 m_values[eBeta] = std::numbers::pi - get(eAlpha);
0037 checkConsistency();
0038 buildSurfaceBounds();
0039 }
0040
0041 TrapezoidVolumeBounds::TrapezoidVolumeBounds(double minhalex, double haley,
0042 double halez, double alpha,
0043 double beta)
0044 : VolumeBounds() {
0045 m_values[eHalfLengthXnegY] = minhalex;
0046 m_values[eHalfLengthY] = haley;
0047 m_values[eHalfLengthZ] = halez;
0048 m_values[eAlpha] = alpha;
0049 m_values[eBeta] = beta;
0050
0051 double gamma = (alpha > beta) ? (alpha - std::numbers::pi / 2.)
0052 : (beta - std::numbers::pi / 2.);
0053 m_values[eHalfLengthXposY] = minhalex + (2. * haley) * std::tan(gamma);
0054
0055 checkConsistency();
0056 buildSurfaceBounds();
0057 }
0058
0059 std::vector<double> TrapezoidVolumeBounds::values() const {
0060 return {m_values.begin(), m_values.end()};
0061 }
0062
0063 std::vector<OrientedSurface> TrapezoidVolumeBounds::orientedSurfaces(
0064 const Transform3& transform) const {
0065 std::vector<OrientedSurface> oSurfaces;
0066 oSurfaces.reserve(6);
0067
0068
0069 RotationMatrix3 trapezoidRotation(transform.rotation());
0070 Vector3 trapezoidX(trapezoidRotation.col(0));
0071 Vector3 trapezoidY(trapezoidRotation.col(1));
0072 Vector3 trapezoidZ(trapezoidRotation.col(2));
0073 Vector3 trapezoidCenter(transform.translation());
0074
0075
0076 auto nzTransform = transform * Translation3(0., 0., -get(eHalfLengthZ));
0077 auto sf =
0078 Surface::makeShared<PlaneSurface>(nzTransform, m_faceXYTrapezoidBounds);
0079 oSurfaces.emplace_back(std::move(sf), Direction::AlongNormal());
0080
0081 auto pzTransform = transform * Translation3(0., 0., get(eHalfLengthZ));
0082 sf = Surface::makeShared<PlaneSurface>(pzTransform, m_faceXYTrapezoidBounds);
0083 oSurfaces.emplace_back(std::move(sf), Direction::OppositeNormal());
0084
0085 double poshOffset = get(eHalfLengthY) / std::tan(get(eAlpha));
0086 double neghOffset = get(eHalfLengthY) / std::tan(get(eBeta));
0087 double topShift = poshOffset + neghOffset;
0088
0089
0090
0091 Vector3 fbPosition(-get(eHalfLengthXnegY) + neghOffset, 0., 0.);
0092 auto fbTransform =
0093 transform * Translation3(fbPosition) *
0094 AngleAxis3(-std::numbers::pi / 2. + get(eBeta), Vector3(0., 0., 1.)) *
0095 s_planeYZ;
0096 sf =
0097 Surface::makeShared<PlaneSurface>(fbTransform, m_faceBetaRectangleBounds);
0098 oSurfaces.emplace_back(std::move(sf), Direction::AlongNormal());
0099
0100
0101 Vector3 faPosition(get(eHalfLengthXnegY) + poshOffset, 0., 0.);
0102 auto faTransform =
0103 transform * Translation3(faPosition) *
0104 AngleAxis3(-std::numbers::pi / 2. + get(eAlpha), Vector3(0., 0., 1.)) *
0105 s_planeYZ;
0106 sf = Surface::makeShared<PlaneSurface>(faTransform,
0107 m_faceAlphaRectangleBounds);
0108 oSurfaces.emplace_back(std::move(sf), Direction::OppositeNormal());
0109
0110
0111
0112 auto nxTransform =
0113 transform * Translation3(0., -get(eHalfLengthY), 0.) * s_planeZX;
0114 sf = Surface::makeShared<PlaneSurface>(nxTransform,
0115 m_faceZXRectangleBoundsBottom);
0116 oSurfaces.emplace_back(std::move(sf), Direction::AlongNormal());
0117
0118 auto pxTransform =
0119 transform * Translation3(topShift, get(eHalfLengthY), 0.) * s_planeZX;
0120 sf = Surface::makeShared<PlaneSurface>(pxTransform,
0121 m_faceZXRectangleBoundsTop);
0122 oSurfaces.emplace_back(std::move(sf), Direction::OppositeNormal());
0123
0124 return oSurfaces;
0125 }
0126
0127 void TrapezoidVolumeBounds::buildSurfaceBounds() {
0128 m_faceXYTrapezoidBounds = std::make_shared<const TrapezoidBounds>(
0129 get(eHalfLengthXnegY), get(eHalfLengthXposY), get(eHalfLengthY));
0130
0131 m_faceAlphaRectangleBounds = std::make_shared<const RectangleBounds>(
0132 get(eHalfLengthY) / std::cos(get(eAlpha) - std::numbers::pi / 2.),
0133 get(eHalfLengthZ));
0134
0135 m_faceBetaRectangleBounds = std::make_shared<const RectangleBounds>(
0136 get(eHalfLengthY) / std::cos(get(eBeta) - std::numbers::pi / 2.),
0137 get(eHalfLengthZ));
0138
0139 m_faceZXRectangleBoundsBottom = std::make_shared<const RectangleBounds>(
0140 get(eHalfLengthZ), get(eHalfLengthXnegY));
0141
0142 m_faceZXRectangleBoundsTop = std::make_shared<const RectangleBounds>(
0143 get(eHalfLengthZ), get(eHalfLengthXposY));
0144 }
0145
0146 bool TrapezoidVolumeBounds::inside(const Vector3& pos, double tol) const {
0147 if (std::abs(pos.z()) > get(eHalfLengthZ) + tol) {
0148 return false;
0149 }
0150 if (std::abs(pos.y()) > get(eHalfLengthY) + tol) {
0151 return false;
0152 }
0153 Vector2 locp(pos.x(), pos.y());
0154 return m_faceXYTrapezoidBounds->inside(
0155 locp, BoundaryTolerance::AbsoluteEuclidean(tol));
0156 }
0157
0158 std::ostream& TrapezoidVolumeBounds::toStream(std::ostream& os) const {
0159 detail::OstreamStateGuard guard{os};
0160 os << std::fixed << std::setprecision(5);
0161 os << "TrapezoidVolumeBounds: (halfX @-Y, halfX @+Y, halfY, halfZ, alpha, "
0162 "beta) "
0163 "= ";
0164 os << "(" << get(eHalfLengthXnegY) << ", " << get(eHalfLengthXposY) << ", "
0165 << get(eHalfLengthY) << ", " << get(eHalfLengthZ);
0166 os << ", " << get(eAlpha) << ", " << get(eBeta) << ")";
0167 return os;
0168 }
0169
0170 Volume::BoundingBox TrapezoidVolumeBounds::boundingBox(
0171 const Transform3* trf, const Vector3& envelope,
0172 const Volume* entity) const {
0173 double minx = get(eHalfLengthXnegY);
0174 double maxx = get(eHalfLengthXposY);
0175 double haley = get(eHalfLengthY);
0176 double halez = get(eHalfLengthZ);
0177
0178 std::array<Vector3, 8> vertices = {{{-minx, -haley, -halez},
0179 {+minx, -haley, -halez},
0180 {-maxx, +haley, -halez},
0181 {+maxx, +haley, -halez},
0182 {-minx, -haley, +halez},
0183 {+minx, -haley, +halez},
0184 {-maxx, +haley, +halez},
0185 {+maxx, +haley, +halez}}};
0186
0187 Transform3 transform = Transform3::Identity();
0188 if (trf != nullptr) {
0189 transform = *trf;
0190 }
0191
0192 Vector3 vmin = transform * vertices[0];
0193 Vector3 vmax = transform * vertices[0];
0194
0195 for (std::size_t i = 1; i < 8; i++) {
0196 const Vector3 vtx = transform * vertices[i];
0197 vmin = vmin.cwiseMin(vtx);
0198 vmax = vmax.cwiseMax(vtx);
0199 }
0200
0201 return {entity, vmin - envelope, vmax + envelope};
0202 }
0203
0204 void TrapezoidVolumeBounds::checkConsistency() noexcept(false) {
0205 if (get(eHalfLengthXnegY) < 0. || get(eHalfLengthXposY) < 0.) {
0206 throw std::invalid_argument(
0207 "TrapezoidVolumeBounds: invalid trapezoid parameters in x.");
0208 }
0209 if (get(eHalfLengthY) <= 0.) {
0210 throw std::invalid_argument("TrapezoidVolumeBounds: invalid y extrusion.");
0211 }
0212 if (get(eHalfLengthZ) <= 0.) {
0213 throw std::invalid_argument("TrapezoidVolumeBounds: invalid z extrusion.");
0214 }
0215 }
0216
0217 }