File indexing completed on 2025-08-06 08:11:28
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/data/test_case.hpp>
0010 #include <boost/test/tools/old/interface.hpp>
0011 #include <boost/test/tools/output_test_stream.hpp>
0012 #include <boost/test/unit_test.hpp>
0013
0014 #include "Acts/Definitions/Algebra.hpp"
0015 #include "Acts/Definitions/Alignment.hpp"
0016 #include "Acts/Definitions/TrackParametrization.hpp"
0017 #include "Acts/EventData/ParticleHypothesis.hpp"
0018 #include "Acts/EventData/TrackParameters.hpp"
0019 #include "Acts/Geometry/GeometryContext.hpp"
0020 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
0021 #include "Acts/Propagator/Propagator.hpp"
0022 #include "Acts/Propagator/StraightLineStepper.hpp"
0023 #include "Acts/Surfaces/BoundaryCheck.hpp"
0024 #include "Acts/Surfaces/LineBounds.hpp"
0025 #include "Acts/Surfaces/Surface.hpp"
0026 #include "Acts/Surfaces/SurfaceBounds.hpp"
0027 #include "Acts/Tests/CommonHelpers/DetectorElementStub.hpp"
0028 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0029 #include "Acts/Tests/CommonHelpers/LineSurfaceStub.hpp"
0030 #include "Acts/Tests/CommonHelpers/PredefinedMaterials.hpp"
0031 #include "Acts/Utilities/BinningType.hpp"
0032 #include "Acts/Utilities/Intersection.hpp"
0033 #include "Acts/Utilities/Result.hpp"
0034 #include "Acts/Utilities/UnitVectors.hpp"
0035 #include "Acts/Utilities/VectorHelpers.hpp"
0036
0037 #include <algorithm>
0038 #include <cmath>
0039 #include <memory>
0040 #include <optional>
0041 #include <ostream>
0042 #include <stdexcept>
0043 #include <string>
0044 #include <tuple>
0045 #include <vector>
0046
0047 namespace Acts {
0048 class AssertionFailureException;
0049
0050 namespace Test {
0051
0052
0053 GeometryContext tgContext = GeometryContext();
0054
0055 BOOST_AUTO_TEST_SUITE(Surfaces)
0056
0057
0058 BOOST_AUTO_TEST_CASE(LineSurface_Constructors_test) {
0059
0060
0061
0062 Translation3 translation{0., 1., 2.};
0063 Transform3 transform(translation);
0064 auto pTransform = Transform3(translation);
0065 const double radius{2.0}, halfz{20.};
0066 BOOST_CHECK(LineSurfaceStub(pTransform, radius, halfz).constructedOk());
0067
0068 BOOST_CHECK(LineSurfaceStub(pTransform).constructedOk());
0069
0070 auto pLineBounds = std::make_shared<const LineBounds>(2., 10.0);
0071 BOOST_CHECK(LineSurfaceStub(pTransform, pLineBounds).constructedOk());
0072
0073 auto pMaterial =
0074 std::make_shared<const HomogeneousSurfaceMaterial>(makePercentSlab());
0075 DetectorElementStub detElement{pTransform, pLineBounds, 0.2, pMaterial};
0076 BOOST_CHECK(LineSurfaceStub(pLineBounds, detElement).constructedOk());
0077 LineSurfaceStub lineToCopy(pTransform, 2.0, 20.);
0078
0079 BOOST_CHECK(LineSurfaceStub(lineToCopy).constructedOk());
0080
0081 BOOST_CHECK(
0082 LineSurfaceStub(tgContext, lineToCopy, transform).constructedOk());
0083
0084
0085 DetectorElementStub detElem;
0086 BOOST_CHECK_THROW(LineSurfaceStub nullBounds(nullptr, detElem),
0087 AssertionFailureException);
0088
0089 BOOST_TEST_MESSAGE(
0090 "All LineSurface constructors are callable without problem");
0091 }
0092
0093
0094 BOOST_AUTO_TEST_CASE(LineSurface_allNamedMethods_test) {
0095
0096 Translation3 translation{0., 1., 2.};
0097 Transform3 transform(translation);
0098 LineSurfaceStub line(transform, 2.0, 20.);
0099 Vector3 referencePosition{0., 1., 2.};
0100 CHECK_CLOSE_ABS(referencePosition, line.binningPosition(tgContext, binX),
0101 1e-6);
0102
0103
0104 auto pLineBounds = std::make_shared<const LineBounds>(2., 10.0);
0105 LineSurfaceStub boundedLine(transform, pLineBounds);
0106 const LineBounds& bounds =
0107 dynamic_cast<const LineBounds&>(boundedLine.bounds());
0108 BOOST_CHECK_EQUAL(bounds, LineBounds(2., 10.0));
0109
0110
0111 Vector3 gpos{0., 1., 0.};
0112 const Vector3 mom{20., 0., 0.};
0113 Vector2 localPosition =
0114 line.globalToLocal(tgContext, gpos, mom.normalized()).value();
0115 const Vector2 expectedResult{0, -2};
0116 CHECK_CLOSE_ABS(expectedResult, localPosition, 1e-6);
0117
0118
0119 {
0120 const Vector3 direction{0., 1., 2.};
0121 BoundaryCheck bcheck(false);
0122 auto sfIntersection =
0123 line.intersect(tgContext, {0., 0., 0.}, direction.normalized(), bcheck)
0124 .closest();
0125 BOOST_CHECK(sfIntersection);
0126 Vector3 expectedIntersection(0, 1., 2.);
0127 CHECK_CLOSE_ABS(sfIntersection.position(), expectedIntersection,
0128 1e-6);
0129 BOOST_CHECK_EQUAL(sfIntersection.object(), &line);
0130 }
0131
0132
0133 const Vector3 insidePosition{0., 2.5, 0.};
0134 BOOST_CHECK(line.isOnSurface(tgContext, insidePosition, mom,
0135 BoundaryCheck(false)));
0136 const Vector3 outsidePosition{100., 100., 200.};
0137 BOOST_CHECK(
0138 !line.isOnSurface(tgContext, outsidePosition, mom, BoundaryCheck(true)));
0139
0140
0141 Vector3 returnedGlobalPosition{0., 0., 0.};
0142
0143 const Vector3 momentum{300., 200., 0.};
0144 returnedGlobalPosition =
0145 line.localToGlobal(tgContext, localPosition, momentum.normalized());
0146 const Vector3 expectedGlobalPosition{0, 1, 0};
0147 CHECK_CLOSE_ABS(returnedGlobalPosition, expectedGlobalPosition, 1e-6);
0148
0149
0150 Vector3 globalPosition{0., 0., 0.};
0151 auto returnedRotationMatrix =
0152 line.referenceFrame(tgContext, globalPosition, momentum.normalized());
0153 double v0 = std::cos(std::atan(2. / 3.));
0154 double v1 = std::sin(std::atan(2. / 3.));
0155 RotationMatrix3 expectedRotationMatrix;
0156 expectedRotationMatrix << -v1, 0., v0, v0, 0., v1, 0., 1., -0.;
0157
0158
0159 CHECK_CLOSE_OR_SMALL(returnedRotationMatrix, expectedRotationMatrix, 1e-6,
0160 1e-9);
0161
0162
0163 boost::test_tools::output_test_stream output;
0164 output << line.name();
0165 BOOST_CHECK(output.is_equal("Acts::LineSurface"));
0166
0167
0168 {
0169 Vector3 position{5, 5, 5};
0170 Vector3 direction{1, 0, 0};
0171 CHECK_CLOSE_ABS(line.normal(tgContext, position, direction), direction,
0172 1e-6);
0173 }
0174 {
0175 Vector3 position{5, 5, 5};
0176 Vector3 direction = Vector3{1, 0, 0.1}.normalized();
0177 CHECK_CLOSE_ABS(line.normal(tgContext, position, direction),
0178 Vector3::UnitX(), 1e-6);
0179 }
0180 {
0181 Vector3 position{5, 5, 5};
0182 Vector3 direction{-1, 0, 0};
0183 CHECK_CLOSE_ABS(line.normal(tgContext, position, direction), direction,
0184 1e-6);
0185 }
0186 {
0187 Vector3 position{5, 5, 5};
0188 Vector3 direction{0, 1, 0};
0189 CHECK_CLOSE_ABS(line.normal(tgContext, position, direction), direction,
0190 1e-6);
0191 }
0192
0193
0194 Vector3 any3DVector = Vector3::Random();
0195 CHECK_CLOSE_REL(line.pathCorrection(tgContext, any3DVector, any3DVector), 1.,
0196 1e-6);
0197 }
0198
0199
0200 BOOST_AUTO_TEST_CASE(LineSurface_assignment_test) {
0201 Translation3 translation{0., 1., 2.};
0202 Transform3 transform(translation);
0203 LineSurfaceStub originalLine(transform, 2.0, 20.);
0204 LineSurfaceStub assignedLine(transform, 1.0, 1.0);
0205 BOOST_CHECK(assignedLine != originalLine);
0206 assignedLine = originalLine;
0207 BOOST_CHECK(assignedLine == originalLine);
0208 }
0209
0210
0211 BOOST_AUTO_TEST_CASE(LineSurfaceAlignment) {
0212 Translation3 translation{0., 1., 2.};
0213 Transform3 transform(translation);
0214 LineSurfaceStub line(transform, 2.0, 20.);
0215
0216 const auto& rotation = transform.rotation();
0217
0218 const Vector3 localZAxis = rotation.col(2);
0219
0220 CHECK_CLOSE_ABS(localZAxis, Vector3(0., 0., 1.), 1e-15);
0221
0222
0223 Vector3 globalPosition{1, 2, 4};
0224 Vector3 momentum{-1, 1, 1};
0225 Vector3 direction = momentum.normalized();
0226
0227
0228 const AlignmentToPathMatrix& alignToPath =
0229 line.alignmentToPathDerivative(tgContext, globalPosition, direction);
0230
0231 AlignmentToPathMatrix expAlignToPath = AlignmentToPathMatrix::Zero();
0232 const double value = std::sqrt(3) / 2;
0233 expAlignToPath << -value, value, 0, -3 * value, -value, 0;
0234
0235 CHECK_CLOSE_ABS(alignToPath, expAlignToPath, 1e-10);
0236
0237
0238
0239 const auto& loc3DToLocBound =
0240 line.localCartesianToBoundLocalDerivative(tgContext, globalPosition);
0241
0242 ActsMatrix<2, 3> expLoc3DToLocBound = ActsMatrix<2, 3>::Zero();
0243 expLoc3DToLocBound << 1 / std::sqrt(2), 1 / std::sqrt(2), 0, 0, 0, 1;
0244 CHECK_CLOSE_ABS(loc3DToLocBound, expLoc3DToLocBound, 1e-10);
0245 }
0246
0247 BOOST_AUTO_TEST_CASE(LineSurfaceTransformRoundTrip) {
0248 LineSurfaceStub surface(Transform3::Identity());
0249
0250 auto roundTrip = [&surface](const Vector3& pos, const Vector3& dir) {
0251 auto intersection = surface.intersect(tgContext, pos, dir).closest();
0252 Vector3 global = intersection.position();
0253 Vector2 local = *surface.globalToLocal(tgContext, global, dir);
0254 Vector3 global2 = surface.localToGlobal(tgContext, local, dir);
0255 return std::make_tuple(global, local, global2);
0256 };
0257
0258 {
0259 Vector3 pos = {-0.02801, 0.00475611, 0.285106};
0260 Vector3 dir = Vector3(-0.03951, -0.221457, -0.564298).normalized();
0261
0262 auto [global, local, global2] = roundTrip(pos, dir);
0263
0264 CHECK_CLOSE_ABS(global, global2, 1e-10);
0265 }
0266
0267 {
0268 Vector3 pos = {-64.2892, 65.2697, -0.839014};
0269 Vector3 dir = Vector3(-0.236602, -0.157616, 0.956786).normalized();
0270
0271 auto [global, local, global2] = roundTrip(pos, dir);
0272
0273 CHECK_CLOSE_ABS(global, global2, 1e-10);
0274 }
0275 }
0276
0277 BOOST_AUTO_TEST_CASE(LineSurfaceTransformRoundTripEtaStability) {
0278 LineSurfaceStub surface(Transform3::Identity());
0279
0280
0281 const std::vector<double> etas = {0, 1, 2, 3, 4, 5};
0282
0283 for (double eta : etas) {
0284 Vector3 pca = {5, 0, 0};
0285 Vector3 dir = makeDirectionFromPhiEta(M_PI_2, eta);
0286 Vector3 pos = pca + dir;
0287
0288 auto intersection = surface.intersect(tgContext, pos, dir).closest();
0289
0290 Vector3 global = intersection.position();
0291 Vector2 local = *surface.globalToLocal(tgContext, global, dir);
0292 Vector3 global2 = surface.localToGlobal(tgContext, local, dir);
0293
0294 CHECK_CLOSE_ABS(global, global2, 1e-10);
0295 CHECK_CLOSE_ABS(pca, global2, 1e-10);
0296 }
0297 }
0298
0299 BOOST_AUTO_TEST_CASE(LineSurfaceIntersection) {
0300 using namespace Acts::UnitLiterals;
0301
0302 double eps = 1e-10;
0303
0304 Vector3 direction = Vector3(1, 1, 100).normalized();
0305 BoundVector boundVector;
0306 boundVector << 1_cm, 1_cm, VectorHelpers::phi(direction),
0307 VectorHelpers::theta(direction), 1, 0;
0308 double pathLimit = 1_cm;
0309
0310 auto surface = std::make_shared<LineSurfaceStub>(Transform3::Identity());
0311
0312 BoundTrackParameters initialParams{surface, boundVector, std::nullopt,
0313 ParticleHypothesis::pion()};
0314
0315 Propagator<StraightLineStepper> propagator({});
0316
0317 CurvilinearTrackParameters displacedParameters{
0318 Vector4::Zero(), Vector3::Zero(), 1, std::nullopt,
0319 ParticleHypothesis::pion()};
0320 {
0321 PropagatorOptions<> options(tgContext, {});
0322 options.direction = Acts::Direction::Backward;
0323 options.pathLimit = pathLimit;
0324
0325 auto result = propagator.propagate(initialParams, options);
0326 BOOST_CHECK(result.ok());
0327 BOOST_CHECK(result.value().endParameters);
0328
0329 displacedParameters = result.value().endParameters.value();
0330 }
0331
0332 auto intersection =
0333 surface
0334 ->intersect(tgContext, displacedParameters.position(tgContext),
0335 displacedParameters.direction())
0336 .closest();
0337 CHECK_CLOSE_ABS(intersection.pathLength(), pathLimit, eps);
0338
0339 BoundTrackParameters endParameters{surface, BoundVector::Zero(), std::nullopt,
0340 ParticleHypothesis::pion()};
0341 {
0342 PropagatorOptions<> options(tgContext, {});
0343 options.direction = Acts::Direction::Forward;
0344 options.maxStepSize = 1_mm;
0345
0346 auto result = propagator.propagate(displacedParameters, *surface, options);
0347 BOOST_CHECK(result.ok());
0348 BOOST_CHECK(result.value().endParameters);
0349 CHECK_CLOSE_ABS(result.value().pathLength, pathLimit, eps);
0350 endParameters = result.value().endParameters.value();
0351 }
0352
0353 CHECK_CLOSE_ABS(initialParams.parameters(), endParameters.parameters(), eps);
0354 }
0355
0356 BOOST_AUTO_TEST_SUITE_END()
0357 }
0358 }