Back to home page

EIC code displayed by LXR

 
 

    


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