Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-01 07:55:10

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