File indexing completed on 2026-07-20 07:53:20
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/tools/old/interface.hpp>
0010 #include <boost/test/tools/output_test_stream.hpp>
0011 #include <boost/test/unit_test.hpp>
0012
0013 #include "Acts/Definitions/Algebra.hpp"
0014 #include "Acts/Definitions/Alignment.hpp"
0015 #include "Acts/Definitions/Tolerance.hpp"
0016 #include "Acts/Definitions/TrackParametrization.hpp"
0017 #include "Acts/Definitions/Units.hpp"
0018 #include "Acts/Geometry/Extent.hpp"
0019 #include "Acts/Geometry/GeometryContext.hpp"
0020 #include "Acts/Geometry/Polyhedron.hpp"
0021 #include "Acts/Material/BinnedSurfaceMaterial.hpp"
0022 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
0023 #include "Acts/Material/Material.hpp"
0024 #include "Acts/Material/MaterialSlab.hpp"
0025 #include "Acts/Surfaces/PlaneSurface.hpp"
0026 #include "Acts/Surfaces/RectangleBounds.hpp"
0027 #include "Acts/Surfaces/Surface.hpp"
0028 #include "Acts/Surfaces/SurfaceBounds.hpp"
0029 #include "Acts/Surfaces/SurfaceMergingException.hpp"
0030 #include "Acts/Surfaces/TrapezoidBounds.hpp"
0031 #include "Acts/Utilities/AxisDefinitions.hpp"
0032 #include "Acts/Utilities/BinUtility.hpp"
0033 #include "Acts/Utilities/BinningType.hpp"
0034 #include "Acts/Utilities/Intersection.hpp"
0035 #include "Acts/Utilities/Result.hpp"
0036 #include "Acts/Utilities/ThrowAssert.hpp"
0037 #include "ActsTests/CommonHelpers/DetectorElementStub.hpp"
0038 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0039
0040 #include <cmath>
0041 #include <memory>
0042 #include <numbers>
0043 #include <string>
0044
0045 using namespace Acts;
0046 using namespace Acts::UnitLiterals;
0047
0048 namespace ActsTests {
0049
0050
0051 GeometryContext tgContext = GeometryContext::dangerouslyDefaultConstruct();
0052
0053 BOOST_AUTO_TEST_SUITE(SurfacesSuite)
0054
0055
0056 BOOST_AUTO_TEST_CASE(PlaneSurfaceConstruction) {
0057
0058
0059
0060
0061 auto rBounds = std::make_shared<const RectangleBounds>(3., 4.);
0062
0063 Translation3 translation{0., 1., 2.};
0064 auto pTransform = Transform3(translation);
0065
0066
0067 BOOST_CHECK_EQUAL(
0068 Surface::makeShared<PlaneSurface>(pTransform, rBounds)->type(),
0069 Surface::Plane);
0070
0071
0072 auto planeSurfaceObject =
0073 Surface::makeShared<PlaneSurface>(pTransform, rBounds);
0074 auto copiedPlaneSurface =
0075 Surface::makeShared<PlaneSurface>(*planeSurfaceObject);
0076 BOOST_CHECK_EQUAL(copiedPlaneSurface->type(), Surface::Plane);
0077 BOOST_CHECK(*copiedPlaneSurface == *planeSurfaceObject);
0078
0079
0080 auto copiedTransformedPlaneSurface = Surface::makeShared<PlaneSurface>(
0081 tgContext, *planeSurfaceObject, pTransform);
0082 BOOST_CHECK_EQUAL(copiedTransformedPlaneSurface->type(), Surface::Plane);
0083
0084
0085 DetectorElementStub detElem;
0086 BOOST_CHECK_THROW(
0087 auto nullBounds = Surface::makeShared<PlaneSurface>(nullptr, detElem),
0088 AssertionFailureException);
0089 }
0090
0091
0092 BOOST_AUTO_TEST_CASE(PlaneSurfaceProperties) {
0093
0094 auto rBounds = std::make_shared<const RectangleBounds>(3., 4.);
0095
0096
0097 Translation3 translation{0., 1., 2.};
0098 auto pTransform = Transform3(translation);
0099 auto planeSurfaceObject =
0100 Surface::makeShared<PlaneSurface>(pTransform, rBounds);
0101
0102 Translation3 translation2{0., 2., 4.};
0103 auto pTransform2 = Transform3(translation2);
0104 auto planeSurfaceObject2 =
0105 Surface::makeShared<PlaneSurface>(pTransform2, rBounds);
0106
0107
0108 BOOST_CHECK_EQUAL(planeSurfaceObject->type(), Surface::Plane);
0109
0110
0111 Vector3 referencePosition{0., 1., 2.};
0112 BOOST_CHECK_EQUAL(
0113 planeSurfaceObject->referencePosition(tgContext, AxisDirection::AxisX),
0114 referencePosition);
0115
0116
0117 Vector3 arbitraryGlobalPosition{2., 2., 2.};
0118 Vector3 momentum{1.e6, 1.e6, 1.e6};
0119 RotationMatrix3 expectedFrame;
0120 expectedFrame << 1., 0., 0., 0., 1., 0., 0., 0., 1.;
0121
0122 CHECK_CLOSE_OR_SMALL(planeSurfaceObject->referenceFrame(
0123 tgContext, arbitraryGlobalPosition, momentum),
0124 expectedFrame, 1e-6, 1e-9);
0125
0126
0127 Vector3 normal3D(0., 0., 1.);
0128 BOOST_CHECK_EQUAL(planeSurfaceObject->normal(tgContext), normal3D);
0129
0130
0131 BOOST_CHECK_EQUAL(planeSurfaceObject->bounds().type(),
0132 SurfaceBounds::eRectangle);
0133
0134
0135 Vector2 localPosition{1.5, 1.7};
0136 Vector3 globalPosition =
0137 planeSurfaceObject->localToGlobal(tgContext, localPosition, momentum);
0138
0139 Vector3 expectedPosition{1.5 + translation.x(), 1.7 + translation.y(),
0140 translation.z()};
0141
0142 CHECK_CLOSE_REL(globalPosition, expectedPosition, 1e-2);
0143
0144
0145 localPosition =
0146 planeSurfaceObject->globalToLocal(tgContext, globalPosition, momentum)
0147 .value();
0148 Vector2 expectedLocalPosition{1.5, 1.7};
0149
0150 CHECK_CLOSE_REL(localPosition, expectedLocalPosition, 1e-2);
0151
0152 Vector3 globalPositionOff =
0153 globalPosition +
0154 planeSurfaceObject->normal(tgContext, localPosition) * 0.1;
0155
0156 BOOST_CHECK(
0157 planeSurfaceObject->globalToLocal(tgContext, globalPositionOff, momentum)
0158 .error());
0159 BOOST_CHECK(planeSurfaceObject
0160 ->globalToLocal(tgContext, globalPositionOff, momentum, 0.05)
0161 .error());
0162 BOOST_CHECK(planeSurfaceObject
0163 ->globalToLocal(tgContext, globalPositionOff, momentum, 0.2)
0164 .ok());
0165
0166
0167 Vector3 offSurface{0, 1, -2.};
0168 BOOST_CHECK(planeSurfaceObject->isOnSurface(
0169 tgContext, globalPosition, momentum, BoundaryTolerance::None()));
0170 BOOST_CHECK(planeSurfaceObject->isOnSurface(tgContext, globalPosition,
0171 BoundaryTolerance::None()));
0172 BOOST_CHECK(!planeSurfaceObject->isOnSurface(tgContext, offSurface, momentum,
0173 BoundaryTolerance::None()));
0174 BOOST_CHECK(!planeSurfaceObject->isOnSurface(tgContext, offSurface,
0175 BoundaryTolerance::None()));
0176
0177
0178 Vector3 direction{0., 0., 1.};
0179 Intersection3D sfIntersection =
0180 planeSurfaceObject
0181 ->intersect(tgContext, offSurface, direction,
0182 BoundaryTolerance::None())
0183 .closest();
0184 Intersection3D expectedIntersect{Vector3{0, 1, 2}, 4.,
0185 IntersectionStatus::reachable};
0186 BOOST_CHECK(sfIntersection.isValid());
0187 BOOST_CHECK_EQUAL(sfIntersection.position(), expectedIntersect.position());
0188 BOOST_CHECK_EQUAL(sfIntersection.pathLength(),
0189 expectedIntersect.pathLength());
0190
0191
0192 CHECK_CLOSE_REL(planeSurfaceObject->pathCorrection(tgContext, offSurface,
0193 momentum.normalized()),
0194 std::numbers::sqrt3, 0.01);
0195
0196
0197 BOOST_CHECK_EQUAL(planeSurfaceObject->name(),
0198 std::string("Acts::PlaneSurface"));
0199
0200
0201 boost::test_tools::output_test_stream dumpOutput;
0202 dumpOutput << planeSurfaceObject->toStream(tgContext);
0203 BOOST_CHECK(dumpOutput.is_equal(
0204 "Acts::PlaneSurface\n"
0205 " Center position (x, y, z) = (0.0000, 1.0000, 2.0000)\n"
0206 " Rotation: colX = (1.000000, 0.000000, 0.000000)\n"
0207 " colY = (0.000000, 1.000000, 0.000000)\n"
0208 " colZ = (0.000000, 0.000000, 1.000000)\n"
0209 " Bounds : Acts::RectangleBounds: (hlX, hlY) = (3.0000000, "
0210 "4.0000000)\n"
0211 "(lower left, upper right):\n"
0212 "-3.0000000 -4.0000000\n"
0213 "3.0000000 4.0000000"));
0214 }
0215
0216 BOOST_AUTO_TEST_CASE(PlaneSurfaceEqualityOperators) {
0217
0218 auto rBounds = std::make_shared<const RectangleBounds>(3., 4.);
0219 Translation3 translation{0., 1., 2.};
0220 auto pTransform = Transform3(translation);
0221 auto planeSurfaceObject =
0222 Surface::makeShared<PlaneSurface>(pTransform, rBounds);
0223 auto planeSurfaceObject2 =
0224 Surface::makeShared<PlaneSurface>(pTransform, rBounds);
0225
0226
0227 BOOST_CHECK(*planeSurfaceObject == *planeSurfaceObject2);
0228
0229 BOOST_TEST_CHECKPOINT(
0230 "Create and then assign a PlaneSurface object to the existing one");
0231
0232
0233 auto assignedPlaneSurface =
0234 Surface::makeShared<PlaneSurface>(Transform3::Identity(), nullptr);
0235 *assignedPlaneSurface = *planeSurfaceObject;
0236
0237
0238 BOOST_CHECK(*assignedPlaneSurface == *planeSurfaceObject);
0239 }
0240
0241
0242 BOOST_AUTO_TEST_CASE(PlaneSurfaceExtent) {
0243
0244 static const Transform3 planeZX =
0245 AngleAxis3(-std::numbers::pi / 2., Vector3::UnitX()) *
0246 AngleAxis3(-std::numbers::pi / 2., Vector3::UnitZ()) *
0247 Transform3::Identity();
0248
0249 double rHx = 2.;
0250 double rHy = 4.;
0251 double yPs = 3.;
0252 auto rBounds = std::make_shared<RectangleBounds>(rHx, rHy);
0253
0254 auto plane = Surface::makeShared<PlaneSurface>(
0255 Transform3(Translation3(Vector3(0., yPs, 0.)) * planeZX), rBounds);
0256
0257 auto planeExtent = plane->polyhedronRepresentation(tgContext, 1).extent();
0258
0259 CHECK_CLOSE_ABS(planeExtent.min(AxisDirection::AxisZ), -rHx,
0260 s_onSurfaceTolerance);
0261 CHECK_CLOSE_ABS(planeExtent.max(AxisDirection::AxisZ), rHx,
0262 s_onSurfaceTolerance);
0263 CHECK_CLOSE_ABS(planeExtent.min(AxisDirection::AxisX), -rHy,
0264 s_onSurfaceTolerance);
0265 CHECK_CLOSE_ABS(planeExtent.max(AxisDirection::AxisX), rHy,
0266 s_onSurfaceTolerance);
0267 CHECK_CLOSE_ABS(planeExtent.min(AxisDirection::AxisY), yPs,
0268 s_onSurfaceTolerance);
0269 CHECK_CLOSE_ABS(planeExtent.max(AxisDirection::AxisY), yPs,
0270 s_onSurfaceTolerance);
0271 CHECK_CLOSE_ABS(planeExtent.min(AxisDirection::AxisR), yPs,
0272 s_onSurfaceTolerance);
0273 CHECK_CLOSE_ABS(planeExtent.max(AxisDirection::AxisR), std::hypot(yPs, rHy),
0274 s_onSurfaceTolerance);
0275
0276
0277 double alpha = 0.123;
0278 auto planeRot = Surface::makeShared<PlaneSurface>(
0279 Transform3(Translation3(Vector3(0., yPs, 0.)) *
0280 AngleAxis3(alpha, Vector3(0., 0., 1.)) * planeZX),
0281 rBounds);
0282
0283 auto planeExtentRot =
0284 planeRot->polyhedronRepresentation(tgContext, 1).extent();
0285 CHECK_CLOSE_ABS(planeExtentRot.min(AxisDirection::AxisZ), -rHx,
0286 s_onSurfaceTolerance);
0287 CHECK_CLOSE_ABS(planeExtentRot.max(AxisDirection::AxisZ), rHx,
0288 s_onSurfaceTolerance);
0289 CHECK_CLOSE_ABS(planeExtentRot.min(AxisDirection::AxisX),
0290 -rHy * std::cos(alpha), s_onSurfaceTolerance);
0291 CHECK_CLOSE_ABS(planeExtentRot.max(AxisDirection::AxisX),
0292 rHy * std::cos(alpha), s_onSurfaceTolerance);
0293 CHECK_CLOSE_ABS(planeExtentRot.min(AxisDirection::AxisY),
0294 yPs - rHy * std::sin(alpha), s_onSurfaceTolerance);
0295 CHECK_CLOSE_ABS(planeExtentRot.max(AxisDirection::AxisY),
0296 yPs + rHy * std::sin(alpha), s_onSurfaceTolerance);
0297 CHECK_CLOSE_ABS(planeExtentRot.min(AxisDirection::AxisR),
0298 yPs * std::cos(alpha), s_onSurfaceTolerance);
0299 }
0300
0301 BOOST_AUTO_TEST_CASE(RotatedTrapezoid) {
0302 const double shortHalfX = 100.;
0303 const double longHalfX = 200.;
0304 const double halfY = 300.;
0305 const double rotAngle = 45._degree;
0306
0307 Vector2 edgePoint{longHalfX - 10., halfY};
0308
0309 std::shared_ptr<TrapezoidBounds> bounds =
0310 std::make_shared<TrapezoidBounds>(shortHalfX, longHalfX, halfY);
0311
0312 BOOST_CHECK(bounds->inside(edgePoint, BoundaryTolerance::None()));
0313 BOOST_CHECK(!bounds->inside(Eigen::Rotation2D(-rotAngle) * edgePoint,
0314 BoundaryTolerance::None()));
0315
0316 std::shared_ptr<TrapezoidBounds> rotatedBounds =
0317 std::make_shared<TrapezoidBounds>(shortHalfX, longHalfX, halfY, rotAngle);
0318
0319 BOOST_CHECK(!rotatedBounds->inside(edgePoint, BoundaryTolerance::None()));
0320 BOOST_CHECK(rotatedBounds->inside(Eigen::Rotation2D(-rotAngle) * edgePoint,
0321 BoundaryTolerance::None()));
0322 }
0323
0324
0325 BOOST_AUTO_TEST_CASE(PlaneSurfaceAlignment) {
0326
0327 auto rBounds = std::make_shared<const RectangleBounds>(3., 4.);
0328
0329 Translation3 translation{0., 1., 2.};
0330 const double rotationAngle = std::numbers::pi / 2.;
0331 AngleAxis3 rotation(rotationAngle, Vector3::UnitY());
0332 RotationMatrix3 rotationMat = rotation.toRotationMatrix();
0333
0334 auto pTransform = Transform3{translation * rotationMat};
0335 auto planeSurfaceObject =
0336 Surface::makeShared<PlaneSurface>(pTransform, rBounds);
0337
0338
0339 const Vector3 localZAxis = rotationMat.col(2);
0340
0341 CHECK_CLOSE_ABS(localZAxis, Vector3(1., 0., 0.), 1e-15);
0342
0343
0344 Vector2 localPosition{1, 2};
0345 Vector3 momentum{1, 0, 0};
0346 Vector3 direction = momentum.normalized();
0347
0348 Vector3 globalPosition =
0349 planeSurfaceObject->localToGlobal(tgContext, localPosition, momentum);
0350
0351
0352 const AlignmentToPathMatrix& alignToPath =
0353 planeSurfaceObject->alignmentToPathDerivative(tgContext, globalPosition,
0354 direction);
0355
0356 AlignmentToPathMatrix expAlignToPath = AlignmentToPathMatrix::Zero();
0357 expAlignToPath << 1, 0, 0, 2, -1, 0;
0358
0359
0360 CHECK_CLOSE_ABS(alignToPath, expAlignToPath, 1e-10);
0361
0362
0363
0364 const auto& loc3DToLocBound =
0365 planeSurfaceObject->localCartesianToBoundLocalDerivative(tgContext,
0366 globalPosition);
0367
0368 CHECK_CLOSE_ABS(loc3DToLocBound, (Matrix<2, 3>::Identity()), 1e-10);
0369
0370
0371
0372 FreeVector derivatives = FreeVector::Zero();
0373 derivatives.head<3>() = direction;
0374 const AlignmentToBoundMatrix& alignToBound =
0375 planeSurfaceObject->alignmentToBoundDerivative(tgContext, globalPosition,
0376 direction, derivatives);
0377 const AlignmentToPathMatrix alignToloc0 =
0378 alignToBound.block<1, 6>(eBoundLoc0, eAlignmentCenter0);
0379 const AlignmentToPathMatrix alignToloc1 =
0380 alignToBound.block<1, 6>(eBoundLoc1, eAlignmentCenter0);
0381
0382 AlignmentToPathMatrix expAlignToloc0;
0383 expAlignToloc0 << 0, 0, 1, 0, 0, 2;
0384 AlignmentToPathMatrix expAlignToloc1;
0385 expAlignToloc1 << 0, -1, 0, 0, 0, -1;
0386
0387 CHECK_CLOSE_ABS(alignToloc0, expAlignToloc0, 1e-10);
0388 CHECK_CLOSE_ABS(alignToloc1, expAlignToloc1, 1e-10);
0389 }
0390
0391 BOOST_AUTO_TEST_SUITE(PlaneSurfaceMerging)
0392
0393 auto logger = Acts::getDefaultLogger("UnitTests", Acts::Logging::VERBOSE);
0394
0395
0396 GeometryContext gctx = GeometryContext::dangerouslyDefaultConstruct();
0397
0398 auto rBounds = std::make_shared<const RectangleBounds>(1., 2.);
0399
0400 BOOST_AUTO_TEST_CASE(SurfaceOverlap) {
0401
0402 Translation3 offsetX{4., 0., 0.};
0403 Translation3 offsetY{0., 2., 0.};
0404
0405 Transform3 base(Translation3::Identity());
0406 Transform3 otherX = base * offsetX;
0407 Transform3 otherY = base * offsetY;
0408
0409 auto plane = Surface::makeShared<PlaneSurface>(base, rBounds);
0410 auto planeX = Surface::makeShared<PlaneSurface>(otherX, rBounds);
0411 auto planeY = Surface::makeShared<PlaneSurface>(otherY, rBounds);
0412
0413 BOOST_CHECK_THROW(plane->mergedWith(*planeX, Acts::AxisDirection::AxisX),
0414 SurfaceMergingException);
0415 BOOST_CHECK_THROW(plane->mergedWith(*planeY, Acts::AxisDirection::AxisY),
0416 SurfaceMergingException);
0417
0418 BOOST_CHECK_THROW(planeX->mergedWith(*plane, Acts::AxisDirection::AxisX),
0419 SurfaceMergingException);
0420 BOOST_CHECK_THROW(planeY->mergedWith(*plane, Acts::AxisDirection::AxisY),
0421 SurfaceMergingException);
0422 }
0423
0424 BOOST_AUTO_TEST_CASE(SurfaceMisalignmentShift) {
0425
0426 Translation3 offsetX{2., 1., 0.};
0427 Translation3 offsetY{-1., 4., 0.};
0428 Translation3 offsetZ{0., 4., 1.};
0429
0430 Transform3 base(Translation3::Identity());
0431 Transform3 otherX = base * offsetX;
0432 Transform3 otherY = base * offsetY;
0433 Transform3 otherZ = base * offsetZ;
0434
0435 auto plane = Surface::makeShared<PlaneSurface>(base, rBounds);
0436 auto planeX = Surface::makeShared<PlaneSurface>(otherX, rBounds);
0437 auto planeY = Surface::makeShared<PlaneSurface>(otherY, rBounds);
0438 auto planeZ = Surface::makeShared<PlaneSurface>(otherZ, rBounds);
0439
0440 BOOST_CHECK_THROW(plane->mergedWith(*planeX, Acts::AxisDirection::AxisX),
0441 SurfaceMergingException);
0442 BOOST_CHECK_THROW(plane->mergedWith(*planeY, Acts::AxisDirection::AxisY),
0443 SurfaceMergingException);
0444 BOOST_CHECK_THROW(plane->mergedWith(*planeZ, Acts::AxisDirection::AxisX),
0445 SurfaceMergingException);
0446
0447 BOOST_CHECK_THROW(planeX->mergedWith(*plane, Acts::AxisDirection::AxisX),
0448 SurfaceMergingException);
0449 BOOST_CHECK_THROW(planeY->mergedWith(*plane, Acts::AxisDirection::AxisY),
0450 SurfaceMergingException);
0451 BOOST_CHECK_THROW(planeZ->mergedWith(*plane, Acts::AxisDirection::AxisX),
0452 SurfaceMergingException);
0453 }
0454
0455 BOOST_AUTO_TEST_CASE(SurfaceMisalignedAngle) {
0456
0457 Translation3 offsetX{2., 0., 0.};
0458 Translation3 offsetY{0., 4., 0.};
0459
0460 double angle = std::numbers::pi / 12;
0461 Transform3 base(Translation3::Identity());
0462 Transform3 otherX = base * offsetX * AngleAxis3(angle, Vector3::UnitZ());
0463 Transform3 otherY = base * offsetY * AngleAxis3(angle, Vector3::UnitY());
0464 Transform3 otherZ = base * offsetY * AngleAxis3(angle, Vector3::UnitZ());
0465
0466 auto plane = Surface::makeShared<PlaneSurface>(base, rBounds);
0467 auto planeX = Surface::makeShared<PlaneSurface>(otherX, rBounds);
0468 auto planeY = Surface::makeShared<PlaneSurface>(otherY, rBounds);
0469 auto planeZ = Surface::makeShared<PlaneSurface>(otherZ, rBounds);
0470
0471 BOOST_CHECK_THROW(plane->mergedWith(*planeX, Acts::AxisDirection::AxisX),
0472 SurfaceMergingException);
0473 BOOST_CHECK_THROW(plane->mergedWith(*planeY, Acts::AxisDirection::AxisY),
0474 SurfaceMergingException);
0475 BOOST_CHECK_THROW(plane->mergedWith(*planeZ, Acts::AxisDirection::AxisY),
0476 SurfaceMergingException);
0477
0478 BOOST_CHECK_THROW(planeX->mergedWith(*plane, Acts::AxisDirection::AxisX),
0479 SurfaceMergingException);
0480 BOOST_CHECK_THROW(planeY->mergedWith(*plane, Acts::AxisDirection::AxisY),
0481 SurfaceMergingException);
0482 BOOST_CHECK_THROW(planeZ->mergedWith(*plane, Acts::AxisDirection::AxisY),
0483 SurfaceMergingException);
0484 }
0485
0486 BOOST_AUTO_TEST_CASE(SurfaceDifferentBounds) {
0487
0488
0489 Translation3 offset{2., 0., 0.};
0490
0491 Transform3 base(Translation3::Identity());
0492 Transform3 other = base * offset;
0493
0494 auto plane = Surface::makeShared<PlaneSurface>(base, rBounds);
0495
0496 auto rBoundsOther = std::make_shared<const RectangleBounds>(2., 4.);
0497 auto planeOther = Surface::makeShared<PlaneSurface>(other, rBoundsOther);
0498
0499 BOOST_CHECK_THROW(plane->mergedWith(*planeOther, Acts::AxisDirection::AxisX),
0500 SurfaceMergingException);
0501 }
0502
0503 BOOST_AUTO_TEST_CASE(XYDirection) {
0504 double angle = std::numbers::pi / 12;
0505 Translation3 offsetX{2., 0., 0.};
0506 Translation3 offsetY{0., 4., 0.};
0507
0508 Transform3 base =
0509 AngleAxis3(angle, Vector3::UnitX()) * Translation3::Identity();
0510 Transform3 otherX = base * offsetX;
0511 Transform3 otherY = base * offsetY;
0512
0513 auto plane = Surface::makeShared<PlaneSurface>(base, rBounds);
0514 auto planeX = Surface::makeShared<PlaneSurface>(otherX, rBounds);
0515 auto planeY = Surface::makeShared<PlaneSurface>(otherY, rBounds);
0516
0517 BOOST_CHECK_THROW(plane->mergedWith(*planeX, Acts::AxisDirection::AxisZ),
0518 SurfaceMergingException);
0519
0520 auto expectedBoundsX = std::make_shared<const RectangleBounds>(2, 2);
0521 auto [planeXMerged, reversedX] =
0522 plane->mergedWith(*planeX, Acts::AxisDirection::AxisX, *logger);
0523 BOOST_REQUIRE_NE(planeXMerged, nullptr);
0524 BOOST_CHECK(!reversedX);
0525 BOOST_CHECK_EQUAL(planeXMerged->bounds(), *expectedBoundsX);
0526 BOOST_CHECK_EQUAL(planeXMerged->center(gctx), base * Vector3::UnitX() * 1);
0527
0528 auto expectedBoundsY = std::make_shared<const RectangleBounds>(1, 4);
0529 auto [planeYMerged, reversedY] =
0530 plane->mergedWith(*planeY, Acts::AxisDirection::AxisY, *logger);
0531 BOOST_REQUIRE_NE(planeYMerged, nullptr);
0532 BOOST_CHECK(!reversedY);
0533 BOOST_CHECK_EQUAL(planeYMerged->bounds(), *expectedBoundsY);
0534 BOOST_CHECK_EQUAL(planeYMerged->center(gctx), base * Vector3::UnitY() * 2);
0535
0536 auto [planeXMerged2, reversedX2] =
0537 planeX->mergedWith(*plane, Acts::AxisDirection::AxisX, *logger);
0538 BOOST_REQUIRE_NE(planeXMerged2, nullptr);
0539 BOOST_CHECK(planeXMerged->bounds() == planeXMerged2->bounds());
0540 BOOST_CHECK(reversedX2);
0541 BOOST_CHECK_EQUAL(planeXMerged2->bounds(), *expectedBoundsX);
0542 BOOST_CHECK_EQUAL(planeXMerged2->center(gctx), base * Vector3::UnitX() * 1);
0543
0544 auto [planeYMerged2, reversedY2] =
0545 planeY->mergedWith(*plane, Acts::AxisDirection::AxisY, *logger);
0546 BOOST_REQUIRE_NE(planeYMerged2, nullptr);
0547 BOOST_CHECK(planeYMerged->bounds() == planeYMerged2->bounds());
0548 BOOST_CHECK(reversedY2);
0549 BOOST_CHECK_EQUAL(planeYMerged2->bounds(), *expectedBoundsY);
0550 BOOST_CHECK_EQUAL(planeYMerged2->center(gctx), base * Vector3::UnitY() * 2);
0551 }
0552
0553 BOOST_AUTO_TEST_SUITE_END()
0554
0555 BOOST_AUTO_TEST_CASE(PlaneSurfaceMaterialAssignment) {
0556 auto rBounds = std::make_shared<RectangleBounds>(100., 100.);
0557 auto surface =
0558 Surface::makeShared<PlaneSurface>(Transform3::Identity(), rBounds);
0559 MaterialSlab slab(Material::fromMolarDensity(1., 2., 3., 4., 5.), 0.1);
0560
0561
0562 auto homMat = std::make_shared<HomogeneousSurfaceMaterial>(slab);
0563 BOOST_CHECK_NO_THROW(surface->assignSurfaceMaterial(homMat));
0564 BOOST_CHECK_NE(surface->surfaceMaterial(), nullptr);
0565
0566
0567 BOOST_CHECK_NO_THROW(surface->assignSurfaceMaterial(nullptr));
0568 BOOST_CHECK_EQUAL(surface->surfaceMaterial(), nullptr);
0569
0570
0571 BinUtility buX(10, -100.f, 100.f, Acts::open, AxisDirection::AxisX);
0572 auto matX = std::make_shared<BinnedSurfaceMaterial>(
0573 buX, MaterialSlabVector(10, slab));
0574 BOOST_CHECK_NO_THROW(surface->assignSurfaceMaterial(matX));
0575
0576
0577 BinUtility buY(10, -100.f, 100.f, Acts::open, AxisDirection::AxisY);
0578 auto matY = std::make_shared<BinnedSurfaceMaterial>(
0579 buY, MaterialSlabVector(10, slab));
0580 BOOST_CHECK_NO_THROW(surface->assignSurfaceMaterial(matY));
0581
0582
0583 BinUtility bu2D(5, -100.f, 100.f, Acts::open, AxisDirection::AxisX);
0584 bu2D += BinUtility(3, -100.f, 100.f, Acts::open, AxisDirection::AxisY);
0585 auto mat2D = std::make_shared<BinnedSurfaceMaterial>(
0586 bu2D, MaterialSlabMatrix(3, MaterialSlabVector(5, slab)));
0587 BOOST_CHECK_NO_THROW(surface->assignSurfaceMaterial(mat2D));
0588
0589
0590 for (auto badDir : {AxisDirection::AxisRPhi, AxisDirection::AxisZ,
0591 AxisDirection::AxisR, AxisDirection::AxisPhi}) {
0592 BinUtility buBad(10, 0.f, 10.f, Acts::open, badDir);
0593 auto matBad = std::make_shared<BinnedSurfaceMaterial>(
0594 buBad, MaterialSlabVector(10, slab));
0595 BOOST_CHECK_THROW(surface->assignSurfaceMaterial(matBad),
0596 std::invalid_argument);
0597 }
0598 }
0599
0600 BOOST_AUTO_TEST_SUITE_END()
0601
0602 }