File indexing completed on 2026-09-18 08:24:26
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/tools/old/interface.hpp>
0010 #include <boost/test/unit_test.hpp>
0011
0012 #include "Acts/Definitions/Algebra.hpp"
0013 #include "Acts/Definitions/TrackParametrization.hpp"
0014 #include "Acts/Definitions/Units.hpp"
0015 #include "Acts/EventData/detail/TestSourceLink.hpp"
0016 #include "Acts/Geometry/GeometryContext.hpp"
0017 #include "Acts/Geometry/GeometryIdentifier.hpp"
0018 #include "Acts/Geometry/LayerCreator.hpp"
0019 #include "Acts/Geometry/TrackingGeometry.hpp"
0020 #include "Acts/MagneticField/ConstantBField.hpp"
0021 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0022 #include "Acts/Propagator/EigenStepper.hpp"
0023 #include "Acts/Propagator/Navigator.hpp"
0024 #include "Acts/Propagator/Propagator.hpp"
0025 #include "Acts/Seeding/EstimateTrackParamsFromSeed.hpp"
0026 #include "Acts/Seeding/TrackParamsEstimationError.hpp"
0027 #include "Acts/Seeding/detail/CircleFit.hpp"
0028 #include "Acts/Surfaces/Surface.hpp"
0029 #include "Acts/Utilities/Logger.hpp"
0030 #include "ActsTests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0031 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0032 #include "ActsTests/CommonHelpers/MeasurementsCreator.hpp"
0033
0034 #include <array>
0035 #include <cmath>
0036 #include <memory>
0037 #include <optional>
0038 #include <random>
0039 #include <set>
0040 #include <span>
0041 #include <utility>
0042 #include <vector>
0043
0044 using namespace Acts;
0045 using namespace Acts::UnitLiterals;
0046
0047 namespace ActsTests {
0048
0049 using ConstantFieldStepper = EigenStepper<>;
0050 using ConstantFieldPropagator = Propagator<ConstantFieldStepper, Navigator>;
0051
0052 const auto geoCtx = GeometryContext::dangerouslyDefaultConstruct();
0053 const MagneticFieldContext magCtx;
0054
0055
0056 CylindricalTrackingGeometry geometryStore(geoCtx);
0057 const auto geometry = geometryStore();
0058
0059
0060 const MeasurementResolutionMap resolutions = {
0061 {GeometryIdentifier(),
0062 MeasurementResolution{MeasurementType::eLoc01, {0, 0}}}};
0063
0064
0065 BoundTrackParameters makeParameters(double phi, double theta, double p,
0066 double q) {
0067
0068 BoundVector stddev;
0069 stddev[eBoundLoc0] = 100_um;
0070 stddev[eBoundLoc1] = 100_um;
0071 stddev[eBoundTime] = 25_ns;
0072 stddev[eBoundPhi] = 2_degree;
0073 stddev[eBoundTheta] = 2_degree;
0074 stddev[eBoundQOverP] = 1 / 100_GeV;
0075 BoundMatrix cov = stddev.cwiseProduct(stddev).asDiagonal();
0076
0077 Vector4 mPos4(0., 0., 0., 0.);
0078 return BoundTrackParameters::createCurvilinear(
0079 mPos4, phi, theta, q / p, cov, ParticleHypothesis::pionLike(std::abs(q)));
0080 }
0081
0082 std::default_random_engine rng(42);
0083
0084 BOOST_AUTO_TEST_SUITE(SeedingSuite)
0085
0086 BOOST_AUTO_TEST_CASE(trackparameters_estimation_test) {
0087
0088
0089 Navigator navigator({
0090 geometry,
0091 true,
0092 true,
0093 false
0094 });
0095 const Vector3 bField(0, 0, 2._T);
0096 auto field = std::make_shared<ConstantBField>(bField);
0097 ConstantFieldStepper stepper(std::move(field));
0098
0099 ConstantFieldPropagator propagator(std::move(stepper), std::move(navigator));
0100
0101 std::array<double, 2> pArray = {0.5_GeV, 1.0_GeV};
0102 std::array<double, 3> phiArray = {20._degree, 0._degree - 20._degree};
0103 std::array<double, 3> thetaArray = {80._degree, 90.0_degree, 100._degree};
0104 std::array<double, 2> qArray = {1, -1};
0105
0106 auto logger = getDefaultLogger("estimateTrackParamsFromSeed", Logging::INFO);
0107
0108 for (const auto& p : pArray) {
0109 for (const auto& phi : phiArray) {
0110 for (const auto& theta : thetaArray) {
0111 for (const auto& q : qArray) {
0112 BOOST_TEST_INFO("Test track with p = " << p << ", phi = " << phi
0113 << ", theta = " << theta
0114 << ", q = " << q);
0115 auto start = makeParameters(phi, theta, p, q);
0116 auto measurements = createMeasurements(propagator, geoCtx, magCtx,
0117 start, resolutions, rng);
0118
0119
0120 std::vector<Vector3> spacePoints;
0121 std::set<GeometryIdentifier::Value> usedLayers;
0122 const Surface* bottomSurface = nullptr;
0123 for (const auto& sl : measurements.sourceLinks) {
0124 const auto geoId = sl.m_geometryId;
0125 const auto& layer = geoId.layer();
0126
0127 if (const auto it = usedLayers.find(layer);
0128 it != usedLayers.end()) {
0129 continue;
0130 }
0131 const auto surface = geometry->findSurface(geoId);
0132 const auto& localPos = sl.parameters;
0133 const Vector3 globalFakeMom(1, 1, 1);
0134 const Vector3 globalPos =
0135 surface->localToGlobal(geoCtx, localPos, globalFakeMom);
0136 spacePoints.push_back(globalPos);
0137 usedLayers.insert(layer);
0138 if (spacePoints.size() == 1) {
0139 bottomSurface = surface;
0140 }
0141 }
0142
0143
0144 if (spacePoints.size() < 3) {
0145 BOOST_TEST_WARN("Number of space points less than 3.");
0146 continue;
0147 }
0148
0149
0150 const auto& expBoundParams = measurements.truthParameters[0];
0151 BOOST_TEST_INFO(
0152 "The truth track parameters at the bottom space point: \n"
0153 << expBoundParams.transpose());
0154
0155
0156 FreeVector estFreeParams = estimateTrackParamsFromSeed(
0157 spacePoints[0], 0, spacePoints[1], spacePoints[2], bField);
0158 BOOST_CHECK(!estFreeParams.hasNaN());
0159
0160
0161 auto estBoundParamsResult = estimateTrackParamsFromSeed(
0162 geoCtx, *bottomSurface, spacePoints[0], 0, spacePoints[1],
0163 spacePoints[2], bField);
0164 BOOST_CHECK(estBoundParamsResult.ok());
0165 const auto& estBoundParams = estBoundParamsResult.value();
0166 BOOST_TEST_INFO(
0167 "The estimated full track parameters at the bottom space point: "
0168 "\n"
0169 << estBoundParams.transpose());
0170
0171 CHECK_CLOSE_ABS(estBoundParams[eBoundLoc0],
0172 expBoundParams[eBoundLoc0], 1e-5);
0173 CHECK_CLOSE_ABS(estBoundParams[eBoundLoc1],
0174 expBoundParams[eBoundLoc1], 1e-5);
0175
0176 CHECK_CLOSE_ABS(estBoundParams[eBoundPhi], expBoundParams[eBoundPhi],
0177 1e-1);
0178 CHECK_CLOSE_ABS(estBoundParams[eBoundTheta],
0179 expBoundParams[eBoundTheta], 1e-2);
0180 CHECK_CLOSE_ABS(estBoundParams[eBoundQOverP],
0181 expBoundParams[eBoundQOverP], 1e-2);
0182
0183 CHECK_CLOSE_ABS(estBoundParams[eBoundTime], 0, 1e-6);
0184 }
0185 }
0186 }
0187 }
0188 }
0189
0190 BOOST_AUTO_TEST_CASE(trackparm_estimate_aligined) {
0191 Vector3 sp0{-72.775, -0.325, -615.6};
0192 Vector3 sp1{-84.325, -0.325, -715.6};
0193 Vector3 sp2{-98.175, -0.325, -835.6};
0194 Vector3 bField{0, 0, 0.000899377};
0195
0196 FreeVector params = estimateTrackParamsFromSeed(sp0, 0, sp1, sp2, bField);
0197 BOOST_CHECK_EQUAL(params[eFreeQOverP], 0);
0198 }
0199
0200 BOOST_AUTO_TEST_CASE(trackparm_estimate_degenerate) {
0201 const Vector3 bField{0, 0, 2_T};
0202
0203
0204
0205 {
0206 const Vector3 sp0{10, 0, 0};
0207 const Vector3 sp1{10, 0, 100};
0208 const Vector3 sp2{10, 0, 200};
0209
0210 BOOST_CHECK(
0211 !estimateTrackParamsFromSeed(sp0, 0, sp1, sp2, bField).allFinite());
0212 }
0213
0214
0215
0216 {
0217 const Vector3 sp0{10, 0, 0};
0218 const Vector3 sp1{20, 5, 0};
0219 const Vector3 sp2{20, 5, 50};
0220
0221 BOOST_CHECK(
0222 !estimateTrackParamsFromSeed(sp0, 0, sp1, sp2, bField).allFinite());
0223 }
0224 }
0225
0226
0227
0228 BOOST_AUTO_TEST_CASE(spacepoint_estimator_vs_truth) {
0229 Navigator navigator({
0230 geometry,
0231 true,
0232 true,
0233 false,
0234 });
0235 const Vector3 bField(0, 0, 2._T);
0236 auto field = std::make_shared<ConstantBField>(bField);
0237 ConstantFieldStepper stepper(std::move(field));
0238 ConstantFieldPropagator propagator(std::move(stepper), std::move(navigator));
0239
0240 std::array<double, 2> pArray = {0.5_GeV, 1.0_GeV};
0241 std::array<double, 3> phiArray = {20._degree, 0._degree, -20._degree};
0242 std::array<double, 3> thetaArray = {80._degree, 90._degree, 100._degree};
0243 std::array<double, 2> qArray = {1, -1};
0244
0245 for (const auto& p : pArray) {
0246 for (const auto& phi : phiArray) {
0247 for (const auto& theta : thetaArray) {
0248 for (const auto& q : qArray) {
0249 BOOST_TEST_INFO("Test track with p = " << p << ", phi = " << phi
0250 << ", theta = " << theta
0251 << ", q = " << q);
0252 auto start = makeParameters(phi, theta, p, q);
0253 auto measurements = createMeasurements(propagator, geoCtx, magCtx,
0254 start, resolutions, rng);
0255
0256
0257 std::vector<Vector3> spacePoints;
0258 std::set<GeometryIdentifier::Value> usedLayers;
0259 const Surface* bottomSurface = nullptr;
0260 for (const auto& sl : measurements.sourceLinks) {
0261 const auto geoId = sl.m_geometryId;
0262 const auto& layer = geoId.layer();
0263 if (const auto it = usedLayers.find(layer);
0264 it != usedLayers.end()) {
0265 continue;
0266 }
0267 const auto surface = geometry->findSurface(geoId);
0268 const Vector3 globalFakeMom(1, 1, 1);
0269 const Vector3 globalPos =
0270 surface->localToGlobal(geoCtx, sl.parameters, globalFakeMom);
0271 spacePoints.push_back(globalPos);
0272 usedLayers.insert(layer);
0273 if (spacePoints.size() == 1) {
0274 bottomSurface = surface;
0275 }
0276 }
0277
0278 if (spacePoints.size() < 3) {
0279 BOOST_TEST_WARN("Number of space points less than 3.");
0280 continue;
0281 }
0282
0283 const auto& expBoundParams = measurements.truthParameters[0];
0284
0285 auto freeResult =
0286 estimateTrackParamsFromSpacePoints(spacePoints, bField);
0287 BOOST_REQUIRE(freeResult.ok());
0288 auto boundResult = transformFreeToBoundParameters(
0289 *freeResult, *bottomSurface, geoCtx);
0290 BOOST_REQUIRE(boundResult.ok());
0291 const auto& estBoundParams = boundResult.value();
0292
0293 CHECK_CLOSE_ABS(estBoundParams[eBoundLoc0],
0294 expBoundParams[eBoundLoc0], 1e-4);
0295 CHECK_CLOSE_ABS(estBoundParams[eBoundLoc1],
0296 expBoundParams[eBoundLoc1], 1e-4);
0297 CHECK_CLOSE_ABS(estBoundParams[eBoundPhi], expBoundParams[eBoundPhi],
0298 1e-1);
0299 CHECK_CLOSE_ABS(estBoundParams[eBoundTheta],
0300 expBoundParams[eBoundTheta], 1e-2);
0301 CHECK_CLOSE_ABS(estBoundParams[eBoundQOverP],
0302 expBoundParams[eBoundQOverP], 1e-2);
0303
0304
0305
0306 auto free3 = estimateTrackParamsFromSpacePoints(
0307 std::span<const Vector3>(spacePoints).first(3), bField, 0);
0308 BOOST_CHECK(free3.ok());
0309 const FreeVector ref = estimateTrackParamsFromSeed(
0310 spacePoints[0], 0, spacePoints[1], spacePoints[2], bField);
0311 for (int i = 0; i < 3; ++i) {
0312 CHECK_CLOSE_ABS((*free3)[eFreeDir0 + i], ref[eFreeDir0 + i], 1e-6);
0313 }
0314 CHECK_CLOSE_ABS((*free3)[eFreeQOverP], ref[eFreeQOverP],
0315 1e-6 * std::abs(ref[eFreeQOverP]) + 1e-9);
0316 }
0317 }
0318 }
0319 }
0320 }
0321
0322
0323 BOOST_AUTO_TEST_CASE(spacepoint_estimator_large_arc) {
0324 const double bMag = 2._T;
0325 const Vector3 bField(0, 0, bMag);
0326 const double radius = 300;
0327 const double theta = 70._degree;
0328 const double lambda = 1 / std::tan(theta);
0329 const double alpha0 = 0.3;
0330 const double dAlpha = 40._degree;
0331 const std::size_t nsp = 6;
0332
0333 auto runWith = [&](std::size_t refineIter) {
0334 std::vector<Vector3> spacePoints;
0335 for (std::size_t i = 0; i < nsp; ++i) {
0336 const double a = alpha0 + i * dAlpha;
0337 const double s = radius * (a - alpha0);
0338 spacePoints.emplace_back(radius * std::cos(a), radius * std::sin(a),
0339 100 + lambda * s);
0340 }
0341 const Vector3 first = spacePoints.front();
0342
0343 auto result =
0344 estimateTrackParamsFromSpacePoints(spacePoints, bField, 0, refineIter);
0345 BOOST_CHECK(result.ok());
0346 const FreeVector& fp = *result;
0347 BOOST_CHECK(!fp.hasNaN());
0348
0349 for (int i = 0; i < 3; ++i) {
0350 CHECK_CLOSE_ABS(fp[eFreePos0 + i], first[i], 1e-6);
0351 }
0352
0353
0354 Vector3 dir(-std::sin(alpha0), std::cos(alpha0), lambda);
0355 dir.normalize();
0356 for (int i = 0; i < 3; ++i) {
0357 CHECK_CLOSE_ABS(fp[eFreeDir0 + i], dir[i], 1e-6);
0358 }
0359
0360
0361 const double expAbsQOverP = std::sin(theta) / (radius * bMag);
0362 CHECK_CLOSE_ABS(std::abs(fp[eFreeQOverP]), expAbsQOverP,
0363 1e-6 * expAbsQOverP);
0364 };
0365
0366 runWith(3);
0367 runWith(0);
0368 }
0369
0370
0371
0372 BOOST_AUTO_TEST_CASE(spacepoint_estimator_reference_index) {
0373 const double bMag = 2._T;
0374 const Vector3 bField(0, 0, bMag);
0375 const double radius = 300;
0376 const double theta = 70._degree;
0377 const double lambda = 1 / std::tan(theta);
0378 const double alpha0 = 0.3;
0379 const double dAlpha = 40._degree;
0380 const std::size_t nsp = 6;
0381
0382 std::vector<Vector3> spacePoints;
0383 for (std::size_t i = 0; i < nsp; ++i) {
0384 const double a = alpha0 + i * dAlpha;
0385 const double s = radius * (a - alpha0);
0386 spacePoints.emplace_back(radius * std::cos(a), radius * std::sin(a),
0387 100 + lambda * s);
0388 }
0389
0390 const auto atFirst = estimateTrackParamsFromSpacePoints(spacePoints, bField);
0391 BOOST_REQUIRE(atFirst.ok());
0392
0393 for (std::size_t ref = 0; ref < nsp; ++ref) {
0394 BOOST_TEST_CONTEXT("referenceIndex = " << ref) {
0395 auto result = estimateTrackParamsFromSpacePoints(spacePoints, bField, 0,
0396 0, {}, ref);
0397 BOOST_REQUIRE(result.ok());
0398 const FreeVector& fp = *result;
0399
0400
0401 for (int i = 0; i < 3; ++i) {
0402 CHECK_CLOSE_ABS(fp[eFreePos0 + i], spacePoints[ref][i], 1e-6);
0403 }
0404
0405
0406
0407 const double a = alpha0 + ref * dAlpha;
0408 Vector3 dir(-std::sin(a), std::cos(a), lambda);
0409 dir.normalize();
0410 for (int i = 0; i < 3; ++i) {
0411 CHECK_CLOSE_ABS(fp[eFreeDir0 + i], dir[i], 1e-6);
0412 }
0413
0414
0415
0416 BOOST_CHECK_EQUAL(fp[eFreeQOverP], (*atFirst)[eFreeQOverP]);
0417 }
0418 }
0419
0420
0421 const auto atZero =
0422 estimateTrackParamsFromSpacePoints(spacePoints, bField, 0, 0, {}, 0);
0423 BOOST_REQUIRE(atZero.ok());
0424 BOOST_CHECK_EQUAL(*atZero, *atFirst);
0425 }
0426
0427
0428 BOOST_AUTO_TEST_CASE(spacepoint_estimator_zero_field) {
0429 const Vector3 bField = Vector3::Zero();
0430 const Vector3 dir = Vector3(1, 2, 3).normalized();
0431 const Vector3 p0(10, -5, 7);
0432 std::vector<Vector3> spacePoints;
0433 for (int i = 0; i < 5; ++i) {
0434 spacePoints.push_back(p0 + i * 20 * dir);
0435 }
0436
0437 auto result = estimateTrackParamsFromSpacePoints(spacePoints, bField, 0);
0438 BOOST_CHECK(result.ok());
0439 const FreeVector& fp = *result;
0440 BOOST_CHECK_EQUAL(fp[eFreeQOverP], 0);
0441 for (int i = 0; i < 3; ++i) {
0442 CHECK_CLOSE_ABS(fp[eFreeDir0 + i], dir[i], 1e-9);
0443 CHECK_CLOSE_ABS(fp[eFreePos0 + i], p0[i], 1e-9);
0444 }
0445 }
0446
0447
0448 BOOST_AUTO_TEST_CASE(spacepoint_estimator_not_enough_points) {
0449 const std::array<Vector3, 2> spacePoints{Vector3(1, 0, 0), Vector3(2, 0, 0)};
0450 auto result =
0451 estimateTrackParamsFromSpacePoints(spacePoints, Vector3(0, 0, 2._T), 0);
0452 BOOST_CHECK(!result.ok());
0453 BOOST_CHECK(result.error() ==
0454 TrackParamsEstimationError::NotEnoughSpacePoints);
0455 }
0456
0457
0458 BOOST_AUTO_TEST_CASE(spacepoint_estimator_degenerate) {
0459 const std::array<Vector3, 4> spacePoints{Vector3(3, 4, 5), Vector3(3, 4, 5),
0460 Vector3(3, 4, 5), Vector3(3, 4, 5)};
0461 auto result =
0462 estimateTrackParamsFromSpacePoints(spacePoints, Vector3(0, 0, 2._T), 0);
0463 BOOST_CHECK(!result.ok());
0464 BOOST_CHECK(result.error() == TrackParamsEstimationError::DegenerateFit);
0465 }
0466
0467
0468 BOOST_AUTO_TEST_CASE(taubin_circle_fit) {
0469 const Vector2 center(3.5, -2);
0470 const double radius = 12;
0471 std::vector<Vector3> points;
0472 for (int i = 0; i < 7; ++i) {
0473 const double a = 0.2 + i * 0.35;
0474 const Vector2 xy = center + radius * Vector2(std::cos(a), std::sin(a));
0475 points.emplace_back(xy.x(), xy.y(), 0);
0476 }
0477 const auto circle = Acts::detail::fitCircleTaubin(points);
0478 BOOST_REQUIRE(circle.has_value());
0479 CHECK_CLOSE_ABS(circle->center.x(), center.x(), 1e-6);
0480 CHECK_CLOSE_ABS(circle->center.y(), center.y(), 1e-6);
0481 CHECK_CLOSE_ABS(circle->radius, radius, 1e-6);
0482
0483
0484 std::vector<Vector3> line;
0485 for (int i = 0; i < 5; ++i) {
0486 line.emplace_back(2 * i, 1 + 6 * i, 0);
0487 }
0488 BOOST_CHECK(!Acts::detail::fitCircleTaubin(line).has_value());
0489 }
0490
0491
0492 BOOST_AUTO_TEST_CASE(taubin_circle_fit_weighted) {
0493 const Vector2 center(3.5, -2);
0494 const double radius = 12;
0495 std::vector<Vector3> points;
0496 std::vector<double> weights;
0497 for (int i = 0; i < 7; ++i) {
0498 const double a = 0.2 + i * 0.35;
0499 const Vector2 xy = center + radius * Vector2(std::cos(a), std::sin(a));
0500 points.emplace_back(xy.x(), xy.y(), 0);
0501 weights.push_back(1);
0502 }
0503
0504 const double aOut = 0.2 + 6 * 0.35;
0505 const Vector2 xyOut =
0506 center + (radius + 5) * Vector2(std::cos(aOut), std::sin(aOut));
0507 points.back() = Vector3(xyOut.x(), xyOut.y(), 0);
0508 weights.back() = 1e-6;
0509
0510 const auto unweighted = Acts::detail::fitCircleTaubin(points);
0511 BOOST_REQUIRE(unweighted.has_value());
0512 BOOST_CHECK(std::abs(unweighted->radius - radius) > 0.1);
0513
0514 const auto weighted = Acts::detail::fitCircleTaubin(points, weights);
0515 BOOST_REQUIRE(weighted.has_value());
0516 CHECK_CLOSE_ABS(weighted->center.x(), center.x(), 1e-3);
0517 CHECK_CLOSE_ABS(weighted->center.y(), center.y(), 1e-3);
0518 CHECK_CLOSE_ABS(weighted->radius, radius, 1e-3);
0519 }
0520
0521
0522
0523 BOOST_AUTO_TEST_CASE(spacepoint_estimator_weighted) {
0524 const double bMag = 2._T;
0525 const Vector3 bField(0, 0, bMag);
0526 const double radius = 300;
0527 const double theta = 70._degree;
0528 const double lambda = 1 / std::tan(theta);
0529 const double alpha0 = 0.3;
0530 const double dAlpha = 40._degree;
0531 const std::size_t nsp = 6;
0532
0533 std::vector<Vector3> spacePoints;
0534 for (std::size_t i = 0; i < nsp; ++i) {
0535 const double a = alpha0 + i * dAlpha;
0536 const double s = radius * (a - alpha0);
0537 spacePoints.emplace_back(radius * std::cos(a), radius * std::sin(a),
0538 100 + lambda * s);
0539 }
0540
0541
0542 spacePoints[3].z() += 50;
0543 std::vector<double> weights(nsp, 1);
0544 weights[3] = 1e-6;
0545
0546 const std::span<const Vector3> sp(spacePoints);
0547
0548 auto biased = estimateTrackParamsFromSpacePoints(sp, bField, 0, 0);
0549 BOOST_CHECK(biased.ok());
0550 auto corrected =
0551 estimateTrackParamsFromSpacePoints(sp, bField, 0, 0, weights);
0552 BOOST_CHECK(corrected.ok());
0553
0554 Vector3 dir(-std::sin(alpha0), std::cos(alpha0), lambda);
0555 dir.normalize();
0556
0557
0558
0559 double biasedErr = 0, correctedErr = 0;
0560 for (int i = 0; i < 3; ++i) {
0561 biasedErr += std::abs((*biased)[eFreeDir0 + i] - dir[i]);
0562 correctedErr += std::abs((*corrected)[eFreeDir0 + i] - dir[i]);
0563 }
0564 BOOST_CHECK(correctedErr < biasedErr);
0565 CHECK_CLOSE_ABS((*corrected)[eFreeDir0 + 2], dir[2], 1e-3);
0566 }
0567
0568 BOOST_AUTO_TEST_SUITE_END()
0569
0570 }