File indexing completed on 2026-11-13 09:38:02
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Surfaces/CylinderBounds.hpp"
0010
0011 #include "Acts/Surfaces/detail/VerticesHelper.hpp"
0012 #include "Acts/Utilities/VectorHelpers.hpp"
0013 #include "Acts/Utilities/detail/OstreamStateGuard.hpp"
0014 #include "Acts/Utilities/detail/periodic.hpp"
0015
0016 #include <cmath>
0017 #include <iomanip>
0018 #include <iostream>
0019 #include <numbers>
0020 #include <utility>
0021
0022 namespace Acts {
0023
0024 using VectorHelpers::perp;
0025 using VectorHelpers::phi;
0026
0027 std::vector<double> CylinderBounds::values() const {
0028 return {m_values.begin(), m_values.end()};
0029 }
0030
0031 Vector2 CylinderBounds::shifted(const Vector2& lposition) const {
0032 return {detail::radian_sym((lposition[0] / get(eR)) - get(eAveragePhi)),
0033 lposition[1]};
0034 }
0035
0036 bool CylinderBounds::inside(const Vector2& lposition) const {
0037 double halfLengthZ = get(eHalfLengthZ);
0038 double halfPhi = get(eHalfPhiSector);
0039 return detail::VerticesHelper::isInsideRectangle(
0040 shifted(lposition), Vector2(-halfPhi, -halfLengthZ),
0041 Vector2(halfPhi, halfLengthZ));
0042 }
0043
0044 Vector2 CylinderBounds::closestPoint(const Vector2& lposition,
0045 const SquareMatrix2& metric) const {
0046 double halfLengthZ = get(eHalfLengthZ);
0047 double radius = get(eR);
0048 double halfRPhi = radius * get(eHalfPhiSector);
0049
0050
0051 double rDeltaPhi =
0052 radius * detail::radian_sym(lposition[0] / radius - get(eAveragePhi));
0053 Vector2 relative{rDeltaPhi, lposition[1]};
0054
0055 Vector2 vertices[] = {{-halfRPhi, -halfLengthZ},
0056 {halfRPhi, -halfLengthZ},
0057 {halfRPhi, halfLengthZ},
0058 {-halfRPhi, halfLengthZ}};
0059
0060 Vector2 closest = detail::VerticesHelper::computeClosestPointOnPolygon(
0061 relative, vertices, metric);
0062
0063 closest[0] += lposition[0] - rDeltaPhi;
0064 return closest;
0065 }
0066
0067 Vector2 CylinderBounds::center() const {
0068
0069
0070 return Vector2(get(eAveragePhi), 0.0);
0071 }
0072
0073 std::ostream& CylinderBounds::toStream(std::ostream& sl) const {
0074 detail::OstreamStateGuard guard{sl};
0075 sl << std::fixed << std::setprecision(7);
0076 sl << "Acts::CylinderBounds: (radius, halfLengthZ, halfPhiSector, "
0077 "averagePhi) = ";
0078 sl << "(" << get(eR) << ", " << get(eHalfLengthZ) << ", ";
0079 sl << get(eHalfPhiSector) << ", " << get(eAveragePhi) << ")";
0080 return sl;
0081 }
0082
0083 std::vector<Vector3> CylinderBounds::circleVertices(
0084 const Transform3 transform, unsigned int quarterSegments) const {
0085 std::vector<Vector3> vertices;
0086
0087 double avgPhi = get(eAveragePhi);
0088 double halfPhi = get(eHalfPhiSector);
0089
0090 std::vector<double> phiRef = {};
0091 if (bool fullCylinder = coversFullAzimuth(); fullCylinder) {
0092 phiRef = {avgPhi};
0093 }
0094
0095
0096 std::vector<int> sides = {-1, 1};
0097 for (auto& side : sides) {
0098
0099 auto svertices = detail::VerticesHelper::segmentVertices(
0100 {get(eR), get(eR)}, avgPhi - halfPhi, avgPhi + halfPhi, phiRef,
0101 quarterSegments, Vector3(0., 0., side * get(eHalfLengthZ)), transform);
0102 vertices.insert(vertices.end(), svertices.begin(), svertices.end());
0103 }
0104
0105 return vertices;
0106 }
0107
0108 void CylinderBounds::checkConsistency() noexcept(false) {
0109 if (get(eR) <= 0.) {
0110 throw std::invalid_argument(
0111 "CylinderBounds: invalid radial setup: radius is negative");
0112 }
0113 if (get(eHalfLengthZ) <= 0.) {
0114 throw std::invalid_argument(
0115 "CylinderBounds: invalid length setup: half length is negative");
0116 }
0117 if (get(eHalfPhiSector) <= 0. || get(eHalfPhiSector) > std::numbers::pi) {
0118 throw std::invalid_argument("CylinderBounds: invalid phi sector setup.");
0119 }
0120 if (get(eAveragePhi) != detail::radian_sym(get(eAveragePhi)) &&
0121 std::abs(std::abs(get(eAveragePhi)) - std::numbers::pi) > s_epsilon) {
0122 throw std::invalid_argument("CylinderBounds: invalid phi positioning.");
0123 }
0124 }
0125
0126 }