Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-22 07:48:38

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/data/monomorphic/fwd.hpp>
0010 #include <boost/test/data/test_case.hpp>
0011 #include <boost/test/tools/context.hpp>
0012 #include <boost/test/tools/old/interface.hpp>
0013 #include <boost/test/unit_test.hpp>
0014 #include <boost/test/unit_test_suite.hpp>
0015 
0016 #include "Acts/Definitions/Algebra.hpp"
0017 #include "Acts/Definitions/Units.hpp"
0018 #include "Acts/Geometry/CuboidPortalShell.hpp"
0019 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0020 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0021 #include "Acts/Geometry/GridPortalLink.hpp"
0022 #include "Acts/Geometry/Portal.hpp"
0023 #include "Acts/Geometry/TrackingVolume.hpp"
0024 #include "Acts/Geometry/TrivialPortalLink.hpp"
0025 #include "Acts/Utilities/AxisDefinitions.hpp"
0026 
0027 #include <cstddef>
0028 #include <initializer_list>
0029 #include <memory>
0030 #include <stdexcept>
0031 #include <utility>
0032 
0033 using namespace Acts;
0034 using namespace Acts::UnitLiterals;
0035 
0036 namespace ActsTests {
0037 auto gctx = GeometryContext::dangerouslyDefaultConstruct();
0038 
0039 std::size_t getVolumeIndex() {
0040   static std::size_t i = 1;
0041   return i++;
0042 }
0043 
0044 auto makeVolume(auto&&... pars) {
0045   TrackingVolume vol(Transform3::Identity(),
0046                      std::make_shared<CuboidVolumeBounds>(
0047                          std::forward<decltype(pars)>(pars)...));
0048   vol.setVolumeName("cube" + std::to_string(getVolumeIndex()));
0049   return vol;
0050 };
0051 
0052 auto logger = getDefaultLogger("UnitTests", Logging::VERBOSE);
0053 
0054 BOOST_AUTO_TEST_SUITE(GeometrySuite)
0055 
0056 BOOST_AUTO_TEST_CASE(ConstructionFromVolume) {
0057   auto cube = makeVolume(30_mm, 40_mm, 50_mm);
0058 
0059   TrackingVolume cylVolume(
0060       Transform3::Identity(),
0061       std::make_shared<CylinderVolumeBounds>(10_mm, 20_mm, 10_mm));
0062 
0063   BOOST_CHECK_THROW(SingleCuboidPortalShell(gctx, cylVolume),
0064                     std::invalid_argument);
0065 
0066   SingleCuboidPortalShell shell1{gctx, cube};
0067   BOOST_CHECK_EQUAL(shell1.size(), 6);
0068 
0069   using enum CuboidVolumeBounds::Face;
0070 
0071   // XY plane
0072   const auto pXY = shell1.portal(PositiveZFace);
0073   BOOST_REQUIRE_NE(pXY, nullptr);
0074   BOOST_CHECK_EQUAL(
0075       pXY->resolveVolume(gctx, Vector3{25_mm, 20_mm, 50_mm}, -Vector3::UnitZ())
0076           .value(),
0077       &cube);
0078   BOOST_CHECK_EQUAL(
0079       pXY->resolveVolume(gctx, Vector3{25_mm, 20_mm, 50_mm}, Vector3::UnitZ())
0080           .value(),
0081       nullptr);
0082 
0083   const auto nXY = shell1.portal(NegativeZFace);
0084   BOOST_REQUIRE_NE(nXY, nullptr);
0085   BOOST_CHECK_EQUAL(
0086       nXY->resolveVolume(gctx, Vector3{25_mm, 20_mm, -50_mm}, -Vector3::UnitZ())
0087           .value(),
0088       nullptr);
0089   BOOST_CHECK_EQUAL(
0090       nXY->resolveVolume(gctx, Vector3{25_mm, 20_mm, -50_mm}, Vector3::UnitZ())
0091           .value(),
0092       &cube);
0093 
0094   // YZ plane
0095   const auto pYZ = shell1.portal(PositiveXFace);
0096   BOOST_REQUIRE_NE(pYZ, nullptr);
0097   BOOST_CHECK_EQUAL(
0098       pYZ->resolveVolume(gctx, Vector3{30_mm, 10_mm, 30_mm}, -Vector3::UnitX())
0099           .value(),
0100       &cube);
0101   BOOST_CHECK_EQUAL(
0102       pYZ->resolveVolume(gctx, Vector3{30_mm, 10_mm, 30_mm}, Vector3::UnitX())
0103           .value(),
0104       nullptr);
0105 
0106   const auto nYZ = shell1.portal(NegativeXFace);
0107   BOOST_REQUIRE_NE(nYZ, nullptr);
0108   BOOST_CHECK_EQUAL(
0109       nYZ->resolveVolume(gctx, Vector3{-30_mm, 10_mm, 30_mm}, -Vector3::UnitX())
0110           .value(),
0111       nullptr);
0112   BOOST_CHECK_EQUAL(
0113       nYZ->resolveVolume(gctx, Vector3{-30_mm, 10_mm, 30_mm}, Vector3::UnitX())
0114           .value(),
0115       &cube);
0116 
0117   // ZX plane
0118   const auto pZX = shell1.portal(PositiveYFace);
0119   BOOST_REQUIRE_NE(pZX, nullptr);
0120   BOOST_CHECK_EQUAL(
0121       pZX->resolveVolume(gctx, Vector3{15_mm, 40_mm, -10_mm}, -Vector3::UnitY())
0122           .value(),
0123       &cube);
0124   BOOST_CHECK_EQUAL(
0125       pZX->resolveVolume(gctx, Vector3{15_mm, 40_mm, -10_mm}, Vector3::UnitY())
0126           .value(),
0127       nullptr);
0128 
0129   const auto nZX = shell1.portal(NegativeYFace);
0130   BOOST_REQUIRE_NE(nZX, nullptr);
0131   BOOST_CHECK_EQUAL(nZX->resolveVolume(gctx, Vector3{15_mm, -40_mm, -10_mm},
0132                                        -Vector3::UnitY())
0133                         .value(),
0134                     nullptr);
0135   BOOST_CHECK_EQUAL(
0136       nZX->resolveVolume(gctx, Vector3{15_mm, -40_mm, -10_mm}, Vector3::UnitY())
0137           .value(),
0138       &cube);
0139 }
0140 
0141 BOOST_AUTO_TEST_CASE(PortalAssignment) {
0142   using enum CuboidVolumeBounds::Face;
0143   TrackingVolume vol(Transform3::Identity(),
0144                      std::make_shared<CuboidVolumeBounds>(30_mm, 40_mm, 50_mm));
0145 
0146   SingleCuboidPortalShell shell{gctx, vol};
0147 
0148   const auto pXY = shell.portal(PositiveZFace);
0149   const auto nXY = shell.portal(NegativeZFace);
0150   const auto nYZ = shell.portal(NegativeXFace);
0151   const auto pZX = shell.portal(PositiveYFace);
0152   auto pYZ = shell.portal(PositiveXFace);
0153   auto nZX = shell.portal(NegativeYFace);
0154 
0155   // Setting new pYZ
0156   BOOST_REQUIRE_NE(pYZ, nullptr);
0157   auto* pYZLink = dynamic_cast<const TrivialPortalLink*>(
0158       pYZ->getLink(Direction::OppositeNormal()));
0159   BOOST_REQUIRE_NE(pYZLink, nullptr);
0160 
0161   auto grid = pYZLink->makeGrid(AxisDirection::AxisX);
0162 
0163   auto portal2 =
0164       std::make_shared<Portal>(Direction::OppositeNormal(), std::move(grid));
0165   shell.setPortal(portal2, PositiveXFace);
0166   BOOST_CHECK_EQUAL(shell.portal(PositiveXFace), portal2);
0167 
0168   // Other portals should stay the same
0169   BOOST_CHECK_EQUAL(shell.portal(PositiveZFace), pXY);
0170   BOOST_CHECK_EQUAL(shell.portal(NegativeZFace), nXY);
0171   BOOST_CHECK_EQUAL(shell.portal(NegativeXFace), nYZ);
0172   BOOST_CHECK_EQUAL(shell.portal(PositiveYFace), pZX);
0173   BOOST_CHECK_EQUAL(shell.portal(NegativeYFace), nZX);
0174 
0175   // Setting new nZX
0176   BOOST_REQUIRE_NE(nZX, nullptr);
0177   auto* nZXLink = dynamic_cast<const TrivialPortalLink*>(
0178       nZX->getLink(Direction::AlongNormal()));
0179   BOOST_REQUIRE_NE(nZXLink, nullptr);
0180 
0181   grid = nZXLink->makeGrid(AxisDirection::AxisY);
0182 
0183   auto portal3 =
0184       std::make_shared<Portal>(Direction::AlongNormal(), std::move(grid));
0185   shell.setPortal(portal3, NegativeYFace);
0186   BOOST_CHECK_EQUAL(shell.portal(NegativeYFace), portal3);
0187 
0188   // Other portals should stay the same
0189   BOOST_CHECK_EQUAL(shell.portal(PositiveZFace), pXY);
0190   BOOST_CHECK_EQUAL(shell.portal(NegativeZFace), nXY);
0191   BOOST_CHECK_EQUAL(shell.portal(NegativeXFace), nYZ);
0192   BOOST_CHECK_EQUAL(shell.portal(PositiveYFace), pZX);
0193   BOOST_CHECK_EQUAL(shell.portal(PositiveXFace), portal2);
0194 }
0195 
0196 BOOST_AUTO_TEST_SUITE(CuboidStack)
0197 BOOST_DATA_TEST_CASE(XYZDirection,
0198                      boost::unit_test::data::make(AxisDirection::AxisX,
0199                                                   AxisDirection::AxisY,
0200                                                   AxisDirection::AxisZ),
0201                      dir) {
0202   AxisDirection dirOrth1{};
0203   AxisDirection dirOrth2{};
0204   std::size_t dirIdx = 0;
0205   switch (dir) {
0206     case AxisDirection::AxisX:
0207       dirOrth1 = AxisDirection::AxisY;
0208       dirOrth2 = AxisDirection::AxisZ;
0209       dirIdx = 0;
0210       break;
0211     case AxisDirection::AxisY:
0212       dirOrth1 = AxisDirection::AxisX;
0213       dirOrth2 = AxisDirection::AxisZ;
0214       dirIdx = 1;
0215       break;
0216     case AxisDirection::AxisZ:
0217       dirOrth1 = AxisDirection::AxisX;
0218       dirOrth2 = AxisDirection::AxisY;
0219       dirIdx = 2;
0220       break;
0221     default:
0222       throw std::invalid_argument("Invalid direction");
0223   }
0224 
0225   auto boundDir = CuboidVolumeBounds::boundsFromAxisDirection(dir);
0226   auto boundDirOrth1 = CuboidVolumeBounds::boundsFromAxisDirection(dirOrth1);
0227   auto boundDirOrth2 = CuboidVolumeBounds::boundsFromAxisDirection(dirOrth2);
0228 
0229   auto [frontFace, backFace, sideFaces] =
0230       CuboidVolumeBounds::facesFromAxisDirection(dir);
0231 
0232   using enum CuboidVolumeBounds::Face;
0233   auto bounds1 = std::make_shared<CuboidVolumeBounds>(
0234       std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0235           {boundDir, 100_mm}, {boundDirOrth1, 30_mm}, {boundDirOrth2, 100_mm}});
0236 
0237   auto bounds2 = std::make_shared<CuboidVolumeBounds>(
0238       std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0239           {boundDir, 100_mm}, {boundDirOrth1, 30_mm}, {boundDirOrth2, 100_mm}});
0240 
0241   TrackingVolume vol1(Transform3{Translation3{Vector3::Unit(dirIdx) * -100_mm}},
0242                       bounds1);
0243   TrackingVolume vol2(Transform3{Translation3{Vector3::Unit(dirIdx) * 100_mm}},
0244                       bounds2);
0245 
0246   SingleCuboidPortalShell shell1{gctx, vol1};
0247   SingleCuboidPortalShell shell2{gctx, vol2};
0248 
0249   std::map<CuboidVolumeBounds::Face, Vector3> centers1;
0250   std::map<CuboidVolumeBounds::Face, Vector3> centers2;
0251   for (const auto face : sideFaces) {
0252     Vector3 normal{};
0253     switch (face) {
0254       case NegativeZFace:
0255         normal = Vector3::UnitZ();
0256         break;
0257       case PositiveZFace:
0258         normal = -Vector3::UnitZ();
0259         break;
0260       case NegativeYFace:
0261         normal = Vector3::UnitY();
0262         break;
0263       case PositiveYFace:
0264         normal = -Vector3::UnitY();
0265         break;
0266       case NegativeXFace:
0267         normal = Vector3::UnitX();
0268         break;
0269       case PositiveXFace:
0270         normal = -Vector3::UnitX();
0271         break;
0272     }
0273 
0274     const auto center1 = shell1.portal(face)->surface().center(gctx);
0275     const auto center2 = shell2.portal(face)->surface().center(gctx);
0276 
0277     centers1[face] = center1;
0278     centers2[face] = center2;
0279 
0280     BOOST_CHECK_EQUAL(
0281         shell1.portal(face)->resolveVolume(gctx, center1, normal).value(),
0282         &vol1);
0283     BOOST_CHECK_EQUAL(
0284         shell1.portal(face)->resolveVolume(gctx, center1, -normal).value(),
0285         nullptr);
0286 
0287     BOOST_CHECK_EQUAL(
0288         shell2.portal(face)->resolveVolume(gctx, center2, normal).value(),
0289         &vol2);
0290     BOOST_CHECK_EQUAL(
0291         shell2.portal(face)->resolveVolume(gctx, center2, -normal).value(),
0292         nullptr);
0293   }
0294 
0295   BOOST_CHECK_NE(shell1.portal(backFace), shell2.portal(frontFace));
0296 
0297   CuboidStackPortalShell stack(gctx, {&shell1, &shell2}, dir, *logger);
0298   BOOST_CHECK_EQUAL(stack.size(), 6);
0299 
0300   BOOST_CHECK_EQUAL(shell1.portal(frontFace), stack.portal(frontFace));
0301   BOOST_CHECK_EQUAL(shell1.portal(backFace), shell2.portal(frontFace));
0302   BOOST_CHECK_EQUAL(shell2.portal(backFace), stack.portal(backFace));
0303 
0304   for (const auto& face : sideFaces) {
0305     Vector3 normal{};
0306     switch (face) {
0307       case NegativeZFace:
0308         normal = Vector3::UnitZ();
0309         break;
0310       case PositiveZFace:
0311         normal = -Vector3::UnitZ();
0312         break;
0313       case NegativeYFace:
0314         normal = Vector3::UnitY();
0315         break;
0316       case PositiveYFace:
0317         normal = -Vector3::UnitY();
0318         break;
0319       case NegativeXFace:
0320         normal = Vector3::UnitX();
0321         break;
0322       case PositiveXFace:
0323         normal = -Vector3::UnitX();
0324         break;
0325     }
0326 
0327     BOOST_CHECK_EQUAL(shell1.portal(face), stack.portal(face));
0328     BOOST_CHECK_EQUAL(shell2.portal(face), stack.portal(face));
0329 
0330     const auto& center1 = centers1.at(face);
0331     const auto& center2 = centers2.at(face);
0332 
0333     BOOST_CHECK_EQUAL(
0334         shell1.portal(face)->resolveVolume(gctx, center1, normal).value(),
0335         &vol1);
0336     BOOST_CHECK_EQUAL(
0337         shell1.portal(face)->resolveVolume(gctx, center1, -normal).value(),
0338         nullptr);
0339 
0340     BOOST_CHECK_EQUAL(
0341         shell2.portal(face)->resolveVolume(gctx, center2, normal).value(),
0342         &vol2);
0343     BOOST_CHECK_EQUAL(
0344         shell2.portal(face)->resolveVolume(gctx, center2, -normal).value(),
0345         nullptr);
0346   }
0347 
0348   shell1 = SingleCuboidPortalShell{gctx, vol1};
0349   shell2 = SingleCuboidPortalShell{gctx, vol2};
0350 
0351   BOOST_CHECK_THROW(
0352       CuboidStackPortalShell(gctx, {&shell1, &shell2}, AxisDirection::AxisR),
0353       std::invalid_argument);
0354 }
0355 
0356 BOOST_AUTO_TEST_CASE(NestedStacks) {
0357   //   ^
0358   // z |    +---------------------------------+---------+
0359   //   |    |                                 |         |
0360   //   |    |                                 |         |
0361   //   |    |              vol3               |         |
0362   //   |    |                                 |         |
0363   //   |    |                                 |         |
0364   //   |    +---------------------------------+         |
0365   //   |    |                                 |         |
0366   //   |    |                                 |         |
0367   //   |    |              vol2               |  vol4   |
0368   //   |    |                                 |         |
0369   //   |    |                                 |         |
0370   //   |    +---------------------------------+         |
0371   //   |    |                                 |         |
0372   //   |    |                                 |         |
0373   //   |    |              vol1               |         |
0374   //   |    |                                 |         |
0375   //   |    |                                 |         |
0376   //   |    +---------------------------------+---------+
0377   //   |
0378   //   +-------------------------------------------------->
0379   //                                                      x
0380 
0381   Transform3 base = Transform3::Identity();
0382 
0383   TrackingVolume vol1(
0384       base, std::make_shared<CuboidVolumeBounds>(30_mm, 100_mm, 200_mm),
0385       "vol1");
0386 
0387   TrackingVolume vol2(
0388       base * Translation3(Vector3::UnitZ() * 300_mm),
0389       std::make_shared<CuboidVolumeBounds>(30_mm, 100_mm, 100_mm), "vol2");
0390 
0391   TrackingVolume vol3(
0392       base * Translation3(Vector3::UnitZ() * 600_mm),
0393       std::make_shared<CuboidVolumeBounds>(30_mm, 100_mm, 200_mm), "vol3");
0394 
0395   TrackingVolume vol4(
0396       base * Translation3{Vector3::UnitX() * 60_mm + Vector3::UnitZ() * 300_mm},
0397       std::make_shared<CuboidVolumeBounds>(30_mm, 100_mm, 500_mm), "vol4");
0398 
0399   SingleCuboidPortalShell shell1{gctx, vol1};
0400   BOOST_CHECK(shell1.isValid());
0401   SingleCuboidPortalShell shell2{gctx, vol2};
0402   BOOST_CHECK(shell2.isValid());
0403   SingleCuboidPortalShell shell3{gctx, vol3};
0404   BOOST_CHECK(shell3.isValid());
0405 
0406   CuboidStackPortalShell stack{
0407       gctx, {&shell1, &shell2, &shell3}, AxisDirection::AxisZ};
0408 
0409   BOOST_CHECK(stack.isValid());
0410 
0411   SingleCuboidPortalShell shell4{gctx, vol4};
0412   BOOST_CHECK(shell4.isValid());
0413 
0414   CuboidStackPortalShell stack2{
0415       gctx, {&stack, &shell4}, AxisDirection::AxisX, *logger};
0416   BOOST_CHECK(stack2.isValid());
0417 
0418   using enum CuboidVolumeBounds::Face;
0419 
0420   auto lookup = [](auto& shell, CuboidPortalShell::Face face, Vector3 position,
0421                    Vector3 direction) -> const TrackingVolume* {
0422     const auto portal = shell.portal(face);
0423     BOOST_REQUIRE_NE(portal, nullptr);
0424     return portal->resolveVolume(gctx, position, direction).value();
0425   };
0426 
0427   // Volume 1
0428   BOOST_CHECK_EQUAL(lookup(shell1, NegativeZFace,
0429                            Vector3(10_mm, 20_mm, -200_mm), -Vector3::UnitZ()),
0430                     nullptr);
0431   BOOST_CHECK_EQUAL(lookup(shell1, NegativeZFace,
0432                            Vector3(10_mm, 20_mm, -200_mm), Vector3::UnitZ()),
0433                     &vol1);
0434 
0435   BOOST_CHECK_EQUAL(lookup(shell1, PositiveZFace, Vector3(10_mm, 20_mm, 200_mm),
0436                            -Vector3::UnitZ()),
0437                     &vol1);
0438   BOOST_CHECK_EQUAL(lookup(shell1, PositiveZFace, Vector3(10_mm, 20_mm, 200_mm),
0439                            Vector3::UnitZ()),
0440                     &vol2);
0441 
0442   BOOST_CHECK_EQUAL(lookup(shell1, NegativeXFace, Vector3(-30_mm, 10_mm, 20_mm),
0443                            -Vector3::UnitX()),
0444                     nullptr);
0445   BOOST_CHECK_EQUAL(lookup(shell1, NegativeXFace, Vector3(-30_mm, 10_mm, 20_mm),
0446                            Vector3::UnitX()),
0447                     &vol1);
0448 
0449   BOOST_CHECK_EQUAL(lookup(shell1, PositiveXFace, Vector3(30_mm, 10_mm, 20_mm),
0450                            -Vector3::UnitX()),
0451                     &vol1);
0452   BOOST_CHECK_EQUAL(lookup(shell1, PositiveXFace, Vector3(30_mm, 10_mm, 20_mm),
0453                            Vector3::UnitX()),
0454                     &vol4);
0455 
0456   BOOST_CHECK_EQUAL(lookup(shell1, NegativeYFace,
0457                            Vector3(10_mm, -100_mm, 20_mm), -Vector3::UnitY()),
0458                     nullptr);
0459   BOOST_CHECK_EQUAL(lookup(shell1, NegativeYFace,
0460                            Vector3(10_mm, -100_mm, 20_mm), Vector3::UnitY()),
0461                     &vol1);
0462 
0463   BOOST_CHECK_EQUAL(lookup(shell1, PositiveYFace, Vector3(10_mm, 100_mm, 20_mm),
0464                            -Vector3::UnitY()),
0465                     &vol1);
0466   BOOST_CHECK_EQUAL(lookup(shell1, PositiveYFace, Vector3(10_mm, 100_mm, 20_mm),
0467                            Vector3::UnitY()),
0468                     nullptr);
0469 
0470   // Volume 2
0471   BOOST_CHECK_EQUAL(lookup(shell2, NegativeZFace, Vector3(10_mm, 20_mm, 200_mm),
0472                            -Vector3::UnitZ()),
0473                     &vol1);
0474   BOOST_CHECK_EQUAL(lookup(shell2, NegativeZFace, Vector3(10_mm, 20_mm, 200_mm),
0475                            Vector3::UnitZ()),
0476                     &vol2);
0477 
0478   BOOST_CHECK_EQUAL(lookup(shell2, PositiveZFace, Vector3(10_mm, 20_mm, 400_mm),
0479                            -Vector3::UnitZ()),
0480                     &vol2);
0481   BOOST_CHECK_EQUAL(lookup(shell2, PositiveZFace, Vector3(10_mm, 20_mm, 400_mm),
0482                            Vector3::UnitZ()),
0483                     &vol3);
0484 
0485   BOOST_CHECK_EQUAL(lookup(shell2, NegativeXFace,
0486                            Vector3(-30_mm, 10_mm, 220_mm), -Vector3::UnitX()),
0487                     nullptr);
0488   BOOST_CHECK_EQUAL(lookup(shell2, NegativeXFace,
0489                            Vector3(-30_mm, 10_mm, 220_mm), Vector3::UnitX()),
0490                     &vol2);
0491 
0492   BOOST_CHECK_EQUAL(lookup(shell2, PositiveXFace, Vector3(30_mm, 10_mm, 220_mm),
0493                            -Vector3::UnitX()),
0494                     &vol2);
0495   BOOST_CHECK_EQUAL(lookup(shell2, PositiveXFace, Vector3(30_mm, 10_mm, 220_mm),
0496                            Vector3::UnitX()),
0497                     &vol4);
0498 
0499   BOOST_CHECK_EQUAL(lookup(shell2, NegativeYFace,
0500                            Vector3(10_mm, -100_mm, 220_mm), -Vector3::UnitY()),
0501                     nullptr);
0502   BOOST_CHECK_EQUAL(lookup(shell2, NegativeYFace,
0503                            Vector3(10_mm, -100_mm, 220_mm), Vector3::UnitY()),
0504                     &vol2);
0505 
0506   BOOST_CHECK_EQUAL(lookup(shell2, PositiveYFace,
0507                            Vector3(10_mm, 100_mm, 220_mm), -Vector3::UnitY()),
0508                     &vol2);
0509   BOOST_CHECK_EQUAL(lookup(shell2, PositiveYFace,
0510                            Vector3(10_mm, 100_mm, 220_mm), Vector3::UnitY()),
0511                     nullptr);
0512 
0513   // Volume 3
0514   BOOST_CHECK_EQUAL(lookup(shell3, NegativeZFace, Vector3(10_mm, 20_mm, 400_mm),
0515                            -Vector3::UnitZ()),
0516                     &vol2);
0517   BOOST_CHECK_EQUAL(lookup(shell3, NegativeZFace, Vector3(10_mm, 20_mm, 400_mm),
0518                            Vector3::UnitZ()),
0519                     &vol3);
0520 
0521   BOOST_CHECK_EQUAL(lookup(shell3, PositiveZFace, Vector3(10_mm, 20_mm, 800_mm),
0522                            -Vector3::UnitZ()),
0523                     &vol3);
0524   BOOST_CHECK_EQUAL(lookup(shell3, PositiveZFace, Vector3(10_mm, 20_mm, 800_mm),
0525                            Vector3::UnitZ()),
0526                     nullptr);
0527 
0528   BOOST_CHECK_EQUAL(lookup(shell3, NegativeXFace,
0529                            Vector3(-30_mm, 10_mm, 420_mm), -Vector3::UnitX()),
0530                     nullptr);
0531   BOOST_CHECK_EQUAL(lookup(shell3, NegativeXFace,
0532                            Vector3(-30_mm, 10_mm, 420_mm), Vector3::UnitX()),
0533                     &vol3);
0534 
0535   BOOST_CHECK_EQUAL(lookup(shell3, PositiveXFace, Vector3(30_mm, 10_mm, 420_mm),
0536                            -Vector3::UnitX()),
0537                     &vol3);
0538   BOOST_CHECK_EQUAL(lookup(shell3, PositiveXFace, Vector3(30_mm, 10_mm, 420_mm),
0539                            Vector3::UnitX()),
0540                     &vol4);
0541 
0542   BOOST_CHECK_EQUAL(lookup(shell3, NegativeYFace,
0543                            Vector3(10_mm, -100_mm, 420_mm), -Vector3::UnitY()),
0544                     nullptr);
0545   BOOST_CHECK_EQUAL(lookup(shell3, NegativeYFace,
0546                            Vector3(10_mm, -100_mm, 420_mm), Vector3::UnitY()),
0547                     &vol3);
0548 
0549   BOOST_CHECK_EQUAL(lookup(shell3, PositiveYFace,
0550                            Vector3(10_mm, 100_mm, 420_mm), -Vector3::UnitY()),
0551                     &vol3);
0552   BOOST_CHECK_EQUAL(lookup(shell3, PositiveYFace,
0553                            Vector3(10_mm, 100_mm, 420_mm), Vector3::UnitY()),
0554                     nullptr);
0555 
0556   // Volume 4
0557   BOOST_CHECK_EQUAL(lookup(shell4, NegativeZFace,
0558                            Vector3(50_mm, 20_mm, -200_mm), -Vector3::UnitZ()),
0559                     nullptr);
0560   BOOST_CHECK_EQUAL(lookup(shell4, NegativeZFace,
0561                            Vector3(50_mm, 20_mm, -200_mm), Vector3::UnitZ()),
0562                     &vol4);
0563 
0564   BOOST_CHECK_EQUAL(lookup(shell4, PositiveZFace, Vector3(50_mm, 20_mm, 800_mm),
0565                            -Vector3::UnitZ()),
0566                     &vol4);
0567   BOOST_CHECK_EQUAL(lookup(shell4, PositiveZFace, Vector3(50_mm, 20_mm, 800_mm),
0568                            Vector3::UnitZ()),
0569                     nullptr);
0570 
0571   BOOST_CHECK_EQUAL(lookup(shell4, NegativeXFace, Vector3(30_mm, 10_mm, 0_mm),
0572                            -Vector3::UnitX()),
0573                     &vol1);
0574   BOOST_CHECK_EQUAL(lookup(shell4, NegativeXFace, Vector3(30_mm, 10_mm, 220_mm),
0575                            -Vector3::UnitX()),
0576                     &vol2);
0577   BOOST_CHECK_EQUAL(lookup(shell4, NegativeXFace, Vector3(30_mm, 10_mm, 420_mm),
0578                            -Vector3::UnitX()),
0579                     &vol3);
0580   BOOST_CHECK_EQUAL(lookup(shell4, NegativeXFace, Vector3(30_mm, 10_mm, 300_mm),
0581                            Vector3::UnitX()),
0582                     &vol4);
0583 
0584   BOOST_CHECK_EQUAL(lookup(shell4, PositiveXFace, Vector3(90_mm, 10_mm, 300_mm),
0585                            -Vector3::UnitX()),
0586                     &vol4);
0587   BOOST_CHECK_EQUAL(lookup(shell4, PositiveXFace, Vector3(90_mm, 10_mm, 300_mm),
0588                            Vector3::UnitX()),
0589                     nullptr);
0590 
0591   BOOST_CHECK_EQUAL(lookup(shell4, NegativeYFace,
0592                            Vector3(50_mm, -100_mm, 300_mm), -Vector3::UnitY()),
0593                     nullptr);
0594   BOOST_CHECK_EQUAL(lookup(shell4, NegativeYFace,
0595                            Vector3(50_mm, -100_mm, 300_mm), Vector3::UnitY()),
0596                     &vol4);
0597 
0598   BOOST_CHECK_EQUAL(lookup(shell4, PositiveYFace,
0599                            Vector3(50_mm, 100_mm, 300_mm), -Vector3::UnitY()),
0600                     &vol4);
0601   BOOST_CHECK_EQUAL(lookup(shell4, PositiveYFace,
0602                            Vector3(50_mm, 100_mm, 300_mm), Vector3::UnitY()),
0603                     nullptr);
0604 
0605   // Stack
0606   BOOST_CHECK_EQUAL(lookup(stack, NegativeZFace, Vector3(10_mm, 20_mm, -200_mm),
0607                            -Vector3::UnitZ()),
0608                     nullptr);
0609   BOOST_CHECK_EQUAL(lookup(stack, NegativeZFace, Vector3(10_mm, 20_mm, -200_mm),
0610                            Vector3::UnitZ()),
0611                     &vol1);
0612 
0613   BOOST_CHECK_EQUAL(lookup(stack, PositiveZFace, Vector3(10_mm, 20_mm, 800_mm),
0614                            -Vector3::UnitZ()),
0615                     &vol3);
0616   BOOST_CHECK_EQUAL(lookup(stack, PositiveZFace, Vector3(10_mm, 20_mm, 800_mm),
0617                            Vector3::UnitZ()),
0618                     nullptr);
0619 
0620   BOOST_CHECK_EQUAL(lookup(stack, NegativeXFace, Vector3(-30_mm, 10_mm, 300_mm),
0621                            -Vector3::UnitX()),
0622                     nullptr);
0623   BOOST_CHECK_EQUAL(lookup(stack, NegativeXFace, Vector3(-30_mm, 10_mm, 0_mm),
0624                            Vector3::UnitX()),
0625                     &vol1);
0626   BOOST_CHECK_EQUAL(lookup(stack, NegativeXFace, Vector3(-30_mm, 10_mm, 220_mm),
0627                            Vector3::UnitX()),
0628                     &vol2);
0629   BOOST_CHECK_EQUAL(lookup(stack, NegativeXFace, Vector3(-30_mm, 10_mm, 420_mm),
0630                            Vector3::UnitX()),
0631                     &vol3);
0632 
0633   BOOST_CHECK_EQUAL(lookup(stack, PositiveXFace, Vector3(30_mm, 10_mm, 0_mm),
0634                            -Vector3::UnitX()),
0635                     &vol1);
0636   BOOST_CHECK_EQUAL(lookup(stack, PositiveXFace, Vector3(30_mm, 10_mm, 220_mm),
0637                            -Vector3::UnitX()),
0638                     &vol2);
0639   BOOST_CHECK_EQUAL(lookup(stack, PositiveXFace, Vector3(30_mm, 10_mm, 420_mm),
0640                            -Vector3::UnitX()),
0641                     &vol3);
0642   BOOST_CHECK_EQUAL(lookup(stack, PositiveXFace, Vector3(30_mm, 10_mm, 300_mm),
0643                            Vector3::UnitX()),
0644                     &vol4);
0645 
0646   BOOST_CHECK_EQUAL(lookup(stack, NegativeYFace,
0647                            Vector3(10_mm, -100_mm, 300_mm), -Vector3::UnitY()),
0648                     nullptr);
0649   BOOST_CHECK_EQUAL(lookup(stack, NegativeYFace, Vector3(10_mm, -100_mm, 0_mm),
0650                            Vector3::UnitY()),
0651                     &vol1);
0652   BOOST_CHECK_EQUAL(lookup(stack, NegativeYFace,
0653                            Vector3(10_mm, -100_mm, 220_mm), Vector3::UnitY()),
0654                     &vol2);
0655   BOOST_CHECK_EQUAL(lookup(stack, NegativeYFace,
0656                            Vector3(10_mm, -100_mm, 420_mm), Vector3::UnitY()),
0657                     &vol3);
0658 
0659   BOOST_CHECK_EQUAL(lookup(stack, PositiveYFace, Vector3(10_mm, 100_mm, 0_mm),
0660                            -Vector3::UnitY()),
0661                     &vol1);
0662   BOOST_CHECK_EQUAL(lookup(stack, PositiveYFace, Vector3(10_mm, 100_mm, 220_mm),
0663                            -Vector3::UnitY()),
0664                     &vol2);
0665   BOOST_CHECK_EQUAL(lookup(stack, PositiveYFace, Vector3(10_mm, 100_mm, 420_mm),
0666                            -Vector3::UnitY()),
0667                     &vol3);
0668   BOOST_CHECK_EQUAL(lookup(stack, PositiveYFace, Vector3(10_mm, 100_mm, 300_mm),
0669                            Vector3::UnitY()),
0670                     nullptr);
0671 
0672   // Stack 2
0673   BOOST_CHECK_EQUAL(lookup(stack2, NegativeZFace,
0674                            Vector3(10_mm, 20_mm, -200_mm), -Vector3::UnitZ()),
0675                     nullptr);
0676   BOOST_CHECK_EQUAL(lookup(stack2, NegativeZFace,
0677                            Vector3(10_mm, 20_mm, -200_mm), Vector3::UnitZ()),
0678                     &vol1);
0679   BOOST_CHECK_EQUAL(lookup(stack2, NegativeZFace,
0680                            Vector3(50_mm, 20_mm, -200_mm), Vector3::UnitZ()),
0681                     &vol4);
0682 
0683   BOOST_CHECK_EQUAL(lookup(stack2, PositiveZFace, Vector3(10_mm, 20_mm, 800_mm),
0684                            -Vector3::UnitZ()),
0685                     &vol3);
0686   BOOST_CHECK_EQUAL(lookup(stack2, PositiveZFace, Vector3(50_mm, 20_mm, 800_mm),
0687                            -Vector3::UnitZ()),
0688                     &vol4);
0689   BOOST_CHECK_EQUAL(lookup(stack2, PositiveZFace, Vector3(10_mm, 20_mm, 800_mm),
0690                            Vector3::UnitZ()),
0691                     nullptr);
0692 
0693   BOOST_CHECK_EQUAL(lookup(stack2, NegativeXFace,
0694                            Vector3(-30_mm, 10_mm, 300_mm), -Vector3::UnitX()),
0695                     nullptr);
0696   BOOST_CHECK_EQUAL(lookup(stack2, NegativeXFace, Vector3(-30_mm, 10_mm, 0_mm),
0697                            Vector3::UnitX()),
0698                     &vol1);
0699   BOOST_CHECK_EQUAL(lookup(stack2, NegativeXFace,
0700                            Vector3(-30_mm, 10_mm, 220_mm), Vector3::UnitX()),
0701                     &vol2);
0702   BOOST_CHECK_EQUAL(lookup(stack2, NegativeXFace,
0703                            Vector3(-30_mm, 10_mm, 420_mm), Vector3::UnitX()),
0704                     &vol3);
0705 
0706   BOOST_CHECK_EQUAL(lookup(shell4, PositiveXFace, Vector3(90_mm, 10_mm, 300_mm),
0707                            -Vector3::UnitX()),
0708                     &vol4);
0709   BOOST_CHECK_EQUAL(lookup(shell4, PositiveXFace, Vector3(90_mm, 10_mm, 300_mm),
0710                            Vector3::UnitX()),
0711                     nullptr);
0712 
0713   BOOST_CHECK_EQUAL(lookup(stack2, NegativeYFace,
0714                            Vector3(10_mm, -100_mm, 300_mm), -Vector3::UnitY()),
0715                     nullptr);
0716   BOOST_CHECK_EQUAL(lookup(stack2, NegativeYFace, Vector3(10_mm, -100_mm, 0_mm),
0717                            Vector3::UnitY()),
0718                     &vol1);
0719   BOOST_CHECK_EQUAL(lookup(stack2, NegativeYFace,
0720                            Vector3(10_mm, -100_mm, 220_mm), Vector3::UnitY()),
0721                     &vol2);
0722   BOOST_CHECK_EQUAL(lookup(stack2, NegativeYFace,
0723                            Vector3(10_mm, -100_mm, 420_mm), Vector3::UnitY()),
0724                     &vol3);
0725   BOOST_CHECK_EQUAL(lookup(stack2, NegativeYFace,
0726                            Vector3(50_mm, -100_mm, 420_mm), Vector3::UnitY()),
0727                     &vol4);
0728 
0729   BOOST_CHECK_EQUAL(lookup(stack2, PositiveYFace, Vector3(10_mm, 100_mm, 0_mm),
0730                            -Vector3::UnitY()),
0731                     &vol1);
0732   BOOST_CHECK_EQUAL(lookup(stack2, PositiveYFace,
0733                            Vector3(10_mm, 100_mm, 220_mm), -Vector3::UnitY()),
0734                     &vol2);
0735   BOOST_CHECK_EQUAL(lookup(stack2, PositiveYFace,
0736                            Vector3(10_mm, 100_mm, 420_mm), -Vector3::UnitY()),
0737                     &vol3);
0738   BOOST_CHECK_EQUAL(lookup(stack2, PositiveYFace,
0739                            Vector3(50_mm, 100_mm, 420_mm), -Vector3::UnitY()),
0740                     &vol4);
0741   BOOST_CHECK_EQUAL(lookup(stack2, PositiveYFace,
0742                            Vector3(10_mm, 100_mm, 300_mm), Vector3::UnitY()),
0743                     nullptr);
0744 }
0745 
0746 BOOST_AUTO_TEST_CASE(Fill) {
0747   Transform3 base = Transform3::Identity();
0748 
0749   TrackingVolume vol1(
0750       base, std::make_shared<CuboidVolumeBounds>(30_mm, 100_mm, 200_mm),
0751       "vol1");
0752 
0753   TrackingVolume vol2(
0754       base * Translation3(Vector3::UnitZ() * 300_mm),
0755       std::make_shared<CuboidVolumeBounds>(30_mm, 100_mm, 100_mm), "vol2");
0756 
0757   SingleCuboidPortalShell shell{gctx, vol1};
0758 
0759   using enum CuboidVolumeBounds::Face;
0760 
0761   BOOST_CHECK_EQUAL(
0762       shell.portal(PositiveZFace)->getLink(Direction::AlongNormal()), nullptr);
0763 
0764   shell.fill(vol2);
0765 
0766   BOOST_CHECK_NE(shell.portal(PositiveZFace)->getLink(Direction::AlongNormal()),
0767                  nullptr);
0768 }
0769 
0770 BOOST_AUTO_TEST_CASE(RegisterInto) {
0771   using enum CuboidVolumeBounds::Face;
0772   TrackingVolume vol1(
0773       Transform3::Identity(),
0774       std::make_shared<CuboidVolumeBounds>(100_mm, 100_mm, 100_mm));
0775 
0776   SingleCuboidPortalShell shell{gctx, vol1};
0777 
0778   BOOST_CHECK_EQUAL(vol1.portals().size(), 0);
0779 
0780   shell.applyToVolume();
0781   BOOST_CHECK_EQUAL(vol1.portals().size(), 6);
0782 }
0783 
0784 BOOST_AUTO_TEST_SUITE_END()  // CuboidStack
0785 BOOST_AUTO_TEST_SUITE_END()
0786 
0787 }  // namespace ActsTests