EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BVHDataTestCase.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file BVHDataTestCase.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 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 namespace bdata = boost::unit_test::data;
12 
15 
16 std::tuple<std::vector<const Volume*>, std::shared_ptr<TrackingGeometry>>
17 gridBoxFactory(size_t n = NBOXES, double hl = 1000, size_t octd = 5) {
18  Box::Size size(Acts::Vector3D(2, 2, 2));
19 
20  std::shared_ptr<CuboidVolumeBounds> vbds =
21  std::make_shared<CuboidVolumeBounds>(10, 10, 10);
22 
23  double min = -hl;
24  double max = hl;
25 
26  double step = (max - min) / double(n);
27  std::vector<std::unique_ptr<const Volume>> volumes;
28  std::vector<std::unique_ptr<Box>> boxStore;
29  boxStore.reserve((n + 1) * (n + 1) * (n + 1));
30 
31  std::cout << "generating: " << (n + 1) * (n + 1) * (n + 1)
32  << " bounding boxes" << std::endl;
33 
34  std::vector<Box*> boxes;
35  boxes.reserve(boxStore.size());
36 
37  for (size_t i = 0; i <= n; i++) {
38  for (size_t j = 0; j <= n; j++) {
39  for (size_t k = 0; k <= n; k++) {
40  Vector3D pos(min + i * step, min + j * step, min + k * step);
41 
42  auto trf = Transform3D(Translation3D(pos));
43  auto vol = std::make_unique<AbstractVolume>(trf, vbds);
44 
45  volumes.push_back(std::move(vol));
46  boxStore.push_back(
47  std::make_unique<Box>(volumes.back()->boundingBox()));
48  boxes.push_back(boxStore.back().get());
49  }
50  }
51  }
52 
53  Box* top = make_octree(boxStore, boxes, octd);
54 
55  // create trackingvolume
56  // will own the volumes, so make non-owning copy first
57  std::vector<const Volume*> volumeCopy;
58  volumeCopy.reserve(volumes.size());
59  for (auto& vol : volumes) {
60  volumeCopy.push_back(vol.get());
61  }
62 
63  // box like overall shape
64  auto tvBounds =
65  std::make_shared<CuboidVolumeBounds>(hl * 1.1, hl * 1.1, hl * 1.1);
66 
67  auto tv = TrackingVolume::create(Transform3D::Identity(), tvBounds,
68  std::move(boxStore), std::move(volumes), top,
69  nullptr, "TheVolume");
70 
71  auto tg = std::make_shared<TrackingGeometry>(tv);
72 
73  return {std::move(volumeCopy), tg};
74 }
75 
76 auto [volumes, tg] = gridBoxFactory();
77 
79  bvhnavigation_test,
80  bdata::random((bdata::seed = 7, bdata::engine = std::mt19937(),
81  bdata::distribution = std::uniform_real_distribution<>(-5,
82  5))) ^
83  bdata::random((bdata::seed = 2, bdata::engine = std::mt19937(),
84  bdata::distribution =
85  std::uniform_real_distribution<>(-M_PI, M_PI))) ^
86  bdata::random((bdata::seed = 3, bdata::engine = std::mt19937(),
87  bdata::distribution =
88  std::uniform_real_distribution<>(-100, 100))) ^
89  bdata::random((bdata::seed = 4, bdata::engine = std::mt19937(),
90  bdata::distribution =
91  std::uniform_real_distribution<>(-100, 100))) ^
92  bdata::random((bdata::seed = 5, bdata::engine = std::mt19937(),
93  bdata::distribution =
94  std::uniform_real_distribution<>(-100, 100))) ^
96  eta, phi, x, y, z, index) {
97  using namespace Acts::UnitLiterals;
98  (void)index;
99 
100  // construct ray from parameters
101  double theta = 2 * std::atan(std::exp(-eta));
102  Acts::Vector3D dir;
103  dir << std::cos(phi), std::sin(phi), 1. / std::tan(theta);
104  dir.normalize();
105  Ray ray({x, y, z}, dir);
106 
107  // naive collection: iterate over all the boxes
108  std::vector<SurfaceIntersection> hits;
109  for (const auto& vol : volumes) {
110  const auto& absVol = dynamic_cast<const AbstractVolume&>(*vol);
111  auto bndSurfaces = absVol.boundarySurfaces();
112  // collect all surfaces that are hit
113  for (const auto& bndSrf : bndSurfaces) {
114  const auto& srf = bndSrf->surfaceRepresentation();
115  auto sri = srf.intersect(tgContext, ray.origin(), ray.dir(), true);
116  if (sri and sri.intersection.pathLength >= s_onSurfaceTolerance) {
117  // does intersect
118  hits.push_back(std::move(sri));
119  }
120  }
121  }
122 
123  // sort by path length
124  std::sort(hits.begin(), hits.end());
125  std::vector<const Surface*> expHits;
126  expHits.reserve(hits.size());
127  for (const auto& hit : hits) {
128  expHits.push_back(hit.object);
129  }
130 
131  // now do the same through a propagator
132  using SteppingLogger = Acts::detail::SteppingLogger;
133  using Stepper = StraightLineStepper;
134  using PropagatorType = Propagator<Stepper, Navigator>;
135 
136  Stepper stepper{};
137  Navigator navigator(tg);
138  PropagatorType propagator(std::move(stepper), navigator);
139 
140  using ActionList = Acts::ActionList<SteppingLogger>;
141  using AbortConditions = Acts::AbortList<>;
142 
145 
146  options.pathLimit = 20_m;
147 
148  Acts::Vector4D pos4 = Acts::Vector4D::Zero();
149  pos4.segment<3>(Acts::ePos0) = ray.origin();
150  // momentum value should be irrelevant.
151  Acts::CurvilinearTrackParameters startPar(pos4, ray.dir(), 50_GeV, 1_e);
152 
153  const auto result = propagator.propagate(startPar, options).value();
154 
155  // collect surfaces
156  std::vector<const Surface*> actHits;
157  auto steppingResults =
158  result.template get<SteppingLogger::result_type>().steps;
159  for (const auto& step : steppingResults) {
160  if (!step.surface) {
161  continue;
162  }
163 
164  auto sensitiveID = step.surface->geometryId().sensitive();
165  if (sensitiveID != 0) {
166  actHits.push_back(step.surface.get());
167  }
168  }
169 
170  BOOST_CHECK_EQUAL(expHits.size(), actHits.size());
171  for (size_t i = 0; i < expHits.size(); i++) {
172  const Surface* exp = expHits[i];
173  const Surface* act = actHits[i];
174 
175  BOOST_CHECK_EQUAL(exp, act);
176  BOOST_CHECK_EQUAL(exp->geometryId(), act->geometryId());
177  }
178 }