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