geo_vectors_utils.h
Go to the documentation of this file.
1 /**
2  * @file larcorealg/Geometry/geo_vectors_utils.h
3  * @brief Utilities to extend the interface of geometry vectors.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date November 27, 2017
6  * @ingroup Geometry
7  *
8  * This library provides facilities that can be used for both LArSoft geometry
9  * vectors (`geo_vectors.h`) and ROOT `TVector3` and related, with the same
10  * interface.
11  *
12  * This library depends on ROOT GenVector.
13  * In the CET link list in `CMakeLists.txt`, link to `${ROOT_GENVECTOR}`.
14  *
15  */
16 
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/PositionVector2D.h"
26 #include "Math/GenVector/DisplacementVector2D.h"
27 #include "Math/GenVector/PositionVector3D.h"
28 #include "Math/GenVector/DisplacementVector3D.h"
29 #include "Math/GenVector/LorentzVector.h"
30 
31 // C/C++ standard library
32 #include <array>
33 #include <vector>
34 #include <iterator> // std::back_inserter()
35 #include <type_traits> // std::declval(), std::is_same<>, ...
36 #include <functional> // std::mem_fn()
37 #include <cassert>
38 
39 
40 namespace geo {
41 
42  /**
43  * @brief Utilities to manipulate geometry vectors.
44  * @ingroup Geometry
45  *
46  * The utilities include generic vector interface facilities allowing to
47  * use different vector types via templates.
48  */
49  namespace vect {
50 
51  //--------------------------------------------------------------------------
52  namespace details {
53  //------------------------------------------------------------------------
54  template <typename Op, typename... T>
56 
57  template
58  <typename Op, typename First, typename Second, typename... Others>
59  struct AccumulateImpl<Op, First, Second, Others...> {
60  static auto compute(Op op, First&& a, Second&& b, Others&&... others)
61  -> decltype(auto)
62  {
63  return op(
64  a,
66  (op, std::forward<Second>(b), std::forward<Others>(others)...)
67  );
68  }
69  }; // AccumulateImpl<>
70 
71  template <typename Op, typename T>
72  struct AccumulateImpl<Op, T> {
73  static auto compute(Op, T&& v) -> decltype(auto)
74  { return std::forward<T>(v); }
75  };
76 
77  template <typename Op, typename... T>
78  auto extended_accumulate(Op op, T&&... args)
79  { return AccumulateImpl<Op, T...>::compute(op, std::forward<T>(args)...); }
80 
81 
82  template <typename... T>
83  auto extended_and(T... args) -> decltype(auto)
84  {
85  auto and_op = [](auto&& a, auto&& b) { return a && b; };
86  return extended_accumulate(and_op, std::forward<T>(args)...);
87  }
88 
89  //------------------------------------------------------------------------
90  //
91  // These two pages of metaprogramming madness are aimed to have objects
92  // that can provide a uniform coordinate get/set for any type of vector,
93  // with the minimal run-time overhead.
94  // Complications arise from the fact that TVector3 setter returns void,
95  // while GenVector vectors return a reference to the vector itself
96  // (hence the need of the additional SetterResult template parameter,
97  // and of quite some code to autodetect its value).
98  // The makeXxxx() functions are aimed to enclose the additional
99  // autodetection overlay, which should become unnecessary with C++17.
100  //
101 
102  template <typename Vector>
103  struct VectorScalar { using type = typename Vector::Scalar; };
104 
105  template <typename Vector>
107 
108 
109  //------------------------------------------------------------------------
110  template <typename Vector>
111  struct HasGetter {
112  private:
113 
114  template<typename Class>
115  static constexpr bool TestX(decltype(std::declval<Class>().X())*) { return true; }
116  template<typename Class>
117  static constexpr bool TestX(...) { return false; }
118  template<typename Class>
119  static constexpr bool TestY(decltype(std::declval<Class>().Y())*) { return true; }
120  template<typename Class>
121  static constexpr bool TestY(...) { return false; }
122  template<typename Class>
123  static constexpr bool TestZ(decltype(std::declval<Class>().Z())*) { return true; }
124  template<typename Class>
125  static constexpr bool TestZ(...) { return false; }
126  template<typename Class>
127  static constexpr bool TestT(decltype(std::declval<Class>().T())*) { return true; }
128  template<typename Class>
129  static constexpr bool TestT(...) { return false; }
130 
131  public:
132  static constexpr bool X = TestX<Vector>(nullptr);
133  static constexpr bool Y = TestY<Vector>(nullptr);
134  static constexpr bool Z = TestZ<Vector>(nullptr);
135  static constexpr bool T = TestT<Vector>(nullptr);
136  }; // struct HasGetter<>
137 
138  template <typename Vector>
139  constexpr bool HasX() { return HasGetter<Vector>::X; }
140  template <typename Vector>
141  constexpr bool HasY() { return HasGetter<Vector>::Y; }
142  template <typename Vector>
143  constexpr bool HasZ() { return HasGetter<Vector>::Z; }
144  template <typename Vector>
145  constexpr bool HasT() { return HasGetter<Vector>::T; }
146 
147  template <typename Vector, typename = void>
149 
150  template <typename Vector>
151  constexpr unsigned int dimension()
152  { return DimensionImpl<Vector>::value; }
153 
154 
155  /// A STL array suitable to contain all coordinate values of a `Vector`.
156  template <typename Vector>
157  using CoordinateArray_t
158  = std::array<VectorScalar_t<Vector>, dimension<Vector>()>;
159 
160 
161  template <typename T>
163  // with C++17 `result_type` is deprecated,
164  // and a different way will be needed
165  using type
166  = typename decltype(std::mem_fn(std::declval<T>()))::result_type;
167  }; // MemberFuncReturnType
168 
169  template <typename T>
171 
172  template <typename T>
174 
175  template <typename Class, typename Func>
176  struct MemberFuncClassType<Func Class::*> { using type = Class; };
177 
178  template <typename T>
180 
181 
182  template <typename Vector, typename SetterType = void>
184 
185  template <typename Vector>
186  struct BaseCoordTypes<Vector, void> {
187  using Vector_t = std::decay_t<Vector>;
189  using Getter_t = Scalar_t (Vector_t::*)() const;
190  }; // struct BaseCoordTypes<void>
191 
192  template <typename Vector, typename SetterType>
193  struct BaseCoordTypes {
194  private:
196 
197  public:
198  using Scalar_t = typename BaseTypes_t::Scalar_t;
199  using Vector_t = typename BaseTypes_t::Vector_t;
200  using Getter_t = typename BaseTypes_t::Getter_t;
201  using Setter_t = SetterType;
203  static_assert(
204  std::is_same<Setter_t, SetterReturn_t (Vector_t::*)(Scalar_t)>(),
205  "Invalid setter type"
206  );
207  }; // struct BaseCoordTypes<>
208 
209 
210  template <typename Vector>
212  private:
214  public:
215  using Vector_t = typename BaseTypes_t::Vector_t;
216  using Scalar_t = typename BaseTypes_t::Scalar_t;
217  using Getter_t = typename BaseTypes_t::Getter_t;
218  }; // struct CoordGetterTraits
219 
220 
221  /// Helper class for read of a single vector coordinate.
222  template <typename Vector>
223  class CoordGetter {
225 
226  public:
227  using Vector_t = typename Traits_t::Vector_t;
228  using Scalar_t = typename Traits_t::Scalar_t;
229  using Getter_t = typename Traits_t::Getter_t;
230 
231  /// Constructor: sets getter and setter functions.
232  constexpr CoordGetter(Getter_t getter): fGetter(getter) {}
233 
234  /// Returns the value of the bound coordinate.
235  Scalar_t operator() (Vector_t const& v) const { return get(v); }
236 
237  /// Returns the value of the bound coordinate.
238  Scalar_t get(Vector_t const& v) const { return (v.*fGetter)(); }
239 
240  private:
241  Getter_t fGetter; ///< Member function returning the coordinate value.
242 
243  }; // class CoordGetter<>
244 
245  template <typename Getter>
246  constexpr auto makeCoordReader(Getter getter)
247  {
248  using Vector_t = std::remove_reference_t<MemberFuncClass_t<Getter>>;
249  return CoordGetter<Vector_t>{ getter };
250  }
251 
252 
253  template <typename Vector, typename SetterType>
255  private:
257  public:
258  using Vector_t = typename BaseTypes_t::Vector_t;
259  using Scalar_t = typename BaseTypes_t::Scalar_t;
260  using Getter_t = typename BaseTypes_t::Getter_t;
261  using Setter_t = typename BaseTypes_t::Setter_t;
262  }; // struct VectorCoordManagerTraits<>
263 
264 
265  /// Helper class for read/write of a single vector coordinate.
266  template <typename Vector, typename SetterType>
267  class CoordManager: public CoordGetter<Vector> {
270 
271  public:
272  using Vector_t = typename Traits_t::Vector_t; // this is not constant
273  using Scalar_t = typename Traits_t::Scalar_t;
274  using Getter_t = typename Traits_t::Getter_t;
275  using Setter_t = typename Traits_t::Setter_t;
276 
277  /// Constructor: sets getter and setter functions.
278  constexpr CoordManager(Getter_t getter, Setter_t setter)
279  : Base_t(getter), fSetter(setter) {}
280 
281  /// Setter: assigns a value to the bound coordinate of specified vector.
282  void operator()(Vector_t& v, Scalar_t c) const { set(v, c); }
283 
284  /// Setter: assigns a value to the bound coordinate of specified vector.
285  void set(Vector_t& v, Scalar_t c) const { (v.*fSetter)(c); }
286 
287  /// Increments the coordinate by the specified amount.
288  void incr(Vector_t& v, Scalar_t c) const { set(v, Base_t::get(v) + c); }
289 
290  /// Decrements the coordinate by the specified amount.
291  void decr(Vector_t& v, Scalar_t c) const { set(v, Base_t::get(v) - c); }
292 
293  /// Multiplies the coordinate by the specified amount.
294  void mult(Vector_t& v, Scalar_t f) const { set(v, Base_t::get(v) * f); }
295 
296  /// Divides the coordinate by the specified amount.
297  void div(Vector_t& v, Scalar_t f) const { set(v, Base_t::get(v) / f); }
298 
299  private:
300  Setter_t fSetter; ///< Member function setting the coordinate value.
301  }; // class CoordManager<>
302 
303 
304  template <typename Getter, typename Setter>
305  constexpr auto makeCoordManager(Getter getter, Setter setter)
306  {
307  using Vector_t = std::remove_reference_t<MemberFuncClass_t<Getter>>;
308  return CoordManager<Vector_t, Setter>{getter, setter};
309  }
310 
311 
312 
313  template <typename CoordHelper, typename StoredVector>
315 
316  public:
317  using Stored_t = StoredVector;
318 
319  using CoordHelper_t = CoordHelper;
321  using Scalar_t = typename CoordHelper_t::Scalar_t;
322  using Getter_t = typename CoordHelper_t::Getter_t;
323 
324  /// Constructor: manage the specified coordinate of specified vector.
326  : fCoord(coordManager), fVector(v) {}
327 
328  /// Constructor: manage the specified vector with specified methods.
330  : fCoord(getter), fVector(v) {}
331 
332  /// Returns the value of the bound coordinate.
333  Scalar_t get() const { return manager().get(vector()); }
334 
335  /// Returns the value of the bound coordinate.
336  Scalar_t operator() () const { return get(); }
337 
338  /// Returns the value of the bound coordinate.
339  operator Scalar_t() const { return manager().get(vector()); }
340 
341  protected:
342  CoordHelper_t const& manager() const { return fCoord; }
343  Stored_t& vector() const { return fVector; }
344 
345  private:
346  CoordHelper_t fCoord; ///< Helper to manage a specific coordinate.
347  Stored_t& fVector; ///< The vector to manage the coordinate of.
348  }; // class VectorCoordGetter<>
349 
350 
351  template <typename CoordHelper, typename StoredVector>
353  : public BoundCoordGetter<CoordHelper, StoredVector>
354  {
356 
357  public:
358  using typename Base_t::Stored_t;
359 
360  using CoordHelper_t = CoordHelper;
362  using Scalar_t = typename CoordHelper_t::Scalar_t;
363  using Getter_t = typename CoordHelper_t::Getter_t;
364  using Setter_t = typename CoordHelper_t::Setter_t;
365 
366  /// Constructor: manage the specified coordinate of specified vector.
368  : Base_t(v, coordManager) {}
369 
370  /// Constructor: manage the specified vector with specified methods.
372  : Base_t(v, CoordHelper_t(getter, setter)) {}
373 
374  /// Setter: assigns a value to the bound coordinate of specified vector.
376  { Base_t::manager().set(Base_t::vector(), c); return *this; }
377 
378  /// Increments by the specified amount.
380  { Base_t::manager().incr(Base_t::vector(), c); return *this; }
381 
382  /// Decrements by the specified amount.
384  { Base_t::manager().decr(Base_t::vector(), c); return *this; }
385 
386  /// Multiplies by the specified amount.
388  { Base_t::manager().mult(Base_t::vector(), f); return *this; }
389 
390  /// Divides by the specified amount.
392  { Base_t::manager().div(Base_t::vector(), f); return *this; }
393 
394  }; // class BoundCoordManager
395 
396  //------------------------------------------------------------------------
397 
398  } // namespace details
399 
400 
401  // BEGIN Geometry group ------------------------------------------------------
402  /// @ingroup Geometry
403  /// @{
404 
405  /// Convenience utilities not directly related to vectors.
406  namespace extra {
407 
408  /// Returns `value`, rounded to 0 if closer than `tol`.
409  template <typename T>
410  constexpr T roundValue0(T value, T tol) {
411  return (std::abs(value) < tol)? T{}: value;
412  } // roundValue0()
413 
414  /// Returns `value`, rounded to 0, -1 or +1 if closer than `tol`.
415  template <typename T>
416  constexpr T roundValue01(T value, T tol) {
417  if (std::abs(value) < tol) return 0.;
418  if (std::abs(std::abs(value) - 1.) < tol) return (value > 0.)? 1.: -1.;
419  return value;
420  } // roundValue01()
421 
422  } // namespace extra
423 
424 
425  // --- BEGIN Vector coordinate access abstraction --------------------------
426  /// @{
427  /**
428  * @name Vector coordinate access abstraction
429  *
430  * This group of utilities provides a common interface for tasks involving
431  * geometry vectors, which may have different interface.
432  * An example of that is the access of coordinates by an index: it is
433  * supported (and "slow") in `TVector3` for read/write access, while in
434  * GenVector it is not supported (and given that the internal representation
435  * might be not cartesian, it's not surprising). We provide utilities which
436  * fill the gaps, relying on some looser requirements.
437  *
438  *
439  * Coordinate managers
440  * ====================
441  *
442  * A "coordinate manager" is an object handling a specific coordinate out of
443  * a specific vector type; i.e., a coordinate manager object will manage for
444  * its entire lifetime the same coordinate, e.g. _x_ or _z_.
445  * A coordinate manager can be:
446  * - bound to a vector object: that manager handles exclusively its managed
447  * coordinate for that vector object;
448  * - unbound: such a manager can handle the managed coordinate of any
449  * vector, which can be passed as an argument; or the unbound manager can
450  * be used to create a bound one.
451  *
452  * Two types of managers are available:
453  * - reader, accesses the coordinate but can't modify it
454  * - manager, requires to be bound to a mutable vector and can assign and
455  * modify the coordinate via selected operations
456  *
457  * Note that a coordinate is never returned as a reference, either mutable
458  * or constant.
459  *
460  *
461  * Handling a coordinate of a vector object: bound managers
462  * ---------------------------------------------------------
463  *
464  * A bound coordinate manager can be created directly:
465  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
466  * geo::Point_t p { 1.0, 2.0, 3.0 };
467  *
468  * auto px = geo::vect::Xcoord(p);
469  * std::cout << p << " has x=" << px() << std::endl;
470  * px += 5.0;
471  * std::cout << p << " has now x=" << px() << std::endl;
472  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
473  * will return something along the line of
474  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
475  * (1,2,3) has x=1
476  * (6,2,3) has now x=6
477  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
478  * Functions `Xcoord()`, `Ycoord()`, `Zcoord()` and `Tcoord()` (in namespace
479  * `geo::vect`) are available for the supporting vector types.
480  *
481  * If access by numeric index is necessary, `coord()` can be used instead:
482  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
483  * geo::Vector_t const v { 1.0, 2.0, 3.0 };
484  *
485  * for (unsigned c = 0; c < 3; ++c) {
486  * auto vc = geo::vect::coord(v, c);
487  * std::cout << v << "[" << c << "]=" << vc() << std::endl;
488  * }
489  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
490  * (note that for this example we have implicitly obtained a coordinate
491  * reader instead of a full coordinate manager because `v` is constant).
492  * This will print:
493  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
494  * v[0]=1
495  * v[1]=2
496  * v[2]=3
497  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
498  * If there are more vectors to access the same coordinate of, it's better
499  * to use unbound managers (see below).
500  *
501  *
502  * Handling a coordinate for any vector object
503  * --------------------------------------------
504  *
505  * Unbound coordinate managers (and readers) can't operate directly on
506  * vectors but they need to be bound to one. Binding produces a new bound
507  * manager, leaving the unbound manager untouched.
508  * Binding is done with `geo::vect::bindCoord()`. For example:
509  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
510  * geo::Point_t A { 1.0, 2.0, 3.0 };
511  * auto Ax = geo::vect::bindCoord(A, YcoordManager<geo::Point_t>);
512  * std::cout << A << " has y=" << Ax << std::endl;
513  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
514  * should produce an output like
515  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
516  * (1,2,3) has y=2
517  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
518  * In the example, `YcoordManager` is a template coordinate manager.
519  * There are managers available for `X`, `Y`, `Z` and `T` coordinates, and
520  * each one can deal only with a specific vector type; also, specifying a
521  * non-constant vector type will deliver a full manager, which can't operate
522  * on constant vectors.
523  * The unbound coordinate managers are not as useful, but a possible use is
524  * for loops on coordinates from multiple vectors:
525  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
526  * geo::Point_t A { 1.0, 2.0, 3.0 }, geo::Point_t B {5.0, 7.0, 9.0 };
527  * for (unsigned c = 0; c < 3; ++c) {
528  * auto coordMan = geo::vect::coordManager(c);
529  * auto Ac = geo::vect::bindCoord(A, coordMan);
530  * auto Bc = geo::vect::bindCoord(B, coordMan);
531  * std::cout << (Bc() - Ac() * 2.0) << std::endl;
532  * } // for
533  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
534  * which will emit
535  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
536  * 3
537  * 3
538  * 3
539  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
540  * This is marginally faster than the same code with
541  * `geo::vect::bindCoord()` call replaced by `geo::vect::coord()`. More
542  * convenient still, if the coordinates are treated all just the same and
543  * `c` is not needed (as above):
544  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
545  * geo::Point_t A { 1.0, 2.0, 3.0 }, geo::Point_t B {5.0, 7.0, 9.0 };
546  * for (auto coordMan: geo::vect::coordManagers<geo::Point_t const>()) {
547  * auto Ac = geo::vect::bindCoord(A, coordMan);
548  * auto Bc = geo::vect::bindCoord(B, coordMan);
549  * std::cout << (Bc() - Ac() * 2.0) << std::endl;
550  * } // for
551  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
552  *
553  *
554  * Conversion between vector types
555  * ================================
556  *
557  * A convenience function `convertTo()` is provided to convert a vector into
558  * another of a different type (for example, from `TVector3` to
559  * `geo::Vector_t`).
560  *
561  *
562  * Vector requirements
563  * ====================
564  *
565  * So far, the requirements for this set of utilities are the following.
566  * The vector type must support:
567  * - a cartesian coordinate constructor: `Vector v { 1.0, 2.0, 3.0 };`
568  * - accessor methods named after the name of the coordinate, acting on
569  * constant vectors, taking no arguments, and returning a copy of the
570  * coordinate value, e.g. `double X() const`
571  * - coordinate assignment methods named `SetC`, where `C` is the name of
572  * each coordinate, after the name of the coordinate, with a single
573  * argument; the return type is not prescribed; e.g. `void SetY(double)`
574  * - the coordinate names must be `X` and `Y` for 2D vectors, plus `Z` for
575  * 3D vectors and `T` for 4D vectors (metric is irrelevant here)
576  *
577  */
578 
579  //@{
580  /// Returns the dimension of the specified vector type.
581  template <typename Vector>
582  constexpr unsigned int dimension() { return details::dimension<Vector>(); }
583  template <typename Vector>
584  constexpr unsigned int dimension(Vector&&) { return dimension<Vector>(); }
585  //@}
586 
587  //@{
588  /// Returns a sequence of indices valid for a vector of the specified type.
589  template <typename Vector>
590  constexpr std::array<std::size_t, geo::vect::dimension<Vector>()> indices();
591  template <typename Vector>
592  constexpr auto indices(Vector const&) -> decltype(indices<Vector>());
593  //@}
594 
595  /// Type of coordinate of the specified vector type.
596  template <typename Vector>
598 
599  /**
600  * @brief Creates a `Vector` object with coordinates from `coords`.
601  * @tparam Vector the type of vector to be created
602  * @tparam Coords type of object holding the value of the needed coordinates
603  * @param coords object holding the value of the needed coordinates
604  * @return a newly created `Vector` object with coordinates from `coords`
605  * @see `geo::vect::fillCoords()`
606  *
607  * To create a vector of dimension _N_, the first _N_ values are extracted
608  * from `coords` using `Coords::operator[](std::size_t)`. For example:
609  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
610  * constexpr std::array<float, 5U> data { 2.0, 5.0, 7.0, 11.0, 15.5 };
611  * constexpr auto p = geo::vect::makeFromCoords<geo::Point_t>(data);
612  * auto v = geo::vect::makeFromCoords<geo::Vector_t>(data.data() + 1);
613  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
614  * will set `p` as `constexpr geo::Point_t {2.0, 5.0, 7.0 }`, ignoring the
615  * additional data. Likewise, it will set `v` to
616  * `geo::Vector_t{ 5.0, 7.0, 11.0 }`. In both cases, the coordinates are
617  * implicitly converted from `float` into the scalar type of the target
618  * vectors (in both cases, `double`).
619  */
620  template <typename Vector, typename Coords>
621  constexpr Vector makeFromCoords(Coords&& coords);
622 
623 
624  /**
625  * @brief Fills a coordinate array with the coordinates of a vector.
626  * @tparam Vector type of vector being copied from
627  * @tparam Coords type of coordinate array to be filled
628  * @param src the vector to read the coordinates from
629  * @param dest the array to be filled
630  * @return the number of coordinates filled (that's `Vector`'s dimension)
631  * @see `geo::vect::makeFromCoords()`
632  *
633  * The `Coords` array type is expected to provide a indexing operator
634  * returning a r-value, that is `coords[i]` can be assigned to.
635  */
636  template <typename Vector, typename Coords>
637  unsigned int fillCoords(Coords& dest, Vector const& src);
638 
639 
640  /// Type of a coordinate reader for a vector type.
641  template <typename Vector>
642  using CoordReader_t
644 
645  /// Type of a coordinate manager for a vector type.
646  template <typename Vector>
647  using CoordManager_t = decltype
649 
650  /**
651  * @brief Object that can be bound to a vector to manage its X coordinate.
652  * @tparam Vector type of vector to get a manager for
653  * (mutable type required)
654  *
655  * The manager exposes a read/write interface.
656  * Example of usage:
657  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
658  * // mutable vectors get a full-featured "manager":
659  * geo::Point_t p { 1.0, 2.0, 3.0 };
660  * auto px
661  * = geo::vect::bindCoord(p, geo::vect::XcoordManager<geo::Point_t>);
662  * px *= 5.0;
663  * std::cout << p << " has now x=" << px() << std::endl;
664  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
665  * will print something like:
666  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
667  * (5,2,3) has now x=5
668  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
669  * Note that the use in the example, `Xcoord()` is preferred.
670  */
671  template <typename Vector>
672  static constexpr auto XcoordManager
674 
675  /**
676  * @brief Object that can be bound to a vector to access its X coordinate.
677  * @tparam Vector type of vector to get a manager for
678  * (constant type required)
679  *
680  * The manager exposes a read-only interface.
681  * Example of usage:
682  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
683  * // constant vectors get a "reader" (read-only manager):
684  * geo::Vector_t v { 1.0, 2.0, 3.0 };
685  *
686  * auto vx = geo::vect::bindCoord
687  * (v, geo::vect::XcoordManager<geo::Vector_t const>);
688  * std::cout << v << " has x=" << vx() << std::endl;
689  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
690  * will print something like:
691  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
692  * (1,2,3) has x=1
693  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
694  * Note that the use in the example, `Xcoord()` is preferred.
695  */
696  template <typename Vector>
697  static constexpr auto XcoordManager<Vector const>
699 
700  /// An object that can be bound to a vector to manage its Y coordinate.
701  /// @see `geo::vect::XcoordManager`
702  template <typename Vector>
703  static constexpr auto const YcoordManager
705 
706  /// An object that can be bound to a vector to manage its Y coordinate.
707  /// @see `geo::vect::XcoordManager`
708  template <typename Vector>
709  static constexpr auto YcoordManager<Vector const>
711 
712  /// An object that can be bound to a vector to manage its Z coordinate.
713  /// @see `geo::vect::XcoordManager`
714  template <typename Vector>
715  static constexpr auto ZcoordManager
717 
718  /// An object that can be bound to a vector to manage its Z coordinate.
719  /// @see `geo::vect::XcoordManager`
720  template <typename Vector>
721  static constexpr auto ZcoordManager<Vector const>
723 
724  /// An object that can be bound to a vector to manage its T coordinate.
725  /// @see `geo::vect::XcoordManager`
726  template <typename Vector>
727  static constexpr auto TcoordManager
729 
730  /// An object that can be bound to a vector to manage its T coordinate.
731  /// @see `geo::vect::XcoordManager`
732  template <typename Vector>
733  static constexpr auto TcoordManager<Vector const>
735 
736 
737  /**
738  * @brief Returns an object that can be bound to a vector to manage one of
739  * its coordinates.
740  * @tparam Vector type of vector to get a manager for (constantness matters)
741  * @param n index of the coordinate (`0`: X, `1`: Y, `2`: Z, `3`: T)
742  * @return a coordinate manager, undefined if index is invalid
743  *
744  * Index `n` is assumed to be smaller than the dimension of the vector.
745  * The manager returned for a mutable vector exposes a read/write interface.
746  * Example of usage:
747  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
748  * // mutable vectors get a full-featured "manager":
749  * geo::Point_t p { 1.0, 2.0, 3.0 };
750  * auto px
751  * = geo::vect::bindCoord(p, geo::vect::coordManager<geo::Point_t>(0U));
752  * px *= 5.0;
753  * std::cout << p << " has now x=" << px() << std::endl;
754  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
755  * will print something like:
756  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
757  * (5,2,3) has now x=5
758  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
759  *
760  * For a constant vector, the returned manager exposes a read-only
761  * interface.
762  * Example of usage:
763  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
764  * // constant vectors get a "reader" (read-only manager):
765  * geo::Vector_t v { 1.0, 2.0, 3.0 };
766  *
767  * auto vx = geo::vect::bindCoord
768  * (v, geo::vect::coordManager<geo::Vector_t const>(1U));
769  * std::cout << v << " has y=" << vy() << std::endl;
770  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
771  * will print something like:
772  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
773  * {1,2,3) has y=2
774  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
775  * Note that the use in these examples, `coord()` is preferred.
776  */
777  template <typename Vector>
778  constexpr auto coordManager(unsigned int n);
779 
780  /**
781  * @brief Returns an object that can be bound to a vector to manage one of
782  * its coordinates.
783  * @tparam Vector type of vector to get a manager for (constantness matters)
784  * @param n index of the coordinate (`0`: X, `1`: Y, `2`: Z, `3`: T)
785  * @param v a vector of type `Vector` (ignored)
786  * @return a coordinate manager, undefined if index is invalid
787  * @see `geo::vect::coordManager(unsigned int)`
788  *
789  * An alias of `geo::vect::coordManager(unsigned int)`.
790  */
791  template <typename Vector>
792  constexpr auto coordManager(unsigned int n, Vector& v);
793 
794 
795  //@{
796  /// Returns an array with all coordinate managers for a type of vector.
797  template <typename Vector>
798  constexpr auto coordManagers();
799  template <typename Vector>
800  constexpr auto coordManagers(Vector&&);
801  //@}
802 
803  //@{
804  /// Returns an array with all coordinate readers for a type of vector.
805  template <typename Vector>
806  constexpr auto coordReaders();
807  template <typename Vector>
808  constexpr auto coordReaders(Vector&&);
809  //@}
810 
811  /// Binds the specified constant vector to the coordinate reader.
812  template <typename Vector>
813  constexpr auto bindCoord
814  (Vector const& v, CoordReader_t<Vector> helper)
815  {
817  (v, helper);
818  }
819 
820  /// Binds the specified vector to the coordinate manager.
821  template <typename Vector>
824  { return { v, helper }; }
825 
826 
827 
828  /**
829  * @brief Returns an object to manage the coordinate X of the vector `v`.
830  * @tparam Vector the type of vector to be managed
831  * @param v the vector with the coordinate X to be managed
832  * @return an object to manage the coordinate X of `v`
833  *
834  * The type `Vector` needs to have a `double X() const` method and a
835  * `auto SetX(auto)` method, where the argument is the type of the managed
836  * coordinate and the return value is unspecified.
837  */
838  template <typename Vector>
839  auto Xcoord(Vector& v)
840  { return bindCoord(v, XcoordManager<Vector>); }
841 
842  /**
843  * @brief Returns an object to manage the coordinate Y of the vector `v`.
844  * @tparam Vector the type of vector to be managed
845  * @param v the vector with the coordinate Y to be managed
846  * @return an object to manage the coordinate Y of `v`
847  *
848  * The type `Vector` needs to have a `double Y() const` method and a
849  * `auto SetY(auto)` method, where the argument is the type of the managed
850  * coordinate and the return value is unspecified.
851  */
852  template <typename Vector>
853  auto Ycoord(Vector& v)
854  { return bindCoord<Vector>(v, YcoordManager<Vector>); }
855 
856  /**
857  * @brief Returns an object to manage the coordinate Z of the vector `v`.
858  * @tparam Vector the type of vector to be managed
859  * @param v the vector with the coordinate Z to be managed
860  * @return an object to manage the coordinate Z of `v`
861  *
862  * The type `Vector` needs to have a `double Z() const` method and a
863  * `auto SetZ(auto)` method, where the argument is the type of the managed
864  * coordinate and the return value is unspecified.
865  */
866  template <typename Vector>
867  auto Zcoord(Vector& v)
868  { return bindCoord<Vector>(v, ZcoordManager<Vector>); }
869 
870  /**
871  * @brief Returns an object to manage the coordinate T of the vector `v`.
872  * @tparam Vector the type of vector to be managed
873  * @param v the vector with the coordinate T to be managed
874  * @return an object to manage the coordinate T of `v`
875  *
876  * The type `Vector` needs to have a `double T() const` method and a
877  * `auto SetT(auto)` method, where the argument is the type of the managed
878  * coordinate and the return value is unspecified.
879  */
880  template <typename Vector>
881  auto Tcoord(Vector& v)
882  { return bindCoord<Vector>(v, TcoordManager<Vector>); }
883 
884  /**
885  * @brief Returns an object to manage the coordinate `n` of a vector
886  * @tparam Vector the type of vector to be managed
887  * @param v the vector to be managed
888  * @param n the coordinate index: `0` for X, `1` for Y and `2` for Z
889  * @return an object to manage the coordinate `n` of a vector
890  * @see `Xcoord()`, `Ycoord()`, `Zcoord()`
891  *
892  * Result is undefined for any value of `n` other than `0`, `1` and `2`.
893  * See `Xcoord()`, `Ycoord()` and `Zcoord()` for `Vector` type requirements.
894  */
895  template <typename Vector>
896  auto coord(Vector& v, unsigned int n) noexcept;
897 
898 
899  /// Returns an array with all coordinate managers bound to the specified
900  /// vector.
901  template <typename Vector>
902  constexpr auto bindCoordManagers(Vector& v);
903 
904  /// Returns an array with all coordinate readers bound to the specified
905  /// vector.
906  template <typename Vector>
907  constexpr auto bindCoordReaders(Vector const& v);
908 
909 
910 
911  /**
912  * @brief Constant iterator to vector coordinates.
913  * @tparam Vector the type of vector being iterated
914  * @see `vector_cbegin()`, `vector_cend()`, `iterateCoords()`
915  * @todo Not fully unit-tested yet!
916  */
917  template <typename Vector>
919 
920  public:
921  using iterator_t = CoordConstIterator<Vector>; ///< Type of this iterator.
922 
923  private:
924  using Vector_t = Vector; ///< Type of vector being iterated.
925  /// Type of vector coordinate.
927 
928  Vector* v = nullptr;
930 
931  decltype(auto) access(unsigned int c) const
932  { return geo::vect::bindCoord(v, index); }
933 
934  iterator_t copy() const { return *this; }
935 
936  public:
937 
938  /// --- BEGIN Iterator traits ------------------------------------------------
939  /// @name Iterator traits
940  /// @{
941  using value_type = std::remove_cv_t<Coord_t>;
942  using difference_type = std::ptrdiff_t;
944  using pointer = Coord_t const*;
945  using iterator_category = std::random_access_iterator_tag;
946  /// @}
947  /// --- END Iterator traits --------------------------------------------------
948 
949  /// Default constructor: invalid iterator.
950  CoordConstIterator() = default;
951 
952  /// Constructor: points to `index` coordinate of vector `v`.
953  CoordConstIterator(Vector& v, unsigned int index = 0)
954  : v(&v), index(index)
955  {}
956 
957  // --- BEGIN Access ----------------------------------------------------------
958  /// @name Access
959  /// @{
960 
961  /// Access the current coordinate.
962  reference operator* () const { return geo::vect::coord(*v, index); }
963 
964  /// Access the current coordinate.
965  reference operator[] (difference_type n) const
966  { return geo::vect::coord(*v, index + n); }
967 
968  /// @}
969  // --- END Access ------------------------------------------------------------
970 
971 
972  // --- BEGIN Moving ----------------------------------------------------------
973  /// @name Moving
974  /// @{
975 
976  /// Points to the next coordinate (unchecked).
977  iterator_t& operator++() { ++index; return *this; }
978 
979  /// Points to the next coordinate (unchecked), returns the previous iterator.
980  iterator_t operator++(int) { iterator_t it(*this); ++index; return it; }
981 
982  /// Points to the previous coordinate (unchecked).
983  iterator_t& operator--() { --index; return *this; }
984 
985  /// Points to previous coordinate (unchecked), returns the previous iterator.
986  iterator_t operator--(int) { iterator_t it(*this); --index; return it; }
987 
988  /// Increments the iterator by `d` positions (unchecked).
989  iterator_t& operator+=(difference_type d) { index += d; return *this; }
990 
991  /// Returns an iterator incremented by `d` positions (unchecked).
992  iterator_t operator+(difference_type d) const { return (copy() += d); }
993 
994  /// Decrements the iterator by `d` positions (unchecked).
995  iterator_t& operator-=(difference_type d) { index -= d; return *this; }
996 
997  /// Returns an iterator decremented by `d` positions (unchecked).
998  iterator_t operator-(difference_type d) const { return (copy() -= d); }
999 
1000  /// Returns the distance from another iterator.
1002  { return index - other.index; }
1003 
1004  ///@}
1005  // --- END Moving ------------------------------------------------------------
1006 
1007 
1008  // --- BEGIN Comparison operators --------------------------------------------
1009  /// @name Comparison operators
1010  ///
1011  /// All comparisons between iterators on different vectors fail.
1012  /// @{
1013 
1014  bool operator== (iterator_t const& other) const
1015  { return (v == other.v) && (index == other.index); }
1016 
1017  bool operator!= (iterator_t const& other) const
1018  { return (v != other.v) || (index != other.index); }
1019 
1020  bool operator<= (iterator_t const& other) const
1021  { return (v == other.v) && (index <= other.index); }
1022 
1023  bool operator>= (iterator_t const& other) const
1024  { return (v == other.v) && (index >= other.index); }
1025 
1026  bool operator< (iterator_t const& other) const
1027  { return (v == other.v) && (index < other.index); }
1028 
1029  bool operator> (iterator_t const& other) const
1030  { return (v == other.v) && (index > other.index); }
1031 
1032  /// @}
1033  // --- END Comparison operators ----------------------------------------------
1034 
1035  }; // class CoordConstIterator
1036 
1037  template <typename Vector>
1041  )
1042  { return v + n; }
1043 
1044  /// Returns a const-iterator pointing to the first coordinate of `v`.
1045  template <typename Vector>
1046  auto vector_cbegin(Vector const& v)
1047  { return CoordConstIterator(v, 0); }
1048 
1049  /// Returns a const-iterator pointing after the last coordinate of `v`.
1050  template <typename Vector>
1051  auto vector_cend(Vector const& v)
1052  { return CoordConstIterator(v, geo::vect::dimension(v)); }
1053 
1054  /**
1055  * @brief Returns an object for ranged-for iteration on coordinates.
1056  * @tparam Vector type of vector to iterate through
1057  * @param v vector whose coordinates will be iterated
1058  * @return an object suitable for range-for loop
1059  *
1060  * Example:
1061  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1062  * geo::Vector_t v{ 3.0, 4.0, 5.0 };
1063  * for (auto c: geo::vect::iterateCoords(v)) std::cout << c << ' ';
1064  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1065  * will print `3 4 5 `.
1066  */
1067  template <typename Vector>
1068  auto iterateCoords(Vector const& v)
1069  { return util::span(vector_cbegin(v), vector_cend(v)); }
1070 
1071 
1072  /**
1073  * @brief Returns a vector of type `Dest` with the same content as a `Src`.
1074  * @tparam Dest target vector type
1075  * @tparam Source type of the vector to be converted from
1076  * @param v the vector to be converted from
1077  * @return a vector with the same content as `v`, but of type `Dest`
1078  *
1079  * For this to work, both `Src` and `Dest` types must satisfy the
1080  * requirements of `Xcoord()`, `Ycoord()`, `Zcoord()` etc.
1081  */
1082  template <typename Dest, typename Source>
1083  Dest convertTo(Source const& v);
1084 
1085 
1086  /**
1087  * @brief Returns a vector of type `Dest` with the same content as a `Src`.
1088  * @tparam Dest target vector type
1089  * @tparam Source type of the vector to be converted from
1090  * @param coll the collection of vectors to be converted from
1091  * @return a collection of vectors with the same content as `coll`, but of
1092  * type `Dest`
1093  * @see `convertTo()`
1094  *
1095  * This version applies `convertTo()` to all the elements of the specified
1096  * collection, returning a collection of the same template type
1097  * (`std::vector`).
1098  *
1099  * For the requirements, see `convertTo()`.
1100  */
1101  template <typename Dest, typename Source>
1102  std::vector<Dest> convertCollTo(std::vector<Source> const& coll);
1103 
1104 
1105  /**
1106  * @brief Returns a new vector applying a predicate to each component.
1107  * @tparam Vector type of the vector in input (and output)
1108  * @tparam Pred type of unary predicate to be applied
1109  * @param v the vector to be transformed
1110  * @param pred the predicate to be applied
1111  * @return a vector equivelent to `{ pred(x), pred(y), ... }`
1112  *
1113  * The predicate is a "functor" type, taking as the single argument the
1114  * coordinate to be transformed, and returning the transformed value of it.
1115  */
1116  template <typename Vector, typename Pred>
1117  Vector transformCoords(Vector const& v, Pred&& pred);
1118 
1119  /// @}
1120  // --- END Vector coordinate access abstraction ----------------------------
1121 
1122 
1123  // --- BEGIN Functions for common vector operations ------------------------
1124  /// @{
1125  /** ************************************************************************
1126  * @name Functions for common vector operations.
1127  *
1128  * This group of template functions are meant to be used with vectors in a
1129  * generic way.
1130  * The default implementation is for `TVector3`. Specializations can be
1131  * easily written for other vector types.
1132  *
1133  * In addition, two "standard" representations for vectors and points are
1134  * provided.
1135  *
1136  * @note The representations for vector and point objects are currently the
1137  * same; this prevents relying on overload resolution to decide which
1138  * function to use. For example, defining two functions with signature:
1139  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1140  * Vector_t Project(Vector_t const& v);
1141  * Point_t Project(Point_t const& v);
1142  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1143  * will not compile since these two are exactly the same.
1144  * A solution might be to derive two different classes from the common
1145  * one:
1146  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1147  * struct Vector_t: public VectorBase_t { using VectorBase_t::VectorBase_t; };
1148  * struct Point_t: public VectorBase_t { using VectorBase_t::VectorBase_t; };
1149  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1150  * This will likely have consequences though (for example, the sum of
1151  * two `Vector_t` or `Point_t` will become a `VectorBase_t`).
1152  *
1153  */
1154 
1155  /// Returns a vector with all components rounded if close to 0.
1156  template <typename Vector, typename Scalar>
1157  Vector rounded0(Vector const& v, Scalar tol)
1158  {
1159  return transformCoords
1160  (v, [tol](auto c){ return extra::roundValue0(c, tol); });
1161  }
1162 
1163  /// Returns a vector with all components rounded if close to 0.
1164  template <typename Vector, typename Scalar>
1165  void round0(Vector& v, Scalar tol) { v = rounded0(v, tol); }
1166 
1167  /// Returns a vector with all components rounded if close to 0, -1 or +1.
1168  template <typename Vector, typename Scalar>
1169  Vector rounded01(Vector const& v, Scalar tol)
1170  {
1171  return transformCoords
1172  (v, [tol](auto c){ return extra::roundValue01(c, tol); });
1173  }
1174 
1175  /// Returns a vector with all components rounded if close to 0, -1 or +1.
1176  template <typename Vector, typename Scalar>
1177  void round01(Vector& v, Scalar tol) { v = rounded01(v, tol); }
1178 
1179 
1180  /// Returns whether all components of the vector are finite.
1181  template <typename Vector>
1182  bool isfinite(Vector const& v);
1183 
1184  /// Returns a vector parallel to v and with norm 1
1185  template <typename Vector>
1186  Vector normalize(Vector const& v) { return v.Unit(); }
1187 
1188  /// Return cross product of two vectors
1189  template <typename Vector>
1190  Vector cross(Vector const& a, Vector const& b) { return a.Cross(b); }
1191 
1192  /// Return cross product of two vectors
1193  template <typename Vector>
1194  constexpr auto dot(Vector const& a, Vector const& b) { return a.Dot(b); }
1195 
1196  /// Return norm of the specified vector
1197  template <typename Vector>
1198  auto mag2(Vector const& v) { return v.Mag2(); }
1199 
1200  /// Return norm of the specified vector
1201  template <typename Vector>
1202  auto norm(Vector const& v) { return v.Mag(); }
1203 
1204  /// Return "mixed" product of three vectors:
1205  /// @f$ \vec{a} \times \vec{b} \cdot \vec{c} @f$
1206  template <typename Vector>
1207  auto mixedProduct(Vector const& a, Vector const& b, Vector const& c)
1208  { return dot(cross(a, b), c); }
1209 
1210 
1211  /// @}
1212  // --- END Functions for common vector operations --------------------------
1213 
1214 
1215  /** ************************************************************************
1216  * @brief Helper class to compute the middle point in a point set.
1217  * @tparam N _(default: `3`)_ dimension of the points
1218  *
1219  * This class accumulates cartesian points and returns their middle point
1220  * when asked.
1221  *
1222  * In the following example, only the points from a list (`points`) which
1223  * have _y_ coordinate larger than 0 are averaged, all with the same weight:
1224  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1225  * std::array<geo::Point_t, 4> const points = {
1226  * geo::Point_t{ 0.0, 1.0, 2.0 },
1227  * geo::Point_t{ 0.0, -1.0, 2.0 },
1228  * geo::Point_t{ 0.0, 1.0, -2.0 },
1229  * geo::Point_t{ 0.0, -1.0, -2.0 }
1230  * };
1231  *
1232  * geo::vect::MiddlePointAccumulatorDim pointsAboveGround;
1233  * for (auto const& point: points)
1234  * if (point.Y() > 0.0) pointsAboveGround.add(point);
1235  *
1236  * if (pointsAboveGround.empty())
1237  * throw std::runtime_error("No point above ground!");
1238  *
1239  * auto middleAboveGround = pointsAboveGround.middlePoint();
1240  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1241  * Note the check to make sure that there are points that fulfil the
1242  * requirement.
1243  *
1244  */
1245  template <unsigned int N = 3U>
1247  static constexpr unsigned int Dim = N; ///< Dimension of the points.
1248  std::array<Length_t, Dim> fSums; ///< Sum of each of the point components.
1249  double fW = 0.0; ///< Total weight.
1250 
1251  public:
1252  /// Default constructor: starts with no accumulated point.
1253  MiddlePointAccumulatorDim() { fSums.fill(0.); }
1254 
1255  /**
1256  * @brief Constructor: starts with accumulating a sequence of points.
1257  * @tparam BeginIter type of iterator to a point type compatible with add()
1258  * @tparam EndIter type of end iterator
1259  * @param begin iterator to the first point to be added
1260  * @param end iterator after the last point to be added
1261  * @see add()
1262  */
1263  template <typename BeginIter, typename EndIter>
1266  { add(begin, end); }
1267 
1268 
1269  // --- BEGIN Result query ------------------------------------------------
1270  /// @{
1271  /// @name Result query
1272 
1273  /// Returns whether the total weight is zero (usually means no points).
1274  bool empty() const { return fW == 0.0; }
1275 
1276  /// Returns the total weight (number of points if all have weight 1).
1277  double weight() const { return fW; }
1278 
1279  /**
1280  * @brief Returns the middle point, NaN components if no point.
1281  * @tparam Point type of the output point
1282  *
1283  * The type of return point must be specified as template argument, e.g.
1284  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1285  * auto mp = accumulator.middlePointAs<TVector3>();
1286  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1287  * The `Point` type is required to have a constructor with the three
1288  * cartesian components as arguments.
1289  */
1290  template <typename Point>
1292  // { return { fSums[0] / fW, fSums[1] / fW, fSums[2] / fW }; }
1293  { return makeWeightedPoint<Point>(1.0 / fW); }
1294 
1295  /// Returns the middle point as a `geo::Point_t`,
1296  /// NaN components if no point.
1298  { return middlePointAs<geo::Point_t>(); }
1299 
1300 
1301  /// @}
1302  // --- END Result query --------------------------------------------------
1303 
1304  // --- BEGIN Addition of points ------------------------------------------
1305  /// @{
1306  /// @name Addition of points
1307 
1308  /**
1309  * @brief Accumulates a point.
1310  * @tparam Point point type, required to have X(), Y() and Z() accessors
1311  * @param p point to be included
1312  *
1313  * The point is added with weight 1.
1314  */
1315  template <typename Point>
1316  void add(Point const& p)
1317  {
1318  std::size_t ic = 0U;
1319  for (auto c: geo::vect::bindCoordManagers(p)) fSums[ic++] += c();
1320  fW += 1.0;
1321  }
1322 
1323  /**
1324  * @brief Accumulates a point.
1325  * @tparam Point point type, required to have X(), Y() and Z() accessors
1326  * @param p point to be included
1327  * @param weight the relative weight of this point
1328  */
1329  template <typename Point>
1330  void add(Point const& p, double weight)
1331  {
1332  std::size_t ic = 0U;
1333  for (auto c: geo::vect::bindCoordManagers(p))
1334  fSums[ic++] += weight * c();
1335  fW += weight;
1336  }
1337 
1338  /**
1339  * @brief Adds a sequence of points.
1340  * @tparam BeginIter type of iterator to a point type compatible with add()
1341  * @tparam EndIter type of end iterator
1342  * @param begin iterator to the first point to be added
1343  * @param end iterator after the last point to be added
1344  *
1345  * Each point is added with weight 1.0.
1346  */
1347  template <typename BeginIter, typename EndIter>
1348  void add(BeginIter begin, EndIter end)
1349  { std::for_each(begin, end, [this](auto const& p){ this->add(p); }); }
1350 
1351  /// Resets the status of the object to no accumulated points.
1352  void clear() { fSums.fill(0.); fW = 0.0; }
1353 
1354  /// @}
1355  // --- END Addition of points --------------------------------------------
1356 
1357  private:
1358  using IndexSequence_t = std::make_index_sequence<Dim>;
1359 
1360  template <typename Point, std::size_t... I>
1361  Point makePointImpl(std::index_sequence<I...>) const
1362  { return { fSums.operator[](I)... }; }
1363 
1364  template <typename Point, std::size_t... I>
1365  Point makeWeightedPointImpl(double w, std::index_sequence<I...>) const
1366  { return { (fSums.operator[](I) * w)... }; }
1367 
1368  /// Converts the internal sums into a `Point`.
1369  template <typename Point>
1371  { return geo::vect::makeFromCoords<Point>(fSums); }
1372 
1373  /// Converts the internal sums into a `Point` with components scaled by
1374  /// `w`.
1375  template <typename Point>
1376  Point makeWeightedPoint(double w) const
1377  { return makeWeightedPointImpl<Point>(w, IndexSequence_t{}); }
1378 
1379 
1380  }; // MiddlePointAccumulatorDim()
1381 
1382 
1383  /// Middle-point accumulator for vectors of dimension 3.
1385 
1386 
1387  // --- BEGIN Middle point functions ----------------------------------------
1388  /// @{
1389  /// @name Middle point functions
1390 
1391  /**
1392  * @brief Returns the middle of the specified points.
1393  * @tparam Point cartesian-represented point type with 3-component constructor
1394  * @tparam BeginIter type of iterator to a point type compatible with add()
1395  * @tparam EndIter type of end iterator
1396  * @param begin iterator to the first point to be averaged
1397  * @param end iterator after the last point to be averaged
1398  * @return an object of type `Point` with the value of the middle point
1399  *
1400  * Example of usage:
1401  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1402  * std::vector<geo::Point_t> points {
1403  * geo::Point_t(1., 2., 3.),
1404  * geo::Point_t(2., 4., 6.),
1405  * geo::Point_t(3., 6., 9.)
1406  * };
1407  *
1408  * auto mp = geo::vect::middlePointAs<geo::Vector_t>(points.begin(), points.end());
1409  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1410  * The variable `mp` of the example will be of type `geo::Vector_t` (converted
1411  * component by components from a `geo::Point_t`).
1412  *
1413  */
1414  template <typename Point, typename BeginIter, typename EndIter>
1415  Point middlePointAs(BeginIter begin, EndIter end)
1416  {
1417  constexpr auto Dim = geo::vect::dimension<Point>();
1419  .template middlePointAs<Point>();
1420  }
1421 
1422  /**
1423  * @brief Returns the middle of the specified points.
1424  * @tparam BeginIter type of iterator to a point type compatible with add()
1425  * @tparam EndIter type of end iterator
1426  * @param begin iterator to the first point to be averaged
1427  * @param end iterator after the last point to be averaged
1428  * @return an object of type `Point_t` with the value of the middle point
1429  *
1430  * Example of usage:
1431  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1432  * std::vector<geo::Point_t> points {
1433  * geo::Point_t(1., 2., 3.),
1434  * geo::Point_t(2., 4., 6.),
1435  * geo::Point_t(3., 6., 9.)
1436  * };
1437  *
1438  * auto mp = geo::vect::middlePoint(points.begin(), points.end());
1439  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1440  * The variable `mp` of the example will be of type `geo::Point_t`.
1441  *
1442  */
1443  template <typename BeginIter, typename EndIter>
1444  geo::Point_t middlePoint(BeginIter begin, EndIter end)
1445  { return middlePointAs<geo::Point_t>(begin, end); }
1446 
1447  /**
1448  * @brief Returns the middle of the specified points.
1449  * @tparam Point cartesian-represented point type with 3-component constructor
1450  * and X(), Y() and Z() accessors.
1451  * @param points the list of points to be included
1452  * @return the value of the middle point
1453  *
1454  * Example of usage:
1455  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1456  * auto mp = geo::vect::middlePoint
1457  * ({ geo::Point_t(1., 2., 3.), geo::Point_t(3., 6., 9.) });
1458  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1459  * The variable `mp` will contain the middle point between the two specified
1460  * in the initializer list.
1461  *
1462  */
1463  template <typename Point>
1464  Point middlePoint(std::initializer_list<Point> points)
1465  {
1466  constexpr auto Dim = geo::vect::dimension<Point>();
1467  return MiddlePointAccumulatorDim<Dim>(points.begin(), points.end())
1468  .template middlePointAs<Point>();
1469  }
1470 
1471  /// @}
1472  // --- END Middle point functions ------------------------------------------
1473 
1474 
1475  // --- BEGIN Support for LArSoft geometry vectors --------------------------
1476  /// @{
1477  /// @name Support for LArSoft geometry vectors
1478 
1479  // import global definitions
1482 
1483  /// Convert the specified point into a `geo::Point_t`.
1484  template <typename Point>
1486  { return geo::vect::convertTo<::geo::Point_t>(p); }
1487 
1488  /// Convert the specified vector into a `geo::Vector_t`.
1489  template <typename Vector>
1491  { return geo::vect::convertTo<::geo::Vector_t>(v); }
1492 
1493 
1494  /// Convert the specified collection of points into a collection of
1495  /// `geo::Point_t`.
1496  template <typename Point>
1497  std::vector<geo::Point_t> convertCollToPoint
1498  (std::vector<Point> const& coll)
1499  { return convertCollTo<geo::Point_t>(coll); }
1500 
1501  /// Convert the specified collection of vectors into a collection of
1502  /// `geo::Vector_t`.
1503  template <typename Vector>
1504  std::vector<geo::Vector_t> convertCollToVector
1505  (std::vector<Vector> const& coll)
1506  { return convertCollTo<geo::Vector_t>(coll); }
1507 
1508 
1509  /// Creates a `geo::Point_t` from its coordinates (see `makeFromCoords()`).
1510  template <typename Coords>
1512  { return makeFromCoords<::geo::Point_t>(std::forward<Coords>(coords)); }
1513 
1514  /// Creates a `geo::Vector_t` from its coordinates (see `makeFromCoords()`).
1515  template <typename Coords>
1517  { return makeFromCoords<::geo::Vector_t>(std::forward<Coords>(coords)); }
1518 
1519  /// @}
1520  // --- END Support for LArSoft geometry vectors ----------------------------
1521 
1522  /// @}
1523  // END Geometry group ------------------------------------------------------
1524 
1525 
1526  } // namespace vect
1527 
1528 } // namespace geo
1529 
1530 
1531 //------------------------------------------------------------------------------
1532 //--- STL specialization for ROOT GenVector vectors
1533 //------------------------------------------------------------------------------
1534 namespace ROOT::Math {
1535 
1536  /// @name Overloads of STL C++ functions for ROOT GenVector vectors
1537  /// @{
1538 
1539  // --- BEGIN 2D vectors ------------------------------------------------------
1540  template<class CoordSystem, class Tag>
1541  decltype(auto) begin(ROOT::Math::PositionVector2D<CoordSystem, Tag> const& v)
1542  { return geo::vect::vector_cbegin(v); }
1543 
1544  template<class CoordSystem, class Tag>
1545  decltype(auto) cbegin(ROOT::Math::PositionVector2D<CoordSystem, Tag> const& v)
1546  { return geo::vect::vector_cbegin(v); }
1547 
1548  template<class CoordSystem, class Tag>
1549  decltype(auto) end(ROOT::Math::PositionVector2D<CoordSystem, Tag> const& v)
1550  { return geo::vect::vector_cend(v); }
1551 
1552  template<class CoordSystem, class Tag>
1553  decltype(auto) cend(ROOT::Math::PositionVector2D<CoordSystem, Tag> const& v)
1554  { return geo::vect::vector_cend(v); }
1555 
1556  template<class CoordSystem, class Tag>
1557  decltype(auto)
1558  begin(ROOT::Math::DisplacementVector2D<CoordSystem, Tag> const& v)
1559  { return geo::vect::vector_cbegin(v); }
1560 
1561  template<class CoordSystem, class Tag>
1562  decltype(auto) cbegin(ROOT::Math::DisplacementVector2D<CoordSystem, Tag> const& v)
1563  { return geo::vect::vector_cbegin(v); }
1564 
1565  template<class CoordSystem, class Tag>
1566  decltype(auto) end(ROOT::Math::DisplacementVector2D<CoordSystem, Tag> const& v)
1567  { return geo::vect::vector_cend(v); }
1568 
1569  template<class CoordSystem, class Tag>
1570  decltype(auto) cend(ROOT::Math::DisplacementVector2D<CoordSystem, Tag> const& v)
1571  { return geo::vect::vector_cend(v); }
1572 
1573  // --- END 2D vectors --------------------------------------------------------
1574 
1575 
1576  // --- BEGIN 3D vectors ------------------------------------------------------
1577  template<class CoordSystem, class Tag>
1578  decltype(auto) begin(ROOT::Math::PositionVector3D<CoordSystem, Tag> const& v)
1579  { return geo::vect::vector_cbegin(v); }
1580 
1581  template<class CoordSystem, class Tag>
1582  decltype(auto) cbegin(ROOT::Math::PositionVector3D<CoordSystem, Tag> const& v)
1583  { return geo::vect::vector_cbegin(v); }
1584 
1585  template<class CoordSystem, class Tag>
1586  decltype(auto) end(ROOT::Math::PositionVector3D<CoordSystem, Tag> const& v)
1587  { return geo::vect::vector_cend(v); }
1588 
1589  template<class CoordSystem, class Tag>
1590  decltype(auto) cend(ROOT::Math::PositionVector3D<CoordSystem, Tag> const& v)
1591  { return geo::vect::vector_cend(v); }
1592 
1593  template<class CoordSystem, class Tag>
1594  decltype(auto)
1595  begin(ROOT::Math::DisplacementVector3D<CoordSystem, Tag> const& v)
1596  { return geo::vect::vector_cbegin(v); }
1597 
1598  template<class CoordSystem, class Tag>
1599  decltype(auto) cbegin(ROOT::Math::DisplacementVector3D<CoordSystem, Tag> const& v)
1600  { return geo::vect::vector_cbegin(v); }
1601 
1602  template<class CoordSystem, class Tag>
1603  decltype(auto) end(ROOT::Math::DisplacementVector3D<CoordSystem, Tag> const& v)
1604  { return geo::vect::vector_cend(v); }
1605 
1606  template<class CoordSystem, class Tag>
1607  decltype(auto) cend(ROOT::Math::DisplacementVector3D<CoordSystem, Tag> const& v)
1608  { return geo::vect::vector_cend(v); }
1609 
1610  // --- END 3D vectors --------------------------------------------------------
1611 
1612 
1613  // --- BEGIN 4D vectors ------------------------------------------------------
1614  template<class CoordSystem>
1615  decltype(auto) begin(ROOT::Math::LorentzVector<CoordSystem> const& v)
1616  { return geo::vect::vector_cbegin(v); }
1617 
1618  template<class CoordSystem>
1619  decltype(auto) cbegin(ROOT::Math::LorentzVector<CoordSystem> const& v)
1620  { return geo::vect::vector_cbegin(v); }
1621 
1622  template<class CoordSystem>
1623  decltype(auto) end(ROOT::Math::LorentzVector<CoordSystem> const& v)
1624  { return geo::vect::vector_cend(v); }
1625 
1626  template<class CoordSystem>
1627  decltype(auto) cend(ROOT::Math::LorentzVector<CoordSystem> const& v)
1628  { return geo::vect::vector_cend(v); }
1629 
1630  // --- END 4D vectors --------------------------------------------------------
1631 
1632 
1633  /// @}
1634 
1635 } // namespace ROOT::Math
1636 
1637 //------------------------------------------------------------------------------
1638 
1639 //------------------------------------------------------------------------------
1640 //--- template specializations for standard geometry vectors
1641 //---
1642 namespace geo::vect {
1643 
1644  //----------------------------------------------------------------------------
1645  template <>
1646  inline auto norm(geo::Vector_t const& v) { return v.R(); }
1647 
1648  //----------------------------------------------------------------------------
1649 
1650 } // namespace geo::vect
1651 
1652 
1653 //------------------------------------------------------------------------------
1654 //--- template implementation
1655 
1656 namespace geo::vect::details {
1657 
1658  //----------------------------------------------------------------------------
1659  template <typename> struct AlwaysFalse: std::false_type {};
1660 
1661 
1662  // constexpr variant of forward (from StackExchange)
1663  template <typename T>
1664  constexpr T&& constexpr_forward(std::remove_reference_t<T>& t)
1665  { return static_cast<T&&>(t); }
1666 
1667  template<typename T>
1668  constexpr T&& constexpr_forward(std::remove_reference_t<T>&& t)
1669  {
1670  static_assert(!std::is_lvalue_reference<T>(),
1671  "template argument substituting T is an lvalue reference type");
1672  return static_cast<T&&>(t);
1673  }
1674 
1675  //----------------------------------------------------------------------------
1676  template <typename Vector, typename /* = void */>
1677  struct DimensionImpl
1678  : public std::integral_constant<
1679  unsigned int,
1680  HasT<Vector>()? 4U
1681  : HasZ<Vector>()? 3U
1682  : HasY<Vector>()? 2U
1683  : HasX<Vector>()? 1U
1684  : 0U
1685  >
1686  {};
1687 
1688  template <typename Array>
1689  struct DimensionImpl<Array, std::enable_if_t<(std::extent_v<Array> > 0)>>
1690  : public std::integral_constant<unsigned int, std::extent_v<Array>>
1691  {};
1692 
1693  template <typename T, std::size_t Dim>
1694  struct DimensionImpl<std::array<T, Dim>, void>
1695  : public std::integral_constant<unsigned int, Dim>
1696  {};
1697 
1698 
1699  //----------------------------------------------------------------------------
1700  /// Type of sequence of indices up to `Vector` size.
1701  template <typename Vector>
1702  using VectorIndices_t = std::make_index_sequence<dimension<Vector>()>;
1703 
1704  template <typename Vector>
1705  constexpr auto makeVectorIndices() { return VectorIndices_t<Vector>{}; }
1706 
1707  template <typename Vector>
1708  constexpr auto makeVectorIndices(Vector&&)
1709  { return makeVectorIndices<Vector>(); }
1710 
1711 
1712  template <typename T, T... Indices>
1713  constexpr auto makeIndexSeqImpl(std::integer_sequence<T, Indices...>)
1714  // BUG the double brace syntax is required to work around clang bug 21629
1715  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1716  { return std::array<T, sizeof...(Indices)>{{ Indices... }}; }
1717 
1718  // fill a sequence object with the first `N` values of type `T`.
1719  template <typename T, T N>
1720  constexpr auto makeIndexSeq()
1721  { return makeIndexSeqImpl<T>(std::make_integer_sequence<T, N>{}); }
1722 
1723 
1724  //----------------------------------------------------------------------------
1725  template <std::size_t I, typename Data>
1726  constexpr auto accessElement(Data&& data) { return data[I]; }
1727 
1728  template <typename Vector, typename Coords, std::size_t... Indices>
1729  constexpr Vector makeFromCoordsImpl
1730  (Coords&& coords, std::index_sequence<Indices...>)
1731  {
1732  return
1733  { accessElement<Indices>(constexpr_forward<Coords>(coords))... };
1734  }
1735 
1736 
1737  //----------------------------------------------------------------------------
1738  template <typename Vector>
1739  constexpr CoordManager_t<Vector> NoCoordManager{ nullptr, nullptr };
1740 
1741  template <typename Vector, unsigned int Dim = dimension<Vector>()>
1743 
1744  template <typename Vector>
1745  struct CoordManagerImpl<Vector, 1U> {
1746  static auto get(unsigned int n) noexcept
1747  { return (n == 0)? XcoordManager<Vector>: NoCoordManager<Vector>; }
1748  }; // CoordManagerImpl<1U>
1749 
1750  template <typename Vector>
1751  struct CoordManagerImpl<Vector, 2U> {
1752  static auto get(unsigned int n) noexcept
1753  {
1754  return (n == 1)
1755  ? YcoordManager<Vector>: CoordManagerImpl<Vector, 1U>::get(n);
1756  }
1757  }; // CoordManagerImpl<2U>
1758 
1759  template <typename Vector>
1760  struct CoordManagerImpl<Vector, 3U> {
1761  static auto get(unsigned int n) noexcept
1762  {
1763  return (n == 2)
1764  ? ZcoordManager<Vector>: CoordManagerImpl<Vector, 2U>::get(n);
1765  }
1766  }; // CoordManagerImpl<3U>
1767 
1768  template <typename Vector>
1769  struct CoordManagerImpl<Vector, 4U> {
1770  static auto get(unsigned int n) noexcept
1771  {
1772  return (n == 3)
1773  ? TcoordManager<Vector>: CoordManagerImpl<Vector, 3U>::get(n);
1774  }
1775 
1776  }; // CoordManagerImpl<4U>
1777 
1778 
1779  //----------------------------------------------------------------------------
1780  template <typename Vector, unsigned int N>
1782  static constexpr unsigned int Dim = N;
1783 
1784  using Manager_t = decltype(XcoordManager<Vector>);
1785  using Return_t = std::array<Manager_t, Dim>;
1786 
1787  static_assert(dimension<Vector>() == Dim, "Inconsistent vector size.");
1788  }; // CoordManagersImplBase
1789 
1790  template <typename Vector, unsigned int N>
1792 
1793  template <typename Vector>
1795  : private CoordManagersImplBase<Vector, 2U>
1796  {
1798  using typename Base_t::Return_t;
1799  static constexpr Return_t get()
1800  {
1801  // BUG the double brace syntax is required to work around clang bug 21629
1802  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1803  return {{
1804  XcoordManager<Vector>
1805  , YcoordManager<Vector>
1806  }};
1807  }
1808  }; // CoordManagersImpl<2U>
1809 
1810  template <typename Vector>
1812  : private CoordManagersImplBase<Vector, 3U>
1813  {
1815  using typename Base_t::Return_t;
1816  static constexpr Return_t get()
1817  {
1818  // BUG the double brace syntax is required to work around clang bug 21629
1819  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1820  return {{
1821  XcoordManager<Vector>
1822  , YcoordManager<Vector>
1823  , ZcoordManager<Vector>
1824  }};
1825  }
1826  }; // CoordManagersImpl<3U>
1827 
1828  template <typename Vector>
1830  : private CoordManagersImplBase<Vector, 4U>
1831  {
1833  using typename Base_t::Return_t;
1834  static constexpr Return_t get()
1835  {
1836  // BUG the double brace syntax is required to work around clang bug 21629
1837  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1838  return {{
1839  XcoordManager<Vector>
1840  , YcoordManager<Vector>
1841  , ZcoordManager<Vector>
1842  , TcoordManager<Vector>
1843  }};
1844  }
1845  }; // CoordManagersImpl<4U>
1846 
1847 
1848  //----------------------------------------------------------------------------
1849  template <typename Vector, unsigned int N>
1851  static constexpr unsigned int Dim = N;
1852 
1853  using Manager_t = decltype(Xcoord(std::declval<Vector>()));
1854  using Return_t = std::array<Manager_t, Dim>;
1855 
1856  static_assert(dimension<Vector>() == Dim, "Inconsistent vector size.");
1857  }; // CoordManagersImplBase
1858 
1859  template <typename Vector, unsigned int N>
1861 
1862  template <typename Vector>
1864  : private BindCoordManagersImplBase<Vector, 2U>
1865  {
1867  using typename Base_t::Return_t;
1868  static Return_t bind(Vector& v)
1869  {
1870  // BUG the double brace syntax is required to work around clang bug 21629
1871  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1872  return {{
1873  Xcoord(v)
1874  , Ycoord(v)
1875  }};
1876  }
1877  }; // BindCoordManagersImpl<2U>
1878 
1879  template <typename Vector>
1881  : private BindCoordManagersImplBase<Vector, 3U>
1882  {
1884  using typename Base_t::Return_t;
1885  static Return_t bind(Vector& v)
1886  {
1887  // BUG the double brace syntax is required to work around clang bug 21629
1888  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1889  return {{
1890  Xcoord(v)
1891  , Ycoord(v)
1892  , Zcoord(v)
1893  }};
1894  }
1895  }; // BindCoordManagersImpl<3U>
1896 
1897  template <typename Vector>
1899  : private BindCoordManagersImplBase<Vector, 4U>
1900  {
1902  using typename Base_t::Return_t;
1903  static Return_t bind(Vector& v)
1904  {
1905  // BUG the double brace syntax is required to work around clang bug 21629
1906  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1907  return {{
1908  Xcoord(v)
1909  , Ycoord(v)
1910  , Zcoord(v)
1911  , Tcoord(v)
1912  }};
1913  }
1914  }; // BindCoordManagersImpl<4U>
1915 
1916 
1917  //----------------------------------------------------------------------------
1918  template<typename Dest, typename Source>
1920  static_assert(dimension<Source>() == dimension<Dest>(),
1921  "Source and destination vectors must have the same dimension.");
1922  }; // struct ConvertToImplBase
1923 
1924 
1925  template <typename Dest, typename Source, unsigned int Dim>
1926  struct ConvertArrayTo: private ConvertToImplBase<Dest, Source>
1927  {
1928  static_assert
1929  (std::is_arithmetic_v<std::decay_t<decltype(std::declval<Source>()[0])>>);
1930  static Dest convert(Source const& v)
1931  { return geo::vect::makeFromCoords<Dest>(v); }
1932  }; // struct ConvertArrayTo
1933 
1934 
1935  // will handle cases with specific dimensionality
1936  template <typename Dest, typename Source, unsigned int Dim>
1938 
1939 
1940  template <typename Dest, typename Source>
1942  : public ConvertToImplDim<Dest, Source, dimension<Source>()>
1943  {};
1944 
1945 
1946  template <typename Dest, typename T, std::size_t Dim>
1947  struct ConvertToImpl<Dest, std::array<T, Dim>>
1948  : public ConvertArrayTo<Dest, std::array<T, Dim>, Dim>
1949  {};
1950 
1951  template <typename Dest, typename T, std::size_t Dim>
1952  struct ConvertToImpl<Dest, T[Dim]>
1953  : public ConvertArrayTo<Dest, T[Dim], Dim>
1954  {};
1955 
1956  // special special implementation for T*, since we can't guess its dimension
1957  template <typename Dest, typename T>
1958  struct ConvertToImpl<Dest, T*> {
1959  static_assert(std::is_arithmetic_v<T>);
1960  static Dest convert(T* v) { return geo::vect::makeFromCoords<Dest>(v); }
1961  }; // struct ConvertToImpl<T*>
1962 
1963 
1964  // handled cases with specific dimensionality
1965  template <typename Dest, typename Source, unsigned int Dim>
1966  struct ConvertToImplDim {
1967  // trivial to do: open a feature request!
1968  static_assert(
1970  "This vector dimensionality is not implemented yet."
1971  );
1972  }; // struct ConvertToImplDim
1973 
1974  template <typename Dest, typename Source>
1975  struct ConvertToImplDim<Dest, Source, 2U>
1976  : private ConvertToImplBase<Dest, Source>
1977  {
1978  static Dest convert(Source const& v)
1979  { return { Xcoord(v)(), Ycoord(v)() }; }
1980  }; // struct ConvertToImplDim<2U>
1981 
1982  template <typename Dest, typename Source>
1983  struct ConvertToImplDim<Dest, Source, 3U>
1984  : private ConvertToImplBase<Dest, Source>
1985  {
1986  static Dest convert(Source const& v)
1987  { return { Xcoord(v)(), Ycoord(v)(), Zcoord(v)() }; }
1988  }; // struct ConvertToImplDim<3U>
1989 
1990  template <typename Dest, typename Source>
1991  struct ConvertToImplDim<Dest, Source, 4U>
1992  : private ConvertToImplBase<Dest, Source>
1993  {
1994  static Dest convert(Source const& v)
1995  { return { Xcoord(v)(), Ycoord(v)(), Zcoord(v)(), Tcoord(v)() }; }
1996  }; // struct ConvertToImplDim<4U>
1997 
1998 
1999  template <typename Dest, typename Source>
2000  struct ConvertToDispatcher: public ConvertToImpl<Dest, Source> {};
2001 
2002  // special pass-through case
2003  template <typename Vector>
2005  static constexpr decltype(auto) convert(Vector const& v) { return v; }
2006  }; // struct ConvertToDispatcher<pass through>
2007 
2008 
2009  //----------------------------------------------------------------------------
2010  template <typename Point, std::size_t... I>
2011  bool isfiniteImpl(Point const& point, std::index_sequence<I...>)
2012  { return extended_and(std::isfinite(coord(point, I).get())...); }
2013 
2014  //----------------------------------------------------------------------------
2015 
2016 } // namespace geo::vect::details
2017 
2018 
2019 //------------------------------------------------------------------------------
2020 template <typename Vector>
2021 constexpr std::array<std::size_t, geo::vect::dimension<Vector>()>
2023 {
2024  return details::makeIndexSeq<std::size_t, dimension<Vector>()>();
2025 }
2026 
2027 template <typename Vector>
2028 constexpr auto geo::vect::indices(Vector const&) -> decltype(indices<Vector>())
2029  { return indices<Vector>(); }
2030 
2031 
2032 //------------------------------------------------------------------------
2033 template <typename Vector, typename Coords>
2034 constexpr Vector geo::vect::makeFromCoords(Coords&& coords) {
2035  using namespace geo::vect::details;
2036  return makeFromCoordsImpl<Vector>
2037  (constexpr_forward<Coords>(coords), makeVectorIndices<Vector>());
2038 } // geo::vect::makeFromCoords()
2039 
2040 
2041 //------------------------------------------------------------------------------
2042 template <typename Vector>
2043 constexpr auto geo::vect::coordManager(unsigned int n)
2045 
2046 
2047 //------------------------------------------------------------------------------
2048 template <typename Vector>
2049 auto geo::vect::coord(Vector& v, unsigned int n) noexcept {
2050  return vect::bindCoord<Vector>(v, coordManager<Vector>(n));
2051 }
2052 
2053 
2054 //------------------------------------------------------------------------
2055 template <typename Vector, typename Coords>
2056 unsigned int geo::vect::fillCoords(Coords& dest, Vector const& src) {
2057  // this is simpler than makeFromCoords() because doesn't attempt constexpr
2058  for (std::size_t i = 0; i < geo::vect::dimension(src); ++i)
2059  dest[i] = geo::vect::coord(src, i);
2060  return geo::vect::dimension(src);
2061 } // geo::vect::fillCoords()
2062 
2063 
2064 //------------------------------------------------------------------------------
2065 template <typename Vector>
2066 constexpr auto geo::vect::coordManagers() {
2067  using PlainVector = std::remove_reference_t<Vector>;
2068  return
2070 } // geo::vect::coordManagers()
2071 
2072 template <typename Vector>
2074  { return coordManagers<Vector>(); }
2075 
2076 
2077 template <typename Vector>
2078 constexpr auto geo::vect::coordReaders() {
2079  using ConstVector = std::add_const_t<std::remove_reference_t<Vector>>;
2080  return
2082 } // geo::vect::coordReaders()
2083 
2084 template <typename Vector>
2086  { return coordReaders<Vector>(); }
2087 
2088 
2089 //------------------------------------------------------------------------------
2090 template <typename Vector>
2093 } // geo::vect::bindCoordManagers()
2094 
2095 
2096 template <typename Vector>
2097 constexpr auto geo::vect::bindCoordReaders(Vector const& v) {
2098  using ConstVector = std::add_const_t<std::remove_reference_t<Vector>>;
2100  ::bind(v);
2101 } // geo::vect::bindCoordReaders()
2102 
2103 
2104 //------------------------------------------------------------------------------
2105 template <typename Dest, typename Source>
2106 Dest geo::vect::convertTo(Source const& v)
2108 
2109 
2110 //----------------------------------------------------------------------------
2111 template <typename Dest, typename Source>
2112 std::vector<Dest> geo::vect::convertCollTo(std::vector<Source> const& coll) {
2113 
2114  std::vector<Dest> dest;
2115  dest.reserve(coll.size());
2116  std::transform(coll.begin(), coll.end(), std::back_inserter(dest),
2117  geo::vect::convertTo<Dest, Source>);
2118  return dest;
2119 
2120 } // geo::vect::convertCollTo()
2121 
2122 
2123 //------------------------------------------------------------------------
2124 template <typename Vector, typename Pred>
2127  unsigned int i = 0;
2128  for (auto c: bindCoordReaders(v)) values[i++] = pred(c());
2129  return makeFromCoords<Vector>(values);
2130 } // geo::vect::transformCoords()
2131 
2132 
2133 //------------------------------------------------------------------------------
2134 template <typename Vector>
2136  { return details::isfiniteImpl(v, details::makeVectorIndices<Vector>()); }
2137 
2138 //------------------------------------------------------------------------------
2139 
2140 
2141 #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. ...
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.
constexpr T && constexpr_forward(std::remove_reference_t< T > &t)
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
span(IterB &&b, IterE &&e, Adaptor &&adaptor) -> span< decltype(adaptor(std::forward< IterB >(b))), decltype(adaptor(std::forward< IterE >(e))) >
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
constexpr auto dot(Vector const &a, Vector const &b)
Return cross product of two vectors.
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.
static constexpr bool TestX(...)
constexpr auto makeIndexSeq()
constexpr auto makeVectorIndices()
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
bool operator>(ScheduleID const left, ScheduleID const right) noexcept
Definition: ScheduleID.cc:53
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.
DoubleProduct & operator+=(DoubleProduct &left, DoubleProduct const &right)
Definition: ToyProducts.h:103
static constexpr auto YcoordManager< Vector const >
static constexpr auto const YcoordManager
typename BaseTypes_t::Vector_t Vector_t
std::vector< float > Vector
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.
auto const tol
Definition: SurfXYZTest.cc:16
constexpr auto bindCoordReaders(Vector const &v)
constexpr bool operator<(CryostatID const &a, CryostatID const &b)
Order cryostats with increasing ID.
Definition: geo_types.h:706
Helper class to compute the middle point in a point set.
Definition: tag.cpp:4
geo::vect::coordinate_t< Vector_t > Coord_t
Type of vector coordinate.
constexpr auto makeCoordReader(Getter getter)
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >> Point_t
typename Traits_t::Setter_t Setter_t
CoordConstIterator< Vector > operator+(typename CoordConstIterator< Vector >::difference_type n, CoordConstIterator< Vector > const &v)
constexpr auto makeIndexSeqImpl(std::integer_sequence< T, Indices... >)
typename MemberFuncReturnType< T >::type MemberFuncReturn_t
Coord add(Coord c1, Coord c2)
Definition: restypedef.cpp:23
struct vector vector
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.
auto iterateCoords(Vector const &v)
Returns an object for ranged-for iteration on coordinates.
constexpr bool operator==(CryostatID const &a, CryostatID const &b)
Comparison: the IDs point to the same cryostat (validity is ignored)
Definition: geo_types.h:698
::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
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
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
typename MemberFuncClassType< T >::type MemberFuncClass_t
static QCString args
Definition: declinfo.cpp:674
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.
ROOT::Math::LorentzVector< ROOT::Math::PxPyPzE4D< double > > LorentzVector
static constexpr auto ZcoordManager< Vector const >
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.
iterator_t operator+(difference_type d) const
Returns an iterator incremented by d positions (unchecked).
static constexpr bool TestX(decltype(std::declval< Class >().X())*)
typename VectorScalar< Vector >::type VectorScalar_t
typename Traits_t::Vector_t Vector_t
constexpr unsigned int dimension()
T abs(T value)
iterator_t operator--(int)
Points to previous coordinate (unchecked), returns the previous iterator.
bool operator<=(ScheduleID const left, ScheduleID const right) noexcept
Definition: ScheduleID.cc:47
std::random_access_iterator_tag iterator_category
constexpr auto coordReaders()
Returns an array with all coordinate readers for a type of vector.
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:228
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).
#define Array
Definition: scanner.cpp:11549
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).
Definitions of geometry vector data types.
std::vector< geo::Point_t > convertCollToPoint(std::vector< Point > const &coll)
constexpr bool operator!=(CryostatID const &a, CryostatID const &b)
Comparison: the IDs point to different cryostats (validity is ignored)
Definition: geo_types.h:702
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
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:44
std::void_t< T > n
const double a
MiddlePointAccumulatorDim(BeginIter begin, EndIter end)
Constructor: starts with accumulating a sequence of points.
def convert(inputfile, outputfile="wire-cell-garfield-fine-response.json.bz2", average=False, shaped=False)
Definition: garfield.py:262
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.
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.
iterator_t & operator++()
Points to the next coordinate (unchecked).
auto Ycoord(Vector &v)
Returns an object to manage the coordinate Y of the vector v.
Q_UINT16 values[128]
typename decltype(std::mem_fn(std::declval< T >()))::result_type type
static constexpr bool TestY(...)
static int max(int a, int b)
constexpr bool HasT()
bool isfiniteImpl(Point const &point, std::index_sequence< I... >)
Vector transformCoords(Vector const &v, Pred &&pred)
Returns a new vector applying a predicate to each component.
static auto compute(Op, T &&v) -> decltype(auto)
CoordHelper_t fCoord
Helper to manage a specific coordinate.
auto norm(Vector const &v)
Return norm of the specified vector.
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.
typename BaseTypes_t::Getter_t Getter_t
p
Definition: test.py:223
Point makeWeightedPointImpl(double w, std::index_sequence< I... >) const
BoundCoordGetter(Stored_t &v, CoordHelper_t coordManager)
Constructor: manage the specified coordinate of specified vector.
constexpr bool HasZ()
static auto compute(Op op, First &&a, Second &&b, Others &&...others) -> decltype(auto)
auto Tcoord(Vector &v)
Returns an object to manage the coordinate T of the vector v.
constexpr bool HasY()
CoordHelper_t const & manager() const
auto extended_accumulate(Op op, T &&...args)
typename BaseTypes_t::Getter_t Getter_t
auto extended_and(T...args) -> decltype(auto)
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.
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)
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.
T copy(T const &v)
Setter_t fSetter
Member function setting the coordinate value.
static bool * b
Definition: config.cpp:1043
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.
details::VectorScalar_t< Vector > coordinate_t
Type of coordinate of the specified vector type.
def access(path, mode)
weight
Definition: test.py:257
constexpr Vector makeFromCoords(Coords &&coords)
Creates a Vector object with coordinates from coords.
bool operator>=(ScheduleID const left, ScheduleID const right) noexcept
Definition: ScheduleID.cc:59
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.
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
Eigen::Vector3f Coords
Definition: DCEL.h:46
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.
iterator_t & operator+=(difference_type d)
Increments the iterator by d positions (unchecked).
decltype(details::makeCoordManager(&Vector::X,&Vector::SetX)) CoordManager_t
Type of a coordinate manager for a vector type.
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
QuadExpr operator*(double v, const QuadExpr &e)
Definition: QuadExpr.h:39
GENVECTOR_CONSTEXPR::geo::Point_t makePointFromCoords(Coords &&coords)
Creates a geo::Point_t from its coordinates (see makeFromCoords()).
Verifies that the geometry check information is available.
GENVECTOR_CONSTEXPR::geo::Vector_t makeVectorFromCoords(Coords &&coords)
Creates a geo::Vector_t from its coordinates (see makeFromCoords()).
recob::tracking::Vector_t Vector_t
geo::Point_t middlePoint(BeginIter begin, EndIter end)
Returns the middle of the specified points.
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.
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())*)