Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-13 09:38:02

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
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   // check with phi wrap around the average phi of the sector
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   // back to the caller's r*phi frame
0063   closest[0] += lposition[0] - rDeltaPhi;
0064   return closest;
0065 }
0066 
0067 Vector2 CylinderBounds::center() const {
0068   // For cylinder bounds in local coordinates (rphi, z),
0069   // centroid is at (averagePhi, 0) since z extends symmetrically
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   // Write the two bows/circles on either side
0096   std::vector<int> sides = {-1, 1};
0097   for (auto& side : sides) {
0098     // Helper method to create the segment
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 }  // namespace Acts