Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:52

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 <boost/test/unit_test.hpp>
0010 
0011 #include "Acts/Definitions/Units.hpp"
0012 #include "Acts/Geometry/Extent.hpp"
0013 #include "Acts/Geometry/Polyhedron.hpp"
0014 #include "Acts/Surfaces/AnnulusBounds.hpp"
0015 #include "Acts/Surfaces/ConeBounds.hpp"
0016 #include "Acts/Surfaces/ConeSurface.hpp"
0017 #include "Acts/Surfaces/ConvexPolygonBounds.hpp"
0018 #include "Acts/Surfaces/CylinderBounds.hpp"
0019 #include "Acts/Surfaces/CylinderSurface.hpp"
0020 #include "Acts/Surfaces/DiamondBounds.hpp"
0021 #include "Acts/Surfaces/DiscSurface.hpp"
0022 #include "Acts/Surfaces/DiscTrapezoidBounds.hpp"
0023 #include "Acts/Surfaces/EllipseBounds.hpp"
0024 #include "Acts/Surfaces/PlaneSurface.hpp"
0025 #include "Acts/Surfaces/RadialBounds.hpp"
0026 #include "Acts/Surfaces/RectangleBounds.hpp"
0027 #include "Acts/Surfaces/TrapezoidBounds.hpp"
0028 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0029 #include "Acts/Utilities/Logger.hpp"
0030 
0031 #include <tuple>
0032 #include <vector>
0033 
0034 using namespace Acts::UnitLiterals;
0035 
0036 Acts::Logging::Level logLevel = Acts::Logging::VERBOSE;
0037 
0038 namespace Acts::Test {
0039 
0040 // Create a test context
0041 const GeometryContext tgContext = GeometryContext();
0042 
0043 const std::vector<std::tuple<std::string, unsigned int>> testModes = {
0044     {"Triangulate", 18}, {"Extrema", 1}};
0045 
0046 const Transform3 transform = Transform3::Identity();
0047 const double epsAbs = 1e-12;
0048 
0049 BOOST_AUTO_TEST_SUITE(PolyhedronSurfaces)
0050 
0051 /// Unit tests for Cone Surfaces
0052 BOOST_AUTO_TEST_CASE(ConeSurfacePolyhedrons) {
0053   ACTS_LOCAL_LOGGER(
0054       Acts::getDefaultLogger("PolyhedronSurfacesTests", logLevel));
0055   ACTS_INFO("Test: ConeSurfacePolyhedrons");
0056 
0057   const double hzPos = 35_mm;
0058   const double hzNeg = -20_mm;
0059   const double alpha = 0.234;
0060 
0061   const double rMax = hzPos * std::tan(alpha);
0062 
0063   for (const auto& [mode, segments] : testModes) {
0064     ACTS_INFO("\tMode: " << mode);
0065 
0066     /// The full cone on one side
0067     {
0068       auto cone = std::make_shared<ConeBounds>(alpha, 0_mm, hzPos);
0069       auto oneCone = Surface::makeShared<ConeSurface>(transform, cone);
0070       auto oneConePh = oneCone->polyhedronRepresentation(tgContext, segments);
0071 
0072       const auto extent = oneConePh.extent();
0073       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), -rMax, epsAbs);
0074       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), rMax, epsAbs);
0075       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -rMax, epsAbs);
0076       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), rMax, epsAbs);
0077       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), 0_mm, epsAbs);
0078       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(), rMax, epsAbs);
0079       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0_mm, epsAbs);
0080       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), hzPos, epsAbs);
0081 
0082       const unsigned int expectedFaces = 4 * segments;
0083       BOOST_CHECK_EQUAL(oneConePh.faces.size(), expectedFaces);
0084       // full segments + overlap at (pi/pi) + tip
0085       BOOST_CHECK_EQUAL(oneConePh.vertices.size(), expectedFaces + 2);
0086     }
0087 
0088     /// The full cone on one side
0089     {
0090       const double hzpMin = 10_mm;
0091       const double rMin = hzpMin * std::tan(alpha);
0092 
0093       auto conePiece = std::make_shared<ConeBounds>(alpha, hzpMin, hzPos);
0094       auto oneConePiece =
0095           Surface::makeShared<ConeSurface>(transform, conePiece);
0096       auto oneConePiecePh =
0097           oneConePiece->polyhedronRepresentation(tgContext, segments);
0098 
0099       const auto extent = oneConePiecePh.extent();
0100       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), -rMax, epsAbs);
0101       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), rMax, epsAbs);
0102       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -rMax, epsAbs);
0103       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), rMax, epsAbs);
0104       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), rMin, epsAbs);
0105       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(), rMax, epsAbs);
0106       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), hzpMin, epsAbs);
0107       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), hzPos, epsAbs);
0108 
0109       const unsigned int expectedFaces = 4 * segments;
0110       BOOST_CHECK_EQUAL(oneConePiecePh.faces.size(), expectedFaces);
0111       BOOST_CHECK_EQUAL(oneConePiecePh.vertices.size(),
0112                         (expectedFaces + 1) * 2);
0113     }
0114 
0115     /// The full cone on both sides
0116     {
0117       auto coneBoth = std::make_shared<ConeBounds>(alpha, hzNeg, hzPos);
0118       auto twoCones = Surface::makeShared<ConeSurface>(transform, coneBoth);
0119       auto twoConesPh = twoCones->polyhedronRepresentation(tgContext, segments);
0120 
0121       const auto extent = twoConesPh.extent();
0122       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), -rMax, epsAbs);
0123       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), rMax, epsAbs);
0124       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -rMax, epsAbs);
0125       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), rMax, epsAbs);
0126       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), 0_mm, epsAbs);
0127       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(), rMax, epsAbs);
0128       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), hzNeg, epsAbs);
0129       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), hzPos, epsAbs);
0130 
0131       const unsigned int expectedFaces = 2 * segments * 4;
0132       const unsigned int expectedVertices = 2 * (4 * segments + 1) + 1;
0133 
0134       BOOST_CHECK_EQUAL(twoConesPh.faces.size(), expectedFaces);
0135       BOOST_CHECK_EQUAL(twoConesPh.vertices.size(), expectedVertices);
0136     }
0137 
0138     /// A centered sectoral cone on both sides
0139     {
0140       const double phiSector = 0.358;
0141 
0142       auto sectoralBoth =
0143           std::make_shared<ConeBounds>(alpha, hzNeg, hzPos, phiSector, 0.);
0144       auto sectoralCones =
0145           Surface::makeShared<ConeSurface>(transform, sectoralBoth);
0146       auto sectoralConesPh =
0147           sectoralCones->polyhedronRepresentation(tgContext, segments);
0148 
0149       const auto extent = sectoralConesPh.extent();
0150       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), 0, epsAbs);
0151       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), rMax, epsAbs);
0152       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(),
0153                       -rMax * std::sin(phiSector), epsAbs);
0154       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(),
0155                       rMax * std::sin(phiSector), epsAbs);
0156       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), 0_mm, epsAbs);
0157       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(), rMax, epsAbs);
0158       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), hzNeg, epsAbs);
0159       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), hzPos, epsAbs);
0160 
0161       // Segment numbers are further checked with the VertexHelper checks
0162     }
0163   }
0164 }
0165 
0166 /// Unit tests for Cylinder Surfaces
0167 BOOST_AUTO_TEST_CASE(CylinderSurfacePolyhedrons) {
0168   ACTS_LOCAL_LOGGER(
0169       Acts::getDefaultLogger("PolyhedronSurfacesTests", logLevel));
0170   ACTS_INFO("Test: CylinderSurfacePolyhedrons");
0171 
0172   const double r = 25_mm;
0173   const double hZ = 35_mm;
0174 
0175   for (const auto& mode : testModes) {
0176     ACTS_INFO("\tMode: " << std::get<std::string>(mode));
0177     const unsigned int segments = std::get<unsigned int>(mode);
0178 
0179     /// The full cone on one side
0180     {
0181       auto cylinder = std::make_shared<CylinderBounds>(r, hZ);
0182       auto fullCylinder =
0183           Surface::makeShared<CylinderSurface>(transform, cylinder);
0184       auto fullCylinderPh =
0185           fullCylinder->polyhedronRepresentation(tgContext, segments);
0186 
0187       const auto extent = fullCylinderPh.extent();
0188       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), -r, epsAbs);
0189       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), r, epsAbs);
0190       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -r, epsAbs);
0191       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), r, epsAbs);
0192       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), r, epsAbs);
0193       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(), r, epsAbs);
0194       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), -hZ, epsAbs);
0195       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), hZ, epsAbs);
0196 
0197       const unsigned int expectedFaces = 4 * segments;
0198       const unsigned int expectedVertices = (4 * segments + 1) * 2;
0199       BOOST_CHECK_EQUAL(fullCylinderPh.faces.size(), expectedFaces);
0200       BOOST_CHECK_EQUAL(fullCylinderPh.vertices.size(), expectedVertices);
0201     }
0202 
0203     /// The full cone on one side
0204     {
0205       const double phiSector = 0.458;
0206 
0207       auto sectorCentered = std::make_shared<CylinderBounds>(r, hZ, phiSector);
0208       auto centerSectoredCylinder =
0209           Surface::makeShared<CylinderSurface>(transform, sectorCentered);
0210       auto centerSectoredCylinderPh =
0211           centerSectoredCylinder->polyhedronRepresentation(tgContext, segments);
0212 
0213       const auto extent = centerSectoredCylinderPh.extent();
0214       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(),
0215                       r * std::cos(phiSector), epsAbs);
0216       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), r, epsAbs);
0217       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(),
0218                       -r * std::sin(phiSector), epsAbs);
0219       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(),
0220                       r * std::sin(phiSector), epsAbs);
0221       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), r, epsAbs);
0222       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(), r, epsAbs);
0223       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), -hZ, epsAbs);
0224       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), hZ, epsAbs);
0225     }
0226   }
0227 }
0228 
0229 /// Unit tests for Disc Surfaces
0230 BOOST_AUTO_TEST_CASE(DiscSurfacePolyhedrons) {
0231   ACTS_LOCAL_LOGGER(
0232       Acts::getDefaultLogger("PolyhedronSurfacesTests", logLevel));
0233   ACTS_INFO("Test: DiscSurfacePolyhedrons");
0234 
0235   const double innerR = 10_mm;
0236   const double outerR = 25_mm;
0237   const double phiSector = 0.345;
0238 
0239   for (const auto& mode : testModes) {
0240     ACTS_INFO("\tMode: " << std::get<std::string>(mode));
0241     const unsigned int segments = std::get<unsigned int>(mode);
0242 
0243     /// Full disc
0244     {
0245       auto disc = std::make_shared<RadialBounds>(0_mm, outerR);
0246       auto fullDisc = Surface::makeShared<DiscSurface>(transform, disc);
0247       auto fullDiscPh = fullDisc->polyhedronRepresentation(tgContext, segments);
0248 
0249       const auto extent = fullDiscPh.extent();
0250       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), -outerR,
0251                       epsAbs);
0252       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), outerR, epsAbs);
0253       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -outerR,
0254                       epsAbs);
0255       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), outerR, epsAbs);
0256       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), 0., epsAbs);
0257       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(), outerR, epsAbs);
0258       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0., epsAbs);
0259       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), 0., epsAbs);
0260 
0261       const unsigned int expectedFaces = 1;
0262       // Segments + overlap + center
0263       const unsigned int expectedVertices = 4 * segments + 1 + 1;
0264       BOOST_CHECK_EQUAL(fullDiscPh.faces.size(), expectedFaces);
0265       BOOST_CHECK_EQUAL(fullDiscPh.vertices.size(), expectedVertices);
0266     }
0267 
0268     /// Ring disc
0269     {
0270       auto radial = std::make_shared<RadialBounds>(innerR, outerR);
0271       auto radialDisc = Surface::makeShared<DiscSurface>(transform, radial);
0272       auto radialPh = radialDisc->polyhedronRepresentation(tgContext, segments);
0273 
0274       const auto extent = radialPh.extent();
0275       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), -outerR,
0276                       epsAbs);
0277       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), outerR, epsAbs);
0278       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -outerR,
0279                       epsAbs);
0280       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), outerR, epsAbs);
0281       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), innerR, epsAbs);
0282       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(), outerR, epsAbs);
0283       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0., epsAbs);
0284       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), 0., epsAbs);
0285     }
0286 
0287     /// Sectoral disc - around 0.
0288     {
0289       auto sector = std::make_shared<RadialBounds>(0., outerR, phiSector);
0290       auto sectorDisc = Surface::makeShared<DiscSurface>(transform, sector);
0291       auto sectorPh = sectorDisc->polyhedronRepresentation(tgContext, segments);
0292 
0293       const auto extent = sectorPh.extent();
0294       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), 0., epsAbs);
0295       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), outerR, epsAbs);
0296       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(),
0297                       -outerR * std::sin(phiSector), epsAbs);
0298       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(),
0299                       outerR * std::sin(phiSector), epsAbs);
0300       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), 0., epsAbs);
0301       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(), outerR, epsAbs);
0302       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0., epsAbs);
0303       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), 0., epsAbs);
0304     }
0305 
0306     /// Sectoral ring - around 0.
0307     {
0308       auto sectorRing =
0309           std::make_shared<RadialBounds>(innerR, outerR, phiSector);
0310       auto sectorRingDisc =
0311           Surface::makeShared<DiscSurface>(transform, sectorRing);
0312       auto sectorRingDiscPh =
0313           sectorRingDisc->polyhedronRepresentation(tgContext, segments);
0314 
0315       const auto extent = sectorRingDiscPh.extent();
0316       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(),
0317                       innerR * std::cos(phiSector), epsAbs);
0318       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), outerR, epsAbs);
0319       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(),
0320                       -outerR * std::sin(phiSector), epsAbs);
0321       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(),
0322                       outerR * std::sin(phiSector), epsAbs);
0323       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), innerR, epsAbs);
0324       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(), outerR, epsAbs);
0325       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0., epsAbs);
0326       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), 0., epsAbs);
0327     }
0328 
0329     /// Trapezoid for a disc
0330     {
0331       const double halfXmin = 10_mm;
0332       const double halfXmax = 20_mm;
0333 
0334       auto trapezoidDisc = std::make_shared<DiscTrapezoidBounds>(
0335           halfXmin, halfXmax, innerR, outerR, 0.);
0336       auto trapezoidDiscSf =
0337           Surface::makeShared<DiscSurface>(transform, trapezoidDisc);
0338       auto trapezoidDiscSfPh =
0339           trapezoidDiscSf->polyhedronRepresentation(tgContext, segments);
0340       const auto extent = trapezoidDiscSfPh.extent();
0341 
0342       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(),
0343                       -std::abs(outerR - innerR) / 2., epsAbs);
0344       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(),
0345                       std::abs(outerR - innerR) / 2., epsAbs);
0346       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -halfXmax,
0347                       epsAbs);
0348       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), halfXmax,
0349                       epsAbs);
0350       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), 0., epsAbs);
0351       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(),
0352                       std::hypot(std::abs(outerR - innerR) / 2., halfXmax),
0353                       epsAbs);
0354       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0., epsAbs);
0355       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), 0., epsAbs);
0356     }
0357 
0358     /// AnnulusBounds for a disc
0359     {
0360       const double minRadius = 7.;
0361       const double maxRadius = 12.;
0362       const double minPhiA = 0.75;
0363       const double maxPhiA = 1.4;
0364       const Vector2 offset(0., 0.);
0365 
0366       auto annulus = std::make_shared<AnnulusBounds>(minRadius, maxRadius,
0367                                                      minPhiA, maxPhiA, offset);
0368       auto annulusDisc = Surface::makeShared<DiscSurface>(transform, annulus);
0369       auto annulusDiscPh =
0370           annulusDisc->polyhedronRepresentation(tgContext, segments);
0371       const auto extent = annulusDiscPh.extent();
0372       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), minRadius,
0373                       epsAbs);
0374       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(), maxRadius,
0375                       epsAbs);
0376       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0., epsAbs);
0377       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), 0., epsAbs);
0378     }
0379   }
0380 }
0381 
0382 /// Unit tests for Plane Surfaces
0383 BOOST_AUTO_TEST_CASE(PlaneSurfacePolyhedrons) {
0384   ACTS_LOCAL_LOGGER(
0385       Acts::getDefaultLogger("PolyhedronSurfacesTests", logLevel));
0386   ACTS_INFO("Test: PlaneSurfacePolyhedrons");
0387 
0388   for (const auto& mode : testModes) {
0389     ACTS_INFO("\tMode: " << std::get<std::string>(mode));
0390     const unsigned int segments = std::get<unsigned int>(mode);
0391 
0392     /// Rectangular Plane
0393     {
0394       const double rhX = 10_mm;
0395       const double rhY = 25_mm;
0396 
0397       auto rectangular = std::make_shared<RectangleBounds>(rhX, rhY);
0398       auto rectangularPlane =
0399           Surface::makeShared<PlaneSurface>(transform, rectangular);
0400       auto rectangularPh =
0401           rectangularPlane->polyhedronRepresentation(tgContext, segments);
0402 
0403       const auto extent = rectangularPh.extent();
0404       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), -rhX, epsAbs);
0405       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), rhX, epsAbs);
0406       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -rhY, epsAbs);
0407       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), rhY, epsAbs);
0408       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), 0., epsAbs);
0409       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(),
0410                       std::hypot(rhX, rhY), epsAbs);
0411       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0., epsAbs);
0412       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), 0., epsAbs);
0413 
0414       BOOST_CHECK_EQUAL(rectangularPh.vertices.size(), 4);
0415       BOOST_CHECK_EQUAL(rectangularPh.faces.size(), 1);
0416 
0417       const std::vector<std::size_t> expectedRect = {0, 1, 2, 3};
0418       BOOST_CHECK(rectangularPh.faces[0] == expectedRect);
0419     }
0420 
0421     /// Trapezoidal Plane
0422     {
0423       const double thX1 = 10_mm;
0424       const double thX2 = 25_mm;
0425       const double thY = 35_mm;
0426 
0427       auto trapezoid = std::make_shared<TrapezoidBounds>(thX1, thX2, thY);
0428       auto trapezoidalPlane =
0429           Surface::makeShared<PlaneSurface>(transform, trapezoid);
0430       auto trapezoidalPh =
0431           trapezoidalPlane->polyhedronRepresentation(tgContext, segments);
0432 
0433       const auto extent = trapezoidalPh.extent();
0434       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(),
0435                       -std::max(thX1, thX2), epsAbs);
0436       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(),
0437                       std::max(thX1, thX2), epsAbs);
0438       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -thY, epsAbs);
0439       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), thY, epsAbs);
0440       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), 0., epsAbs);
0441       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(),
0442                       std::hypot(std::max(thX1, thX2), thY), epsAbs);
0443       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0., epsAbs);
0444       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), 0., epsAbs);
0445 
0446       BOOST_CHECK_EQUAL(trapezoidalPh.vertices.size(), 4);
0447       BOOST_CHECK_EQUAL(trapezoidalPh.faces.size(), 1);
0448 
0449       const std::vector<std::size_t> expectedTra = {0, 1, 2, 3};
0450       BOOST_CHECK(trapezoidalPh.faces[0] == expectedTra);
0451     }
0452 
0453     /// Ring-like ellipsoidal plane
0454     {
0455       const double rMinX = 0_mm;
0456       const double rMinY = 0_mm;
0457       const double rMaxX = 30_mm;
0458       const double rMaxY = 40_mm;
0459       auto ellipse =
0460           std::make_shared<EllipseBounds>(rMinX, rMinY, rMaxX, rMaxY);
0461       auto ellipsoidPlane =
0462           Surface::makeShared<PlaneSurface>(transform, ellipse);
0463       auto ellipsoidPh =
0464           ellipsoidPlane->polyhedronRepresentation(tgContext, segments);
0465 
0466       const auto extent = ellipsoidPh.extent();
0467       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), -rMaxX, epsAbs);
0468       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), rMaxX, epsAbs);
0469       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -rMaxY, epsAbs);
0470       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), rMaxY, epsAbs);
0471       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(),
0472                       std::min(rMinX, rMinY), epsAbs);
0473       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(),
0474                       std::max(rMaxX, rMaxY), epsAbs);
0475       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0., epsAbs);
0476       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), 0., epsAbs);
0477     }
0478 
0479     {
0480       const double rMinX = 10_mm;
0481       const double rMinY = 20_mm;
0482       const double rMaxX = 30_mm;
0483       const double rMaxY = 40_mm;
0484       auto ellipseRing =
0485           std::make_shared<EllipseBounds>(rMinX, rMinY, rMaxX, rMaxY);
0486       auto ellipsoidRingPlane =
0487           Surface::makeShared<PlaneSurface>(transform, ellipseRing);
0488       auto ellipsoidRingPh =
0489           ellipsoidRingPlane->polyhedronRepresentation(tgContext, segments);
0490 
0491       const auto extent = ellipsoidRingPh.extent();
0492       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), -rMaxX, epsAbs);
0493       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), rMaxX, epsAbs);
0494       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -rMaxY, epsAbs);
0495       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), rMaxY, epsAbs);
0496       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(),
0497                       std::min(rMinX, rMinY), epsAbs);
0498       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(),
0499                       std::max(rMaxX, rMaxY), epsAbs);
0500       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0., epsAbs);
0501       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), 0., epsAbs);
0502     }
0503 
0504     /// ConvexPolygonBounds test
0505     {
0506       std::vector<Vector2> vtxs = {
0507           Vector2(-40_mm, -10_mm), Vector2(-10_mm, -30_mm),
0508           Vector2(30_mm, -20_mm),  Vector2(10_mm, 20_mm),
0509           Vector2(-20_mm, 50_mm),  Vector2(-30_mm, 30_mm)};
0510 
0511       auto hexagon = std::make_shared<ConvexPolygonBounds<6>>(vtxs);
0512       auto hexagonPlane = Surface::makeShared<PlaneSurface>(transform, hexagon);
0513       auto hexagonPlanePh =
0514           hexagonPlane->polyhedronRepresentation(tgContext, segments);
0515 
0516       const auto extent = hexagonPlanePh.extent();
0517       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), -40, epsAbs);
0518       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), 30, epsAbs);
0519       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -30, epsAbs);
0520       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), 50, epsAbs);
0521       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), 0, epsAbs);
0522       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(), std::sqrt(2900),
0523                       epsAbs);
0524       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0., epsAbs);
0525       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), 0., epsAbs);
0526     }
0527 
0528     /// Diamond shaped plane
0529     {
0530       const double hMinX = 10_mm;
0531       const double hMedX = 20_mm;
0532       const double hMaxX = 15_mm;
0533       const double hMinY = 40_mm;
0534       const double hMaxY = 50_mm;
0535 
0536       auto diamond =
0537           std::make_shared<DiamondBounds>(hMinX, hMedX, hMaxX, hMinY, hMaxY);
0538       auto diamondPlane = Surface::makeShared<PlaneSurface>(transform, diamond);
0539       auto diamondPh =
0540           diamondPlane->polyhedronRepresentation(tgContext, segments);
0541 
0542       const auto extent = diamondPh.extent();
0543       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), -hMedX, epsAbs);
0544       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), hMedX, epsAbs);
0545       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -hMinY, epsAbs);
0546       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), hMaxY, epsAbs);
0547       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), 0., epsAbs);
0548       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(),
0549                       std::hypot(hMaxX, hMaxY), epsAbs);
0550       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0., epsAbs);
0551       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), 0., epsAbs);
0552 
0553       BOOST_CHECK_EQUAL(diamondPh.vertices.size(), 6);
0554       BOOST_CHECK_EQUAL(diamondPh.faces.size(), 1);
0555     }
0556   }
0557 }
0558 
0559 /// Unit tests shifted plane
0560 BOOST_AUTO_TEST_CASE(ShiftedSurfacePolyhedrons) {
0561   ACTS_LOCAL_LOGGER(
0562       Acts::getDefaultLogger("PolyhedronSurfacesTests", logLevel));
0563   ACTS_INFO("Test: ShiftedSurfacePolyhedrons");
0564 
0565   const double shiftY = 50_mm;
0566   Vector3 shift(0., shiftY, 0.);
0567   Transform3 shiftedTransform = Transform3::Identity();
0568   shiftedTransform.pretranslate(shift);
0569 
0570   for (const auto& mode : testModes) {
0571     ACTS_INFO("\tMode: " << std::get<std::string>(mode));
0572     const unsigned int segments = std::get<unsigned int>(mode);
0573 
0574     /// Rectangular Plane
0575     {
0576       const double rhX = 10_mm;
0577       const double rhY = 25_mm;
0578 
0579       auto rectangular = std::make_shared<RectangleBounds>(rhX, rhY);
0580       auto rectangularPlane =
0581           Surface::makeShared<PlaneSurface>(shiftedTransform, rectangular);
0582       auto rectangularPh =
0583           rectangularPlane->polyhedronRepresentation(tgContext, segments);
0584 
0585       const auto extent = rectangularPh.extent();
0586       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).min(), -rhX, epsAbs);
0587       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisX).max(), rhX, epsAbs);
0588       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).min(), -rhY + shiftY,
0589                       epsAbs);
0590       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisY).max(), rhY + shiftY,
0591                       epsAbs);
0592       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).min(), 25, epsAbs);
0593       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisR).max(),
0594                       std::hypot(rhX, rhY + shiftY), epsAbs);
0595       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).min(), 0., epsAbs);
0596       CHECK_CLOSE_ABS(extent.range(AxisDirection::AxisZ).max(), 0., epsAbs);
0597 
0598       BOOST_CHECK_EQUAL(rectangularPh.vertices.size(), 4);
0599       BOOST_CHECK_EQUAL(rectangularPh.faces.size(), 1);
0600 
0601       const std::vector<std::size_t> expectedRect = {0, 1, 2, 3};
0602       BOOST_CHECK(rectangularPh.faces[0] == expectedRect);
0603     }
0604   }
0605 }
0606 BOOST_AUTO_TEST_SUITE_END()
0607 
0608 }  // namespace Acts::Test