EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CylinderSurfaceTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CylinderSurfaceTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-2018 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include <boost/test/data/test_case.hpp>
10 #include <boost/test/tools/output_test_stream.hpp>
11 #include <boost/test/unit_test.hpp>
12 
18 
19 #include <limits>
20 
21 namespace tt = boost::test_tools;
22 using boost::test_tools::output_test_stream;
23 namespace utf = boost::unit_test;
24 
25 namespace Acts {
26 
27 namespace Test {
28 
29 // Create a test context
31 
32 BOOST_AUTO_TEST_SUITE(CylinderSurfaces)
34 BOOST_AUTO_TEST_CASE(CylinderSurfaceConstruction) {
35  // CylinderSurface default constructor is deleted
36  //
38  double radius(1.0), halfZ(10.), halfPhiSector(M_PI / 8.);
39  Translation3D translation{0., 1., 2.};
40  auto pTransform = Transform3D(translation);
41  BOOST_CHECK_EQUAL(
42  Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ)->type(),
44  //
46  BOOST_CHECK_EQUAL(Surface::makeShared<CylinderSurface>(pTransform, radius,
47  halfZ, halfPhiSector)
48  ->type(),
50 
52  auto pCylinderBounds = std::make_shared<const CylinderBounds>(radius, halfZ);
53  BOOST_CHECK_EQUAL(
54  Surface::makeShared<CylinderSurface>(pTransform, pCylinderBounds)->type(),
56  //
57  //
59  auto cylinderSurfaceObject =
60  Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ);
61  auto copiedCylinderSurface =
62  Surface::makeShared<CylinderSurface>(*cylinderSurfaceObject);
63  BOOST_CHECK_EQUAL(copiedCylinderSurface->type(), Surface::Cylinder);
64  BOOST_CHECK(*copiedCylinderSurface == *cylinderSurfaceObject);
65  //
67  auto copiedTransformedCylinderSurface = Surface::makeShared<CylinderSurface>(
68  testContext, *cylinderSurfaceObject, pTransform);
69  BOOST_CHECK_EQUAL(copiedTransformedCylinderSurface->type(),
71 
73  BOOST_CHECK_THROW(auto nullBounds = Surface::makeShared<CylinderSurface>(
74  Transform3D::Identity(), nullptr),
76 }
77 //
79 BOOST_AUTO_TEST_CASE(CylinderSurfaceProperties) {
81  double radius(1.0), halfZ(10.);
82  Translation3D translation{0., 1., 2.};
83  auto pTransform = Transform3D(translation);
84  auto cylinderSurfaceObject =
85  Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ);
86  //
88  BOOST_CHECK_EQUAL(cylinderSurfaceObject->type(), Surface::Cylinder);
89  //
91  Vector3D binningPosition{0., 1., 2.};
93  cylinderSurfaceObject->binningPosition(testContext, BinningValue::binPhi),
94  binningPosition, 1e-9);
95  //
97  double rootHalf = std::sqrt(0.5);
98  Vector3D globalPosition{rootHalf, 1. - rootHalf, 0.};
99  Vector3D globalPositionZ{rootHalf, 1. - rootHalf, 2.0};
100  Vector3D momentum{15., 15., 15.};
101  Vector3D momentum2{6.6, -3., 2.};
102  RotationMatrix3D expectedFrame;
103  expectedFrame << rootHalf, 0., rootHalf, rootHalf, 0., -rootHalf, 0., 1., 0.;
104  // check without shift
105  CHECK_CLOSE_OR_SMALL(cylinderSurfaceObject->referenceFrame(
106  testContext, globalPosition, momentum),
107  expectedFrame, 1e-6, 1e-9);
108  // check with shift and different momentum
109  CHECK_CLOSE_OR_SMALL(cylinderSurfaceObject->referenceFrame(
110  testContext, globalPositionZ, momentum2),
111  expectedFrame, 1e-6, 1e-9);
112  //
114  Vector3D origin{0., 0., 0.};
115  Vector3D normal3D = {0., -1., 0.};
116  CHECK_CLOSE_ABS(cylinderSurfaceObject->normal(testContext, origin), normal3D,
117  1e-9);
118 
119  Vector3D pos45deg = {rootHalf, 1 + rootHalf, 0.};
120  Vector3D pos45degZ = {rootHalf, 1 + rootHalf, 4.};
121  Vector3D normal45deg = {rootHalf, rootHalf, 0.};
122  // test the normal vector
123  CHECK_CLOSE_ABS(cylinderSurfaceObject->normal(testContext, pos45deg),
124  normal45deg, 1e-6 * rootHalf);
125  // thest that the normal vector is independent of z coordinate
126  CHECK_CLOSE_ABS(cylinderSurfaceObject->normal(testContext, pos45degZ),
127  normal45deg, 1e-6 * rootHalf);
128  //
130  Vector2D positionPiBy2(1.0, 0.);
131  Vector3D normalAtPiBy2{std::cos(1.), std::sin(1.), 0.};
132  CHECK_CLOSE_ABS(cylinderSurfaceObject->normal(testContext, positionPiBy2),
133  normalAtPiBy2, 1e-9);
134 
135  //
137  Vector3D symmetryAxis{0., 0., 1.};
138  CHECK_CLOSE_ABS(cylinderSurfaceObject->rotSymmetryAxis(testContext),
139  symmetryAxis, 1e-9);
140  //
142  BOOST_CHECK_EQUAL(cylinderSurfaceObject->bounds().type(),
144  //
146  Vector2D localPosition{0., 0.};
147  globalPosition = cylinderSurfaceObject->localToGlobal(
148  testContext, localPosition, momentum);
149  Vector3D expectedPosition{1, 1, 2};
150  BOOST_CHECK_EQUAL(globalPosition, expectedPosition);
151  //
153  localPosition = cylinderSurfaceObject
154  ->globalToLocal(testContext, globalPosition, momentum)
155  .value();
156  Vector2D expectedLocalPosition{0., 0.};
157  BOOST_CHECK_EQUAL(localPosition, expectedLocalPosition);
158  //
160  Vector3D offSurface{100, 1, 2};
161  BOOST_CHECK(cylinderSurfaceObject->isOnSurface(testContext, globalPosition,
162  momentum, true));
163  BOOST_CHECK(!cylinderSurfaceObject->isOnSurface(testContext, offSurface,
164  momentum, true));
165  //
167  Vector3D direction{-1., 0, 0};
168  auto sfIntersection = cylinderSurfaceObject->intersect(
169  testContext, offSurface, direction, false);
170  Intersection3D expectedIntersect{Vector3D{1, 1, 2}, 99.,
171  Intersection3D::Status::reachable};
172  BOOST_CHECK(bool(sfIntersection));
173  CHECK_CLOSE_ABS(sfIntersection.intersection.position,
174  expectedIntersect.position, 1e-9);
175  CHECK_CLOSE_ABS(sfIntersection.intersection.pathLength,
176  expectedIntersect.pathLength, 1e-9);
177  // there is a second solution & and it should be valid
178  BOOST_CHECK(sfIntersection.alternative);
179  // And it's path should be further away then the primary solution
180  double pn = sfIntersection.intersection.pathLength;
181  double pa = sfIntersection.alternative.pathLength;
182  BOOST_CHECK(pn * pn < pa * pa);
183  BOOST_CHECK_EQUAL(sfIntersection.object, cylinderSurfaceObject.get());
184 
185  //
187  CHECK_CLOSE_REL(cylinderSurfaceObject->pathCorrection(testContext, offSurface,
188  momentum.normalized()),
189  std::sqrt(3.), 0.01);
190  //
192  BOOST_CHECK_EQUAL(cylinderSurfaceObject->name(),
193  std::string("Acts::CylinderSurface"));
194  //
196  boost::test_tools::output_test_stream dumpOuput;
197  cylinderSurfaceObject->toStream(testContext, dumpOuput);
198  BOOST_CHECK(
199  dumpOuput.is_equal("Acts::CylinderSurface\n\
200  Center position (x, y, z) = (0.0000, 1.0000, 2.0000)\n\
201  Rotation: colX = (1.000000, 0.000000, 0.000000)\n\
202  colY = (0.000000, 1.000000, 0.000000)\n\
203  colZ = (0.000000, 0.000000, 1.000000)\n\
204  Bounds : Acts::CylinderBounds: (radius, halfLengthZ, halfPhiSector, averagePhi) = (1.0000000, 10.0000000, 3.1415927, 0.0000000)"));
205 }
206 
207 BOOST_AUTO_TEST_CASE(CylinderSurfaceEqualityOperators) {
208  double radius(1.0), halfZ(10.);
209  Translation3D translation{0., 1., 2.};
210  auto pTransform = Transform3D(translation);
211  auto cylinderSurfaceObject =
212  Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ);
213  //
214  auto cylinderSurfaceObject2 =
215  Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ);
216  //
218  BOOST_CHECK(*cylinderSurfaceObject == *cylinderSurfaceObject2);
219  //
220  BOOST_TEST_CHECKPOINT(
221  "Create and then assign a CylinderSurface object to the existing one");
223  auto assignedCylinderSurface =
224  Surface::makeShared<CylinderSurface>(Transform3D::Identity(), 6.6, 5.4);
225  *assignedCylinderSurface = *cylinderSurfaceObject;
227  BOOST_CHECK(*assignedCylinderSurface == *cylinderSurfaceObject);
228 }
229 
231 BOOST_AUTO_TEST_CASE(CylinderSurfaceExtent) {
232  // Some radius and half length
233  double radius(1.0), halfZ(10.);
234  Translation3D translation{0., 0., 2.};
235  auto pTransform = Transform3D(translation);
236  auto cylinderSurface =
237  Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ);
238  // The Extent, let's measure it
239  auto cylinderExtent =
240  cylinderSurface->polyhedronRepresentation(testContext, 1).extent();
241 
242  CHECK_CLOSE_ABS(-8, cylinderExtent.min(binZ), s_onSurfaceTolerance);
243  CHECK_CLOSE_ABS(12, cylinderExtent.max(binZ), s_onSurfaceTolerance);
244  CHECK_CLOSE_ABS(radius, cylinderExtent.min(binR), s_onSurfaceTolerance);
245  CHECK_CLOSE_ABS(radius, cylinderExtent.max(binR), s_onSurfaceTolerance);
246  CHECK_CLOSE_ABS(-radius, cylinderExtent.min(binX), s_onSurfaceTolerance);
247  CHECK_CLOSE_ABS(radius, cylinderExtent.max(binX), s_onSurfaceTolerance);
248  CHECK_CLOSE_ABS(-radius, cylinderExtent.min(binY), s_onSurfaceTolerance);
249  CHECK_CLOSE_ABS(radius, cylinderExtent.max(binY), s_onSurfaceTolerance);
250 }
251 
253 BOOST_AUTO_TEST_CASE(CylinderSurfaceAlignment) {
254  double radius(1.0), halfZ(10.);
255  Translation3D translation{0., 1., 2.};
256  auto pTransform = Transform3D(translation);
257  auto cylinderSurfaceObject =
258  Surface::makeShared<CylinderSurface>(pTransform, radius, halfZ);
259 
260  const auto& rotation = pTransform.rotation();
261  // The local frame z axis
262  const Vector3D localZAxis = rotation.col(2);
263  // Check the local z axis is aligned to global z axis
264  CHECK_CLOSE_ABS(localZAxis, Vector3D(0., 0., 1.), 1e-15);
265 
267  Vector3D globalPosition{0, 2, 2};
268 
269  // Test the derivative of bound track parameters local position w.r.t.
270  // position in local 3D Cartesian coordinates
271  const auto& loc3DToLocBound =
272  cylinderSurfaceObject->localCartesianToBoundLocalDerivative(
273  testContext, globalPosition);
274  // Check if the result is as expected
275  LocalCartesianToBoundLocalMatrix expLoc3DToLocBound =
276  LocalCartesianToBoundLocalMatrix::Zero();
277  expLoc3DToLocBound << -1, 0, 0, 0, 0, 1;
278  CHECK_CLOSE_ABS(loc3DToLocBound, expLoc3DToLocBound, 1e-10);
279 }
280 
281 BOOST_AUTO_TEST_SUITE_END()
282 
283 } // namespace Test
284 
285 } // namespace Acts