Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:11:29

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