Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:50

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include <boost/test/execution_monitor.hpp>
0010 #include <boost/test/unit_test.hpp>
0011 
0012 #include "Acts/Definitions/Algebra.hpp"
0013 #include "Acts/Surfaces/BoundaryTolerance.hpp"
0014 #include "Acts/Surfaces/detail/BoundaryCheckHelper.hpp"
0015 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0016 #include "Acts/Utilities/Helpers.hpp"
0017 
0018 #include <algorithm>
0019 #include <cstddef>
0020 #include <fstream>
0021 #include <limits>
0022 #include <optional>
0023 #include <random>
0024 #include <vector>
0025 
0026 namespace Acts::Test {
0027 
0028 BOOST_AUTO_TEST_SUITE(Surfaces)
0029 
0030 BOOST_AUTO_TEST_CASE(BoundaryToleranceConstructors) {
0031   using enum BoundaryTolerance::ToleranceMode;
0032   {
0033     // Test None constructor
0034     BoundaryTolerance tolerance = BoundaryTolerance::None();
0035     BOOST_CHECK(tolerance.toleranceMode() == None);
0036   }
0037 
0038   // Test AbsoluteBound constructor
0039   {
0040     // Valid positive tolerances
0041     auto tolerance = BoundaryTolerance::AbsoluteBound(1.0, 2.0);
0042     BOOST_CHECK_EQUAL(tolerance.asAbsoluteBound().tolerance0, 1.0);
0043     BOOST_CHECK_EQUAL(tolerance.asAbsoluteBound().tolerance1, 2.0);
0044     BOOST_CHECK(tolerance.toleranceMode() == Extend);
0045     BOOST_CHECK(BoundaryTolerance::AbsoluteBound(0.0, 0.0).toleranceMode() ==
0046                 None);
0047 
0048     // Negative tolerances should throw
0049     BOOST_CHECK_THROW(BoundaryTolerance::AbsoluteBound(-1.0, 2.0),
0050                       std::invalid_argument);
0051     BOOST_CHECK_THROW(BoundaryTolerance::AbsoluteBound(1.0, -2.0),
0052                       std::invalid_argument);
0053   }
0054 
0055   // Test AbsoluteEuclidean constructor
0056   {
0057     // Valid positive tolerance
0058     auto tolerance = BoundaryTolerance::AbsoluteEuclidean(1.0);
0059     BOOST_CHECK_EQUAL(tolerance.asAbsoluteEuclidean().tolerance, 1.0);
0060     BOOST_CHECK(tolerance.toleranceMode() == Extend);
0061     BOOST_CHECK(BoundaryTolerance::AbsoluteEuclidean(0.0).toleranceMode() ==
0062                 None);
0063 
0064     // Valid negative tolerance
0065     tolerance = BoundaryTolerance::AbsoluteEuclidean(-1.0);
0066     BOOST_CHECK_EQUAL(tolerance.asAbsoluteEuclidean().tolerance, -1.0);
0067     BOOST_CHECK(tolerance.toleranceMode() == Shrink);
0068   }
0069 
0070   // Test AbsoluteCartesian constructor
0071   {
0072     // Valid positive tolerance
0073     auto tolerance = BoundaryTolerance::AbsoluteCartesian(1.0, 2.0);
0074     BOOST_CHECK_EQUAL(tolerance.asAbsoluteCartesian().tolerance0, 1.0);
0075     BOOST_CHECK_EQUAL(tolerance.asAbsoluteCartesian().tolerance1, 2.0);
0076     BOOST_CHECK(tolerance.toleranceMode() == Extend);
0077     BOOST_CHECK(
0078         BoundaryTolerance::AbsoluteCartesian(0.0, 0.0).toleranceMode() == None);
0079 
0080     // Negative tolerances should throw
0081     BOOST_CHECK_THROW(BoundaryTolerance::AbsoluteCartesian(-1.0, 2.0),
0082                       std::invalid_argument);
0083     BOOST_CHECK_THROW(BoundaryTolerance::AbsoluteCartesian(1.0, -2.0),
0084                       std::invalid_argument);
0085   }
0086 
0087   // Test Chi2Bound constructor
0088   {
0089     SquareMatrix2 cov;
0090     cov << 1, 0.5, 0.5, 2;
0091 
0092     // Valid positive chi2 bound
0093     auto tolerance = BoundaryTolerance::Chi2Bound(cov, 3.0);
0094     BOOST_CHECK_EQUAL(tolerance.asChi2Bound().maxChi2, 3.0);
0095     BOOST_CHECK(tolerance.toleranceMode() == Extend);
0096     BOOST_CHECK(BoundaryTolerance::Chi2Bound(cov, 0.0).toleranceMode() == None);
0097 
0098     // Valid negative chi2 bound
0099     tolerance = BoundaryTolerance::Chi2Bound(cov, -3.0);
0100     BOOST_CHECK_EQUAL(tolerance.asChi2Bound().maxChi2, -3.0);
0101     BOOST_CHECK(tolerance.toleranceMode() == Shrink);
0102   }
0103 
0104   // Test None constructor
0105   BoundaryTolerance::None();
0106 }
0107 
0108 // See: https://en.wikipedia.org/wiki/Bounding_volume
0109 //
0110 // Aligned box w/ simple check
0111 BOOST_AUTO_TEST_CASE(BoundaryCheckBoxSimple) {
0112   Vector2 ll(-1, -1);
0113   Vector2 ur(1, 1);
0114   auto tolerance = BoundaryTolerance::None();
0115   BOOST_CHECK(
0116       detail::insideAlignedBox(ll, ur, tolerance, {0, 0}, std::nullopt));
0117   BOOST_CHECK(
0118       !detail::insideAlignedBox(ll, ur, tolerance, {2, 2}, std::nullopt));
0119   BOOST_CHECK(
0120       !detail::insideAlignedBox(ll, ur, tolerance, {0, 2}, std::nullopt));
0121   BOOST_CHECK(
0122       !detail::insideAlignedBox(ll, ur, tolerance, {2, 0}, std::nullopt));
0123 }
0124 
0125 // Aligned box w/ tolerance check along first axis
0126 BOOST_AUTO_TEST_CASE(BoundaryCheckBoxToleranceLoc0) {
0127   boost::execution_monitor em;
0128   em.p_detect_fp_exceptions.set(boost::fpe::BOOST_FPE_ALL);
0129 
0130   em.execute([]() {
0131     Vector2 ll(-1, -1);
0132     Vector2 ur(1, 1);
0133     auto tolerance = BoundaryTolerance::AbsoluteBound(
0134         1.5, std::numeric_limits<double>::infinity());
0135     BOOST_CHECK(
0136         detail::insideAlignedBox(ll, ur, tolerance, {0, 0}, std::nullopt));
0137     BOOST_CHECK(
0138         detail::insideAlignedBox(ll, ur, tolerance, {2, 2}, std::nullopt));
0139     BOOST_CHECK(
0140         !detail::insideAlignedBox(ll, ur, tolerance, {4, 4}, std::nullopt));
0141     BOOST_CHECK(
0142         detail::insideAlignedBox(ll, ur, tolerance, {0, 2}, std::nullopt));
0143     BOOST_CHECK(
0144         detail::insideAlignedBox(ll, ur, tolerance, {2, 0}, std::nullopt));
0145 
0146     return 0;
0147   });
0148 }
0149 
0150 // Aligned box w/ covariance check
0151 BOOST_AUTO_TEST_CASE(BoundaryCheckBoxCovariance) {
0152   SquareMatrix2 cov;
0153   cov << 1, 0.5, 0.5, 2;
0154   Vector2 ll(-1, -1);
0155   Vector2 ur(1, 1);
0156   auto tolerance = BoundaryTolerance::Chi2Bound(cov.inverse(), 3.);
0157   BOOST_CHECK(
0158       detail::insideAlignedBox(ll, ur, tolerance, {0, 0}, std::nullopt));
0159   BOOST_CHECK(
0160       detail::insideAlignedBox(ll, ur, tolerance, {2, 2}, std::nullopt));
0161   BOOST_CHECK(
0162       !detail::insideAlignedBox(ll, ur, tolerance, {4, 4}, std::nullopt));
0163   BOOST_CHECK(
0164       detail::insideAlignedBox(ll, ur, tolerance, {0, 3}, std::nullopt));
0165   BOOST_CHECK(
0166       detail::insideAlignedBox(ll, ur, tolerance, {3, 0}, std::nullopt));
0167 }
0168 
0169 // Triangle w/ simple check
0170 BOOST_AUTO_TEST_CASE(BoundaryCheckTriangleSimple) {
0171   Vector2 vertices[] = {{-2, 0}, {2, 0}, {0, 2}};
0172   auto tolerance = BoundaryTolerance::None();
0173   BOOST_CHECK(detail::insidePolygon(vertices, tolerance, {0, 0}, std::nullopt));
0174   BOOST_CHECK(detail::insidePolygon(vertices, tolerance, {0, 1}, std::nullopt));
0175   BOOST_CHECK(
0176       !detail::insidePolygon(vertices, tolerance, {2, 2}, std::nullopt));
0177   BOOST_CHECK(
0178       !detail::insidePolygon(vertices, tolerance, {0, -1}, std::nullopt));
0179 }
0180 // Triangle w/ covariance check
0181 BOOST_AUTO_TEST_CASE(BoundaryCheckTriangleCovariance) {
0182   Vector2 vertices[] = {{-2, 0}, {2, 0}, {0, 2}};
0183   SquareMatrix2 cov;
0184   cov << 0.5, 0, 0, 0.5;
0185   auto tolerance = BoundaryTolerance::Chi2Bound(cov.inverse(), 4.1);
0186   BOOST_CHECK(detail::insidePolygon(vertices, tolerance, {0, 0}, std::nullopt));
0187   BOOST_CHECK(detail::insidePolygon(vertices, tolerance, {0, 1}, std::nullopt));
0188   BOOST_CHECK(detail::insidePolygon(vertices, tolerance, {0, 2}, std::nullopt));
0189   BOOST_CHECK(detail::insidePolygon(vertices, tolerance, {0, 3}, std::nullopt));
0190   BOOST_CHECK(detail::insidePolygon(vertices, tolerance, {0, 4}, std::nullopt));
0191   BOOST_CHECK(
0192       !detail::insidePolygon(vertices, tolerance, {0, 5}, std::nullopt));
0193 }
0194 
0195 BOOST_AUTO_TEST_CASE(BoundaryCheckDifferentTolerances) {
0196   Vector2 ll(-1, -1);
0197   Vector2 ur(1, 1);
0198 
0199   {
0200     auto tolerance = BoundaryTolerance::None();
0201     BOOST_CHECK(
0202         detail::insideAlignedBox(ll, ur, tolerance, {0, 0}, std::nullopt));
0203     BOOST_CHECK(
0204         !detail::insideAlignedBox(ll, ur, tolerance, {2, 2}, std::nullopt));
0205     BOOST_CHECK(
0206         !detail::insideAlignedBox(ll, ur, tolerance, {0, 2}, std::nullopt));
0207     BOOST_CHECK(
0208         !detail::insideAlignedBox(ll, ur, tolerance, {2, 0}, std::nullopt));
0209   }
0210 
0211   {
0212     auto tolerance = BoundaryTolerance::Infinite();
0213     BOOST_CHECK(
0214         detail::insideAlignedBox(ll, ur, tolerance, {0, 0}, std::nullopt));
0215     BOOST_CHECK(
0216         detail::insideAlignedBox(ll, ur, tolerance, {2, 2}, std::nullopt));
0217     BOOST_CHECK(
0218         detail::insideAlignedBox(ll, ur, tolerance, {0, 2}, std::nullopt));
0219     BOOST_CHECK(
0220         detail::insideAlignedBox(ll, ur, tolerance, {2, 0}, std::nullopt));
0221   }
0222 
0223   {
0224     auto tolerance = BoundaryTolerance::AbsoluteBound(0.5, 0.5);
0225     BOOST_CHECK(
0226         detail::insideAlignedBox(ll, ur, tolerance, {0, 0}, std::nullopt));
0227     BOOST_CHECK(
0228         detail::insideAlignedBox(ll, ur, tolerance, {1.1, 1.1}, std::nullopt));
0229     BOOST_CHECK(
0230         detail::insideAlignedBox(ll, ur, tolerance, {0, 1.1}, std::nullopt));
0231     BOOST_CHECK(
0232         detail::insideAlignedBox(ll, ur, tolerance, {1.1, 0}, std::nullopt));
0233     BOOST_CHECK(
0234         !detail::insideAlignedBox(ll, ur, tolerance, {2, 2}, std::nullopt));
0235     BOOST_CHECK(
0236         !detail::insideAlignedBox(ll, ur, tolerance, {0, 2}, std::nullopt));
0237     BOOST_CHECK(
0238         !detail::insideAlignedBox(ll, ur, tolerance, {2, 0}, std::nullopt));
0239   }
0240 
0241   {
0242     auto tolerance = BoundaryTolerance::AbsoluteCartesian(0.5, 0.5);
0243     BOOST_CHECK(
0244         detail::insideAlignedBox(ll, ur, tolerance, {0, 0}, std::nullopt));
0245     BOOST_CHECK(
0246         detail::insideAlignedBox(ll, ur, tolerance, {1.1, 1.1}, std::nullopt));
0247     BOOST_CHECK(
0248         detail::insideAlignedBox(ll, ur, tolerance, {0, 1.1}, std::nullopt));
0249     BOOST_CHECK(
0250         detail::insideAlignedBox(ll, ur, tolerance, {1.1, 0}, std::nullopt));
0251     BOOST_CHECK(
0252         !detail::insideAlignedBox(ll, ur, tolerance, {2, 2}, std::nullopt));
0253     BOOST_CHECK(
0254         !detail::insideAlignedBox(ll, ur, tolerance, {0, 2}, std::nullopt));
0255     BOOST_CHECK(
0256         !detail::insideAlignedBox(ll, ur, tolerance, {2, 0}, std::nullopt));
0257   }
0258 
0259   {
0260     auto tolerance = BoundaryTolerance::AbsoluteEuclidean(1.1);
0261     BOOST_CHECK(
0262         detail::insideAlignedBox(ll, ur, tolerance, {0, 0}, std::nullopt));
0263     BOOST_CHECK(
0264         !detail::insideAlignedBox(ll, ur, tolerance, {2, 2}, std::nullopt));
0265     BOOST_CHECK(
0266         detail::insideAlignedBox(ll, ur, tolerance, {0, 2}, std::nullopt));
0267     BOOST_CHECK(
0268         detail::insideAlignedBox(ll, ur, tolerance, {2, 0}, std::nullopt));
0269   }
0270 
0271   {
0272     auto tolerance =
0273         BoundaryTolerance::Chi2Bound(SquareMatrix2::Identity(), 1.);
0274     BOOST_CHECK(
0275         detail::insideAlignedBox(ll, ur, tolerance, {0, 0}, std::nullopt));
0276     BOOST_CHECK(
0277         detail::insideAlignedBox(ll, ur, tolerance, {2, 2}, std::nullopt));
0278     BOOST_CHECK(
0279         detail::insideAlignedBox(ll, ur, tolerance, {0, 2}, std::nullopt));
0280     BOOST_CHECK(
0281         detail::insideAlignedBox(ll, ur, tolerance, {2, 0}, std::nullopt));
0282     BOOST_CHECK(
0283         !detail::insideAlignedBox(ll, ur, tolerance, {3, 3}, std::nullopt));
0284   }
0285 }
0286 
0287 BOOST_AUTO_TEST_CASE(BoundaryCheckNegativeToleranceRect) {
0288   // Test points for boundary check with euclidean tolerance
0289   Vector2 ll(1, 1);
0290   Vector2 ur(3, 3);
0291 
0292   auto check = [&ll, &ur](const BoundaryTolerance& tolerance,
0293                           const Vector2& point) {
0294     return detail::insideAlignedBox(ll, ur, tolerance, point, std::nullopt);
0295   };
0296 
0297   {
0298     auto tolerance = BoundaryTolerance::AbsoluteEuclidean(-0.25);
0299 
0300     BOOST_CHECK(!check(tolerance, {2.8, 2}));
0301     BOOST_CHECK(!check(tolerance, {3.1, 2}));
0302     BOOST_CHECK(check(tolerance, {2.7, 2}));
0303     BOOST_CHECK(!check(tolerance, {2, 3.1}));
0304     BOOST_CHECK(!check(tolerance, {2, 2.8}));
0305     BOOST_CHECK(check(tolerance, {2, 2.7}));
0306 
0307     BOOST_CHECK(!check(tolerance, {0.8, 2}));
0308     BOOST_CHECK(!check(tolerance, {1.2, 2}));
0309     BOOST_CHECK(check(tolerance, {1.5, 2}));
0310     BOOST_CHECK(!check(tolerance, {2, 0.8}));
0311     BOOST_CHECK(!check(tolerance, {2, 1.2}));
0312     BOOST_CHECK(check(tolerance, {2, 1.5}));
0313   }
0314 
0315   {
0316     auto tolerance =
0317         BoundaryTolerance::Chi2Bound(SquareMatrix2::Identity(), -0.1);
0318 
0319     BOOST_CHECK(!check(tolerance, {2.8, 2}));
0320     BOOST_CHECK(!check(tolerance, {3.1, 2}));
0321     BOOST_CHECK(check(tolerance, {2.5, 2}));
0322     BOOST_CHECK(!check(tolerance, {2, 3.1}));
0323     BOOST_CHECK(!check(tolerance, {2, 2.8}));
0324     BOOST_CHECK(check(tolerance, {2, 2.5}));
0325 
0326     BOOST_CHECK(!check(tolerance, {0.8, 2}));
0327     BOOST_CHECK(!check(tolerance, {1.4, 2}));
0328     BOOST_CHECK(check(tolerance, {1.5, 2}));
0329     BOOST_CHECK(!check(tolerance, {2, 0.8}));
0330     BOOST_CHECK(!check(tolerance, {2, 1.4}));
0331     BOOST_CHECK(check(tolerance, {2, 1.5}));
0332   }
0333 }
0334 
0335 BOOST_AUTO_TEST_CASE(BoundaryCheckNegativeToleranceTrap) {
0336   Vector2 vertices[] = {{1.5, 1}, {2.5, 1}, {3, 3}, {1, 3}};
0337 
0338   auto check = [&vertices](const BoundaryTolerance& tolerance,
0339                            const Vector2& point) {
0340     return detail::insidePolygon(vertices, tolerance, point, std::nullopt);
0341   };
0342 
0343   {
0344     auto tolerance = BoundaryTolerance::AbsoluteEuclidean(0.25);
0345     // Axes
0346     BOOST_CHECK(!check(tolerance, {3.1, 2}));
0347     BOOST_CHECK(check(tolerance, {2.75, 2}));
0348     BOOST_CHECK(check(tolerance, {2.5, 2}));
0349     BOOST_CHECK(check(tolerance, {2.25, 2}));
0350     BOOST_CHECK(check(tolerance, {2, 3.1}));
0351     BOOST_CHECK(check(tolerance, {2, 2.75}));
0352     BOOST_CHECK(check(tolerance, {2, 2.5}));
0353     BOOST_CHECK(check(tolerance, {2, 2.25}));
0354     BOOST_CHECK(check(tolerance, {2, 2}));
0355 
0356     // Corners
0357     BOOST_CHECK(check(tolerance, {3.1, 3.2}));
0358     BOOST_CHECK(check(tolerance, {0.9, 3.2}));
0359     BOOST_CHECK(check(tolerance, {1.5, 0.8}));
0360     BOOST_CHECK(check(tolerance, {2.5, 0.8}));
0361   }
0362 
0363   {
0364     auto tolerance = BoundaryTolerance::AbsoluteEuclidean(-0.25);
0365     // Axes
0366     BOOST_CHECK(!check(tolerance, {3.0, 2}));
0367     BOOST_CHECK(!check(tolerance, {2.5, 2}));
0368     BOOST_CHECK(check(tolerance, {2.25, 2}));
0369     BOOST_CHECK(!check(tolerance, {2, 3.1}));
0370     BOOST_CHECK(!check(tolerance, {2, 2.9}));
0371     BOOST_CHECK(check(tolerance, {2, 2.7}));
0372 
0373     // Corners
0374     BOOST_CHECK(!check(tolerance, {2.7, 2.9}));
0375     BOOST_CHECK(check(tolerance, {2.4, 2.6}));
0376     BOOST_CHECK(!check(tolerance, {1.3, 2.9}));
0377     BOOST_CHECK(check(tolerance, {1.6, 2.6}));
0378     BOOST_CHECK(!check(tolerance, {2.4, 1.1}));
0379     BOOST_CHECK(check(tolerance, {1.75, 1.4}));
0380     BOOST_CHECK(!check(tolerance, {1.6, 1.1}));
0381     BOOST_CHECK(check(tolerance, {2.25, 1.4}));
0382   }
0383 }
0384 
0385 BOOST_AUTO_TEST_SUITE_END()
0386 
0387 }  // namespace Acts::Test