LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
BoxBoundedGeo.cxx
Go to the documentation of this file.
1 
9 
10 // LArSoft libraries
12 
13 // ROOT libraries
14 #include "Math/GenVector/Cartesian3D.h"
15 #include "Math/GenVector/DisplacementVector3D.h"
16 #include "Math/GenVector/PositionVector3D.h"
17 
18 #include <array>
19 #include <type_traits>
20 #include <vector>
21 
22 namespace geo {
23  //----------------------------------------------------------------------------
24  bool BoxBoundedGeo::ContainsPosition(TVector3 const& point, double wiggle /* = 1.0 */) const
25  {
26  return ContainsPosition(geo::vect::toPoint(point), wiggle);
27  }
28 
29  //----------------------------------------------------------------------------
30  bool BoxBoundedGeo::ContainsPosition(double const* point, double wiggle /* = 1.0 */) const
31  {
32  return ContainsPosition(geo::vect::makePointFromCoords(point), wiggle);
33  }
34 
35  //----------------------------------------------------------------------------
36  std::vector<geo::Point_t> BoxBoundedGeo::GetIntersections(
37  geo::Point_t const& TrajectoryStart,
38  geo::Vector_t const& TrajectoryDirect) const
39  {
40 
41  std::vector<geo::Point_t> IntersectionPoints;
42  std::vector<double> LineParameters;
43 
44  // Generate normal vectors and offsets for every plane of the box
45  // All normal vectors are headed outwards
46  // BUG the double brace syntax is required to work around clang bug 21629
47  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
48  static std::array<geo::Vector_t, 6U> const NormalVectors = {{
49  -geo::Xaxis<geo::Vector_t>(),
50  geo::Xaxis<geo::Vector_t>(), // anode, cathode,
51  -geo::Yaxis<geo::Vector_t>(),
52  geo::Yaxis<geo::Vector_t>(), // bottom, top,
53  -geo::Zaxis<geo::Vector_t>(),
54  geo::Zaxis<geo::Vector_t>() // upstream, downstream
55  }};
56  // BUG the double brace syntax is required to work around clang bug 21629
57  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
58  std::array<geo::Point_t, 6U> const NormalVectorOffsets = {{
59  geo::Point_t{Min().X(), Min().Y(), Min().Z()}, // Anode offset
60  geo::Point_t{Max().X(), Min().Y(), Min().Z()}, // Cathode
61  geo::Point_t{Min().X(), Min().Y(), Min().Z()}, // Bottom
62  geo::Point_t{Min().X(), Max().Y(), Min().Z()}, // Top
63  geo::Point_t{Min().X(), Min().Y(), Min().Z()}, // upstream
64  geo::Point_t{Min().X(), Min().Y(), Max().Z()} // downstream
65  }};
66 
67  // Loop over all surfaces of the box
68  for (unsigned int face_no = 0; face_no < NormalVectors.size(); face_no++) {
69  // Check if trajectory and surface are not parallel
70  if (NormalVectors[face_no].Dot(TrajectoryDirect)) {
71  // Calculate the line parameter for the intersection points
72  LineParameters.push_back(
73  NormalVectors[face_no].Dot(NormalVectorOffsets.at(face_no) - TrajectoryStart) /
74  NormalVectors[face_no].Dot(TrajectoryDirect));
75  }
76  else
77  continue;
78 
79  // Calculate intersection point using the line parameter
80  IntersectionPoints.push_back(TrajectoryStart + LineParameters.back() * TrajectoryDirect);
81 
82  // Coordinate which should be ignored when checking for limits added by Christoph Rudolf von Rohr 05/21/2016
83  unsigned int NoCheckCoord;
84 
85  // Calculate NoCheckCoord out of the face_no
86  if (face_no % 2) {
87  // Convert odd face number to coordinate
88  NoCheckCoord = (face_no - 1) / 2;
89  }
90  else {
91  // Convert even face number to coordinate
92  NoCheckCoord = face_no / 2;
93  }
94 
95  // Loop over all three space coordinates
96  unsigned int coord = 0;
97  for (auto extractCoord : geo::vect::coordReaders<geo::Point_t>()) {
98  auto const lastPointCoord = geo::vect::bindCoord(IntersectionPoints.back(), extractCoord);
99  auto const minCoord = geo::vect::bindCoord(c_min, extractCoord);
100  auto const maxCoord = geo::vect::bindCoord(c_max, extractCoord);
101 
102  // Changed by Christoph Rudolf von Rohr 05/21/2016
103  // Then check if point is not within the surface limits at this coordinate, without looking
104  // at the plane normal vector coordinate. We can assume, that our algorithm already found this coordinate correctily.
105  // In rare cases, looking for boundaries in this coordinate causes unexpected behavior due to floating point inaccuracies.
106  if (coord++ != NoCheckCoord &&
107  ((lastPointCoord() > maxCoord()) || (lastPointCoord() < minCoord))) {
108  // if off limits, get rid of the useless data and break the coordinate loop
109  LineParameters.pop_back();
110  IntersectionPoints.pop_back();
111  break;
112  }
113  } // coordinate loop
114  } // Surcaces loop
115 
116  // sort points according to their parameter value (first is entry, second is exit)
117  if (LineParameters.size() == 2 && LineParameters.front() > LineParameters.back()) {
118  std::swap(IntersectionPoints.front(), IntersectionPoints.back());
119  }
120 
121  return IntersectionPoints;
122  } // GetIntersections()
123 
124  //----------------------------------------------------------------------------
125  std::vector<TVector3> BoxBoundedGeo::GetIntersections(TVector3 const& TrajectoryStart,
126  TVector3 const& TrajectoryDirect) const
127  {
128  std::vector<TVector3> intersections;
129  for (auto const& point :
130  GetIntersections(geo::Point_t(TrajectoryStart), geo::Vector_t(TrajectoryDirect)))
131  intersections.emplace_back(point.X(), point.Y(), point.Z());
132  return intersections;
133  } // GetIntersections(TVector3)
134 
135  //----------------------------------------------------------------------------
137  {
138 
139  for (auto coordMan : geo::vect::coordManagers<geo::Point_t>()) {
140  auto min = geo::vect::bindCoord(c_min, coordMan);
141  auto max = geo::vect::bindCoord(c_max, coordMan);
142  if (min() > max()) {
143  auto temp = min();
144  min = max();
145  max = temp;
146  }
147  } // for
148 
149  } // BoxBoundedGeo::SortCoordinates()
150 
151  //----------------------------------------------------------------------------
152 
153 } // namespace geo
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Definition: geo_vectors.h:160
auto coord(Vector &v, unsigned int n) noexcept
Returns an object to manage the coordinate n of a vector.
::geo::Point_t toPoint(Point const &p)
Convert the specified point into a geo::Point_t.
constexpr auto bindCoord(Vector const &v, CoordReader_t< Vector > helper)
Binds the specified constant vector to the coordinate reader.
Utilities to extend the interface of geometry vectors.
geo::Point_t Min() const
Returns the corner point with the smallest coordinates.
Provides a base class aware of world box coordinates.
Coords_t c_max
maximum coordinates (x, y, z)
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:180
Coords_t c_min
minimum coordinates (x, y, z)
void SortCoordinates()
Makes sure each coordinate of the minimum point is smaller than maximum.
std::vector< TVector3 > GetIntersections(TVector3 const &TrajectoryStart, TVector3 const &TrajectoryDirect) const
Calculates the entry and exit points of a trajectory on the box surface.
GENVECTOR_CONSTEXPR::geo::Point_t makePointFromCoords(Coords &&coords)
Creates a geo::Point_t from its coordinates (see makeFromCoords()).
Namespace collecting geometry-related classes utilities.
geo::Point_t Max() const
Returns the corner point with the largest coordinates.
bool ContainsPosition(geo::Point_t const &point, double wiggle=1.0) const
Returns whether this volume contains the specified point.