File indexing completed on 2025-12-07 09:02:52
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/Tolerance.hpp"
0013 #include "Acts/Definitions/Units.hpp"
0014 #include "Acts/Geometry/GeometryContext.hpp"
0015 #include "Acts/Surfaces/ConeSurface.hpp"
0016 #include "Acts/Surfaces/CylinderSurface.hpp"
0017 #include "Acts/Surfaces/PlaneSurface.hpp"
0018 #include "Acts/Surfaces/RectangleBounds.hpp"
0019 #include "Acts/Surfaces/StrawSurface.hpp"
0020 #include "Acts/Surfaces/Surface.hpp"
0021 #include "Acts/Utilities/Intersection.hpp"
0022 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0023
0024 #include <cmath>
0025 #include <memory>
0026 #include <numbers>
0027
0028 using namespace Acts::UnitLiterals;
0029
0030 using namespace Acts;
0031
0032 namespace ActsTests {
0033
0034
0035 GeometryContext tgContext = GeometryContext();
0036
0037
0038 Transform3 aTransform = Transform3::Identity() *
0039 Translation3(30_cm, 7_m, -87_mm) *
0040 AngleAxis3(0.42, Vector3(-3., 1., 8).normalized());
0041
0042 BOOST_AUTO_TEST_SUITE(SurfacesSuite)
0043
0044
0045
0046 BOOST_AUTO_TEST_CASE(CylinderIntersectionTests) {
0047 const double radius = 1_m;
0048 const double halfZ = 10_m;
0049
0050 auto testCylinderIntersection = [&](const Transform3& transform) -> void {
0051
0052 auto aCylinder =
0053 Surface::makeShared<CylinderSurface>(transform, radius, halfZ);
0054
0055
0056 auto lTransform = transform.linear();
0057
0058
0059 Vector3 onCylinder = transform * Vector3(radius, 0., 0.);
0060 Vector3 outCylinder = transform * Vector3(-radius, 0.6 * radius, 90_cm);
0061 Vector3 atCenter = transform * Vector3(0., 0., 0.);
0062 Vector3 atEdge = transform * Vector3(0.5 * radius, 0., 0.99 * halfZ);
0063
0064 Vector3 alongX = lTransform * Vector3(1., 0., 0.);
0065 Vector3 transXY = lTransform * Vector3(1., 1., 0).normalized();
0066 Vector3 transTZ = lTransform * Vector3(1., 0., 1.).normalized();
0067
0068
0069 auto aIntersection = aCylinder->intersect(tgContext, onCylinder, alongX,
0070 BoundaryTolerance::None());
0071
0072
0073 BOOST_CHECK(aIntersection[0].isValid());
0074
0075 BOOST_CHECK_EQUAL(aIntersection[0].status(), IntersectionStatus::reachable);
0076
0077 CHECK_CLOSE_ABS(aIntersection[0].pathLength(), -2_m, s_onSurfaceTolerance);
0078
0079 BOOST_CHECK(aIntersection[1].isValid());
0080
0081 BOOST_CHECK_EQUAL(aIntersection[1].status(), IntersectionStatus::onSurface);
0082
0083
0084 auto cIntersection = aCylinder->intersect(tgContext, atCenter, alongX,
0085 BoundaryTolerance::None());
0086
0087
0088 BOOST_CHECK(cIntersection[0].isValid());
0089
0090 BOOST_CHECK_EQUAL(cIntersection[0].status(), IntersectionStatus::reachable);
0091
0092 BOOST_CHECK(cIntersection[1].isValid());
0093
0094 BOOST_CHECK_EQUAL(cIntersection[1].status(), IntersectionStatus::reachable);
0095
0096 BOOST_CHECK_LT(
0097 cIntersection[1].pathLength() * cIntersection[0].pathLength(), 0);
0098
0099
0100 auto oIntersection = aCylinder->intersect(tgContext, outCylinder, alongX,
0101 BoundaryTolerance::None());
0102
0103
0104 BOOST_CHECK(oIntersection[0].isValid());
0105
0106 BOOST_CHECK_EQUAL(oIntersection[0].status(), IntersectionStatus::reachable);
0107
0108 BOOST_CHECK(oIntersection[1].isValid());
0109
0110 BOOST_CHECK_EQUAL(oIntersection[1].status(), IntersectionStatus::reachable);
0111
0112 BOOST_CHECK_GT(
0113 oIntersection[1].pathLength() * oIntersection[0].pathLength(), 0);
0114
0115
0116 auto iIntersection = aCylinder->intersect(tgContext, outCylinder, transXY,
0117 BoundaryTolerance::Infinite());
0118
0119
0120 BOOST_CHECK(!iIntersection[0].isValid());
0121
0122
0123 auto eIntersection = aCylinder->intersect(tgContext, atEdge, transTZ,
0124 BoundaryTolerance::Infinite());
0125
0126
0127 BOOST_CHECK(eIntersection[0].isValid());
0128
0129 BOOST_CHECK_LT(eIntersection[0].pathLength(), 0.);
0130
0131 BOOST_CHECK_EQUAL(eIntersection[0].status(), IntersectionStatus::reachable);
0132
0133 BOOST_CHECK(eIntersection[1].isValid());
0134
0135 BOOST_CHECK_EQUAL(eIntersection[1].status(), IntersectionStatus::reachable);
0136
0137 BOOST_CHECK_GT(eIntersection[1].pathLength(), 0.);
0138
0139
0140 eIntersection = aCylinder->intersect(tgContext, atEdge, transTZ,
0141 BoundaryTolerance::None());
0142
0143 BOOST_CHECK_LT(eIntersection[0].pathLength(), 0.);
0144
0145 BOOST_CHECK_EQUAL(eIntersection[0].status(), IntersectionStatus::reachable);
0146
0147 BOOST_CHECK(!eIntersection[1].isValid());
0148
0149 BOOST_CHECK_EQUAL(eIntersection[1].status(),
0150 IntersectionStatus::unreachable);
0151
0152 BOOST_CHECK_GT(eIntersection[1].pathLength(), 0.);
0153 };
0154
0155
0156 testCylinderIntersection(Transform3::Identity());
0157
0158
0159 testCylinderIntersection(aTransform);
0160 }
0161
0162
0163
0164 BOOST_AUTO_TEST_CASE(ConeIntersectionTest) {
0165 const double alpha = std::numbers::pi / 4.;
0166
0167 auto testConeIntersection = [&](const Transform3& transform) -> void {
0168
0169 auto aCone = Surface::makeShared<ConeSurface>(transform, alpha, true);
0170
0171
0172 auto lTransform = transform.linear();
0173
0174
0175 Vector3 onCone =
0176 transform * Vector3(std::numbers::sqrt2, std::numbers::sqrt2, 2.);
0177 Vector3 outCone = transform * Vector3(std::sqrt(4.), std::sqrt(4.), 2.);
0178
0179 Vector3 perpXY = lTransform * Vector3(1., -1., 0.).normalized();
0180 Vector3 transXY = lTransform * Vector3(1., 1., 0).normalized();
0181
0182
0183 BOOST_CHECK(aCone->isOnSurface(tgContext, onCone, transXY,
0184 BoundaryTolerance::Infinite()));
0185 auto aIntersection =
0186 aCone->intersect(tgContext, onCone, transXY, BoundaryTolerance::None());
0187
0188
0189 BOOST_CHECK(aIntersection[0].isValid());
0190
0191 BOOST_CHECK_EQUAL(aIntersection[0].status(), IntersectionStatus::reachable);
0192
0193 CHECK_CLOSE_ABS(aIntersection[0].pathLength(), -4., s_onSurfaceTolerance);
0194
0195 BOOST_CHECK(aIntersection[1].isValid());
0196
0197 BOOST_CHECK_EQUAL(aIntersection[1].status(), IntersectionStatus::onSurface);
0198
0199
0200 auto iIntersection = aCone->intersect(tgContext, outCone, perpXY,
0201 BoundaryTolerance::Infinite());
0202
0203
0204 BOOST_CHECK(!iIntersection[0].isValid());
0205 };
0206
0207
0208 testConeIntersection(Transform3::Identity());
0209
0210
0211 testConeIntersection(aTransform);
0212 }
0213
0214
0215
0216
0217
0218 BOOST_AUTO_TEST_CASE(PlanarIntersectionTest) {
0219 const double halfX = 1_m;
0220 const double halfY = 10_m;
0221
0222 auto testPlanarIntersection = [&](const Transform3& transform) -> void {
0223
0224 auto aPlane = Surface::makeShared<PlaneSurface>(
0225 transform, std::make_shared<RectangleBounds>(halfX, halfY));
0226
0227
0228 Vector3 before = transform * Vector3(-50_cm, -1_m, -1_m);
0229 Vector3 onit = transform * Vector3(11_cm, -22_cm, 0_m);
0230 Vector3 after = transform * Vector3(33_cm, 12_mm, 1_m);
0231 Vector3 outside = transform * Vector3(2. * halfX, 2 * halfY, -1_mm);
0232
0233
0234 auto lTransform = transform.linear();
0235
0236
0237 Vector3 direction = lTransform * Vector3(4_mm, 8_mm, 50_cm).normalized();
0238 Vector3 parallel = lTransform * Vector3(1., 1., 0.).normalized();
0239
0240
0241 auto fIntersection = aPlane->intersect(tgContext, before, direction,
0242 BoundaryTolerance::None());
0243
0244
0245 BOOST_CHECK(fIntersection[0].isValid());
0246
0247 BOOST_CHECK_EQUAL(fIntersection[0].status(), IntersectionStatus::reachable);
0248
0249 BOOST_CHECK_GT(fIntersection[0].pathLength(), 0.);
0250
0251 BOOST_CHECK(!fIntersection[1].isValid());
0252
0253
0254 auto oIntersection = aPlane->intersect(tgContext, onit, direction,
0255 BoundaryTolerance::None());
0256
0257 BOOST_CHECK(oIntersection[0].isValid());
0258
0259 BOOST_CHECK_EQUAL(oIntersection[0].status(), IntersectionStatus::onSurface);
0260
0261 BOOST_CHECK_LT(std::abs(oIntersection[0].pathLength()),
0262 s_onSurfaceTolerance);
0263
0264 BOOST_CHECK(!oIntersection[1].isValid());
0265
0266
0267 auto bIntersection = aPlane->intersect(tgContext, after, direction,
0268 BoundaryTolerance::None());
0269
0270 BOOST_CHECK(bIntersection[0].isValid());
0271
0272 BOOST_CHECK_EQUAL(bIntersection[0].status(), IntersectionStatus::reachable);
0273
0274 BOOST_CHECK_LT(bIntersection[0].pathLength(), 0.);
0275
0276 BOOST_CHECK(!bIntersection[1].isValid());
0277
0278
0279 auto mIntersection = aPlane->intersect(tgContext, outside, direction,
0280 BoundaryTolerance::None());
0281
0282 BOOST_CHECK(!mIntersection[0].isValid());
0283
0284 BOOST_CHECK_EQUAL(mIntersection[0].status(),
0285 IntersectionStatus::unreachable);
0286
0287 BOOST_CHECK_GT(mIntersection[0].pathLength(), 0.);
0288
0289 BOOST_CHECK(!mIntersection[1].isValid());
0290
0291
0292 auto iIntersection = aPlane->intersect(tgContext, before, parallel,
0293 BoundaryTolerance::None());
0294
0295 BOOST_CHECK(!iIntersection[0].isValid());
0296
0297 BOOST_CHECK_EQUAL(iIntersection[0].status(),
0298 IntersectionStatus::unreachable);
0299
0300 BOOST_CHECK(!iIntersection[1].isValid());
0301 };
0302
0303
0304 testPlanarIntersection(Transform3::Identity());
0305
0306
0307 testPlanarIntersection(aTransform);
0308 }
0309
0310
0311
0312
0313
0314 BOOST_AUTO_TEST_CASE(LineIntersectionTest) {
0315 const double radius = 1_m;
0316 const double halfZ = 10_m;
0317
0318 auto testLineAppraoch = [&](const Transform3& transform) -> void {
0319
0320 auto aLine = Surface::makeShared<StrawSurface>(transform, radius, halfZ);
0321
0322
0323 Vector3 before = transform * Vector3(-50_cm, -1_m, -1_m);
0324 Vector3 onit1 = transform * Vector3(0_m, 0_m, 0_m);
0325 Vector3 onitP = transform * Vector3(1_cm, 0_m, 23_um);
0326 Vector3 after = transform * Vector3(33_cm, 12_mm, 1_m);
0327 Vector3 outside = transform * Vector3(2., 0., 100_m);
0328
0329
0330 auto lTransform = transform.linear();
0331 Vector3 direction = lTransform * Vector3(2_cm, 3_cm, 5_cm).normalized();
0332 Vector3 normalP = lTransform * Vector3(0, 1., 0.).normalized();
0333 Vector3 parallel = lTransform * Vector3(0, 0., 1.).normalized();
0334
0335
0336
0337 auto fIntersection = aLine->intersect(tgContext, before, direction,
0338 BoundaryTolerance::None());
0339
0340 BOOST_CHECK(fIntersection[0].isValid());
0341
0342 BOOST_CHECK_EQUAL(fIntersection[0].status(), IntersectionStatus::reachable);
0343
0344 BOOST_CHECK_GT(fIntersection[0].pathLength(), 0.);
0345
0346 BOOST_CHECK(!fIntersection[1].isValid());
0347
0348
0349 auto oIntersection = aLine->intersect(tgContext, onit1, direction,
0350 BoundaryTolerance::None());
0351
0352 BOOST_CHECK(oIntersection[0].isValid());
0353
0354 BOOST_CHECK_EQUAL(oIntersection[0].status(), IntersectionStatus::onSurface);
0355
0356 BOOST_CHECK_LT(std::abs(oIntersection[0].pathLength()),
0357 s_onSurfaceTolerance);
0358
0359 BOOST_CHECK(!oIntersection[1].isValid());
0360
0361
0362 oIntersection =
0363 aLine->intersect(tgContext, onitP, normalP, BoundaryTolerance::None());
0364
0365 BOOST_CHECK(oIntersection[0].isValid());
0366
0367 BOOST_CHECK_EQUAL(oIntersection[0].status(), IntersectionStatus::onSurface);
0368
0369 BOOST_CHECK_LT(std::abs(oIntersection[0].pathLength()),
0370 s_onSurfaceTolerance);
0371
0372 BOOST_CHECK(!oIntersection[1].isValid());
0373
0374
0375 auto bIntersection = aLine->intersect(tgContext, after, direction,
0376 BoundaryTolerance::None());
0377
0378 BOOST_CHECK(bIntersection[0].isValid());
0379
0380 BOOST_CHECK_EQUAL(bIntersection[0].status(), IntersectionStatus::reachable);
0381
0382 BOOST_CHECK_LT(bIntersection[0].pathLength(), 0.);
0383
0384 BOOST_CHECK(!bIntersection[1].isValid());
0385
0386
0387 auto mIntersection = aLine->intersect(tgContext, outside, direction,
0388 BoundaryTolerance::None());
0389
0390 BOOST_CHECK(!mIntersection[0].isValid());
0391
0392 BOOST_CHECK_EQUAL(mIntersection[0].status(),
0393 IntersectionStatus::unreachable);
0394
0395 BOOST_CHECK_LT(mIntersection[0].pathLength(), 0.);
0396
0397 BOOST_CHECK(!mIntersection[1].isValid());
0398
0399
0400 auto iIntersection = aLine->intersect(tgContext, before, parallel,
0401 BoundaryTolerance::None());
0402
0403 BOOST_CHECK(!iIntersection[0].isValid());
0404
0405 BOOST_CHECK_EQUAL(iIntersection[0].status(),
0406 IntersectionStatus::unreachable);
0407
0408 BOOST_CHECK(!iIntersection[1].isValid());
0409 };
0410
0411
0412 testLineAppraoch(Transform3::Identity());
0413
0414
0415 testLineAppraoch(aTransform);
0416 }
0417
0418 BOOST_AUTO_TEST_SUITE_END()
0419
0420 }