BoxBoundedGeo.cxx
Go to the documentation of this file.
1 /**
2  * @file larcorealg/Geometry/BoxBoundedGeo.cxx
3  * @brief Provides a additional hit information of a line through the box
4  * @author Christoph Rudolf von Rohr (crohr@fnal.gov)
5  * @date July 27th, 2015
6  */
7 
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  //----------------------------------------------------------------------------
26  (TVector3 const& point, double wiggle /* = 1.0 */) const
27  { return ContainsPosition(geo::vect::toPoint(point), wiggle); }
28 
29  //----------------------------------------------------------------------------
31  (double const* point, double wiggle /* = 1.0 */) const
32  { return ContainsPosition(geo::vect::makePointFromCoords(point), wiggle); }
33 
34  //----------------------------------------------------------------------------
35  std::vector<geo::Point_t> BoxBoundedGeo::GetIntersections(
36  geo::Point_t const& TrajectoryStart,
37  geo::Vector_t const& TrajectoryDirect
38  ) const {
39 
40  std::vector<geo::Point_t> IntersectionPoints;
41  std::vector<double> LineParameters;
42 
43  // Generate normal vectors and offsets for every plane of the box
44  // All normal vectors are headed outwards
45  // BUG the double brace syntax is required to work around clang bug 21629
46  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
47  static std::array<geo::Vector_t, 6U> const NormalVectors = {{
48  -geo::Xaxis<geo::Vector_t>(), geo::Xaxis<geo::Vector_t>(), // anode, cathode,
49  -geo::Yaxis<geo::Vector_t>(), geo::Yaxis<geo::Vector_t>(), // bottom, top,
50  -geo::Zaxis<geo::Vector_t>(), geo::Zaxis<geo::Vector_t>() // upstream, downstream
51  }};
52  // BUG the double brace syntax is required to work around clang bug 21629
53  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
54  std::array<geo::Point_t, 6U> const NormalVectorOffsets = {{
55  geo::Point_t{ Min().X(), Min().Y(), Min().Z() }, // Anode offset
56  geo::Point_t{ Max().X(), Min().Y(), Min().Z() }, // Cathode
57  geo::Point_t{ Min().X(), Min().Y(), Min().Z() }, // Bottom
58  geo::Point_t{ Min().X(), Max().Y(), Min().Z() }, // Top
59  geo::Point_t{ Min().X(), Min().Y(), Min().Z() }, // upstream
60  geo::Point_t{ Min().X(), Min().Y(), Max().Z() } // downstream
61  }};
62 
63  // Loop over all surfaces of the box
64  for(unsigned int face_no = 0; face_no < NormalVectors.size(); face_no++)
65  {
66  // Check if trajectory and surface are not parallel
67  if(NormalVectors[face_no].Dot(TrajectoryDirect))
68  {
69  // Calculate the line parameter for the intersection points
70  LineParameters.push_back( NormalVectors[face_no].Dot(NormalVectorOffsets.at(face_no) - TrajectoryStart)
71  / NormalVectors[face_no].Dot(TrajectoryDirect) );
72  }
73  else continue;
74 
75  // Calculate intersection point using the line parameter
76  IntersectionPoints.push_back( TrajectoryStart + LineParameters.back()*TrajectoryDirect );
77 
78  // Coordinate which should be ignored when checking for limits added by Christoph Rudolf von Rohr 05/21/2016
79  unsigned int NoCheckCoord;
80 
81  // Calculate NoCheckCoord out of the face_no
82  if(face_no % 2)
83  {
84  // Convert odd face number to coordinate
85  NoCheckCoord = (face_no - 1)/2;
86  }
87  else
88  {
89  // Convert even face number to coordinate
90  NoCheckCoord = face_no/2;
91  }
92 
93  // Loop over all three space coordinates
94  unsigned int coord = 0;
95  for(auto extractCoord: geo::vect::coordReaders<geo::Point_t>())
96  {
97  auto const lastPointCoord = geo::vect::bindCoord(IntersectionPoints.back(), extractCoord);
98  auto const minCoord = geo::vect::bindCoord(c_min, extractCoord);
99  auto const maxCoord = geo::vect::bindCoord(c_max, extractCoord);
100 
101  // Changed by Christoph Rudolf von Rohr 05/21/2016
102  // Then check if point is not within the surface limits at this coordinate, without looking
103  // at the plane normal vector coordinate. We can assume, that our algorithm already found this coordinate correctily.
104  // In rare cases, looking for boundaries in this coordinate causes unexpected behavior due to floating point inaccuracies.
105  if( coord++ != NoCheckCoord && ((lastPointCoord() > maxCoord()) || (lastPointCoord() < minCoord)) )
106  {
107  // if off limits, get rid of the useless data and break the coordinate loop
108  LineParameters.pop_back();
109  IntersectionPoints.pop_back();
110  break;
111  }
112  }// coordinate loop
113  }// Surcaces loop
114 
115  // sort points according to their parameter value (first is entry, second is exit)
116  if(LineParameters.size() == 2 && LineParameters.front() > LineParameters.back())
117  {
118  std::swap(IntersectionPoints.front(),IntersectionPoints.back());
119  }
120 
121  return IntersectionPoints;
122  } // GetIntersections()
123 
124  //----------------------------------------------------------------------------
125  std::vector<TVector3> BoxBoundedGeo::GetIntersections
126  (TVector3 const& TrajectoryStart, TVector3 const& TrajectoryDirect) const
127  {
128  std::vector<TVector3> intersections;
129  for (auto const& point: GetIntersections(geo::Point_t(TrajectoryStart), geo::Vector_t(TrajectoryDirect)))
130  intersections.emplace_back(point.X(), point.Y(), point.Z());
131  return intersections;
132  } // GetIntersections(TVector3)
133 
134  //----------------------------------------------------------------------------
136 
137  for (auto coordMan: geo::vect::coordManagers<geo::Point_t>()) {
138  auto min = geo::vect::bindCoord(c_min, coordMan);
139  auto max = geo::vect::bindCoord(c_max, coordMan);
140  if (min() > max()) {
141  auto temp = min();
142  min = max();
143  max = temp;
144  }
145  } // for
146 
147  } // BoxBoundedGeo::SortCoordinates()
148 
149  //----------------------------------------------------------------------------
150 
151 
152 } // namespace geo
Utilities to extend the interface of geometry vectors.
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.
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Definition: geo_vectors.h:164
GENVECTOR_CONSTEXPR::geo::Point_t makePointFromCoords(Coords &&coords)
Creates a geo::Point_t from its coordinates (see makeFromCoords()).
void swap(Handle< T > &a, Handle< T > &b)
geo::Point_t Min() const
Returns the corner point with the smallest coordinates.
static int max(int a, int b)
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:184
Coords_t c_min
minimum coordinates (x, y, z)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
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.
LArSoft geometry interface.
Definition: ChannelGeo.h:16
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.