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