File indexing completed on 2025-08-06 08:11:35
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/Tests/CommonHelpers/FloatComparisons.hpp"
0013 #include "Acts/Utilities/UnitVectors.hpp"
0014
0015 #include <algorithm>
0016 #include <cmath>
0017 #include <limits>
0018
0019 using Acts::Vector3;
0020
0021 namespace {
0022 constexpr auto eps = std::numeric_limits<double>::epsilon();
0023 }
0024
0025 BOOST_AUTO_TEST_SUITE(UnitVectors)
0026
0027 BOOST_AUTO_TEST_CASE(DirectionPhiEta) {
0028 using Acts::makeDirectionFromPhiEta;
0029
0030
0031 const auto xPos1 = makeDirectionFromPhiEta(0.0, 0.0);
0032 CHECK_CLOSE_REL(xPos1.norm(), 1, eps);
0033 CHECK_CLOSE_REL(xPos1.dot(Vector3(1, 0, 0)), 1, eps);
0034 const auto xPos2 = makeDirectionFromPhiEta(2 * M_PI, 0.0);
0035 CHECK_CLOSE_REL(xPos2.norm(), 1, eps);
0036 CHECK_CLOSE_REL(xPos2.dot(Vector3(1, 0, 0)), 1, eps);
0037
0038 const auto xNeg1 = makeDirectionFromPhiEta(M_PI, 0.0);
0039 CHECK_CLOSE_REL(xNeg1.norm(), 1, eps);
0040 CHECK_CLOSE_REL(xNeg1.dot(Vector3(-1, 0, 0)), 1, eps);
0041 const auto xNeg2 = makeDirectionFromPhiEta(-M_PI, 0.0);
0042 CHECK_CLOSE_REL(xNeg2.norm(), 1, eps);
0043 CHECK_CLOSE_REL(xNeg2.dot(Vector3(-1, 0, 0)), 1, eps);
0044
0045 const auto yPos1 = makeDirectionFromPhiEta(M_PI_2, 0.0);
0046 CHECK_CLOSE_REL(yPos1.norm(), 1, eps);
0047 CHECK_CLOSE_REL(yPos1.dot(Vector3(0, 1, 0)), 1, eps);
0048 const auto yPos2 = makeDirectionFromPhiEta(-3 * M_PI_2, 0.0);
0049 CHECK_CLOSE_REL(yPos2.norm(), 1, eps);
0050 CHECK_CLOSE_REL(yPos2.dot(Vector3(0, 1, 0)), 1, eps);
0051
0052 const auto yNeg1 = makeDirectionFromPhiEta(-M_PI_2, 0.0);
0053 CHECK_CLOSE_REL(yNeg1.norm(), 1, eps);
0054 CHECK_CLOSE_REL(yNeg1.dot(Vector3(0, -1, 0)), 1, eps);
0055 const auto yNeg2 = makeDirectionFromPhiEta(3 * M_PI_2, 0.0);
0056 CHECK_CLOSE_REL(yNeg2.norm(), 1, eps);
0057 CHECK_CLOSE_REL(yNeg2.dot(Vector3(0, -1, 0)), 1, eps);
0058
0059 const auto inf = std::numeric_limits<double>::infinity();
0060
0061 const auto zPos1 = makeDirectionFromPhiEta(0.0, inf);
0062 CHECK_CLOSE_REL(zPos1.norm(), 1, eps);
0063 CHECK_CLOSE_REL(zPos1.dot(Vector3(0, 0, 1)), 1, eps);
0064 const auto zPos2 = makeDirectionFromPhiEta(M_PI_2, inf);
0065 CHECK_CLOSE_REL(zPos2.norm(), 1, eps);
0066 CHECK_CLOSE_REL(zPos2.dot(Vector3(0, 0, 1)), 1, eps);
0067
0068 const auto zNeg1 = makeDirectionFromPhiEta(0.0, -inf);
0069 CHECK_CLOSE_REL(zNeg1.norm(), 1, eps);
0070 CHECK_CLOSE_REL(zNeg1.dot(Vector3(0, 0, -1)), 1, eps);
0071 const auto zNeg2 = makeDirectionFromPhiEta(M_PI_2, -inf);
0072 CHECK_CLOSE_REL(zNeg2.norm(), 1, eps);
0073 CHECK_CLOSE_REL(zNeg2.dot(Vector3(0, 0, -1)), 1, eps);
0074
0075
0076 const auto mixed1 = makeDirectionFromPhiEta(M_PI_4, 1.0);
0077 CHECK_CLOSE_REL(mixed1.norm(), 1, eps);
0078 CHECK_CLOSE_REL(
0079 mixed1.dot(Vector3(1, 1, M_SQRT2 * std::sinh(1.0)).normalized()), 1, eps);
0080 const auto mixed2 = makeDirectionFromPhiEta(M_PI_4, -1.0);
0081 CHECK_CLOSE_REL(mixed2.norm(), 1, eps);
0082 CHECK_CLOSE_REL(
0083 mixed2.dot(Vector3(1, 1, M_SQRT2 * std::sinh(-1.0)).normalized()), 1,
0084 eps);
0085 const auto mixed3 = makeDirectionFromPhiEta(-M_PI_4, -1.0);
0086 CHECK_CLOSE_REL(mixed3.norm(), 1, eps);
0087 CHECK_CLOSE_REL(
0088 mixed3.dot(Vector3(1, -1, M_SQRT2 * std::sinh(-1.0)).normalized()), 1,
0089 eps);
0090 }
0091
0092 BOOST_AUTO_TEST_CASE(DirectionPhiTheta) {
0093 using Acts::makeDirectionFromPhiTheta;
0094
0095
0096 const auto xPos1 = makeDirectionFromPhiTheta(0.0, M_PI_2);
0097 CHECK_CLOSE_REL(xPos1.norm(), 1, eps);
0098 CHECK_CLOSE_REL(xPos1.dot(Vector3(1, 0, 0)), 1, eps);
0099 const auto xPos2 = makeDirectionFromPhiTheta(2 * M_PI, M_PI_2);
0100 CHECK_CLOSE_REL(xPos2.norm(), 1, eps);
0101 CHECK_CLOSE_REL(xPos2.dot(Vector3(1, 0, 0)), 1, eps);
0102
0103 const auto xNeg1 = makeDirectionFromPhiTheta(M_PI, M_PI_2);
0104 CHECK_CLOSE_REL(xNeg1.norm(), 1, eps);
0105 CHECK_CLOSE_REL(xNeg1.dot(Vector3(-1, 0, 0)), 1, eps);
0106 const auto xNeg2 = makeDirectionFromPhiTheta(-M_PI, M_PI_2);
0107 CHECK_CLOSE_REL(xNeg2.norm(), 1, eps);
0108 CHECK_CLOSE_REL(xNeg2.dot(Vector3(-1, 0, 0)), 1, eps);
0109
0110 const auto yPos1 = makeDirectionFromPhiTheta(M_PI_2, M_PI_2);
0111 CHECK_CLOSE_REL(yPos1.norm(), 1, eps);
0112 CHECK_CLOSE_REL(yPos1.dot(Vector3(0, 1, 0)), 1, eps);
0113 const auto yPos2 = makeDirectionFromPhiTheta(-3 * M_PI_2, M_PI_2);
0114 CHECK_CLOSE_REL(yPos2.norm(), 1, eps);
0115 CHECK_CLOSE_REL(yPos2.dot(Vector3(0, 1, 0)), 1, eps);
0116
0117 const auto yNeg1 = makeDirectionFromPhiTheta(-M_PI_2, M_PI_2);
0118 CHECK_CLOSE_REL(yNeg1.norm(), 1, eps);
0119 CHECK_CLOSE_REL(yNeg1.dot(Vector3(0, -1, 0)), 1, eps);
0120 const auto yNeg2 = makeDirectionFromPhiTheta(3 * M_PI_2, M_PI_2);
0121 CHECK_CLOSE_REL(yNeg2.norm(), 1, eps);
0122 CHECK_CLOSE_REL(yNeg2.dot(Vector3(0, -1, 0)), 1, eps);
0123
0124
0125 const auto zPos1 = makeDirectionFromPhiTheta(0.0, 0.0);
0126 CHECK_CLOSE_REL(zPos1.norm(), 1, eps);
0127 CHECK_CLOSE_REL(zPos1.dot(Vector3(0, 0, 1)), 1, eps);
0128 const auto zPos2 = makeDirectionFromPhiTheta(M_PI_2, 0.0);
0129 CHECK_CLOSE_REL(zPos2.norm(), 1, eps);
0130 CHECK_CLOSE_REL(zPos2.dot(Vector3(0, 0, 1)), 1, eps);
0131
0132 const auto zNeg1 = makeDirectionFromPhiTheta(0.0, M_PI);
0133 CHECK_CLOSE_REL(zNeg1.norm(), 1, eps);
0134 CHECK_CLOSE_REL(zNeg1.dot(Vector3(0, 0, -1)), 1, eps);
0135 const auto zNeg2 = makeDirectionFromPhiTheta(M_PI_2, M_PI);
0136 CHECK_CLOSE_REL(zNeg2.norm(), 1, eps);
0137 CHECK_CLOSE_REL(zNeg2.dot(Vector3(0, 0, -1)), 1, eps);
0138
0139
0140 const auto mixed1 = makeDirectionFromPhiTheta(M_PI_4, M_PI_4);
0141 CHECK_CLOSE_REL(mixed1.norm(), 1, eps);
0142 CHECK_CLOSE_REL(mixed1.dot(Vector3(1, 1, M_SQRT2).normalized()), 1, eps);
0143 const auto mixed2 = makeDirectionFromPhiTheta(M_PI_4, 3 * M_PI_4);
0144 CHECK_CLOSE_REL(mixed2.norm(), 1, eps);
0145 CHECK_CLOSE_REL(mixed2.dot(Vector3(1, 1, -M_SQRT2).normalized()), 1, eps);
0146 const auto mixed3 = makeDirectionFromPhiTheta(-M_PI_4, 3 * M_PI_4);
0147 CHECK_CLOSE_REL(mixed3.norm(), 1, eps);
0148 CHECK_CLOSE_REL(mixed3.dot(Vector3(1, -1, -M_SQRT2).normalized()), 1, eps);
0149 }
0150
0151 namespace {
0152 template <typename Direction, typename RefUnitU, typename RefUnitV>
0153 void testCurvilinear(const Eigen::MatrixBase<Direction>& direction,
0154 const Eigen::MatrixBase<RefUnitU>& refU,
0155 const Eigen::MatrixBase<RefUnitV>& refV) {
0156 const auto u = Acts::makeCurvilinearUnitU(direction);
0157 const auto uv = Acts::makeCurvilinearUnitVectors(direction);
0158
0159 CHECK_CLOSE_ABS(u.norm(), 1, eps);
0160 CHECK_CLOSE_ABS(uv.first.norm(), 1, eps);
0161 CHECK_CLOSE_ABS(uv.second.norm(), 1, eps);
0162
0163 CHECK_SMALL(u.dot(direction), eps);
0164 CHECK_SMALL(uv.first.dot(direction), eps);
0165 CHECK_SMALL(uv.second.dot(direction), eps);
0166 CHECK_SMALL(uv.first.dot(uv.second), eps);
0167
0168 CHECK_SMALL(u[2], eps);
0169 CHECK_SMALL(uv.first[2], eps);
0170
0171
0172 CHECK_CLOSE_ABS(u.dot(refU), 1, eps);
0173 CHECK_CLOSE_ABS(uv.first.dot(refU), 1, eps);
0174 CHECK_CLOSE_ABS(uv.second.dot(refV), 1, eps);
0175 }
0176 }
0177
0178 BOOST_AUTO_TEST_CASE(CurvilinearTransverse) {
0179
0180 testCurvilinear(Vector3(1, 1, 0), Vector3(-1, 1, 0).normalized(),
0181 Vector3(0, 0, 1).normalized());
0182 }
0183
0184 BOOST_AUTO_TEST_CASE(CurvilinearPositiveZ) {
0185
0186 testCurvilinear(Vector3(0, 0, 1), Vector3(1, 0, 0), Vector3(0, 1, 0));
0187 }
0188
0189 BOOST_AUTO_TEST_CASE(CurvilinearNegativeZ) {
0190
0191 testCurvilinear(Vector3(0, 0, -1), Vector3(1, 0, 0), Vector3(0, -1, 0));
0192 }
0193
0194 BOOST_AUTO_TEST_CASE(CurvilinearCloseToZ) {
0195
0196 testCurvilinear(Vector3(0, 32 * eps, 1 - 32 * eps), Vector3(-1, 0, 0),
0197 Vector3(0, -1, 32 * eps));
0198 }
0199
0200 BOOST_AUTO_TEST_SUITE_END()