LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
geo_vectors_utils.h
Go to the documentation of this file.
1 
17 #ifndef LARCOREOBJ_SIMPLETYPESANDCONSTANTS_GEO_VECTORS_UTILS_H
18 #define LARCOREOBJ_SIMPLETYPESANDCONSTANTS_GEO_VECTORS_UTILS_H
19 
20 // LArSoft libraries
23 
24 // ROOT libraries
25 #include "Math/GenVector/DisplacementVector2D.h"
26 #include "Math/GenVector/DisplacementVector3D.h"
27 #include "Math/GenVector/LorentzVector.h"
28 #include "Math/GenVector/PositionVector2D.h"
29 #include "Math/GenVector/PositionVector3D.h"
30 
31 // C/C++ standard library
32 #include <array>
33 #include <cassert>
34 #include <functional> // std::mem_fn()
35 #include <iterator> // std::back_inserter()
36 #include <type_traits> // std::declval(), std::is_same<>, ...
37 #include <vector>
38 
40  template <typename T>
41  struct Point2D;
42  template <typename T>
43  struct Point3D;
44 }
45 
46 namespace geo {
47 
55  namespace vect {
56 
57  //--------------------------------------------------------------------------
58  namespace details {
59  //------------------------------------------------------------------------
60  template <typename Op, typename... T>
62 
63  template <typename Op, typename First, typename Second, typename... Others>
64  struct AccumulateImpl<Op, First, Second, Others...> {
65  static auto compute(Op op, First&& a, Second&& b, Others&&... others) -> decltype(auto)
66  {
67  return op(a,
69  op, std::forward<Second>(b), std::forward<Others>(others)...));
70  }
71  }; // AccumulateImpl<>
72 
73  template <typename Op, typename T>
74  struct AccumulateImpl<Op, T> {
75  static auto compute(Op, T&& v) -> decltype(auto) { return std::forward<T>(v); }
76  };
77 
78  template <typename Op, typename... T>
79  auto extended_accumulate(Op op, T&&... args)
80  {
81  return AccumulateImpl<Op, T...>::compute(op, std::forward<T>(args)...);
82  }
83 
84  template <typename... T>
85  auto extended_and(T... args) -> decltype(auto)
86  {
87  auto and_op = [](auto&& a, auto&& b) { return a && b; };
88  return extended_accumulate(and_op, std::forward<T>(args)...);
89  }
90 
91  //------------------------------------------------------------------------
92  //
93  // These two pages of metaprogramming madness are aimed to have objects
94  // that can provide a uniform coordinate get/set for any type of vector,
95  // with the minimal run-time overhead.
96  // Complications arise from the fact that TVector3 setter returns void,
97  // while GenVector vectors return a reference to the vector itself
98  // (hence the need of the additional SetterResult template parameter,
99  // and of quite some code to autodetect its value).
100  // The makeXxxx() functions are aimed to enclose the additional
101  // autodetection overlay, which should become unnecessary with C++17.
102  //
103 
104  template <typename Vector>
105  struct VectorScalar {
106  using type = typename Vector::Scalar;
107  };
108 
109  template <typename Vector>
111 
112  //------------------------------------------------------------------------
113  template <typename Vector>
114  struct HasGetter {
115  private:
116  template <typename Class>
117  static constexpr bool TestX(decltype(std::declval<Class>().X())*)
118  {
119  return true;
120  }
121  template <typename Class>
122  static constexpr bool TestX(...)
123  {
124  return false;
125  }
126  template <typename Class>
127  static constexpr bool TestY(decltype(std::declval<Class>().Y())*)
128  {
129  return true;
130  }
131  template <typename Class>
132  static constexpr bool TestY(...)
133  {
134  return false;
135  }
136  template <typename Class>
137  static constexpr bool TestZ(decltype(std::declval<Class>().Z())*)
138  {
139  return true;
140  }
141  template <typename Class>
142  static constexpr bool TestZ(...)
143  {
144  return false;
145  }
146  template <typename Class>
147  static constexpr bool TestT(decltype(std::declval<Class>().T())*)
148  {
149  return true;
150  }
151  template <typename Class>
152  static constexpr bool TestT(...)
153  {
154  return false;
155  }
156 
157  public:
158  static constexpr bool X = TestX<Vector>(nullptr);
159  static constexpr bool Y = TestY<Vector>(nullptr);
160  static constexpr bool Z = TestZ<Vector>(nullptr);
161  static constexpr bool T = TestT<Vector>(nullptr);
162  }; // struct HasGetter<>
163 
164  template <typename Vector>
165  constexpr bool HasX()
166  {
167  return HasGetter<Vector>::X;
168  }
169  template <typename Vector>
170  constexpr bool HasY()
171  {
172  return HasGetter<Vector>::Y;
173  }
174  template <typename Vector>
175  constexpr bool HasZ()
176  {
177  return HasGetter<Vector>::Z;
178  }
179  template <typename Vector>
180  constexpr bool HasT()
181  {
182  return HasGetter<Vector>::T;
183  }
184 
185  template <typename Vector, typename = void>
187 
188  template <typename Vector>
189  constexpr unsigned int dimension()
190  {
192  }
193 
195  template <typename Vector>
196  using CoordinateArray_t = std::array<VectorScalar_t<Vector>, dimension<Vector>()>;
197 
198  template <typename T>
200  // with C++17 `result_type` is deprecated,
201  // and a different way will be needed
202  using type = typename decltype(std::mem_fn(std::declval<T>()))::result_type;
203  }; // MemberFuncReturnType
204 
205  template <typename T>
207 
208  template <typename T>
210 
211  template <typename Class, typename Func>
212  struct MemberFuncClassType<Func Class::*> {
213  using type = Class;
214  };
215 
216  template <typename T>
218 
219  template <typename Vector, typename SetterType = void>
221 
222  template <typename Vector>
223  struct BaseCoordTypes<Vector, void> {
224  using Vector_t = std::decay_t<Vector>;
226  using Getter_t = Scalar_t (Vector_t::*)() const;
227  }; // struct BaseCoordTypes<void>
228 
229  template <typename Vector, typename SetterType>
230  struct BaseCoordTypes {
231  private:
233 
234  public:
235  using Scalar_t = typename BaseTypes_t::Scalar_t;
236  using Vector_t = typename BaseTypes_t::Vector_t;
237  using Getter_t = typename BaseTypes_t::Getter_t;
238  using Setter_t = SetterType;
240  static_assert(std::is_same<Setter_t, SetterReturn_t (Vector_t::*)(Scalar_t)>(),
241  "Invalid setter type");
242  }; // struct BaseCoordTypes<>
243 
244  template <typename Vector>
246  private:
248 
249  public:
250  using Vector_t = typename BaseTypes_t::Vector_t;
251  using Scalar_t = typename BaseTypes_t::Scalar_t;
252  using Getter_t = typename BaseTypes_t::Getter_t;
253  }; // struct CoordGetterTraits
254 
256  template <typename Vector>
257  class CoordGetter {
259 
260  public:
261  using Vector_t = typename Traits_t::Vector_t;
262  using Scalar_t = typename Traits_t::Scalar_t;
263  using Getter_t = typename Traits_t::Getter_t;
264 
266  constexpr CoordGetter(Getter_t getter) : fGetter(getter) {}
267 
269  Scalar_t operator()(Vector_t const& v) const { return get(v); }
270 
272  Scalar_t get(Vector_t const& v) const { return (v.*fGetter)(); }
273 
274  private:
276 
277  }; // class CoordGetter<>
278 
279  template <typename Getter>
280  constexpr auto makeCoordReader(Getter getter)
281  {
282  using Vector_t = std::remove_reference_t<MemberFuncClass_t<Getter>>;
283  return CoordGetter<Vector_t>{getter};
284  }
285 
286  template <typename Vector, typename SetterType>
288  private:
290 
291  public:
292  using Vector_t = typename BaseTypes_t::Vector_t;
293  using Scalar_t = typename BaseTypes_t::Scalar_t;
294  using Getter_t = typename BaseTypes_t::Getter_t;
295  using Setter_t = typename BaseTypes_t::Setter_t;
296  }; // struct VectorCoordManagerTraits<>
297 
299  template <typename Vector, typename SetterType>
300  class CoordManager : public CoordGetter<Vector> {
303 
304  public:
305  using Vector_t = typename Traits_t::Vector_t; // this is not constant
306  using Scalar_t = typename Traits_t::Scalar_t;
307  using Getter_t = typename Traits_t::Getter_t;
308  using Setter_t = typename Traits_t::Setter_t;
309 
311  constexpr CoordManager(Getter_t getter, Setter_t setter) : Base_t(getter), fSetter(setter)
312  {}
313 
315  void operator()(Vector_t& v, Scalar_t c) const { set(v, c); }
316 
318  void set(Vector_t& v, Scalar_t c) const { (v.*fSetter)(c); }
319 
321  void incr(Vector_t& v, Scalar_t c) const { set(v, Base_t::get(v) + c); }
322 
324  void decr(Vector_t& v, Scalar_t c) const { set(v, Base_t::get(v) - c); }
325 
327  void mult(Vector_t& v, Scalar_t f) const { set(v, Base_t::get(v) * f); }
328 
330  void div(Vector_t& v, Scalar_t f) const { set(v, Base_t::get(v) / f); }
331 
332  private:
334  }; // class CoordManager<>
335 
336  template <typename Getter, typename Setter>
337  constexpr auto makeCoordManager(Getter getter, Setter setter)
338  {
339  using Vector_t = std::remove_reference_t<MemberFuncClass_t<Getter>>;
340  return CoordManager<Vector_t, Setter>{getter, setter};
341  }
342 
343  template <typename CoordHelper, typename StoredVector>
345 
346  public:
347  using Stored_t = StoredVector;
348 
349  using CoordHelper_t = CoordHelper;
351  using Scalar_t = typename CoordHelper_t::Scalar_t;
352  using Getter_t = typename CoordHelper_t::Getter_t;
353 
355  BoundCoordGetter(Stored_t& v, CoordHelper_t coordManager) : fCoord(coordManager), fVector(v)
356  {}
357 
359  BoundCoordGetter(Stored_t& v, Getter_t getter) : fCoord(getter), fVector(v) {}
360 
362  Scalar_t get() const { return manager().get(vector()); }
363 
365  Scalar_t operator()() const { return get(); }
366 
368  operator Scalar_t() const { return manager().get(vector()); }
369 
370  protected:
371  CoordHelper_t const& manager() const { return fCoord; }
372  Stored_t& vector() const { return fVector; }
373 
374  private:
377  }; // class VectorCoordGetter<>
378 
379  template <typename CoordHelper, typename StoredVector>
380  class BoundCoordManager : public BoundCoordGetter<CoordHelper, StoredVector> {
382 
383  public:
384  using typename Base_t::Stored_t;
385 
386  using CoordHelper_t = CoordHelper;
388  using Scalar_t = typename CoordHelper_t::Scalar_t;
389  using Getter_t = typename CoordHelper_t::Getter_t;
390  using Setter_t = typename CoordHelper_t::Setter_t;
391 
394 
397  : Base_t(v, CoordHelper_t(getter, setter))
398  {}
399 
402  {
403  Base_t::manager().set(Base_t::vector(), c);
404  return *this;
405  }
406 
409  {
410  Base_t::manager().incr(Base_t::vector(), c);
411  return *this;
412  }
413 
416  {
417  Base_t::manager().decr(Base_t::vector(), c);
418  return *this;
419  }
420 
423  {
424  Base_t::manager().mult(Base_t::vector(), f);
425  return *this;
426  }
427 
430  {
431  Base_t::manager().div(Base_t::vector(), f);
432  return *this;
433  }
434 
435  }; // class BoundCoordManager
436 
437  //------------------------------------------------------------------------
438 
439  } // namespace details
440 
441  // BEGIN Geometry group ------------------------------------------------------
444 
446  namespace extra {
447 
449  template <typename T>
450  constexpr T roundValue0(T value, T tol)
451  {
452  return (std::abs(value) < tol) ? T{} : value;
453  } // roundValue0()
454 
456  template <typename T>
457  constexpr T roundValue01(T value, T tol)
458  {
459  if (std::abs(value) < tol) return 0.;
460  if (std::abs(std::abs(value) - 1.) < tol) return (value > 0.) ? 1. : -1.;
461  return value;
462  } // roundValue01()
463 
464  } // namespace extra
465 
466  // --- BEGIN Vector coordinate access abstraction --------------------------
468 
621  template <typename Vector>
623  constexpr unsigned int dimension()
624  {
625  return details::dimension<Vector>();
626  }
627  template <typename Vector>
628  constexpr unsigned int dimension(Vector&&)
629  {
630  return dimension<Vector>();
631  }
633 
635  template <typename Vector>
637  constexpr std::array<std::size_t, geo::vect::dimension<Vector>()> indices();
638  template <typename Vector>
639  constexpr auto indices(Vector const&) -> decltype(indices<Vector>());
641 
643  template <typename Vector>
645 
667  template <typename Vector, typename Coords>
668  constexpr Vector makeFromCoords(Coords&& coords);
669 
682  template <typename Vector, typename Coords>
683  unsigned int fillCoords(Coords& dest, Vector const& src);
684 
686  template <typename Vector>
688 
690  template <typename Vector>
691  using CoordManager_t = decltype(details::makeCoordManager(&Vector::X, &Vector::SetX));
692 
714  template <typename Vector>
715  static constexpr auto XcoordManager = details::makeCoordManager(&Vector::X, &Vector::SetX);
716 
738  template <typename Vector>
740 
743  template <typename Vector>
744  static constexpr auto const YcoordManager =
745  details::makeCoordManager(&Vector::Y, &Vector::SetY);
746 
749  template <typename Vector>
751 
754  template <typename Vector>
755  static constexpr auto ZcoordManager = details::makeCoordManager(&Vector::Z, &Vector::SetZ);
756 
759  template <typename Vector>
761 
764  template <typename Vector>
765  static constexpr auto TcoordManager = details::makeCoordManager(&Vector::T, &Vector::SetT);
766 
769  template <typename Vector>
770  static constexpr auto TcoordManager<Vector const> = details::makeCoordReader(&Vector::T);
771 
812  template <typename Vector>
813  constexpr auto coordManager(unsigned int n);
814 
826  template <typename Vector>
827  constexpr auto coordManager(unsigned int n, Vector& v);
828 
830  template <typename Vector>
832  constexpr auto coordManagers();
833  template <typename Vector>
834  constexpr auto coordManagers(Vector&&);
836 
838  template <typename Vector>
840  constexpr auto coordReaders();
841  template <typename Vector>
842  constexpr auto coordReaders(Vector&&);
844 
846  template <typename Vector>
847  constexpr auto bindCoord(Vector const& v, CoordReader_t<Vector> helper)
848  {
849  return details::BoundCoordGetter<CoordReader_t<Vector>, Vector const>(v, helper);
850  }
851 
853  template <typename Vector>
854  auto bindCoord(Vector& v, CoordManager_t<Vector> helper)
856  {
857  return {v, helper};
858  }
859 
870  template <typename Vector>
871  auto Xcoord(Vector& v)
872  {
873  return bindCoord(v, XcoordManager<Vector>);
874  }
875 
886  template <typename Vector>
887  auto Ycoord(Vector& v)
888  {
889  return bindCoord<Vector>(v, YcoordManager<Vector>);
890  }
891 
902  template <typename Vector>
903  auto Zcoord(Vector& v)
904  {
905  return bindCoord<Vector>(v, ZcoordManager<Vector>);
906  }
907 
918  template <typename Vector>
919  auto Tcoord(Vector& v)
920  {
921  return bindCoord<Vector>(v, TcoordManager<Vector>);
922  }
923 
935  template <typename Vector>
936  auto coord(Vector& v, unsigned int n) noexcept;
937 
940  template <typename Vector>
941  constexpr auto bindCoordManagers(Vector& v);
942 
945  template <typename Vector>
946  constexpr auto bindCoordReaders(Vector const& v);
947 
954  template <typename Vector>
956 
957  public:
959 
960  private:
961  using Vector_t = Vector;
964 
965  Vector* v = nullptr;
966  unsigned int index = std::numeric_limits<unsigned int>::max();
967 
968  decltype(auto) access(unsigned int c) const { return geo::vect::bindCoord(v, index); }
969 
970  iterator_t copy() const { return *this; }
971 
972  public:
976  using value_type = std::remove_cv_t<Coord_t>;
977  using difference_type = std::ptrdiff_t;
979  using pointer = Coord_t const*;
980  using iterator_category = std::random_access_iterator_tag;
983 
985  CoordConstIterator() = default;
986 
988  CoordConstIterator(Vector& v, unsigned int index = 0) : v(&v), index(index) {}
989 
990  // --- BEGIN Access ----------------------------------------------------------
993 
995  reference operator*() const { return geo::vect::coord(*v, index); }
996 
998  reference operator[](difference_type n) const { return geo::vect::coord(*v, index + n); }
999 
1001  // --- END Access ------------------------------------------------------------
1002 
1003  // --- BEGIN Moving ----------------------------------------------------------
1006 
1009  {
1010  ++index;
1011  return *this;
1012  }
1013 
1016  {
1017  iterator_t it(*this);
1018  ++index;
1019  return it;
1020  }
1021 
1024  {
1025  --index;
1026  return *this;
1027  }
1028 
1031  {
1032  iterator_t it(*this);
1033  --index;
1034  return it;
1035  }
1036 
1039  {
1040  index += d;
1041  return *this;
1042  }
1043 
1045  iterator_t operator+(difference_type d) const { return (copy() += d); }
1046 
1049  {
1050  index -= d;
1051  return *this;
1052  }
1053 
1055  iterator_t operator-(difference_type d) const { return (copy() -= d); }
1056 
1058  iterator_t operator-(iterator_t const& other) const { return index - other.index; }
1059 
1061  // --- END Moving ------------------------------------------------------------
1062 
1063  // --- BEGIN Comparison operators --------------------------------------------
1068 
1069  bool operator==(iterator_t const& other) const
1070  {
1071  return (v == other.v) && (index == other.index);
1072  }
1073 
1074  bool operator!=(iterator_t const& other) const
1075  {
1076  return (v != other.v) || (index != other.index);
1077  }
1078 
1079  bool operator<=(iterator_t const& other) const
1080  {
1081  return (v == other.v) && (index <= other.index);
1082  }
1083 
1084  bool operator>=(iterator_t const& other) const
1085  {
1086  return (v == other.v) && (index >= other.index);
1087  }
1088 
1089  bool operator<(iterator_t const& other) const
1090  {
1091  return (v == other.v) && (index < other.index);
1092  }
1093 
1094  bool operator>(iterator_t const& other) const
1095  {
1096  return (v == other.v) && (index > other.index);
1097  }
1098 
1100  // --- END Comparison operators ----------------------------------------------
1101 
1102  }; // class CoordConstIterator
1103 
1104  template <typename Vector>
1106  CoordConstIterator<Vector> const& v)
1107  {
1108  return v + n;
1109  }
1110 
1112  template <typename Vector>
1113  auto vector_cbegin(Vector const& v)
1114  {
1115  return CoordConstIterator(v, 0);
1116  }
1117 
1119  template <typename Vector>
1120  auto vector_cend(Vector const& v)
1121  {
1123  }
1124 
1138  template <typename Vector>
1139  auto iterateCoords(Vector const& v)
1140  {
1141  return util::span(vector_cbegin(v), vector_cend(v));
1142  }
1143 
1154  template <typename Dest, typename Source>
1155  Dest convertTo(Source const& v);
1156 
1172  template <typename Dest, typename Source>
1173  std::vector<Dest> convertCollTo(std::vector<Source> const& coll);
1174 
1186  template <typename Vector, typename Pred>
1187  Vector transformCoords(Vector const& v, Pred&& pred);
1188 
1190  // --- END Vector coordinate access abstraction ----------------------------
1191 
1192  // --- BEGIN Functions for common vector operations ------------------------
1194 
1224  template <typename Vector, typename Scalar>
1226  Vector rounded0(Vector const& v, Scalar tol)
1227  {
1228  return transformCoords(v, [tol](auto c) { return extra::roundValue0(c, tol); });
1229  }
1230 
1232  template <typename Vector, typename Scalar>
1233  void round0(Vector& v, Scalar tol)
1234  {
1235  v = rounded0(v, tol);
1236  }
1237 
1239  template <typename Vector, typename Scalar>
1240  Vector rounded01(Vector const& v, Scalar tol)
1241  {
1242  return transformCoords(v, [tol](auto c) { return extra::roundValue01(c, tol); });
1243  }
1244 
1246  template <typename Vector, typename Scalar>
1247  void round01(Vector& v, Scalar tol)
1248  {
1249  v = rounded01(v, tol);
1250  }
1251 
1253  template <typename Vector>
1254  bool isfinite(Vector const& v);
1255 
1257  template <typename Vector>
1258  Vector normalize(Vector const& v)
1259  {
1260  return v.Unit();
1261  }
1262 
1264  template <typename Vector>
1265  Vector cross(Vector const& a, Vector const& b)
1266  {
1267  return a.Cross(b);
1268  }
1269 
1271  template <typename Vector, typename OtherVector>
1272  constexpr auto dot(Vector const& a, OtherVector const& b)
1273  {
1274  return a.Dot(b);
1275  }
1276 
1278  template <typename Vector>
1279  auto mag2(Vector const& v)
1280  {
1281  return v.Mag2();
1282  }
1283 
1285  template <typename Vector>
1286  auto norm(Vector const& v)
1287  {
1288  return v.Mag();
1289  }
1290 
1293  template <typename Vector>
1294  auto mixedProduct(Vector const& a, Vector const& b, Vector const& c)
1295  {
1296  return dot(cross(a, b), c);
1297  }
1298 
1300  // --- END Functions for common vector operations --------------------------
1301 
1332  template <unsigned int N = 3U>
1334  static constexpr unsigned int Dim = N;
1335  std::array<Length_t, Dim> fSums;
1336  double fW = 0.0;
1337 
1338  public:
1340  MiddlePointAccumulatorDim() { fSums.fill(0.); }
1341 
1350  template <typename BeginIter, typename EndIter>
1352  {
1353  add(begin, end);
1354  }
1355 
1356  // --- BEGIN Result query ------------------------------------------------
1359 
1361  bool empty() const { return fW == 0.0; }
1362 
1364  double weight() const { return fW; }
1365 
1377  template <typename Point>
1379  // { return { fSums[0] / fW, fSums[1] / fW, fSums[2] / fW }; }
1380  {
1381  return makeWeightedPoint<Point>(1.0 / fW);
1382  }
1383 
1386  geo::Point_t middlePoint() const { return middlePointAs<geo::Point_t>(); }
1387 
1389  // --- END Result query --------------------------------------------------
1390 
1391  // --- BEGIN Addition of points ------------------------------------------
1394 
1402  template <typename Point>
1403  void add(Point const& p)
1404  {
1405  std::size_t ic = 0U;
1406  for (auto c : geo::vect::bindCoordManagers(p))
1407  fSums[ic++] += c();
1408  fW += 1.0;
1409  }
1410 
1417  template <typename Point>
1418  void add(Point const& p, double weight)
1419  {
1420  std::size_t ic = 0U;
1421  for (auto c : geo::vect::bindCoordManagers(p))
1422  fSums[ic++] += weight * c();
1423  fW += weight;
1424  }
1425 
1435  template <typename BeginIter, typename EndIter>
1436  void add(BeginIter begin, EndIter end)
1437  {
1438  std::for_each(begin, end, [this](auto const& p) { this->add(p); });
1439  }
1440 
1442  void clear()
1443  {
1444  fSums.fill(0.);
1445  fW = 0.0;
1446  }
1447 
1449  // --- END Addition of points --------------------------------------------
1450 
1451  private:
1452  using IndexSequence_t = std::make_index_sequence<Dim>;
1453 
1454  template <typename Point, std::size_t... I>
1455  Point makePointImpl(std::index_sequence<I...>) const
1456  {
1457  return {fSums.operator[](I)...};
1458  }
1459 
1460  template <typename Point, std::size_t... I>
1461  Point makeWeightedPointImpl(double w, std::index_sequence<I...>) const
1462  {
1463  return {(fSums.operator[](I) * w)...};
1464  }
1465 
1467  template <typename Point>
1469  {
1470  return geo::vect::makeFromCoords<Point>(fSums);
1471  }
1472 
1475  template <typename Point>
1476  Point makeWeightedPoint(double w) const
1477  {
1478  return makeWeightedPointImpl<Point>(w, IndexSequence_t{});
1479  }
1480 
1481  }; // MiddlePointAccumulatorDim()
1482 
1485 
1486  // --- BEGIN Middle point functions ----------------------------------------
1489 
1513  template <typename Point, typename BeginIter, typename EndIter>
1514  Point middlePointAs(BeginIter begin, EndIter end)
1515  {
1516  constexpr auto Dim = geo::vect::dimension<Point>();
1517  return MiddlePointAccumulatorDim<Dim>(begin, end).template middlePointAs<Point>();
1518  }
1519 
1541  template <typename BeginIter, typename EndIter>
1542  geo::Point_t middlePoint(BeginIter begin, EndIter end)
1543  {
1544  return middlePointAs<geo::Point_t>(begin, end);
1545  }
1546 
1563  template <typename Point>
1564  Point middlePoint(std::initializer_list<Point> points)
1565  {
1566  constexpr auto Dim = geo::vect::dimension<Point>();
1567  return MiddlePointAccumulatorDim<Dim>(points.begin(), points.end())
1568  .template middlePointAs<Point>();
1569  }
1570 
1572  // --- END Middle point functions ------------------------------------------
1573 
1574  // --- BEGIN Support for LArSoft geometry vectors --------------------------
1577 
1578  // import global definitions
1581 
1583  template <typename Point>
1585  {
1586  return geo::vect::convertTo<::geo::Point_t>(p);
1587  }
1588 
1590  template <typename Vector>
1591  ::geo::Vector_t toVector(Vector const& v)
1592  {
1593  return geo::vect::convertTo<::geo::Vector_t>(v);
1594  }
1595 
1598  template <typename Point>
1599  std::vector<geo::Point_t> convertCollToPoint(std::vector<Point> const& coll)
1600  {
1601  return convertCollTo<geo::Point_t>(coll);
1602  }
1603 
1606  template <typename Vector>
1607  std::vector<geo::Vector_t> convertCollToVector(std::vector<Vector> const& coll)
1608  {
1609  return convertCollTo<geo::Vector_t>(coll);
1610  }
1611 
1613  template <typename Coords>
1615  {
1616  return makeFromCoords<::geo::Point_t>(std::forward<Coords>(coords));
1617  }
1618 
1620  template <typename Coords>
1622  {
1623  return makeFromCoords<::geo::Vector_t>(std::forward<Coords>(coords));
1624  }
1625 
1627  // --- END Support for LArSoft geometry vectors ----------------------------
1628 
1630  // END Geometry group ------------------------------------------------------
1631 
1632  } // namespace vect
1633 
1634 } // namespace geo
1635 
1636 //------------------------------------------------------------------------------
1637 //--- STL specialization for ROOT GenVector vectors
1638 //------------------------------------------------------------------------------
1639 namespace ROOT::Math {
1640 
1643 
1644  // --- BEGIN 2D vectors ------------------------------------------------------
1645  template <class CoordSystem, class Tag>
1646  decltype(auto) begin(ROOT::Math::PositionVector2D<CoordSystem, Tag> const& v)
1647  {
1648  return geo::vect::vector_cbegin(v);
1649  }
1650 
1651  template <class CoordSystem, class Tag>
1652  decltype(auto) cbegin(ROOT::Math::PositionVector2D<CoordSystem, Tag> const& v)
1653  {
1654  return geo::vect::vector_cbegin(v);
1655  }
1656 
1657  template <class CoordSystem, class Tag>
1658  decltype(auto) end(ROOT::Math::PositionVector2D<CoordSystem, Tag> const& v)
1659  {
1660  return geo::vect::vector_cend(v);
1661  }
1662 
1663  template <class CoordSystem, class Tag>
1664  decltype(auto) cend(ROOT::Math::PositionVector2D<CoordSystem, Tag> const& v)
1665  {
1666  return geo::vect::vector_cend(v);
1667  }
1668 
1669  template <class CoordSystem, class Tag>
1670  decltype(auto) begin(ROOT::Math::DisplacementVector2D<CoordSystem, Tag> const& v)
1671  {
1672  return geo::vect::vector_cbegin(v);
1673  }
1674 
1675  template <class CoordSystem, class Tag>
1676  decltype(auto) cbegin(ROOT::Math::DisplacementVector2D<CoordSystem, Tag> const& v)
1677  {
1678  return geo::vect::vector_cbegin(v);
1679  }
1680 
1681  template <class CoordSystem, class Tag>
1682  decltype(auto) end(ROOT::Math::DisplacementVector2D<CoordSystem, Tag> const& v)
1683  {
1684  return geo::vect::vector_cend(v);
1685  }
1686 
1687  template <class CoordSystem, class Tag>
1688  decltype(auto) cend(ROOT::Math::DisplacementVector2D<CoordSystem, Tag> const& v)
1689  {
1690  return geo::vect::vector_cend(v);
1691  }
1692 
1693  // --- END 2D vectors --------------------------------------------------------
1694 
1695  // --- BEGIN 3D vectors ------------------------------------------------------
1696  template <class CoordSystem, class Tag>
1697  decltype(auto) begin(ROOT::Math::PositionVector3D<CoordSystem, Tag> const& v)
1698  {
1699  return geo::vect::vector_cbegin(v);
1700  }
1701 
1702  template <class CoordSystem, class Tag>
1703  decltype(auto) cbegin(ROOT::Math::PositionVector3D<CoordSystem, Tag> const& v)
1704  {
1705  return geo::vect::vector_cbegin(v);
1706  }
1707 
1708  template <class CoordSystem, class Tag>
1709  decltype(auto) end(ROOT::Math::PositionVector3D<CoordSystem, Tag> const& v)
1710  {
1711  return geo::vect::vector_cend(v);
1712  }
1713 
1714  template <class CoordSystem, class Tag>
1715  decltype(auto) cend(ROOT::Math::PositionVector3D<CoordSystem, Tag> const& v)
1716  {
1717  return geo::vect::vector_cend(v);
1718  }
1719 
1720  template <class CoordSystem, class Tag>
1721  decltype(auto) begin(ROOT::Math::DisplacementVector3D<CoordSystem, Tag> const& v)
1722  {
1723  return geo::vect::vector_cbegin(v);
1724  }
1725 
1726  template <class CoordSystem, class Tag>
1727  decltype(auto) cbegin(ROOT::Math::DisplacementVector3D<CoordSystem, Tag> const& v)
1728  {
1729  return geo::vect::vector_cbegin(v);
1730  }
1731 
1732  template <class CoordSystem, class Tag>
1733  decltype(auto) end(ROOT::Math::DisplacementVector3D<CoordSystem, Tag> const& v)
1734  {
1735  return geo::vect::vector_cend(v);
1736  }
1737 
1738  template <class CoordSystem, class Tag>
1739  decltype(auto) cend(ROOT::Math::DisplacementVector3D<CoordSystem, Tag> const& v)
1740  {
1741  return geo::vect::vector_cend(v);
1742  }
1743 
1744  // --- END 3D vectors --------------------------------------------------------
1745 
1746  // --- BEGIN 4D vectors ------------------------------------------------------
1747  template <class CoordSystem>
1748  decltype(auto) begin(ROOT::Math::LorentzVector<CoordSystem> const& v)
1749  {
1750  return geo::vect::vector_cbegin(v);
1751  }
1752 
1753  template <class CoordSystem>
1754  decltype(auto) cbegin(ROOT::Math::LorentzVector<CoordSystem> const& v)
1755  {
1756  return geo::vect::vector_cbegin(v);
1757  }
1758 
1759  template <class CoordSystem>
1760  decltype(auto) end(ROOT::Math::LorentzVector<CoordSystem> const& v)
1761  {
1762  return geo::vect::vector_cend(v);
1763  }
1764 
1765  template <class CoordSystem>
1766  decltype(auto) cend(ROOT::Math::LorentzVector<CoordSystem> const& v)
1767  {
1768  return geo::vect::vector_cend(v);
1769  }
1770 
1771  // --- END 4D vectors --------------------------------------------------------
1772 
1774 
1775 } // namespace ROOT::Math
1776 
1777 //------------------------------------------------------------------------------
1778 
1779 //------------------------------------------------------------------------------
1780 //--- template specializations for standard geometry vectors
1781 //---
1782 namespace geo::vect {
1783 
1784  //----------------------------------------------------------------------------
1785  template <>
1786  inline auto norm(geo::Vector_t const& v)
1787  {
1788  return v.R();
1789  }
1790 
1791  //----------------------------------------------------------------------------
1792 
1793 } // namespace geo::vect
1794 
1795 //------------------------------------------------------------------------------
1796 //--- template implementation
1797 
1798 namespace geo::vect::details {
1799 
1800  //----------------------------------------------------------------------------
1801  template <typename>
1802  struct AlwaysFalse : std::false_type {};
1803 
1804  // constexpr variant of forward (from StackExchange)
1805  template <typename T>
1806  constexpr T&& constexpr_forward(std::remove_reference_t<T>& t)
1807  {
1808  return static_cast<T&&>(t);
1809  }
1810 
1811  template <typename T>
1812  constexpr T&& constexpr_forward(std::remove_reference_t<T>&& t)
1813  {
1814  static_assert(!std::is_lvalue_reference<T>(),
1815  "template argument substituting T is an lvalue reference type");
1816  return static_cast<T&&>(t);
1817  }
1818 
1819  //----------------------------------------------------------------------------
1820  template <typename Vector, typename /* = void */>
1821  struct DimensionImpl : public std::integral_constant<unsigned int,
1822  HasT<Vector>() ? 4U :
1823  HasZ<Vector>() ? 3U :
1824  HasY<Vector>() ? 2U :
1825  HasX<Vector>() ? 1U :
1826  0U> {};
1827 
1828  template <typename Array>
1829  struct DimensionImpl<Array, std::enable_if_t<(std::extent_v < Array >> 0)>>
1830  : public std::integral_constant<unsigned int, std::extent_v<Array>> {};
1831 
1832  template <typename T, std::size_t Dim>
1833  struct DimensionImpl<std::array<T, Dim>, void>
1834  : public std::integral_constant<unsigned int, Dim> {};
1835 
1836  template <typename T>
1837  struct DimensionImpl<lar::util::simple_geo::Point2D<T>, void>
1838  : public std::integral_constant<unsigned int, 2> {};
1839 
1840  template <typename T>
1842  : public std::integral_constant<unsigned int, 3> {};
1843 
1844  //----------------------------------------------------------------------------
1846  template <typename Vector>
1847  using VectorIndices_t = std::make_index_sequence<dimension<Vector>()>;
1848 
1849  template <typename Vector>
1850  constexpr auto makeVectorIndices()
1851  {
1852  return VectorIndices_t<Vector>{};
1853  }
1854 
1855  template <typename Vector>
1856  constexpr auto makeVectorIndices(Vector&&)
1857  {
1858  return makeVectorIndices<Vector>();
1859  }
1860 
1861  template <typename T, T... Indices>
1862  constexpr auto makeIndexSeqImpl(std::integer_sequence<T, Indices...>)
1863  // BUG the double brace syntax is required to work around clang bug 21629
1864  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1865  {
1866  return std::array<T, sizeof...(Indices)>{{Indices...}};
1867  }
1868 
1869  // fill a sequence object with the first `N` values of type `T`.
1870  template <typename T, T N>
1871  constexpr auto makeIndexSeq()
1872  {
1873  return makeIndexSeqImpl<T>(std::make_integer_sequence<T, N>{});
1874  }
1875 
1876  //----------------------------------------------------------------------------
1877  template <std::size_t I, typename Data>
1878  constexpr auto accessElement(Data&& data)
1879  {
1880  return data[I];
1881  }
1882 
1883  template <typename Vector, typename Coords, std::size_t... Indices>
1884  constexpr Vector makeFromCoordsImpl(Coords&& coords, std::index_sequence<Indices...>)
1885  {
1886  return {accessElement<Indices>(constexpr_forward<Coords>(coords))...};
1887  }
1888 
1889  //----------------------------------------------------------------------------
1890  template <typename Vector>
1891  constexpr CoordManager_t<Vector> NoCoordManager{nullptr, nullptr};
1892 
1893  template <typename Vector, unsigned int Dim = dimension<Vector>()>
1895 
1896  template <typename Vector>
1897  struct CoordManagerImpl<Vector, 1U> {
1898  static auto get(unsigned int n) noexcept
1899  {
1900  return (n == 0) ? XcoordManager<Vector> : NoCoordManager<Vector>;
1901  }
1902  }; // CoordManagerImpl<1U>
1903 
1904  template <typename Vector>
1905  struct CoordManagerImpl<Vector, 2U> {
1906  static auto get(unsigned int n) noexcept
1907  {
1908  return (n == 1) ? YcoordManager<Vector> : CoordManagerImpl<Vector, 1U>::get(n);
1909  }
1910  }; // CoordManagerImpl<2U>
1911 
1912  template <typename Vector>
1913  struct CoordManagerImpl<Vector, 3U> {
1914  static auto get(unsigned int n) noexcept
1915  {
1916  return (n == 2) ? ZcoordManager<Vector> : CoordManagerImpl<Vector, 2U>::get(n);
1917  }
1918  }; // CoordManagerImpl<3U>
1919 
1920  template <typename Vector>
1921  struct CoordManagerImpl<Vector, 4U> {
1922  static auto get(unsigned int n) noexcept
1923  {
1924  return (n == 3) ? TcoordManager<Vector> : CoordManagerImpl<Vector, 3U>::get(n);
1925  }
1926 
1927  }; // CoordManagerImpl<4U>
1928 
1929  //----------------------------------------------------------------------------
1930  template <typename Vector, unsigned int N>
1932  static constexpr unsigned int Dim = N;
1933 
1934  using Manager_t = decltype(XcoordManager<Vector>);
1935  using Return_t = std::array<Manager_t, Dim>;
1936 
1937  static_assert(dimension<Vector>() == Dim, "Inconsistent vector size.");
1938  }; // CoordManagersImplBase
1939 
1940  template <typename Vector, unsigned int N>
1942 
1943  template <typename Vector>
1944  struct CoordManagersImpl<Vector, 2U> : private CoordManagersImplBase<Vector, 2U> {
1946  using typename Base_t::Return_t;
1947  static constexpr Return_t get()
1948  {
1949  // BUG the double brace syntax is required to work around clang bug 21629
1950  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1951  return {{XcoordManager<Vector>, YcoordManager<Vector>}};
1952  }
1953  }; // CoordManagersImpl<2U>
1954 
1955  template <typename Vector>
1956  struct CoordManagersImpl<Vector, 3U> : private CoordManagersImplBase<Vector, 3U> {
1958  using typename Base_t::Return_t;
1959  static constexpr Return_t get()
1960  {
1961  // BUG the double brace syntax is required to work around clang bug 21629
1962  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1963  return {{XcoordManager<Vector>, YcoordManager<Vector>, ZcoordManager<Vector>}};
1964  }
1965  }; // CoordManagersImpl<3U>
1966 
1967  template <typename Vector>
1968  struct CoordManagersImpl<Vector, 4U> : private CoordManagersImplBase<Vector, 4U> {
1970  using typename Base_t::Return_t;
1971  static constexpr Return_t get()
1972  {
1973  // BUG the double brace syntax is required to work around clang bug 21629
1974  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1975  return {{XcoordManager<Vector>,
1976  YcoordManager<Vector>,
1977  ZcoordManager<Vector>,
1978  TcoordManager<Vector>}};
1979  }
1980  }; // CoordManagersImpl<4U>
1981 
1982  //----------------------------------------------------------------------------
1983  template <typename Vector, unsigned int N>
1985  static constexpr unsigned int Dim = N;
1986 
1987  using Manager_t = decltype(Xcoord(std::declval<Vector>()));
1988  using Return_t = std::array<Manager_t, Dim>;
1989 
1990  static_assert(dimension<Vector>() == Dim, "Inconsistent vector size.");
1991  }; // CoordManagersImplBase
1992 
1993  template <typename Vector, unsigned int N>
1995 
1996  template <typename Vector>
1997  struct BindCoordManagersImpl<Vector, 2U> : private BindCoordManagersImplBase<Vector, 2U> {
1999  using typename Base_t::Return_t;
2000  static Return_t bind(Vector& v)
2001  {
2002  // BUG the double brace syntax is required to work around clang bug 21629
2003  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
2004  return {{Xcoord(v), Ycoord(v)}};
2005  }
2006  }; // BindCoordManagersImpl<2U>
2007 
2008  template <typename Vector>
2009  struct BindCoordManagersImpl<Vector, 3U> : private BindCoordManagersImplBase<Vector, 3U> {
2011  using typename Base_t::Return_t;
2012  static Return_t bind(Vector& v)
2013  {
2014  // BUG the double brace syntax is required to work around clang bug 21629
2015  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
2016  return {{Xcoord(v), Ycoord(v), Zcoord(v)}};
2017  }
2018  }; // BindCoordManagersImpl<3U>
2019 
2020  template <typename Vector>
2021  struct BindCoordManagersImpl<Vector, 4U> : private BindCoordManagersImplBase<Vector, 4U> {
2023  using typename Base_t::Return_t;
2024  static Return_t bind(Vector& v)
2025  {
2026  // BUG the double brace syntax is required to work around clang bug 21629
2027  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
2028  return {{Xcoord(v), Ycoord(v), Zcoord(v), Tcoord(v)}};
2029  }
2030  }; // BindCoordManagersImpl<4U>
2031 
2032  //----------------------------------------------------------------------------
2033  template <typename Dest, typename Source>
2035  static_assert(dimension<Source>() == dimension<Dest>(),
2036  "Source and destination vectors must have the same dimension.");
2037  }; // struct ConvertToImplBase
2038 
2039  template <typename Dest, typename Source, unsigned int Dim>
2040  struct ConvertArrayTo : private ConvertToImplBase<Dest, Source> {
2041  static_assert(std::is_arithmetic_v<std::decay_t<decltype(std::declval<Source>()[0])>>);
2042  static Dest convert(Source const& v) { return geo::vect::makeFromCoords<Dest>(v); }
2043  }; // struct ConvertArrayTo
2044 
2045  // will handle cases with specific dimensionality
2046  template <typename Dest, typename Source, unsigned int Dim>
2048 
2049  template <typename Dest, typename Source>
2050  struct ConvertToImpl : public ConvertToImplDim<Dest, Source, dimension<Source>()> {};
2051 
2052  template <typename Dest, typename T, std::size_t Dim>
2053  struct ConvertToImpl<Dest, std::array<T, Dim>>
2054  : public ConvertArrayTo<Dest, std::array<T, Dim>, Dim> {};
2055 
2056  template <typename Dest, typename T, std::size_t Dim>
2057  struct ConvertToImpl<Dest, T[Dim]> : public ConvertArrayTo<Dest, T[Dim], Dim> {};
2058 
2059  // special special implementation for T*, since we can't guess its dimension
2060  template <typename Dest, typename T>
2061  struct ConvertToImpl<Dest, T*> {
2062  static_assert(std::is_arithmetic_v<T>);
2063  static Dest convert(T* v) { return geo::vect::makeFromCoords<Dest>(v); }
2064  }; // struct ConvertToImpl<T*>
2065 
2066  // handled cases with specific dimensionality
2067  template <typename Dest, typename Source, unsigned int Dim>
2068  struct ConvertToImplDim {
2069  // trivial to do: open a feature request!
2070  static_assert(AlwaysFalse<Dest>(), "This vector dimensionality is not implemented yet.");
2071  }; // struct ConvertToImplDim
2072 
2073  template <typename Dest, typename Source>
2074  struct ConvertToImplDim<Dest, Source, 2U> : private ConvertToImplBase<Dest, Source> {
2075  static Dest convert(Source const& v) { return {Xcoord(v)(), Ycoord(v)()}; }
2076  }; // struct ConvertToImplDim<2U>
2077 
2078  template <typename Dest, typename Source>
2079  struct ConvertToImplDim<Dest, Source, 3U> : private ConvertToImplBase<Dest, Source> {
2080  static Dest convert(Source const& v) { return {Xcoord(v)(), Ycoord(v)(), Zcoord(v)()}; }
2081  }; // struct ConvertToImplDim<3U>
2082 
2083  template <typename Dest, typename Source>
2084  struct ConvertToImplDim<Dest, Source, 4U> : private ConvertToImplBase<Dest, Source> {
2085  static Dest convert(Source const& v)
2086  {
2087  return {Xcoord(v)(), Ycoord(v)(), Zcoord(v)(), Tcoord(v)()};
2088  }
2089  }; // struct ConvertToImplDim<4U>
2090 
2091  template <typename Dest, typename Source>
2092  struct ConvertToDispatcher : public ConvertToImpl<Dest, Source> {};
2093 
2094  // special pass-through case
2095  template <typename Vector>
2096  struct ConvertToDispatcher<Vector, Vector> {
2097  static constexpr decltype(auto) convert(Vector const& v) { return v; }
2098  }; // struct ConvertToDispatcher<pass through>
2099 
2100  //----------------------------------------------------------------------------
2101  template <typename Point, std::size_t... I>
2102  bool isfiniteImpl(Point const& point, std::index_sequence<I...>)
2103  {
2104  return extended_and(std::isfinite(coord(point, I).get())...);
2105  }
2106 
2107  //----------------------------------------------------------------------------
2108 
2109 } // namespace geo::vect::details
2110 
2111 //------------------------------------------------------------------------------
2112 template <typename Vector>
2113 constexpr std::array<std::size_t, geo::vect::dimension<Vector>()> geo::vect::indices()
2114 {
2115  return details::makeIndexSeq<std::size_t, dimension<Vector>()>();
2116 }
2117 
2118 template <typename Vector>
2119 constexpr auto geo::vect::indices(Vector const&) -> decltype(indices<Vector>())
2120 {
2121  return indices<Vector>();
2122 }
2123 
2124 //------------------------------------------------------------------------
2125 template <typename Vector, typename Coords>
2126 constexpr Vector geo::vect::makeFromCoords(Coords&& coords)
2127 {
2128  using namespace geo::vect::details;
2129  return makeFromCoordsImpl<Vector>(constexpr_forward<Coords>(coords), makeVectorIndices<Vector>());
2130 } // geo::vect::makeFromCoords()
2131 
2132 //------------------------------------------------------------------------------
2133 template <typename Vector>
2134 constexpr auto geo::vect::coordManager(unsigned int n)
2135 {
2137 }
2138 
2139 //------------------------------------------------------------------------------
2140 template <typename Vector>
2141 auto geo::vect::coord(Vector& v, unsigned int n) noexcept
2142 {
2143  return vect::bindCoord<Vector>(v, coordManager<Vector>(n));
2144 }
2145 
2146 //------------------------------------------------------------------------
2147 template <typename Vector, typename Coords>
2148 unsigned int geo::vect::fillCoords(Coords& dest, Vector const& src)
2149 {
2150  // this is simpler than makeFromCoords() because doesn't attempt constexpr
2151  for (std::size_t i = 0; i < geo::vect::dimension(src); ++i)
2152  dest[i] = geo::vect::coord(src, i);
2153  return geo::vect::dimension(src);
2154 } // geo::vect::fillCoords()
2155 
2156 //------------------------------------------------------------------------------
2157 template <typename Vector>
2159 {
2160  using PlainVector = std::remove_reference_t<Vector>;
2162 } // geo::vect::coordManagers()
2163 
2164 template <typename Vector>
2165 constexpr auto geo::vect::coordManagers(Vector&&)
2166 {
2167  return coordManagers<Vector>();
2168 }
2169 
2170 template <typename Vector>
2171 constexpr auto geo::vect::coordReaders()
2172 {
2173  using ConstVector = std::add_const_t<std::remove_reference_t<Vector>>;
2175 } // geo::vect::coordReaders()
2176 
2177 template <typename Vector>
2178 constexpr auto geo::vect::coordReaders(Vector&&)
2179 {
2180  return coordReaders<Vector>();
2181 }
2182 
2183 //------------------------------------------------------------------------------
2184 template <typename Vector>
2185 constexpr auto geo::vect::bindCoordManagers(Vector& v)
2186 {
2188 } // geo::vect::bindCoordManagers()
2189 
2190 template <typename Vector>
2191 constexpr auto geo::vect::bindCoordReaders(Vector const& v)
2192 {
2193  using ConstVector = std::add_const_t<std::remove_reference_t<Vector>>;
2195 } // geo::vect::bindCoordReaders()
2196 
2197 //------------------------------------------------------------------------------
2198 template <typename Dest, typename Source>
2199 Dest geo::vect::convertTo(Source const& v)
2200 {
2202 }
2203 
2204 //----------------------------------------------------------------------------
2205 template <typename Dest, typename Source>
2206 std::vector<Dest> geo::vect::convertCollTo(std::vector<Source> const& coll)
2207 {
2208 
2209  std::vector<Dest> dest;
2210  dest.reserve(coll.size());
2211  std::transform(
2212  coll.begin(), coll.end(), std::back_inserter(dest), geo::vect::convertTo<Dest, Source>);
2213  return dest;
2214 
2215 } // geo::vect::convertCollTo()
2216 
2217 //------------------------------------------------------------------------
2218 template <typename Vector, typename Pred>
2219 Vector geo::vect::transformCoords(Vector const& v, Pred&& pred)
2220 {
2222  unsigned int i = 0;
2223  for (auto c : bindCoordReaders(v))
2224  values[i++] = pred(c());
2225  return makeFromCoords<Vector>(values);
2226 } // geo::vect::transformCoords()
2227 
2228 //------------------------------------------------------------------------------
2229 template <typename Vector>
2230 bool geo::vect::isfinite(Vector const& v)
2231 {
2232  return details::isfiniteImpl(v, details::makeVectorIndices<Vector>());
2233 }
2234 
2235 //------------------------------------------------------------------------------
2236 
2237 #endif // LARCOREOBJ_SIMPLETYPESANDCONSTANTS_GEO_VECTORS_UTILS_H
void operator()(Vector_t &v, Scalar_t c) const
Setter: assigns a value to the bound coordinate of specified vector.
constexpr auto coordManager(unsigned int n)
Returns an object that can be bound to a vector to manage one of its coordinates. ...
constexpr T && constexpr_forward(std::remove_reference_t< T > &&t)
constexpr auto coordManager(unsigned int n, Vector &v)
Returns an object that can be bound to a vector to manage one of its coordinates. ...
static constexpr bool TestZ(...)
void round01(Vector &v, Scalar tol)
Returns a vector with all components rounded if close to 0, -1 or +1.
static constexpr auto XcoordManager< Vector const >
Object that can be bound to a vector to access its X coordinate.
decltype(auto) cbegin(ROOT::Math::LorentzVector< CoordSystem > const &v)
Constant iterator to vector coordinates.
typename BaseTypes_t::Scalar_t Scalar_t
BoundCoordManager(Stored_t &v, CoordHelper_t coordManager)
Constructor: manage the specified coordinate of specified vector.
typename Traits_t::Getter_t Getter_t
void clear()
Resets the status of the object to no accumulated points.
typename CoordHelper_t::Getter_t Getter_t
Point makePoint() const
Converts the internal sums into a Point.
constexpr auto accessElement(Data &&data)
CoordConstIterator(Vector &v, unsigned int index=0)
Constructor: points to index coordinate of vector v.
Point middlePointAs() const
Returns the middle point, NaN components if no point.
auto Zcoord(Vector &v)
Returns an object to manage the coordinate Z of the vector v.
2D point (x, y) (by default, with double precision)
constexpr auto makeVectorIndices(Vector &&)
static constexpr bool TestX(...)
constexpr auto makeIndexSeq()
static auto compute(Op, T &&v) -> decltype(auto)
An object with a begin and end iterator.
static constexpr auto XcoordManager
Object that can be bound to a vector to manage its X coordinate.
Point makePointImpl(std::index_sequence< I... >) const
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
std::vector< Dest > convertCollTo(std::vector< Source > const &coll)
Returns a vector of type Dest with the same content as a Src.
void mult(Vector_t &v, Scalar_t f) const
Multiplies the coordinate by the specified amount.
static constexpr auto YcoordManager< Vector const >
static constexpr auto const YcoordManager
typename BaseTypes_t::Vector_t Vector_t
auto mixedProduct(Vector const &a, Vector const &b, Vector const &c)
auto coord(Vector &v, unsigned int n) noexcept
Returns an object to manage the coordinate n of a vector.
constexpr auto bindCoordReaders(Vector const &v)
Helper class to compute the middle point in a point set.
bool operator<=(iterator_t const &other) const
geo::vect::coordinate_t< Vector_t > Coord_t
Type of vector coordinate.
constexpr auto indices(Vector const &) -> decltype(indices< Vector >())
Returns a sequence of indices valid for a vector of the specified type.
constexpr auto makeCoordReader(Getter getter)
Float_t Y
Definition: plot.C:37
typename Traits_t::Setter_t Setter_t
constexpr auto makeIndexSeqImpl(std::integer_sequence< T, Indices... >)
typename MemberFuncReturnType< T >::type MemberFuncReturn_t
::fhicl::TupleAs< Point(::geo::Length_t,::geo::Length_t,::geo::Length_t)> Point3D
Atom object for reading a 3D point or vector (centimeters).
double weight() const
Returns the total weight (number of points if all have weight 1).
::geo::Point_t toPoint(Point const &p)
Convert the specified point into a geo::Point_t.
constexpr bool HasX()
iterator_t operator-(iterator_t const &other) const
Returns the distance from another iterator.
constexpr auto abs(T v)
Returns the absolute value of the argument.
auto iterateCoords(Vector const &v)
Returns an object for ranged-for iteration on coordinates.
::geo::Vector_t toVector(Vector const &v)
Convert the specified vector into a geo::Vector_t.
static constexpr auto TcoordManager
std::remove_cv_t< Coord_t > value_type
BoundCoordManager & operator+=(Scalar_t c)
Increments by the specified amount.
STL namespace.
constexpr auto bindCoord(Vector const &v, CoordReader_t< Vector > helper)
Binds the specified constant vector to the coordinate reader.
BoundCoordManager(Stored_t &v, Getter_t getter, Setter_t setter)
Constructor: manage the specified vector with specified methods.
static constexpr auto ZcoordManager
decltype(Xcoord(std::declval< Vector >())) Manager_t
enum geo::coordinates Coord_t
Enumerate the possible plane projections.
iterator_t operator-(difference_type d) const
Returns an iterator decremented by d positions (unchecked).
typename BaseTypes_t::Getter_t Getter_t
typename BaseTypes_t::Setter_t Setter_t
constexpr auto coordManagers()
Returns an array with all coordinate managers for a type of vector.
void round0(Vector &v, Scalar tol)
Returns a vector with all components rounded if close to 0.
Helper class for read/write of a single vector coordinate.
typename CoordHelper_t::Vector_t Vector_t
bool operator>(iterator_t const &other) const
typename MemberFuncClassType< T >::type MemberFuncClass_t
BoundCoordGetter(Stored_t &v, Getter_t getter)
Constructor: manage the specified vector with specified methods.
std::array< Length_t, Dim > fSums
Sum of each of the point components.
void add(Point const &p)
Accumulates a point.
constexpr unsigned int dimension()
Returns the dimension of the specified vector type.
Point middlePoint(std::initializer_list< Point > points)
Returns the middle of the specified points.
static constexpr auto ZcoordManager< Vector const >
recob::tracking::Point_t Point_t
static auto compute(Op op, First &&a, Second &&b, Others &&...others) -> decltype(auto)
unsigned int fillCoords(Coords &dest, Vector const &src)
Fills a coordinate array with the coordinates of a vector.
typename BaseTypes_t::Scalar_t Scalar_t
Point middlePointAs(BeginIter begin, EndIter end)
Returns the middle of the specified points.
void add(Point const &p, double weight)
Accumulates a point.
Float_t Z
Definition: plot.C:37
iterator_t operator+(difference_type d) const
Returns an iterator incremented by d positions (unchecked).
static constexpr bool TestX(decltype(std::declval< Class >().X())*)
TFile f
Definition: plotHisto.C:6
typename VectorScalar< Vector >::type VectorScalar_t
typename Traits_t::Vector_t Vector_t
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:289
iterator_t operator--(int)
Points to previous coordinate (unchecked), returns the previous iterator.
std::random_access_iterator_tag iterator_category
constexpr auto coordReaders()
Returns an array with all coordinate readers for a type of vector.
BoundCoordManager & operator/=(Scalar_t f)
Divides by the specified amount.
void decr(Vector_t &v, Scalar_t c) const
Decrements the coordinate by the specified amount.
Utilities to manipulate geometry vectors.The utilities include generic vector interface facilities al...
bool isfinite(Vector const &v)
Returns whether all components of the vector are finite.
typename BaseTypes_t::Vector_t Vector_t
auto array(Array const &a)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:250
typename Traits_t::Scalar_t Scalar_t
Getter_t fGetter
Member function returning the coordinate value.
constexpr CoordManager_t< Vector > NoCoordManager
void add(BeginIter begin, EndIter end)
Adds a sequence of points.
bool empty() const
Returns whether the total weight is zero (usually means no points).
typename BaseTypes_t::Vector_t Vector_t
void incr(Vector_t &v, Scalar_t c) const
Increments the coordinate by the specified amount.
iterator_t & operator--()
Points to the previous coordinate (unchecked).
Point2D< T > operator+(Point2D< T > const &a, Point2D< T > const &b)
Definition: SimpleGeo.h:72
Definitions of geometry vector data types.
std::vector< geo::Point_t > convertCollToPoint(std::vector< Point > const &coll)
auto vector_cend(Vector const &v)
Returns a const-iterator pointing after the last coordinate of v.
constexpr Vector makeFromCoordsImpl(Coords &&coords, std::index_sequence< Indices... >)
constexpr CoordGetter(Getter_t getter)
Constructor: sets getter and setter functions.
typename BaseTypes_t::Scalar_t Scalar_t
decltype(auto) values(Coll &&coll)
Range-for loop helper iterating across the values of the specified collection.
MiddlePointAccumulatorDim(BeginIter begin, EndIter end)
Constructor: starts with accumulating a sequence of points.
auto extended_and(T...args) -> decltype(auto)
typename CoordHelper_t::Setter_t Setter_t
decltype(auto) begin(ROOT::Math::LorentzVector< CoordSystem > const &v)
typename CoordHelper_t::Scalar_t Scalar_t
constexpr std::array< std::size_t, geo::vect::dimension< Vector >)> indices()
Returns a sequence of indices valid for a vector of the specified type.
bool operator>=(iterator_t const &other) const
Simple class definitions for geometry concepts.
MemberFuncReturn_t< Setter_t > SetterReturn_t
constexpr auto makeCoordManager(Getter getter, Setter setter)
constexpr T roundValue0(T value, T tol)
Returns value, rounded to 0 if closer than tol.
3D point (x, y, z) (by default, with double precision)
Float_t d
Definition: plot.C:235
void LorentzVector(Stream &&out, TLorentzVector const &v)
Print a TLorentzVector to an output stream.
iterator_t & operator++()
Points to the next coordinate (unchecked).
BoundCoordManager & operator*=(Scalar_t f)
Multiplies by the specified amount.
auto Ycoord(Vector &v)
Returns an object to manage the coordinate Y of the vector v.
typename decltype(std::mem_fn(std::declval< T >()))::result_type type
static constexpr bool TestY(...)
decltype(details::makeCoordManager(&Vector::X,&Vector::SetX)) CoordManager_t
Type of a coordinate manager for a vector type.
constexpr bool HasT()
bool isfiniteImpl(Point const &point, std::index_sequence< I... >)
constexpr auto dot(Vector const &a, OtherVector const &b)
Return cross product of two vectors.
Vector transformCoords(Vector const &v, Pred &&pred)
Returns a new vector applying a predicate to each component.
constexpr auto coordReaders(Vector &&)
Returns an array with all coordinate readers for a type of vector.
CoordHelper_t fCoord
Helper to manage a specific coordinate.
double value
Definition: spectrum.C:18
Vector rounded01(Vector const &v, Scalar tol)
Returns a vector with all components rounded if close to 0, -1 or +1.
auto mag2(Vector const &v)
Return norm of the specified vector.
auto Xcoord(Vector &v)
Returns an object to manage the coordinate X of the vector v.
BoundCoordManager & operator-=(Scalar_t c)
Decrements by the specified amount.
typename BaseTypes_t::Getter_t Getter_t
Point makeWeightedPointImpl(double w, std::index_sequence< I... >) const
BoundCoordGetter(Stored_t &v, CoordHelper_t coordManager)
Constructor: manage the specified coordinate of specified vector.
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
Scalar_t operator()(Vector_t const &v) const
Returns the value of the bound coordinate.
constexpr bool HasZ()
double weight
Definition: plottest35.C:25
auto Tcoord(Vector &v)
Returns an object to manage the coordinate T of the vector v.
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
Definition: StdUtils.h:120
constexpr bool HasY()
CoordHelper_t const & manager() const
auto extended_accumulate(Op op, T &&...args)
BoundCoordManager & operator=(Scalar_t c)
Setter: assigns a value to the bound coordinate of specified vector.
typename BaseTypes_t::Getter_t Getter_t
Float_t norm
LArSoft-specific namespace.
std::make_index_sequence< Dim > IndexSequence_t
static constexpr auto TcoordManager< Vector const >
auto vector_cbegin(Vector const &v)
Returns a const-iterator pointing to the first coordinate of v.
std::array< VectorScalar_t< Vector >, dimension< Vector >()> CoordinateArray_t
A STL array suitable to contain all coordinate values of a Vector.
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:42
decltype(details::makeCoordReader(&Vector::X)) CoordReader_t
Type of a coordinate reader for a vector type.
std::vector< geo::Vector_t > convertCollToVector(std::vector< Vector > const &coll)
decltype(auto) end(ROOT::Math::LorentzVector< CoordSystem > const &v)
Scalar_t operator()() const
Returns the value of the bound coordinate.
constexpr T roundValue01(T value, T tol)
Returns value, rounded to 0, -1 or +1 if closer than tol.
constexpr auto bindCoordManagers(Vector &v)
constexpr CoordManager(Getter_t getter, Setter_t setter)
Constructor: sets getter and setter functions.
span(IterB &&b, IterE &&e, Adaptor &&adaptor) -> span< decltype(adaptor(std::forward< IterB >(b))), decltype(adaptor(std::forward< IterE >(e))) >
constexpr auto coordManagers(Vector &&)
Returns an array with all coordinate managers for a type of vector.
Setter_t fSetter
Member function setting the coordinate value.
reference operator[](difference_type n) const
Access the current coordinate.
bool operator==(iterator_t const &other) const
Stored_t & fVector
The vector to manage the coordinate of.
MiddlePointAccumulatorDim()
Default constructor: starts with no accumulated point.
Helper class for read of a single vector coordinate.
bool operator!=(iterator_t const &other) const
Char_t n[5]
details::VectorScalar_t< Vector > coordinate_t
Type of coordinate of the specified vector type.
constexpr unsigned int dimension(Vector &&)
Returns the dimension of the specified vector type.
constexpr Vector makeFromCoords(Coords &&coords)
Creates a Vector object with coordinates from coords.
static constexpr bool TestT(...)
std::make_index_sequence< dimension< Vector >()> VectorIndices_t
Type of sequence of indices up to Vector size.
Vector cross(Vector const &a, Vector const &b)
Return cross product of two vectors.
Vector normalize(Vector const &v)
Returns a vector parallel to v and with norm 1.
Dest convertTo(Source const &v)
Returns a vector of type Dest with the same content as a Src.
Eigen::Vector3f Coords
Definition: DCEL.h:44
void div(Vector_t &v, Scalar_t f) const
Divides the coordinate by the specified amount.
Vector rounded0(Vector const &v, Scalar tol)
Returns a vector with all components rounded if close to 0.
reference operator*() const
Access the current coordinate.
auto bindCoord(Vector &v, CoordManager_t< Vector > helper) -> details::BoundCoordManager< CoordManager_t< Vector >, Vector >
Binds the specified vector to the coordinate manager.
iterator_t & operator+=(difference_type d)
Increments the iterator by d positions (unchecked).
Float_t X
Definition: plot.C:37
GENVECTOR_CONSTEXPR::geo::Point_t makePointFromCoords(Coords &&coords)
Creates a geo::Point_t from its coordinates (see makeFromCoords()).
Namespace collecting geometry-related classes utilities.
Float_t w
Definition: plot.C:20
GENVECTOR_CONSTEXPR::geo::Vector_t makeVectorFromCoords(Coords &&coords)
Creates a geo::Vector_t from its coordinates (see makeFromCoords()).
recob::tracking::Vector_t Vector_t
static Dest convert(Source const &v)
decltype(auto) cend(ROOT::Math::LorentzVector< CoordSystem > const &v)
iterator_t & operator-=(difference_type d)
Decrements the iterator by d positions (unchecked).
iterator_t operator++(int)
Points to the next coordinate (unchecked), returns the previous iterator.
bool operator<(iterator_t const &other) const
static constexpr bool TestY(decltype(std::declval< Class >().Y())*)
static constexpr bool TestZ(decltype(std::declval< Class >().Z())*)
static constexpr bool TestT(decltype(std::declval< Class >().T())*)