File indexing completed on 2026-07-31 08:18:27
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Units.hpp"
0013 #include "Acts/Geometry/Blueprint.hpp"
0014 #include "Acts/Geometry/ContainerBlueprintNode.hpp"
0015 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0016 #include "Acts/Geometry/GeometryContext.hpp"
0017 #include "Acts/Geometry/Portal.hpp"
0018 #include "Acts/Geometry/TrackingGeometry.hpp"
0019 #include "Acts/Geometry/TrackingVolume.hpp"
0020 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0021 #include "Acts/Surfaces/Surface.hpp"
0022 #include "Acts/Surfaces/SurfaceError.hpp"
0023 #include "Acts/Utilities/AxisDefinitions.hpp"
0024 #include "Acts/Utilities/Logger.hpp"
0025 #include "ActsTests/CommonHelpers/CubicTrackingGeometry.hpp"
0026
0027 #include <memory>
0028 #include <optional>
0029
0030 using namespace Acts;
0031 using namespace Acts::UnitLiterals;
0032
0033 namespace ActsTests {
0034
0035 namespace {
0036
0037 auto logger = getDefaultLogger("UnitTests", Logging::INFO);
0038 auto gctx = GeometryContext::dangerouslyDefaultConstruct();
0039
0040 const TrackingVolume* findVolumeByName(const TrackingGeometry& trackingGeometry,
0041 const std::string& name) {
0042 const TrackingVolume* result = nullptr;
0043 trackingGeometry.apply([&](const TrackingVolume& volume) {
0044 if (volume.volumeName() == name) {
0045 result = &volume;
0046 }
0047 });
0048 return result;
0049 }
0050
0051 }
0052
0053 BOOST_AUTO_TEST_SUITE(GeometrySuite)
0054
0055
0056
0057
0058 BOOST_AUTO_TEST_CASE(BoundaryVolumeResolutionGen3) {
0059 Blueprint::Config cfg;
0060 cfg.envelope[AxisDirection::AxisX] = {20_mm, 20_mm};
0061 cfg.envelope[AxisDirection::AxisY] = {20_mm, 20_mm};
0062 cfg.envelope[AxisDirection::AxisZ] = {20_mm, 20_mm};
0063 Blueprint root{cfg};
0064
0065 root.addCuboidContainer("Stack", AxisDirection::AxisX, [&](auto& stack) {
0066 stack.addStaticVolume(
0067 Transform3{Translation3{Vector3{-100_mm, 0, 0}}},
0068 std::make_shared<CuboidVolumeBounds>(100_mm, 100_mm, 100_mm),
0069 "VolumeA");
0070 stack.addStaticVolume(
0071 Transform3{Translation3{Vector3{100_mm, 0, 0}}},
0072 std::make_shared<CuboidVolumeBounds>(100_mm, 100_mm, 100_mm),
0073 "VolumeB");
0074 });
0075
0076 std::unique_ptr<TrackingGeometry> trackingGeometry =
0077 root.construct({}, gctx, *logger);
0078 BOOST_REQUIRE(trackingGeometry != nullptr);
0079 BOOST_CHECK(trackingGeometry->geometryVersion() ==
0080 TrackingGeometry::GeometryVersion::Gen3);
0081
0082 const TrackingVolume* volumeA =
0083 findVolumeByName(*trackingGeometry, "VolumeA");
0084 const TrackingVolume* volumeB =
0085 findVolumeByName(*trackingGeometry, "VolumeB");
0086 BOOST_REQUIRE(volumeA != nullptr);
0087 BOOST_REQUIRE(volumeB != nullptr);
0088
0089
0090 const Vector3 onBoundary{0, 0, 0};
0091
0092
0093
0094
0095 const Portal* sharedPortal = nullptr;
0096 for (const Portal& pa : volumeA->portals()) {
0097 for (const Portal& pb : volumeB->portals()) {
0098 if (&pa == &pb &&
0099 pa.surface().isOnSurface(gctx, onBoundary, Vector3::UnitX(),
0100 BoundaryTolerance::None())) {
0101 sharedPortal = &pa;
0102 }
0103 }
0104 }
0105 BOOST_REQUIRE(sharedPortal != nullptr);
0106
0107 const Surface& portalSurface = sharedPortal->surface();
0108
0109
0110 auto forward = trackingGeometry->resolveLowestTrackingVolume(
0111 gctx, onBoundary, Vector3::UnitX(), &portalSurface);
0112 BOOST_REQUIRE(forward.ok());
0113 BOOST_CHECK_EQUAL(*forward, volumeB);
0114
0115 auto backward = trackingGeometry->resolveLowestTrackingVolume(
0116 gctx, onBoundary, -Vector3::UnitX(), &portalSurface);
0117 BOOST_REQUIRE(backward.ok());
0118 BOOST_CHECK_EQUAL(*backward, volumeA);
0119
0120
0121
0122 auto plain = trackingGeometry->resolveLowestTrackingVolume(gctx, onBoundary);
0123 BOOST_REQUIRE(plain.ok());
0124 BOOST_CHECK(*plain == volumeA || *plain == volumeB);
0125 }
0126
0127
0128 BOOST_AUTO_TEST_CASE(BoundaryVolumeResolutionGen1) {
0129 CubicTrackingGeometry geometryBuilder{gctx};
0130 std::shared_ptr<const TrackingGeometry> trackingGeometry = geometryBuilder();
0131 BOOST_REQUIRE(trackingGeometry != nullptr);
0132 BOOST_CHECK(trackingGeometry->geometryVersion() ==
0133 TrackingGeometry::GeometryVersion::Gen1);
0134
0135 const TrackingVolume* volume1 =
0136 trackingGeometry->resolveLowestTrackingVolume(gctx, Vector3{-1.5_m, 0, 0})
0137 .value();
0138 const TrackingVolume* volume2 =
0139 trackingGeometry->resolveLowestTrackingVolume(gctx, Vector3{1.5_m, 0, 0})
0140 .value();
0141 BOOST_REQUIRE(volume1 != nullptr);
0142 BOOST_REQUIRE(volume2 != nullptr);
0143 BOOST_CHECK_EQUAL(volume1->volumeName(), "Volume 1");
0144 BOOST_CHECK_EQUAL(volume2->volumeName(), "Volume 2");
0145
0146
0147 const Vector3 onBoundary{0, 0, 0};
0148 auto findBoundarySurface = [&](const TrackingVolume& volume,
0149 const Vector3& position) -> const Surface* {
0150 for (const auto& boundary : volume.boundarySurfaces()) {
0151 const Surface& surface = boundary->surfaceRepresentation();
0152 if (surface.isOnSurface(gctx, position, Vector3::UnitX(),
0153 BoundaryTolerance::None())) {
0154 return &surface;
0155 }
0156 }
0157 return nullptr;
0158 };
0159
0160 const Surface* boundarySurface = findBoundarySurface(*volume1, onBoundary);
0161 BOOST_REQUIRE(boundarySurface != nullptr);
0162
0163
0164 auto forward = trackingGeometry->resolveLowestTrackingVolume(
0165 gctx, onBoundary, Vector3::UnitX(), boundarySurface);
0166 BOOST_REQUIRE(forward.ok());
0167 BOOST_CHECK_EQUAL(*forward, volume2);
0168
0169 auto backward = trackingGeometry->resolveLowestTrackingVolume(
0170 gctx, onBoundary, -Vector3::UnitX(), boundarySurface);
0171 BOOST_REQUIRE(backward.ok());
0172 BOOST_CHECK_EQUAL(*backward, volume1);
0173
0174
0175
0176 const Vector3 onOuterBoundary{-3_m, 0, 0};
0177 const Surface* outerSurface = findBoundarySurface(*volume1, onOuterBoundary);
0178 BOOST_REQUIRE(outerSurface != nullptr);
0179
0180 auto outward = trackingGeometry->resolveLowestTrackingVolume(
0181 gctx, onOuterBoundary, -Vector3::UnitX(), outerSurface);
0182 BOOST_REQUIRE(outward.ok());
0183 BOOST_CHECK_EQUAL(*outward, nullptr);
0184
0185
0186 auto inward = trackingGeometry->resolveLowestTrackingVolume(
0187 gctx, onOuterBoundary, Vector3::UnitX(), outerSurface);
0188 BOOST_REQUIRE(inward.ok());
0189 BOOST_CHECK_EQUAL(*inward, volume1);
0190
0191
0192
0193 const Vector3 nearBoundary{0.01_mm, 0, 0};
0194 auto nearResult = trackingGeometry->resolveLowestTrackingVolume(
0195 gctx, nearBoundary, -Vector3::UnitX(), boundarySurface, 0.1_mm);
0196 BOOST_REQUIRE(nearResult.ok());
0197 BOOST_CHECK_EQUAL(*nearResult, volume1);
0198 }
0199
0200
0201
0202 BOOST_AUTO_TEST_CASE(BoundaryVolumeResolutionOffBounds) {
0203 CubicTrackingGeometry geometryBuilder{gctx};
0204 std::shared_ptr<const TrackingGeometry> trackingGeometry = geometryBuilder();
0205 BOOST_REQUIRE(trackingGeometry != nullptr);
0206
0207 const TrackingVolume* volume1 =
0208 trackingGeometry->resolveLowestTrackingVolume(gctx, Vector3{-1.5_m, 0, 0})
0209 .value();
0210 BOOST_REQUIRE(volume1 != nullptr);
0211
0212
0213
0214 const Surface* boundarySurface = nullptr;
0215 for (const auto& boundary : volume1->boundarySurfaces()) {
0216 const Surface& surface = boundary->surfaceRepresentation();
0217 if (surface.isOnSurface(gctx, Vector3::Zero(), Vector3::UnitX(),
0218 BoundaryTolerance::None())) {
0219 boundarySurface = &surface;
0220 }
0221 }
0222 BOOST_REQUIRE(boundarySurface != nullptr);
0223
0224
0225
0226 const Vector3 offBounds{0, 0.5_m + 0.5_mm, 0};
0227 const double tolerance = 1_mm;
0228 BOOST_REQUIRE(trackingGeometry
0229 ->resolveLowestTrackingVolume(gctx, offBounds, std::nullopt,
0230 nullptr, tolerance)
0231 .value() != nullptr);
0232 BOOST_REQUIRE(!boundarySurface->isOnSurface(
0233 gctx, offBounds, Vector3::UnitX(), BoundaryTolerance::None(), tolerance));
0234
0235 auto result = trackingGeometry->resolveLowestTrackingVolume(
0236 gctx, offBounds, Vector3::UnitX(), boundarySurface, tolerance);
0237 BOOST_CHECK(!result.ok());
0238 BOOST_CHECK(result.error() == SurfaceError::GlobalPositionNotOnSurface);
0239 }
0240
0241 BOOST_AUTO_TEST_SUITE_END()
0242
0243 }