File indexing completed on 2025-07-01 07:53:53
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/data/test_case.hpp>
0010 #include <boost/test/detail/log_level.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_log.hpp>
0015 #include <boost/test/unit_test_parameters.hpp>
0016 #include <boost/test/unit_test_suite.hpp>
0017
0018 #include "Acts/Definitions/Algebra.hpp"
0019 #include "Acts/Definitions/Units.hpp"
0020 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0021 #include "Acts/Geometry/CuboidVolumeStack.hpp"
0022 #include "Acts/Geometry/VolumeAttachmentStrategy.hpp"
0023 #include "Acts/Geometry/VolumeResizeStrategy.hpp"
0024 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0025 #include "Acts/Utilities/AxisDefinitions.hpp"
0026 #include "Acts/Utilities/Logger.hpp"
0027 #include "Acts/Utilities/ThrowAssert.hpp"
0028 #include "Acts/Utilities/Zip.hpp"
0029
0030 #include <cassert>
0031 #include <initializer_list>
0032 #include <stdexcept>
0033 #include <utility>
0034
0035 using namespace Acts::UnitLiterals;
0036
0037 namespace Acts::Test {
0038
0039 auto logger = Acts::getDefaultLogger("UnitTests", Acts::Logging::VERBOSE);
0040
0041 struct Fixture {
0042 Logging::Level m_level;
0043 Fixture() {
0044 m_level = Acts::Logging::getFailureThreshold();
0045 Acts::Logging::setFailureThreshold(Acts::Logging::FATAL);
0046 }
0047
0048 ~Fixture() { Acts::Logging::setFailureThreshold(m_level); }
0049 };
0050
0051 BOOST_FIXTURE_TEST_SUITE(Geometry, Fixture)
0052
0053 static const std::vector<VolumeAttachmentStrategy> strategies = {
0054 VolumeAttachmentStrategy::Gap,
0055 VolumeAttachmentStrategy::First,
0056 VolumeAttachmentStrategy::Second,
0057 VolumeAttachmentStrategy::Midpoint,
0058 };
0059
0060 static const std::vector<VolumeResizeStrategy> resizeStrategies = {
0061 VolumeResizeStrategy::Expand,
0062 VolumeResizeStrategy::Gap,
0063 };
0064
0065 BOOST_AUTO_TEST_SUITE(CuboidVolumeStackTest)
0066
0067 BOOST_DATA_TEST_CASE(BaselineLocal,
0068 (boost::unit_test::data::xrange(-135, 180, 45) *
0069 boost::unit_test::data::xrange(0, 2, 1) *
0070 boost::unit_test::data::make(0.8, 1.0, 1.2) *
0071 boost::unit_test::data::make(Vector3{0_mm, 0_mm, 0_mm},
0072 Vector3{20_mm, 0_mm, 0_mm},
0073 Vector3{0_mm, 20_mm, 0_mm},
0074 Vector3{20_mm, 20_mm, 0_mm},
0075 Vector3{0_mm, 0_mm, 20_mm}) *
0076 boost::unit_test::data::make(strategies) *
0077 boost::unit_test::data::make(Acts::AxisDirection::AxisX,
0078 Acts::AxisDirection::AxisY,
0079 Acts::AxisDirection::AxisZ)),
0080 angle, rotate, shift, offset, strategy, dir) {
0081 double halfDir = 400_mm;
0082
0083 auto [dirOrth1, dirOrth2] = CuboidVolumeStack::getOrthogonalAxes(dir);
0084
0085 auto dirIdx = CuboidVolumeStack::axisToIndex(dir);
0086 auto dirOrth1Idx = CuboidVolumeStack::axisToIndex(dirOrth1);
0087
0088 auto boundDir = CuboidVolumeBounds::boundsFromAxisDirection(dir);
0089 auto boundDirOrth1 = CuboidVolumeBounds::boundsFromAxisDirection(dirOrth1);
0090 auto boundDirOrth2 = CuboidVolumeBounds::boundsFromAxisDirection(dirOrth2);
0091
0092 auto bounds1 = std::make_shared<CuboidVolumeBounds>(
0093 std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0094 {boundDir, halfDir},
0095 {boundDirOrth1, 100_mm},
0096 {boundDirOrth2, 400_mm}});
0097
0098 auto bounds2 = std::make_shared<CuboidVolumeBounds>(
0099 std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0100 {boundDir, halfDir},
0101 {boundDirOrth1, 200_mm},
0102 {boundDirOrth2, 600_mm}});
0103
0104 auto bounds3 = std::make_shared<CuboidVolumeBounds>(
0105 std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0106 {boundDir, halfDir},
0107 {boundDirOrth1, 300_mm},
0108 {boundDirOrth2, 500_mm}});
0109
0110 Transform3 base = AngleAxis3(angle * 1_degree, Vector3::Unit(dirOrth1Idx)) *
0111 Translation3(offset);
0112
0113 Translation3 translation1(Vector3::Unit(dirIdx) * (-2 * halfDir * shift));
0114 Transform3 transform1 = base * translation1;
0115 auto vol1 = std::make_shared<Volume>(transform1, bounds1);
0116
0117 Transform3 transform2 = base;
0118 auto vol2 = std::make_shared<Volume>(transform2, bounds2);
0119
0120 Translation3 translation3(Vector3::Unit(dirIdx) * (2 * halfDir * shift));
0121 Transform3 transform3 = base * translation3;
0122 auto vol3 = std::make_shared<Volume>(transform3, bounds3);
0123
0124 std::vector<Volume*> volumes = {vol1.get(), vol2.get(), vol3.get()};
0125
0126 std::rotate(volumes.begin(), volumes.begin() + rotate, volumes.end());
0127
0128 auto origVolumes = volumes;
0129
0130 std::vector<CuboidVolumeBounds> originalBounds;
0131 std::transform(volumes.begin(), volumes.end(),
0132 std::back_inserter(originalBounds), [](const auto& vol) {
0133 const auto* res =
0134 dynamic_cast<CuboidVolumeBounds*>(&vol->volumeBounds());
0135 throw_assert(res != nullptr, "");
0136 return *res;
0137 });
0138
0139 if (shift < 1.0) {
0140 BOOST_CHECK_THROW(CuboidVolumeStack(volumes, dir, strategy,
0141 VolumeResizeStrategy::Gap, *logger),
0142 std::invalid_argument);
0143 return;
0144 }
0145 CuboidVolumeStack stack(volumes, dir, strategy, VolumeResizeStrategy::Gap,
0146 *logger);
0147
0148 auto stackBounds =
0149 dynamic_cast<const CuboidVolumeBounds*>(&stack.volumeBounds());
0150 BOOST_REQUIRE(stackBounds != nullptr);
0151
0152 BOOST_CHECK_CLOSE(stackBounds->get(boundDirOrth1), 300_mm, 1e-6);
0153 BOOST_CHECK_CLOSE(stackBounds->get(boundDirOrth2), 600_mm, 1e-6);
0154 BOOST_CHECK_CLOSE(stackBounds->get(boundDir), halfDir + 2 * halfDir * shift,
0155 1e-6);
0156 CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), base.matrix(), 1e-10, 1e-12);
0157
0158
0159
0160 for (const auto& volume : volumes) {
0161 const auto* cuboidBounds =
0162 dynamic_cast<const CuboidVolumeBounds*>(&volume->volumeBounds());
0163 BOOST_REQUIRE(cuboidBounds != nullptr);
0164 BOOST_CHECK_CLOSE(cuboidBounds->get(boundDirOrth1), 300_mm, 1e-6);
0165 BOOST_CHECK_CLOSE(cuboidBounds->get(boundDirOrth2), 600_mm, 1e-6);
0166 }
0167
0168
0169 for (std::size_t i = 0; i < volumes.size() - 1; ++i) {
0170 const auto& a = volumes.at(i);
0171 const auto& b = volumes.at(i + 1);
0172
0173 BOOST_CHECK_LT((base.inverse() * a->center())[dirIdx],
0174 (base.inverse() * b->center())[dirIdx]);
0175 }
0176
0177 if (shift <= 1.0) {
0178
0179 BOOST_CHECK_EQUAL(volumes.size(), 3);
0180
0181
0182 BOOST_CHECK_EQUAL(vol1->transform().matrix(), transform1.matrix());
0183 BOOST_CHECK_EQUAL(vol2->transform().matrix(), transform2.matrix());
0184 BOOST_CHECK_EQUAL(vol3->transform().matrix(), transform3.matrix());
0185
0186 for (const auto& [volume, bounds] : zip(origVolumes, originalBounds)) {
0187 const auto* newBounds =
0188 dynamic_cast<const CuboidVolumeBounds*>(&volume->volumeBounds());
0189 BOOST_CHECK_CLOSE(newBounds->get(boundDir), bounds.get(boundDir), 1e-6);
0190 }
0191 } else {
0192 if (strategy == VolumeAttachmentStrategy::Gap) {
0193
0194 BOOST_CHECK_EQUAL(volumes.size(), 5);
0195 auto gap1 = volumes.at(1);
0196 auto gap2 = volumes.at(3);
0197
0198 BOOST_TEST_MESSAGE("Gap 1: " << gap1->transform().matrix());
0199 BOOST_TEST_MESSAGE("Gap 2: " << gap2->transform().matrix());
0200
0201 const auto* gapBounds1 =
0202 dynamic_cast<const CuboidVolumeBounds*>(&gap1->volumeBounds());
0203 const auto* gapBounds2 =
0204 dynamic_cast<const CuboidVolumeBounds*>(&gap2->volumeBounds());
0205
0206 double gapHlDir = (shift - 1.0) * halfDir;
0207
0208 BOOST_CHECK(std::abs(gapBounds1->get(boundDir) - gapHlDir) < 1e-12);
0209 BOOST_CHECK(std::abs(gapBounds2->get(boundDir) - gapHlDir) < 1e-12);
0210
0211 double gap1Dir = (-2 * halfDir * shift) + halfDir + gapHlDir;
0212 double gap2Dir = (2 * halfDir * shift) - halfDir - gapHlDir;
0213
0214 Translation3 gap1Translation(Vector3::Unit(dirIdx) * gap1Dir);
0215 Translation3 gap2Translation(Vector3::Unit(dirIdx) * gap2Dir);
0216
0217 Transform3 gap1Transform = base * gap1Translation;
0218 Transform3 gap2Transform = base * gap2Translation;
0219
0220 CHECK_CLOSE_OR_SMALL(gap1->transform().matrix(), gap1Transform.matrix(),
0221 1e-10, 1e-12);
0222 CHECK_CLOSE_OR_SMALL(gap2->transform().matrix(), gap2Transform.matrix(),
0223 1e-10, 1e-12);
0224
0225
0226 for (const auto& [volume, bounds] : zip(origVolumes, originalBounds)) {
0227 const auto* newBounds =
0228 dynamic_cast<const CuboidVolumeBounds*>(&volume->volumeBounds());
0229 BOOST_CHECK_CLOSE(newBounds->get(boundDir), bounds.get(boundDir), 1e-6);
0230 }
0231
0232
0233 BOOST_CHECK_EQUAL(vol1->transform().matrix(), transform1.matrix());
0234 BOOST_CHECK_EQUAL(vol2->transform().matrix(), transform2.matrix());
0235 BOOST_CHECK_EQUAL(vol3->transform().matrix(), transform3.matrix());
0236 } else if (strategy == VolumeAttachmentStrategy::First) {
0237
0238 BOOST_CHECK_EQUAL(volumes.size(), 3);
0239
0240 double wGap = (shift - 1.0) * halfDir * 2;
0241
0242
0243 auto newBounds1 =
0244 dynamic_cast<const CuboidVolumeBounds*>(&vol1->volumeBounds());
0245 BOOST_CHECK_CLOSE(newBounds1->get(boundDir), halfDir + wGap / 2.0, 1e-6);
0246 double pDir1 = -2 * halfDir * shift + wGap / 2.0;
0247 Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1);
0248 Transform3 expectedTransform1 = base * expectedTranslation1;
0249 CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(),
0250 expectedTransform1.matrix(), 1e-10, 1e-12);
0251
0252
0253 auto newBounds2 =
0254 dynamic_cast<const CuboidVolumeBounds*>(&vol2->volumeBounds());
0255 BOOST_CHECK_CLOSE(newBounds2->get(boundDir), halfDir + wGap / 2.0, 1e-6);
0256 double pDir2 = wGap / 2.0;
0257 Translation3 expectedTranslation2(Vector3::Unit(dirIdx) * pDir2);
0258 Transform3 expectedTransform2 = base * expectedTranslation2;
0259 CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(),
0260 expectedTransform2.matrix(), 1e-10, 1e-12);
0261
0262
0263 auto newBounds3 =
0264 dynamic_cast<const CuboidVolumeBounds*>(&vol3->volumeBounds());
0265 BOOST_CHECK_CLOSE(newBounds3->get(boundDir), halfDir, 1e-6);
0266 double pDir3 = 2 * halfDir * shift;
0267 Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3);
0268 Transform3 expectedTransform3 = base * expectedTranslation3;
0269 CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(),
0270 expectedTransform3.matrix(), 1e-10, 1e-12);
0271 } else if (strategy == VolumeAttachmentStrategy::Second) {
0272
0273 BOOST_CHECK_EQUAL(volumes.size(), 3);
0274
0275 double wGap = (shift - 1.0) * halfDir * 2;
0276
0277
0278 auto newBounds1 =
0279 dynamic_cast<const CuboidVolumeBounds*>(&vol1->volumeBounds());
0280 BOOST_CHECK_CLOSE(newBounds1->get(boundDir), halfDir, 1e-6);
0281 double pDir1 = -2 * halfDir * shift;
0282 Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1);
0283 Transform3 expectedTransform1 = base * expectedTranslation1;
0284 CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(),
0285 expectedTransform1.matrix(), 1e-10, 1e-12);
0286
0287
0288 auto newBounds2 =
0289 dynamic_cast<const CuboidVolumeBounds*>(&vol2->volumeBounds());
0290 BOOST_CHECK_CLOSE(newBounds2->get(boundDir), halfDir + wGap / 2.0, 1e-6);
0291 double pDir2 = -wGap / 2.0;
0292 Translation3 expectedTranslation2(Vector3::Unit(dirIdx) * pDir2);
0293 Transform3 expectedTransform2 = base * expectedTranslation2;
0294 CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(),
0295 expectedTransform2.matrix(), 1e-10, 1e-12);
0296
0297
0298 auto newBounds3 =
0299 dynamic_cast<const CuboidVolumeBounds*>(&vol3->volumeBounds());
0300 BOOST_CHECK_CLOSE(newBounds3->get(boundDir), halfDir + wGap / 2.0, 1e-6);
0301 double pDir3 = 2 * halfDir * shift - wGap / 2.0;
0302 Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3);
0303 Transform3 expectedTransform3 = base * expectedTranslation3;
0304 CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(),
0305 expectedTransform3.matrix(), 1e-10, 1e-12);
0306 } else if (strategy == VolumeAttachmentStrategy::Midpoint) {
0307
0308 BOOST_CHECK_EQUAL(volumes.size(), 3);
0309
0310 double wGap = (shift - 1.0) * halfDir * 2;
0311
0312
0313 auto newBounds1 =
0314 dynamic_cast<const CuboidVolumeBounds*>(&vol1->volumeBounds());
0315 BOOST_CHECK_CLOSE(newBounds1->get(boundDir), halfDir + wGap / 4.0, 1e-6);
0316 double pDir1 = -2 * halfDir * shift + wGap / 4.0;
0317 Translation3 expectedTranslation1(Vector3::Unit(dirIdx) * pDir1);
0318 Transform3 expectedTransform1 = base * expectedTranslation1;
0319 CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(),
0320 expectedTransform1.matrix(), 1e-10, 1e-12);
0321
0322
0323 auto newBounds2 =
0324 dynamic_cast<const CuboidVolumeBounds*>(&vol2->volumeBounds());
0325 BOOST_CHECK_CLOSE(newBounds2->get(boundDir), halfDir + wGap / 2.0, 1e-6);
0326 CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), base.matrix(), 1e-10,
0327 1e-12);
0328
0329
0330 auto newBounds3 =
0331 dynamic_cast<const CuboidVolumeBounds*>(&vol3->volumeBounds());
0332 BOOST_CHECK_CLOSE(newBounds3->get(boundDir), halfDir + wGap / 4.0, 1e-6);
0333 double pDir3 = 2 * halfDir * shift - wGap / 4.0;
0334 Translation3 expectedTranslation3(Vector3::Unit(dirIdx) * pDir3);
0335 Transform3 expectedTransform3 = base * expectedTranslation3;
0336 CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(),
0337 expectedTransform3.matrix(), 1e-10, 1e-12);
0338 }
0339 }
0340 }
0341
0342 BOOST_DATA_TEST_CASE(Asymmetric,
0343 boost::unit_test::data::make(Acts::AxisDirection::AxisX,
0344 Acts::AxisDirection::AxisY,
0345 Acts::AxisDirection::AxisZ),
0346 dir) {
0347 double halfDir1 = 200_mm;
0348 double pDir1 = -1100_mm;
0349 double halfDir2 = 600_mm;
0350 double pDir2 = -200_mm;
0351 double halfDir3 = 400_mm;
0352 double pDir3 = 850_mm;
0353
0354 auto [dirOrth1, dirOrth2] = CuboidVolumeStack::getOrthogonalAxes(dir);
0355
0356 auto dirIdx = CuboidVolumeStack::axisToIndex(dir);
0357
0358 auto boundDir = CuboidVolumeBounds::boundsFromAxisDirection(dir);
0359 auto boundDirOrth1 = CuboidVolumeBounds::boundsFromAxisDirection(dirOrth1);
0360 auto boundDirOrth2 = CuboidVolumeBounds::boundsFromAxisDirection(dirOrth2);
0361
0362 auto bounds1 = std::make_shared<CuboidVolumeBounds>(
0363 std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0364 {boundDir, halfDir1},
0365 {boundDirOrth1, 100_mm},
0366 {boundDirOrth2, 400_mm}});
0367
0368 auto bounds2 = std::make_shared<CuboidVolumeBounds>(
0369 std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0370 {boundDir, halfDir2},
0371 {boundDirOrth1, 200_mm},
0372 {boundDirOrth2, 600_mm}});
0373
0374 auto bounds3 = std::make_shared<CuboidVolumeBounds>(
0375 std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0376 {boundDir, halfDir3},
0377 {boundDirOrth1, 300_mm},
0378 {boundDirOrth2, 500_mm}});
0379
0380 Translation3 translation1(Vector3::Unit(dirIdx) * pDir1);
0381 Transform3 transform1(translation1);
0382 auto vol1 = std::make_shared<Volume>(transform1, bounds1);
0383
0384 Translation3 translation2(Vector3::Unit(dirIdx) * pDir2);
0385 Transform3 transform2(translation2);
0386 auto vol2 = std::make_shared<Volume>(transform2, bounds2);
0387
0388 Translation3 translation3(Vector3::Unit(dirIdx) * pDir3);
0389 Transform3 transform3(translation3);
0390 auto vol3 = std::make_shared<Volume>(transform3, bounds3);
0391
0392 std::vector<Volume*> volumes = {vol2.get(), vol1.get(), vol3.get()};
0393
0394 CuboidVolumeStack stack(volumes, dir, VolumeAttachmentStrategy::Gap,
0395 VolumeResizeStrategy::Gap, *logger);
0396 BOOST_CHECK_EQUAL(volumes.size(), 5);
0397
0398 auto stackBounds =
0399 dynamic_cast<const CuboidVolumeBounds*>(&stack.volumeBounds());
0400 BOOST_REQUIRE(stackBounds != nullptr);
0401
0402 BOOST_CHECK_CLOSE(stackBounds->get(boundDirOrth1), 300_mm, 1e-6);
0403 BOOST_CHECK_CLOSE(stackBounds->get(boundDirOrth2), 600_mm, 1e-6);
0404 BOOST_CHECK_CLOSE(stackBounds->get(boundDir),
0405 (std::abs(pDir1 - halfDir1) + pDir3 + halfDir3) / 2.0,
0406 1e-6);
0407
0408 double midDir = (pDir1 - halfDir1 + pDir3 + halfDir3) / 2.0;
0409 Translation3 expectedTranslation(Vector3::Unit(dirIdx) * midDir);
0410 Transform3 expectedTransform = Transform3::Identity() * expectedTranslation;
0411 CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), expectedTransform.matrix(),
0412 1e-10, 1e-12);
0413 }
0414
0415 BOOST_DATA_TEST_CASE(UpdateStack,
0416 (boost::unit_test::data::xrange(-135, 180, 45) *
0417 boost::unit_test::data::make(Vector3{0_mm, 0_mm, 0_mm},
0418 Vector3{20_mm, 0_mm, 0_mm},
0419 Vector3{0_mm, 20_mm, 0_mm},
0420 Vector3{20_mm, 20_mm, 0_mm},
0421 Vector3{0_mm, 0_mm, 20_mm}) *
0422 boost::unit_test::data::make(-100_mm, 0_mm, 100_mm) *
0423 boost::unit_test::data::make(resizeStrategies) *
0424 boost::unit_test::data::make(Acts::AxisDirection::AxisX,
0425 Acts::AxisDirection::AxisY,
0426 Acts::AxisDirection::AxisZ)),
0427 angle, offset, zshift, strategy, dir) {
0428 double halfDir = 400_mm;
0429
0430 auto [dirOrth1, dirOrth2] = CuboidVolumeStack::getOrthogonalAxes(dir);
0431
0432 auto dirIdx = CuboidVolumeStack::axisToIndex(dir);
0433 auto dirOrth1Idx = CuboidVolumeStack::axisToIndex(dirOrth1);
0434
0435 auto boundDir = CuboidVolumeBounds::boundsFromAxisDirection(dir);
0436 auto boundDirOrth1 = CuboidVolumeBounds::boundsFromAxisDirection(dirOrth1);
0437 auto boundDirOrth2 = CuboidVolumeBounds::boundsFromAxisDirection(dirOrth2);
0438
0439 auto bounds1 = std::make_shared<CuboidVolumeBounds>(
0440 std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0441 {boundDir, halfDir},
0442 {boundDirOrth1, 100_mm},
0443 {boundDirOrth2, 600_mm}});
0444
0445 auto bounds2 = std::make_shared<CuboidVolumeBounds>(
0446 std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0447 {boundDir, halfDir},
0448 {boundDirOrth1, 100_mm},
0449 {boundDirOrth2, 600_mm}});
0450
0451 auto bounds3 = std::make_shared<CuboidVolumeBounds>(
0452 std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0453 {boundDir, halfDir},
0454 {boundDirOrth1, 100_mm},
0455 {boundDirOrth2, 600_mm}});
0456
0457 Vector3 shift = Vector3::Unit(dirIdx) * zshift;
0458 Transform3 base = AngleAxis3(angle * 1_degree, Vector3::Unit(dirOrth1Idx)) *
0459 Translation3(offset + shift);
0460
0461 Translation3 translation1(Vector3::Unit(dirIdx) * -2 * halfDir);
0462 Transform3 transform1 = base * translation1;
0463 auto vol1 = std::make_shared<Volume>(transform1, bounds1);
0464
0465 Transform3 transform2 = base;
0466 auto vol2 = std::make_shared<Volume>(transform2, bounds2);
0467
0468 Translation3 translation3(Vector3::Unit(dirIdx) * 2 * halfDir);
0469 Transform3 transform3 = base * translation3;
0470 auto vol3 = std::make_shared<Volume>(transform3, bounds3);
0471
0472 std::vector<Volume*> volumes = {vol1.get(), vol2.get(), vol3.get()};
0473 std::vector<Volume*> originalVolumes = volumes;
0474
0475 std::vector<Transform3> originalTransforms = {transform1, transform2,
0476 transform3};
0477
0478 CuboidVolumeStack stack(volumes, dir,
0479 VolumeAttachmentStrategy::Gap,
0480
0481 strategy, *logger);
0482
0483 const auto* originalBounds =
0484 dynamic_cast<const CuboidVolumeBounds*>(&stack.volumeBounds());
0485
0486 auto assertOriginalBounds = [&]() {
0487 const auto* bounds =
0488 dynamic_cast<const CuboidVolumeBounds*>(&stack.volumeBounds());
0489 BOOST_REQUIRE(bounds != nullptr);
0490 BOOST_CHECK_EQUAL(bounds, originalBounds);
0491 BOOST_CHECK_CLOSE(bounds->get(boundDirOrth1), 100_mm, 1e-6);
0492 BOOST_CHECK_CLOSE(bounds->get(boundDirOrth2), 600_mm, 1e-6);
0493 BOOST_CHECK_CLOSE(bounds->get(boundDir), 3 * halfDir, 1e-6);
0494 };
0495
0496 assertOriginalBounds();
0497
0498 {
0499
0500 auto bounds = std::make_shared<CuboidVolumeBounds>(
0501 dynamic_cast<const CuboidVolumeBounds&>(stack.volumeBounds()));
0502 stack.update(bounds, std::nullopt, *logger);
0503 assertOriginalBounds();
0504 }
0505
0506 {
0507
0508 auto bounds = std::make_shared<CuboidVolumeBounds>(
0509 dynamic_cast<const CuboidVolumeBounds&>(stack.volumeBounds()));
0510 bounds->set(boundDirOrth1, 20_mm);
0511 BOOST_CHECK_THROW(stack.update(bounds, std::nullopt, *logger),
0512 std::invalid_argument);
0513 assertOriginalBounds();
0514 }
0515
0516 {
0517
0518 auto bounds = std::make_shared<CuboidVolumeBounds>(
0519 dynamic_cast<const CuboidVolumeBounds&>(stack.volumeBounds()));
0520 bounds->set(boundDirOrth2, 200_mm);
0521 BOOST_CHECK_THROW(stack.update(bounds, std::nullopt, *logger),
0522 std::invalid_argument);
0523 assertOriginalBounds();
0524 }
0525
0526 {
0527
0528 auto bounds = std::make_shared<CuboidVolumeBounds>(
0529 dynamic_cast<const CuboidVolumeBounds&>(stack.volumeBounds()));
0530 bounds->set(boundDir, 2 * halfDir);
0531 BOOST_CHECK_THROW(stack.update(bounds, std::nullopt, *logger),
0532 std::invalid_argument);
0533 assertOriginalBounds();
0534 }
0535
0536 {
0537
0538 auto bounds = std::make_shared<CuboidVolumeBounds>(
0539 dynamic_cast<const CuboidVolumeBounds&>(stack.volumeBounds()));
0540 bounds->set(boundDirOrth1, 700_mm);
0541 stack.update(bounds, std::nullopt, *logger);
0542 const auto* updatedBounds =
0543 dynamic_cast<const CuboidVolumeBounds*>(&stack.volumeBounds());
0544 BOOST_REQUIRE(updatedBounds != nullptr);
0545 BOOST_CHECK_CLOSE(updatedBounds->get(boundDirOrth1), 700_mm, 1e-6);
0546 BOOST_CHECK_CLOSE(updatedBounds->get(boundDirOrth2), 600_mm, 1e-6);
0547 BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 3 * halfDir, 1e-6);
0548
0549
0550 BOOST_CHECK_EQUAL(volumes.size(), 3);
0551
0552
0553 for (const auto& [volume, origTransform] :
0554 zip(volumes, originalTransforms)) {
0555 const auto* newBounds =
0556 dynamic_cast<const CuboidVolumeBounds*>(&volume->volumeBounds());
0557 BOOST_CHECK_CLOSE(newBounds->get(boundDirOrth1), 700_mm, 1e-6);
0558 BOOST_CHECK_CLOSE(newBounds->get(boundDirOrth2), 600_mm, 1e-6);
0559 BOOST_CHECK_CLOSE(newBounds->get(boundDir), halfDir, 1e-6);
0560
0561
0562 BOOST_CHECK_EQUAL(volume->transform().matrix(), origTransform.matrix());
0563 }
0564 }
0565 {
0566
0567 auto bounds = std::make_shared<CuboidVolumeBounds>(
0568 dynamic_cast<const CuboidVolumeBounds&>(stack.volumeBounds()));
0569 bounds->set(boundDirOrth2, 700_mm);
0570 stack.update(bounds, std::nullopt, *logger);
0571 const auto* updatedBounds =
0572 dynamic_cast<const CuboidVolumeBounds*>(&stack.volumeBounds());
0573 BOOST_REQUIRE(updatedBounds != nullptr);
0574 BOOST_CHECK_CLOSE(updatedBounds->get(boundDirOrth1), 700_mm, 1e-6);
0575 BOOST_CHECK_CLOSE(updatedBounds->get(boundDirOrth2), 700_mm, 1e-6);
0576 BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 3 * halfDir, 1e-6);
0577
0578
0579 BOOST_CHECK_EQUAL(volumes.size(), 3);
0580
0581
0582 for (const auto& [volume, origTransform] :
0583 zip(volumes, originalTransforms)) {
0584 const auto* newBounds =
0585 dynamic_cast<const CuboidVolumeBounds*>(&volume->volumeBounds());
0586 BOOST_CHECK_CLOSE(newBounds->get(boundDirOrth1), 700_mm, 1e-6);
0587 BOOST_CHECK_CLOSE(newBounds->get(boundDirOrth2), 700_mm, 1e-6);
0588 BOOST_CHECK_CLOSE(newBounds->get(boundDir), halfDir, 1e-6);
0589
0590
0591 BOOST_CHECK_EQUAL(volume->transform().matrix(), origTransform.matrix());
0592 }
0593 }
0594
0595 {
0596
0597 auto bounds = std::make_shared<CuboidVolumeBounds>(
0598 dynamic_cast<const CuboidVolumeBounds&>(stack.volumeBounds()));
0599 bounds->set(boundDir, 4 * halfDir);
0600 stack.update(bounds, std::nullopt, *logger);
0601 const auto* updatedBounds =
0602 dynamic_cast<const CuboidVolumeBounds*>(&stack.volumeBounds());
0603 BOOST_REQUIRE(updatedBounds != nullptr);
0604 BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 4 * halfDir, 1e-6);
0605 BOOST_CHECK_CLOSE(updatedBounds->get(boundDirOrth1), 700_mm, 1e-6);
0606 BOOST_CHECK_CLOSE(updatedBounds->get(boundDirOrth2), 700_mm, 1e-6);
0607
0608 if (strategy == VolumeResizeStrategy::Expand) {
0609
0610 BOOST_CHECK_EQUAL(volumes.size(), 3);
0611
0612
0613 auto newBounds1 =
0614 dynamic_cast<const CuboidVolumeBounds*>(&vol1->volumeBounds());
0615 BOOST_CHECK_CLOSE(newBounds1->get(boundDir), halfDir + halfDir / 2.0,
0616 1e-6);
0617 auto expectedTranslation1 =
0618 Translation3(Vector3::Unit(dirIdx) * (-2 * halfDir - halfDir / 2.0));
0619 Transform3 expectedTransform1 = base * expectedTranslation1;
0620 CHECK_CLOSE_OR_SMALL(vol1->transform().matrix(),
0621 expectedTransform1.matrix(), 1e-10, 1e-12);
0622
0623
0624 auto newBounds2 =
0625 dynamic_cast<const CuboidVolumeBounds*>(&vol2->volumeBounds());
0626 BOOST_CHECK_CLOSE(newBounds2->get(boundDir), halfDir, 1e-6);
0627 CHECK_CLOSE_OR_SMALL(vol2->transform().matrix(), transform2.matrix(),
0628 1e-10, 1e-12);
0629
0630
0631 auto newBounds3 =
0632 dynamic_cast<const CuboidVolumeBounds*>(&vol3->volumeBounds());
0633 BOOST_CHECK_CLOSE(newBounds3->get(boundDir), halfDir + halfDir / 2.0,
0634 1e-6);
0635 auto expectedTranslation3 =
0636 Translation3(Vector3::Unit(dirIdx) * (2 * halfDir + halfDir / 2.0));
0637 Transform3 expectedTransform3 = base * expectedTranslation3;
0638 CHECK_CLOSE_OR_SMALL(vol3->transform().matrix(),
0639 expectedTransform3.matrix(), 1e-10, 1e-12);
0640 } else if (strategy == VolumeResizeStrategy::Gap) {
0641
0642 BOOST_CHECK_EQUAL(volumes.size(), 5);
0643
0644 for (const auto& [volume, origTransform] :
0645 zip(originalVolumes, originalTransforms)) {
0646 const auto* newBounds =
0647 dynamic_cast<const CuboidVolumeBounds*>(&volume->volumeBounds());
0648 BOOST_CHECK_CLOSE(newBounds->get(boundDirOrth1), 700_mm, 1e-6);
0649 BOOST_CHECK_CLOSE(newBounds->get(boundDirOrth2), 700_mm, 1e-6);
0650 BOOST_CHECK_CLOSE(newBounds->get(boundDir), halfDir, 1e-6);
0651
0652 CHECK_CLOSE_OR_SMALL(volume->transform().matrix(),
0653 origTransform.matrix(), 1e-10, 1e-12);
0654 }
0655
0656 auto gap1 = volumes.front();
0657 auto gap2 = volumes.back();
0658
0659 const auto* gapBounds1 =
0660 dynamic_cast<const CuboidVolumeBounds*>(&gap1->volumeBounds());
0661 const auto* gapBounds2 =
0662 dynamic_cast<const CuboidVolumeBounds*>(&gap2->volumeBounds());
0663
0664 BOOST_CHECK_CLOSE(gapBounds1->get(boundDir), halfDir / 2.0, 1e-6);
0665 BOOST_CHECK_CLOSE(gapBounds2->get(boundDir), halfDir / 2.0, 1e-6);
0666 auto gap1Translation =
0667 Translation3(Vector3::Unit(dirIdx) * (-3 * halfDir - halfDir / 2.0));
0668 Transform3 gap1Transform = base * gap1Translation;
0669
0670 auto gap2Translation =
0671 Translation3(Vector3::Unit(dirIdx) * (3 * halfDir + halfDir / 2.0));
0672 Transform3 gap2Transform = base * gap2Translation;
0673 CHECK_CLOSE_OR_SMALL(gap1->transform().matrix(), gap1Transform.matrix(),
0674 1e-10, 1e-12);
0675 CHECK_CLOSE_OR_SMALL(gap2->transform().matrix(), gap2Transform.matrix(),
0676 1e-10, 1e-12);
0677 }
0678 }
0679 }
0680
0681 BOOST_DATA_TEST_CASE(
0682 UpdateStackOneSided,
0683 ((boost::unit_test::data::make(-1.0, 1.0) ^
0684 boost::unit_test::data::make(VolumeResizeStrategy::Gap,
0685 VolumeResizeStrategy::Expand)) *
0686 boost::unit_test::data::make(Acts::AxisDirection::AxisX,
0687 Acts::AxisDirection::AxisY,
0688 Acts::AxisDirection::AxisZ)),
0689 f, strategy, dir) {
0690 auto [dirOrth1, dirOrth2] = CuboidVolumeStack::getOrthogonalAxes(dir);
0691
0692 auto dirIdx = CuboidVolumeStack::axisToIndex(dir);
0693 auto dirOrth1Idx = CuboidVolumeStack::axisToIndex(dirOrth1);
0694 auto dirOrth2Idx = CuboidVolumeStack::axisToIndex(dirOrth2);
0695
0696 auto boundDir = CuboidVolumeBounds::boundsFromAxisDirection(dir);
0697 auto boundDirOrth1 = CuboidVolumeBounds::boundsFromAxisDirection(dirOrth1);
0698 auto boundDirOrth2 = CuboidVolumeBounds::boundsFromAxisDirection(dirOrth2);
0699
0700 auto bounds1 = std::make_shared<CuboidVolumeBounds>(
0701 std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0702 {boundDir, 400_mm},
0703 {boundDirOrth1, 100_mm},
0704 {boundDirOrth2, 300_mm}});
0705
0706 auto bounds2 = std::make_shared<CuboidVolumeBounds>(
0707 std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0708 {boundDir, 400_mm},
0709 {boundDirOrth1, 100_mm},
0710 {boundDirOrth2, 300_mm}});
0711
0712 auto trf = Transform3::Identity();
0713
0714 auto translation1 = Translation3(Vector3::Unit(dirIdx) * -500_mm);
0715 auto trf1 = trf * translation1;
0716 auto vol1 = std::make_shared<Volume>(trf1, bounds1);
0717
0718 auto translation2 = Translation3(Vector3::Unit(dirIdx) * 500_mm);
0719 auto trf2 = trf * translation2;
0720 auto vol2 = std::make_shared<Volume>(trf2, bounds2);
0721
0722 std::vector<Volume*> volumes = {vol1.get(), vol2.get()};
0723
0724 CuboidVolumeStack stack{volumes, dir, VolumeAttachmentStrategy::Gap, strategy,
0725 *logger};
0726 const auto* originalBounds =
0727 dynamic_cast<const CuboidVolumeBounds*>(&stack.volumeBounds());
0728
0729
0730 auto newBounds = std::make_shared<CuboidVolumeBounds>(
0731 dynamic_cast<const CuboidVolumeBounds&>(stack.volumeBounds()));
0732 newBounds->set(boundDir, 950_mm);
0733
0734 auto delta = Translation3(Vector3::Unit(dirIdx) * f * 50_mm);
0735 trf *= delta;
0736
0737
0738 auto checkUnchanged = [&]() {
0739 const auto* bounds =
0740 dynamic_cast<const CuboidVolumeBounds*>(&stack.volumeBounds());
0741 BOOST_REQUIRE(bounds != nullptr);
0742 BOOST_CHECK_EQUAL(*bounds, *originalBounds);
0743 };
0744
0745
0746 BOOST_CHECK_THROW(
0747 auto errDelta = Translation3(Vector3::Unit(dirIdx) * f * 20_mm);
0748 stack.update(newBounds, trf * errDelta, *logger), std::invalid_argument);
0749 checkUnchanged();
0750
0751
0752 BOOST_CHECK_THROW(
0753 auto errDelta = Translation3(Vector3::Unit(dirOrth1Idx) * 10_mm);
0754 stack.update(newBounds, trf * errDelta, *logger), std::invalid_argument);
0755 checkUnchanged();
0756
0757
0758 BOOST_CHECK_THROW(
0759 auto errDelta = Translation3(Vector3::Unit(dirOrth2Idx) * 10_mm);
0760 stack.update(newBounds, trf * errDelta, *logger), std::invalid_argument);
0761 checkUnchanged();
0762
0763
0764 BOOST_CHECK_THROW(
0765 stack.update(newBounds,
0766 trf * AngleAxis3{10_degree, Vector3::Unit(dirOrth1Idx)},
0767 *logger),
0768 std::invalid_argument);
0769 checkUnchanged();
0770
0771 stack.update(newBounds, trf, *logger);
0772
0773 CHECK_CLOSE_OR_SMALL(stack.transform().matrix(), trf.matrix(), 1e-10, 1e-12);
0774 const auto* bounds =
0775 dynamic_cast<const CuboidVolumeBounds*>(&stack.volumeBounds());
0776 BOOST_REQUIRE(bounds != nullptr);
0777 BOOST_CHECK_CLOSE(bounds->get(boundDir), 950_mm, 1e-6);
0778
0779
0780 for (const auto* vol : volumes) {
0781 const auto* volBounds =
0782 dynamic_cast<const CuboidVolumeBounds*>(&vol->volumeBounds());
0783 BOOST_REQUIRE(volBounds != nullptr);
0784 BOOST_CHECK_CLOSE(volBounds->get(boundDirOrth1), 100_mm, 1e-6);
0785 BOOST_CHECK_CLOSE(volBounds->get(boundDirOrth2), 300_mm, 1e-6);
0786 }
0787
0788 if (strategy == VolumeResizeStrategy::Expand) {
0789
0790 BOOST_CHECK_EQUAL(volumes.size(), 3);
0791 const Volume* vol = nullptr;
0792 if (f < 0.0) {
0793
0794 vol = volumes.front();
0795 } else {
0796
0797 vol = volumes.back();
0798 }
0799
0800 const auto* volBounds =
0801 dynamic_cast<const CuboidVolumeBounds*>(&vol->volumeBounds());
0802 BOOST_REQUIRE(volBounds != nullptr);
0803 BOOST_CHECK_CLOSE(volBounds->get(boundDir), 450_mm, 1e-6);
0804 BOOST_CHECK_EQUAL(vol->center()[dirIdx], f * 550_mm);
0805 } else if (strategy == VolumeResizeStrategy::Gap) {
0806
0807 BOOST_CHECK_EQUAL(volumes.size(), 4);
0808
0809 const Volume* gap = nullptr;
0810 if (f < 0.0) {
0811 gap = volumes.front();
0812 } else {
0813 gap = volumes.back();
0814 }
0815 const auto* gapBounds =
0816 dynamic_cast<const CuboidVolumeBounds*>(&gap->volumeBounds());
0817 BOOST_REQUIRE(gapBounds != nullptr);
0818
0819 BOOST_CHECK_CLOSE(gapBounds->get(boundDir), 50_mm, 1e-6);
0820 BOOST_CHECK_EQUAL(gap->center()[dirIdx], f * 950_mm);
0821 }
0822 }
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849
0850
0851
0852 BOOST_DATA_TEST_CASE(ResizeGapMultiple,
0853 boost::unit_test::data::make(Acts::AxisDirection::AxisX,
0854 Acts::AxisDirection::AxisY,
0855 Acts::AxisDirection::AxisZ),
0856 dir) {
0857 auto [dirOrth1, dirOrth2] = CuboidVolumeStack::getOrthogonalAxes(dir);
0858
0859 auto dirIdx = CuboidVolumeStack::axisToIndex(dir);
0860
0861 auto boundDir = CuboidVolumeBounds::boundsFromAxisDirection(dir);
0862 auto boundDirOrth1 = CuboidVolumeBounds::boundsFromAxisDirection(dirOrth1);
0863 auto boundDirOrth2 = CuboidVolumeBounds::boundsFromAxisDirection(dirOrth2);
0864
0865 auto bounds = std::make_shared<CuboidVolumeBounds>(
0866 std::initializer_list<std::pair<CuboidVolumeBounds::BoundValues, double>>{
0867 {boundDir, 100}, {boundDirOrth1, 70}, {boundDirOrth2, 100}});
0868 Transform3 trf = Transform3::Identity();
0869 Volume vol{trf, bounds};
0870
0871 BOOST_TEST_CONTEXT("Positive") {
0872 std::vector<Volume*> volumes = {&vol};
0873 CuboidVolumeStack stack(volumes, dir, VolumeAttachmentStrategy::Gap,
0874 VolumeResizeStrategy::Gap, *logger);
0875
0876 BOOST_CHECK_EQUAL(volumes.size(), 1);
0877 BOOST_CHECK(stack.gaps().empty());
0878
0879 auto newBounds1 = std::make_shared<CuboidVolumeBounds>(
0880 std::initializer_list<
0881 std::pair<CuboidVolumeBounds::BoundValues, double>>{
0882 {boundDir, 200}, {boundDirOrth1, 70}, {boundDirOrth2, 100}});
0883 stack.update(newBounds1, trf * Translation3{Vector3::Unit(dirIdx) * 100},
0884 *logger);
0885 BOOST_CHECK_EQUAL(volumes.size(), 2);
0886 BOOST_CHECK_EQUAL(stack.gaps().size(), 1);
0887
0888 BOOST_CHECK_EQUAL(stack.gaps().front()->center()[dirIdx], 200.0);
0889 const auto* updatedBounds = dynamic_cast<const CuboidVolumeBounds*>(
0890 &stack.gaps().front()->volumeBounds());
0891 BOOST_REQUIRE_NE(updatedBounds, nullptr);
0892 BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 100.0, 1e-6);
0893
0894 auto newBounds2 = std::make_shared<CuboidVolumeBounds>(
0895 std::initializer_list<
0896 std::pair<CuboidVolumeBounds::BoundValues, double>>{
0897 {boundDir, 300}, {boundDirOrth1, 70}, {boundDirOrth2, 100}});
0898 stack.update(newBounds2, trf * Translation3{Vector3::Unit(dirIdx) * 200},
0899 *logger);
0900
0901 BOOST_CHECK_EQUAL(volumes.size(), 2);
0902
0903 BOOST_CHECK_EQUAL(stack.gaps().size(), 1);
0904
0905 BOOST_CHECK_EQUAL(stack.gaps().front()->center()[dirIdx], 300.0);
0906 updatedBounds = dynamic_cast<const CuboidVolumeBounds*>(
0907 &stack.gaps().front()->volumeBounds());
0908 BOOST_REQUIRE_NE(updatedBounds, nullptr);
0909 BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 200.0, 1e-6);
0910 }
0911
0912 BOOST_TEST_CONTEXT("Negative") {
0913 std::vector<Volume*> volumes = {&vol};
0914 CuboidVolumeStack stack(volumes, dir, VolumeAttachmentStrategy::Gap,
0915 VolumeResizeStrategy::Gap, *logger);
0916
0917 BOOST_CHECK_EQUAL(volumes.size(), 1);
0918 BOOST_CHECK(stack.gaps().empty());
0919
0920 auto newBounds1 = std::make_shared<CuboidVolumeBounds>(
0921 std::initializer_list<
0922 std::pair<CuboidVolumeBounds::BoundValues, double>>{
0923 {boundDir, 200}, {boundDirOrth1, 70}, {boundDirOrth2, 100}});
0924 stack.update(newBounds1, trf * Translation3{Vector3::Unit(dirIdx) * -100},
0925 *logger);
0926 BOOST_CHECK_EQUAL(volumes.size(), 2);
0927 BOOST_CHECK_EQUAL(stack.gaps().size(), 1);
0928
0929 BOOST_CHECK_EQUAL(stack.gaps().front()->center()[dirIdx], -200.0);
0930 const auto* updatedBounds = dynamic_cast<const CuboidVolumeBounds*>(
0931 &stack.gaps().front()->volumeBounds());
0932 BOOST_REQUIRE_NE(updatedBounds, nullptr);
0933 BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 100.0, 1e-6);
0934
0935 auto newBounds2 = std::make_shared<CuboidVolumeBounds>(
0936 std::initializer_list<
0937 std::pair<CuboidVolumeBounds::BoundValues, double>>{
0938 {boundDir, 300}, {boundDirOrth1, 70}, {boundDirOrth2, 100}});
0939 stack.update(newBounds2, trf * Translation3{Vector3::Unit(dirIdx) * -200},
0940 *logger);
0941
0942 BOOST_CHECK_EQUAL(volumes.size(), 2);
0943
0944 BOOST_CHECK_EQUAL(stack.gaps().size(), 1);
0945
0946 BOOST_CHECK_EQUAL(stack.gaps().front()->center()[dirIdx], -300.0);
0947 updatedBounds = dynamic_cast<const CuboidVolumeBounds*>(
0948 &stack.gaps().front()->volumeBounds());
0949 BOOST_REQUIRE_NE(updatedBounds, nullptr);
0950 BOOST_CHECK_CLOSE(updatedBounds->get(boundDir), 200.0, 1e-6);
0951 }
0952 }
0953
0954 BOOST_DATA_TEST_CASE(InvalidDirection, boost::unit_test::data::make(strategies),
0955 strategy) {
0956 std::vector<Volume*> volumes;
0957 auto vol1 = std::make_shared<Volume>(
0958 Transform3::Identity(),
0959 std::make_shared<CuboidVolumeBounds>(100_mm, 400_mm, 400_mm));
0960 volumes.push_back(vol1.get());
0961
0962
0963 BOOST_CHECK_THROW(CuboidVolumeStack(volumes, AxisDirection::AxisR, strategy),
0964 std::invalid_argument);
0965
0966 auto vol2 = std::make_shared<Volume>(
0967 Transform3::Identity(),
0968 std::make_shared<CuboidVolumeBounds>(100_mm, 400_mm, 400_mm));
0969 volumes.push_back(vol2.get());
0970
0971 BOOST_CHECK_THROW(CuboidVolumeStack(volumes, AxisDirection::AxisR, strategy),
0972 std::invalid_argument);
0973 }
0974
0975 BOOST_DATA_TEST_CASE(InvalidInput,
0976 (boost::unit_test::data::make(strategies) *
0977 boost::unit_test::data::make(Acts::AxisDirection::AxisX,
0978 Acts::AxisDirection::AxisY,
0979 Acts::AxisDirection::AxisZ)),
0980 strategy, direction) {
0981 BOOST_TEST_CONTEXT("Empty Volume") {
0982 std::vector<Volume*> volumes;
0983 BOOST_CHECK_THROW(CuboidVolumeStack(volumes, direction, strategy),
0984 std::invalid_argument);
0985 }
0986
0987 BOOST_TEST_CONTEXT("Volumes rotated relative to each other") {
0988
0989
0990 for (const Vector3 axis : {Vector3::UnitX(), Vector3::UnitY()}) {
0991 std::vector<Volume*> volumes;
0992 auto vol1 = std::make_shared<Volume>(
0993 Transform3{Translation3{Vector3{0_mm, 0_mm, -500_mm}}},
0994 std::make_shared<CuboidVolumeBounds>(100_mm, 400_mm, 400_mm));
0995 volumes.push_back(vol1.get());
0996
0997 BOOST_TEST_MESSAGE("Axis: " << axis);
0998 auto vol2 = std::make_shared<Volume>(
0999 Transform3{Translation3{Vector3{0_mm, 0_mm, 500_mm}} *
1000 AngleAxis3(1_degree, axis)},
1001 std::make_shared<CuboidVolumeBounds>(100_mm, 400_mm, 400_mm));
1002 volumes.push_back(vol2.get());
1003
1004 BOOST_CHECK_THROW(CuboidVolumeStack(volumes, direction, strategy,
1005 VolumeResizeStrategy::Gap, *logger),
1006 std::invalid_argument);
1007 }
1008 }
1009
1010 BOOST_TEST_CONTEXT(
1011 "Volumes shifted in the orthogonal plane relative to each other") {
1012 for (const Vector3& shift :
1013 {Vector3{5_mm, 0, 0}, Vector3{0, -5_mm, 0}, Vector3{2_mm, -2_mm, 0}}) {
1014 std::vector<Volume*> volumes;
1015 auto vol1 = std::make_shared<Volume>(
1016 Transform3{Translation3{Vector3{0_mm, 0_mm, -500_mm}}},
1017 std::make_shared<CuboidVolumeBounds>(100_mm, 400_mm, 400_mm));
1018 volumes.push_back(vol1.get());
1019
1020 auto vol2 = std::make_shared<Volume>(
1021 Transform3{Translation3{Vector3{0_mm, 0_mm, 500_mm} + shift}},
1022 std::make_shared<CuboidVolumeBounds>(100_mm, 400_mm, 400_mm));
1023 volumes.push_back(vol2.get());
1024
1025 BOOST_CHECK_THROW(CuboidVolumeStack(volumes, direction, strategy,
1026 VolumeResizeStrategy::Gap, *logger),
1027 std::invalid_argument);
1028 }
1029 }
1030 }
1031
1032 BOOST_DATA_TEST_CASE(JoinCuboidVolumeSingle,
1033 (boost::unit_test::data::make(Acts::AxisDirection::AxisX,
1034 Acts::AxisDirection::AxisY,
1035 Acts::AxisDirection::AxisZ) *
1036 boost::unit_test::data::make(strategies)),
1037 direction, strategy) {
1038 auto vol = std::make_shared<Volume>(
1039 Transform3::Identity() * Translation3{14_mm, 24_mm, 0_mm} *
1040 AngleAxis3(73_degree, Vector3::UnitX()),
1041 std::make_shared<CuboidVolumeBounds>(100_mm, 400_mm, 400_mm));
1042
1043 std::vector<Volume*> volumes{vol.get()};
1044
1045 CuboidVolumeStack stack(volumes, direction, strategy,
1046 VolumeResizeStrategy::Gap, *logger);
1047
1048
1049
1050 BOOST_CHECK_EQUAL(volumes.size(), 1);
1051 BOOST_CHECK_EQUAL(volumes.at(0), vol.get());
1052 BOOST_CHECK_EQUAL(vol->transform().matrix(), stack.transform().matrix());
1053 BOOST_CHECK_EQUAL(vol->volumeBounds(), stack.volumeBounds());
1054 }
1055
1056 BOOST_AUTO_TEST_SUITE_END()
1057 BOOST_AUTO_TEST_SUITE_END()
1058
1059 }