geo_vectors_utils.h
Go to the documentation of this file.
1 /**
2  * @file garsoft/Utilities/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 GArSoft 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 GARSOFT_UTILITIES_GEO_VECTORS_UTILS_H
18 #define GARSOFT_UTILITIES_GEO_VECTORS_UTILS_H
19 
20 #include "geo_vectors.h"
21 
22 // C/C++ standard library
23 #include <array>
24 #include <vector>
25 #include <iterator> // std::back_inserter()
26 #include <type_traits> // std::declval(), std::is_same<>, ...
27 #include <functional> // std::mem_fn()
28 #include <cassert>
29 
30 
31 namespace geo {
32 
33  /**
34  * @brief Utilities to manipulate geometry vectors.
35  * @ingroup Geometry
36  *
37  * The utilities include generic vector interface facilities allowing to
38  * use different vector types via templates.
39  */
40  namespace vect {
41 
42  //--------------------------------------------------------------------------
43  namespace details {
44  //------------------------------------------------------------------------
45  template <typename Op, typename... T>
47 
48  template
49  <typename Op, typename First, typename Second, typename... Others>
50  struct AccumulateImpl<Op, First, Second, Others...> {
51  static auto compute(Op op, First&& a, Second&& b, Others&&... others)
52  -> decltype(auto)
53  {
54  return op(
55  a,
57  (op, std::forward<Second>(b), std::forward<Others>(others)...)
58  );
59  }
60  }; // AccumulateImpl<>
61 
62  template <typename Op, typename T>
63  struct AccumulateImpl<Op, T> {
64  static auto compute(Op, T&& v) -> decltype(auto)
65  { return std::forward<T>(v); }
66  };
67 
68  template <typename Op, typename... T>
69  auto extended_accumulate(Op op, T&&... args)
70  { return AccumulateImpl<Op, T...>::compute(op, std::forward<T>(args)...); }
71 
72 
73  template <typename... T>
74  auto extended_and(T... args) -> decltype(auto)
75  {
76  auto and_op = [](auto&& a, auto&& b) { return a && b; };
77  return extended_accumulate(and_op, std::forward<T>(args)...);
78  }
79 
80  //------------------------------------------------------------------------
81  //
82  // These two pages of metaprogramming madness are aimed to have objects
83  // that can provide a uniform coordinate get/set for any type of vector,
84  // with the minimal run-time overhead.
85  // Complications arise from the fact that TVector3 setter returns void,
86  // while GenVector vectors return a reference to the vector itself
87  // (hence the need of the additional SetterResult template parameter,
88  // and of quite some code to autodetect its value).
89  // The makeXxxx() functions are aimed to enclose the additional
90  // autodetection overlay, which should become unnecessary with C++17.
91  //
92 
93  template <typename Vector>
94  struct VectorScalar { using type = typename Vector::Scalar; };
95 
96  template <typename Vector>
98 
99 
100  //------------------------------------------------------------------------
101  template <typename Vector>
102  struct HasGetter {
103  private:
104 
105  template<typename Class>
106  static constexpr bool TestX(decltype(std::declval<Class>().X())*) { return true; }
107  template<typename Class>
108  static constexpr bool TestX(...) { return false; }
109  template<typename Class>
110  static constexpr bool TestY(decltype(std::declval<Class>().Y())*) { return true; }
111  template<typename Class>
112  static constexpr bool TestY(...) { return false; }
113  template<typename Class>
114  static constexpr bool TestZ(decltype(std::declval<Class>().Z())*) { return true; }
115  template<typename Class>
116  static constexpr bool TestZ(...) { return false; }
117  template<typename Class>
118  static constexpr bool TestT(decltype(std::declval<Class>().T())*) { return true; }
119  template<typename Class>
120  static constexpr bool TestT(...) { return false; }
121 
122  public:
123  static constexpr bool X = TestX<Vector>(nullptr);
124  static constexpr bool Y = TestY<Vector>(nullptr);
125  static constexpr bool Z = TestZ<Vector>(nullptr);
126  static constexpr bool T = TestT<Vector>(nullptr);
127  }; // struct HasGetter<>
128 
129  template <typename Vector>
130  constexpr bool HasX() { return HasGetter<Vector>::X; }
131  template <typename Vector>
132  constexpr bool HasY() { return HasGetter<Vector>::Y; }
133  template <typename Vector>
134  constexpr bool HasZ() { return HasGetter<Vector>::Z; }
135  template <typename Vector>
136  constexpr bool HasT() { return HasGetter<Vector>::T; }
137 
138  template <typename Vector>
139  constexpr unsigned int dimension() {
140  return HasT<Vector>()? 4U
141  : HasZ<Vector>()? 3U
142  : HasY<Vector>()? 2U
143  : HasX<Vector>()? 1U
144  : 0U;
145  } // dimension()
146 
147 
148  /// A STL array suitable to contain all coordinate values of a `Vector`.
149  template <typename Vector>
150  using CoordinateArray_t
151  = std::array<VectorScalar_t<Vector>, dimension<Vector>()>;
152 
153 
154  template <typename T>
156  // with C++17 `result_type` is deprecated,
157  // and a different way will be needed
158  using type
159  = typename decltype(std::mem_fn(std::declval<T>()))::result_type;
160  }; // MemberFuncReturnType
161 
162  template <typename T>
164 
165  template <typename T>
167 
168  template <typename Class, typename Func>
169  struct MemberFuncClassType<Func Class::*> { using type = Class; };
170 
171  template <typename T>
173 
174 
175  template <typename Vector, typename SetterType = void>
177 
178  template <typename Vector>
179  struct BaseCoordTypes<Vector, void> {
180  using Vector_t = std::decay_t<Vector>;
182  using Getter_t = Scalar_t (Vector_t::*)() const;
183  }; // struct BaseCoordTypes<void>
184 
185  template <typename Vector, typename SetterType>
186  struct BaseCoordTypes {
187  private:
189 
190  public:
191  using Scalar_t = typename BaseTypes_t::Scalar_t;
192  using Vector_t = typename BaseTypes_t::Vector_t;
193  using Getter_t = typename BaseTypes_t::Getter_t;
194  using Setter_t = SetterType;
196  static_assert(
197  std::is_same<Setter_t, SetterReturn_t (Vector_t::*)(Scalar_t)>(),
198  "Invalid setter type"
199  );
200  }; // struct BaseCoordTypes<>
201 
202 
203  template <typename Vector>
205  private:
207  public:
208  using Vector_t = typename BaseTypes_t::Vector_t;
209  using Scalar_t = typename BaseTypes_t::Scalar_t;
210  using Getter_t = typename BaseTypes_t::Getter_t;
211  }; // struct CoordGetterTraits
212 
213 
214  /// Helper class for read of a single vector coordinate.
215  template <typename Vector>
216  class CoordGetter {
218 
219  public:
220  using Vector_t = typename Traits_t::Vector_t;
221  using Scalar_t = typename Traits_t::Scalar_t;
222  using Getter_t = typename Traits_t::Getter_t;
223 
224  /// Constructor: sets getter and setter functions.
225  constexpr CoordGetter(Getter_t getter): fGetter(getter) {}
226 
227  /// Returns the value of the bound coordinate.
228  Scalar_t operator() (Vector_t const& v) const { return get(v); }
229 
230  /// Returns the value of the bound coordinate.
231  Scalar_t get(Vector_t const& v) const { return (v.*fGetter)(); }
232 
233  private:
234  Getter_t fGetter; ///< Member function returning the coordinate value.
235 
236  }; // class CoordGetter<>
237 
238  template <typename Getter>
239  constexpr auto makeCoordReader(Getter getter)
240  {
241  using Vector_t = std::remove_reference_t<MemberFuncClass_t<Getter>>;
242  return CoordGetter<Vector_t>{ getter };
243  }
244 
245 
246  template <typename Vector, typename SetterType>
248  private:
250  public:
251  using Vector_t = typename BaseTypes_t::Vector_t;
252  using Scalar_t = typename BaseTypes_t::Scalar_t;
253  using Getter_t = typename BaseTypes_t::Getter_t;
254  using Setter_t = typename BaseTypes_t::Setter_t;
255  }; // struct VectorCoordManagerTraits<>
256 
257 
258  /// Helper class for read/write of a single vector coordinate.
259  template <typename Vector, typename SetterType>
260  class CoordManager: public CoordGetter<Vector> {
263 
264  public:
265  using Vector_t = typename Traits_t::Vector_t; // this is not constant
266  using Scalar_t = typename Traits_t::Scalar_t;
267  using Getter_t = typename Traits_t::Getter_t;
268  using Setter_t = typename Traits_t::Setter_t;
269 
270  /// Constructor: sets getter and setter functions.
271  constexpr CoordManager(Getter_t getter, Setter_t setter)
272  : Base_t(getter), fSetter(setter) {}
273 
274  /// Setter: assigns a value to the bound coordinate of specified vector.
275  void operator()(Vector_t& v, Scalar_t c) const { set(v, c); }
276 
277  /// Setter: assigns a value to the bound coordinate of specified vector.
278  void set(Vector_t& v, Scalar_t c) const { (v.*fSetter)(c); }
279 
280  /// Increments the coordinate by the specified amount.
281  void incr(Vector_t& v, Scalar_t c) const { set(v, Base_t::get(v) + c); }
282 
283  /// Decrements the coordinate by the specified amount.
284  void decr(Vector_t& v, Scalar_t c) const { set(v, Base_t::get(v) - c); }
285 
286  /// Multiplies the coordinate by the specified amount.
287  void mult(Vector_t& v, Scalar_t f) const { set(v, Base_t::get(v) * f); }
288 
289  /// Divides the coordinate by the specified amount.
290  void div(Vector_t& v, Scalar_t f) const { set(v, Base_t::get(v) / f); }
291 
292  private:
293  Setter_t fSetter; ///< Member function setting the coordinate value.
294  }; // class CoordManager<>
295 
296 
297  template <typename Getter, typename Setter>
298  constexpr auto makeCoordManager(Getter getter, Setter setter)
299  {
300  using Vector_t = std::remove_reference_t<MemberFuncClass_t<Getter>>;
301  return CoordManager<Vector_t, Setter>{getter, setter};
302  }
303 
304 
305 
306  template <typename CoordHelper, typename StoredVector>
308 
309  public:
310  using Stored_t = StoredVector;
311 
312  using CoordHelper_t = CoordHelper;
314  using Scalar_t = typename CoordHelper_t::Scalar_t;
315  using Getter_t = typename CoordHelper_t::Getter_t;
316 
317  /// Constructor: manage the specified coordinate of specified vector.
319  : fCoord(coordManager), fVector(v) {}
320 
321  /// Constructor: manage the specified vector with specified methods.
323  : fCoord(getter), fVector(v) {}
324 
325  /// Returns the value of the bound coordinate.
326  Scalar_t get() const { return manager().get(vector()); }
327 
328  /// Returns the value of the bound coordinate.
329  Scalar_t operator() () const { return get(); }
330 
331  /// Returns the value of the bound coordinate.
332  operator Scalar_t() const { return manager().get(vector()); }
333 
334  protected:
335  CoordHelper_t const& manager() const { return fCoord; }
336  Stored_t& vector() const { return fVector; }
337 
338  private:
339  CoordHelper_t fCoord; ///< Helper to manage a specific coordinate.
340  Stored_t& fVector; ///< The vector to manage the coordinate of.
341  }; // class VectorCoordGetter<>
342 
343 
344  template <typename CoordHelper, typename StoredVector>
346  : public BoundCoordGetter<CoordHelper, StoredVector>
347  {
349 
350  public:
351  using typename Base_t::Stored_t;
352 
353  using CoordHelper_t = CoordHelper;
355  using Scalar_t = typename CoordHelper_t::Scalar_t;
356  using Getter_t = typename CoordHelper_t::Getter_t;
357  using Setter_t = typename CoordHelper_t::Setter_t;
358 
359  /// Constructor: manage the specified coordinate of specified vector.
361  : Base_t(v, coordManager) {}
362 
363  /// Constructor: manage the specified vector with specified methods.
365  : Base_t(v, CoordHelper_t(getter, setter)) {}
366 
367  /// Setter: assigns a value to the bound coordinate of specified vector.
369  { Base_t::manager().set(Base_t::vector(), c); return *this; }
370 
371  /// Increments by the specified amount.
373  { Base_t::manager().incr(Base_t::vector(), c); return *this; }
374 
375  /// Decrements by the specified amount.
377  { Base_t::manager().decr(Base_t::vector(), c); return *this; }
378 
379  /// Multiplies by the specified amount.
381  { Base_t::manager().mult(Base_t::vector(), f); return *this; }
382 
383  /// Divides by the specified amount.
385  { Base_t::manager().div(Base_t::vector(), f); return *this; }
386 
387  }; // class BoundCoordManager
388 
389  //------------------------------------------------------------------------
390 
391  } // namespace details
392 
393 
394  // BEGIN Geometry group ------------------------------------------------------
395  /// @ingroup Geometry
396  /// @{
397 
398  /// Convenience utilities not directly related to vectors.
399  namespace extra {
400 
401  /// Returns `value`, rounded to 0, -1 or +1 if closer than `tol`.
402  template <typename T>
404  if (std::abs(value) < tol) return 0.;
405  if (std::abs(std::abs(value) - 1.) < tol) return (value > 0.)? 1.: -1.;
406  return value;
407  } // roundValue01()
408 
409  } // namespace extra
410 
411 
412  // --- BEGIN Vector coordinate access abstraction --------------------------
413  /// @{
414  /**
415  * @name Vector coordinate access abstraction
416  *
417  * This group of utilities provides a common interface for tasks involving
418  * geometry vectors, which may have different interface.
419  * An example of that is the access of coordinates by an index: it is
420  * supported (and "slow") in `TVector3` for read/write access, while in
421  * GenVector it is not supported (and given that the internal representation
422  * might be not cartesian, it's not surprising). We provide utilities which
423  * fill the gaps, relying on some looser requirements.
424  *
425  *
426  * Coordinate managers
427  * ====================
428  *
429  * A "coordinate manager" is an object handling a specific coordinate out of
430  * a specific vector type; i.e., a coordinate manager object will manage for
431  * its entire lifetime the same coordinate, e.g. _x_ or _z_.
432  * A coordinate manager can be:
433  * - bound to a vector object: that manager handles exclusively its managed
434  * coordinate for that vector object;
435  * - unbound: such a manager can handle the managed coordinate of any
436  * vector, which can be passed as an argument; or the unbound manager can
437  * be used to create a bound one.
438  *
439  * Two types of managers are available:
440  * - reader, accesses the coordinate but can't modify it
441  * - manager, requires to be bound to a mutable vector and can assign and
442  * modify the coordinate via selected operations
443  *
444  * Note that a coordinate is never returned as a reference, either mutable
445  * or constant.
446  *
447  *
448  * Handling a coordinate of a vector object: bound managers
449  * ---------------------------------------------------------
450  *
451  * A bound coordinate manager can be created directly:
452  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
453  * geo::Point_t p { 1.0, 2.0, 3.0 };
454  *
455  * auto px = geo::vect::Xcoord(p);
456  * std::cout << p << " has x=" << px() << std::endl;
457  * px += 5.0;
458  * std::cout << p << " has now x=" << px() << std::endl;
459  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
460  * will return something along the line of
461  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
462  * (1,2,3) has x=1
463  * (6,2,3) has now x=6
464  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
465  * Functions `Xcoord()`, `Ycoord()`, `Zcoord()` and `Tcoord()` (in namespace
466  * `geo::vect`) are available for the supporting vector types.
467  *
468  * If access by numeric index is necessary, `coord()` can be used instead:
469  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
470  * geo::Vector_t const v { 1.0, 2.0, 3.0 };
471  *
472  * for (unsigned c = 0; c < 3; ++c) {
473  * auto vc = geo::vect::coord(v, c);
474  * std::cout << v << "[" << c << "]=" << vc() << std::endl;
475  * }
476  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
477  * (note that for this example we have implicitly obtained a coordinate
478  * reader instead of a full coordinate manager because `v` is constant).
479  * This will print:
480  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
481  * v[0]=1
482  * v[1]=2
483  * v[2]=3
484  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
485  * If there are more vectors to access the same coordinate of, it's better
486  * to use unbound managers (see below).
487  *
488  *
489  * Handling a coordinate for any vector object
490  * --------------------------------------------
491  *
492  * Unbound coordinate managers (and readers) can't operate directly on
493  * vectors but they need to be bound to one. Binding produces a new bound
494  * manager, leaving the unbound manager untouched.
495  * Binding is done with `geo::vect::bindCoord()`. For example:
496  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
497  * geo::Point_t A { 1.0, 2.0, 3.0 };
498  * auto Ax = geo::vect::bindCoord(A, YcoordManager<geo::Point_t>);
499  * std::cout << A << " has y=" << Ax << std::endl;
500  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
501  * should produce an output like
502  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
503  * (1,2,3) has y=2
504  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
505  * In the example, `YcoordManager` is a template coordinate manager.
506  * There are managers available for `X`, `Y`, `Z` and `T` coordinates, and
507  * each one can deal only with a specific vector type; also, specifying a
508  * non-constant vector type will deliver a full manager, which can't operate
509  * on constant vectors.
510  * The unbound coordinate managers are not as useful, but a possible use is
511  * for loops on coordinates from multiple vectors:
512  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
513  * geo::Point_t A { 1.0, 2.0, 3.0 }, geo::Point_t B {5.0, 7.0, 9.0 };
514  * for (unsigned c = 0; c < 3; ++c) {
515  * auto coordMan = geo::vect::coordManager(c);
516  * auto Ac = geo::vect::bindCoord(A, coordMan);
517  * auto Bc = geo::vect::bindCoord(B, coordMan);
518  * std::cout << (Bc() - Ac() * 2.0) << std::endl;
519  * } // for
520  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
521  * which will emit
522  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
523  * 3
524  * 3
525  * 3
526  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
527  * This is marginally faster than the same code with
528  * `geo::vect::bindCoord()` call replaced by `geo::vect::coord()`. More
529  * convenient still, if the coordinates are treated all just the same and
530  * `c` is not needed (as above):
531  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
532  * geo::Point_t A { 1.0, 2.0, 3.0 }, geo::Point_t B {5.0, 7.0, 9.0 };
533  * for (auto coordMan: geo::vect::coordManagers<geo::Point_t const>()) {
534  * auto Ac = geo::vect::bindCoord(A, coordMan);
535  * auto Bc = geo::vect::bindCoord(B, coordMan);
536  * std::cout << (Bc() - Ac() * 2.0) << std::endl;
537  * } // for
538  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
539  *
540  *
541  * Conversion between vector types
542  * ================================
543  *
544  * A convenience function `convertTo()` is provided to convert a vector into
545  * another of a different type (for example, from `TVector3` to
546  * `geo::Vector_t`).
547  *
548  *
549  * Vector requirements
550  * ====================
551  *
552  * So far, the requirements for this set of utilities are the following.
553  * The vector type must support:
554  * - a cartesian coordinate constructor: `Vector v { 1.0, 2.0, 3.0 };`
555  * - accessor methods named after the name of the coordinate, acting on
556  * constant vectors, taking no arguments, and returning a copy of the
557  * coordinate value, e.g. `double X() const`
558  * - coordinate assignment methods named `SetC`, where `C` is the name of
559  * each coordinate, after the name of the coordinate, with a single
560  * argument; the return type is not prescribed; e.g. `void SetY(double)`
561  * - the coordinate names must be `X` and `Y` for 2D vectors, plus `Z` for
562  * 3D vectors and `T` for 4D vectors (metric is irrelevant here)
563  *
564  */
565 
566  //@{
567  /// Returns the dimension of the specified vector type.
568  template <typename Vector>
569  constexpr unsigned int dimension() { return details::dimension<Vector>(); }
570  template <typename Vector>
571  constexpr unsigned int dimension(Vector&&) { return dimension<Vector>(); }
572  //@}
573 
574  //@{
575  /// Returns a sequence of indices valid for a vector of the specified type.
576  template <typename Vector>
577  constexpr std::array<std::size_t, geo::vect::dimension<Vector>()> indices();
578  template <typename Vector>
579  constexpr auto indices(Vector const&) -> decltype(indices<Vector>());
580  //@}
581 
582  /// Type of coordinate of the specified vector type.
583  template <typename Vector>
585 
586  /**
587  * @brief Creates a `Vector` object with coordinates from `coords`.
588  * @tparam Vector the type of vector to be created
589  * @tparam Coords type of object holding the value of the needed coordinates
590  * @param coords object holding the value of the needed coordinates
591  * @return a newly created `Vector` object with coordinates from `coords`
592  *
593  * To create a vector of dimension _N_, the first _N_ values are extracted
594  * from `coords` using `Coords::operator[](std::size_t)`. For example:
595  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
596  * constexpr std::array<float, 5U> data { 2.0, 5.0, 7.0, 11.0, 15.5 };
597  * constexpr auto p = geo::vect::makeFromCoords<geo::Point_t>(data);
598  * auto v = geo::vect::makeFromCoords<geo::Vector_t>(data.data() + 1);
599  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
600  * will set `p` as `constexpr geo::Point_t {2.0, 5.0, 7.0 }`, ignoring the
601  * additional data. Likewise, it will set `v` to
602  * `geo::Vector_t{ 5.0, 7.0, 11.0 }`. In both cases, the coordinates are
603  * implicitly converted from `float` into the scalar type of the target
604  * vectors (in both cases, `double`).
605  */
606  template <typename Vector, typename Coords>
607  constexpr Vector makeFromCoords(Coords&& coords);
608 
609  /// Type of a coordinate reader for a vector type.
610  template <typename Vector>
611  using CoordReader_t
613 
614  /// Type of a coordinate manager for a vector type.
615  template <typename Vector>
616  using CoordManager_t = decltype
618 
619  /**
620  * @brief Object that can be bound to a vector to manage its X coordinate.
621  * @tparam Vector type of vector to get a manager for
622  * (mutable type required)
623  *
624  * The manager exposes a read/write interface.
625  * Example of usage:
626  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
627  * // mutable vectors get a full-featured "manager":
628  * geo::Point_t p { 1.0, 2.0, 3.0 };
629  * auto px
630  * = geo::vect::bindCoord(p, geo::vect::XcoordManager<geo::Point_t>);
631  * px *= 5.0;
632  * std::cout << p << " has now x=" << px() << std::endl;
633  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
634  * will print something like:
635  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
636  * (5,2,3) has now x=5
637  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
638  * Note that the use in the example, `Xcoord()` is preferred.
639  */
640  template <typename Vector>
641  static constexpr auto XcoordManager
643 
644  /**
645  * @brief Object that can be bound to a vector to access its X coordinate.
646  * @tparam Vector type of vector to get a manager for
647  * (constant type required)
648  *
649  * The manager exposes a read-only interface.
650  * Example of usage:
651  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
652  * // constant vectors get a "reader" (read-only manager):
653  * geo::Vector_t v { 1.0, 2.0, 3.0 };
654  *
655  * auto vx = geo::vect::bindCoord
656  * (v, geo::vect::XcoordManager<geo::Vector_t const>);
657  * std::cout << v << " has x=" << vx() << std::endl;
658  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
659  * will print something like:
660  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
661  * (1,2,3) has x=1
662  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
663  * Note that the use in the example, `Xcoord()` is preferred.
664  */
665  template <typename Vector>
666  static constexpr auto XcoordManager<Vector const>
668 
669  /// An object that can be bound to a vector to manage its Y coordinate.
670  /// @see `geo::vect::XcoordManager`
671  template <typename Vector>
672  static constexpr auto const YcoordManager
674 
675  /// An object that can be bound to a vector to manage its Y coordinate.
676  /// @see `geo::vect::XcoordManager`
677  template <typename Vector>
678  static constexpr auto YcoordManager<Vector const>
680 
681  /// An object that can be bound to a vector to manage its Z coordinate.
682  /// @see `geo::vect::XcoordManager`
683  template <typename Vector>
684  static constexpr auto ZcoordManager
686 
687  /// An object that can be bound to a vector to manage its Z coordinate.
688  /// @see `geo::vect::XcoordManager`
689  template <typename Vector>
690  static constexpr auto ZcoordManager<Vector const>
692 
693  /// An object that can be bound to a vector to manage its T coordinate.
694  /// @see `geo::vect::XcoordManager`
695  template <typename Vector>
696  static constexpr auto TcoordManager
698 
699  /// An object that can be bound to a vector to manage its T coordinate.
700  /// @see `geo::vect::XcoordManager`
701  template <typename Vector>
702  static constexpr auto TcoordManager<Vector const>
704 
705 
706  /**
707  * @brief Returns an object that can be bound to a vector to manage one of
708  * its coordinates.
709  * @tparam Vector type of vector to get a manager for (constantness matters)
710  * @param n index of the coordinate (`0`: X, `1`: Y, `2`: Z, `3`: T)
711  * @return a coordinate manager, undefined if index is invalid
712  *
713  * Index `n` is assumed to be smaller than the dimension of the vector.
714  * The manager returned for a mutable vector exposes a read/write interface.
715  * Example of usage:
716  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
717  * // mutable vectors get a full-featured "manager":
718  * geo::Point_t p { 1.0, 2.0, 3.0 };
719  * auto px
720  * = geo::vect::bindCoord(p, geo::vect::coordManager<geo::Point_t>(0U));
721  * px *= 5.0;
722  * std::cout << p << " has now x=" << px() << std::endl;
723  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
724  * will print something like:
725  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
726  * (5,2,3) has now x=5
727  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
728  *
729  * For a constant vector, the returned manager exposes a read-only
730  * interface.
731  * Example of usage:
732  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
733  * // constant vectors get a "reader" (read-only manager):
734  * geo::Vector_t v { 1.0, 2.0, 3.0 };
735  *
736  * auto vx = geo::vect::bindCoord
737  * (v, geo::vect::coordManager<geo::Vector_t const>(1U));
738  * std::cout << v << " has y=" << vy() << std::endl;
739  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
740  * will print something like:
741  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
742  * {1,2,3) has y=2
743  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
744  * Note that the use in these examples, `coord()` is preferred.
745  */
746  template <typename Vector>
747  constexpr auto coordManager(unsigned int n);
748 
749  /**
750  * @brief Returns an object that can be bound to a vector to manage one of
751  * its coordinates.
752  * @tparam Vector type of vector to get a manager for (constantness matters)
753  * @param n index of the coordinate (`0`: X, `1`: Y, `2`: Z, `3`: T)
754  * @param v a vector of type `Vector` (ignored)
755  * @return a coordinate manager, undefined if index is invalid
756  * @see `geo::vect::coordManager(unsigned int)`
757  *
758  * An alias of `geo::vect::coordManager(unsigned int)`.
759  */
760  template <typename Vector>
761  constexpr auto coordManager(unsigned int n, Vector& v);
762 
763 
764  //@{
765  /// Returns an array with all coordinate managers for a type of vector.
766  template <typename Vector>
767  constexpr auto coordManagers();
768  template <typename Vector>
769  constexpr auto coordManagers(Vector&&);
770  //@}
771 
772  //@{
773  /// Returns an array with all coordinate readers for a type of vector.
774  template <typename Vector>
775  constexpr auto coordReaders();
776  template <typename Vector>
777  constexpr auto coordReaders(Vector&&);
778  //@}
779 
780 
781  /// Binds the specified constant vector to the coordinate reader.
782  template <typename Vector>
783  constexpr auto bindCoord
784  (Vector const& v, CoordReader_t<Vector> helper)
785  {
787  (v, helper);
788  }
789 
790  /// Binds the specified vector to the coordinate manager.
791  template <typename Vector>
794  { return { v, helper }; }
795 
796 
797  /**
798  * @brief Returns an object to manage the coordinate X of the vector `v`.
799  * @tparam Vector the type of vector to be managed
800  * @param v the vector with the coordinate X to be managed
801  * @return an object to manage the coordinate X of `v`
802  *
803  * The type `Vector` needs to have a `double X() const` method and a
804  * `auto SetX(auto)` method, where the argument is the type of the managed
805  * coordinate and the return value is unspecified.
806  */
807  template <typename Vector>
808  auto Xcoord(Vector& v)
809  { return bindCoord(v, XcoordManager<Vector>); }
810 
811  /**
812  * @brief Returns an object to manage the coordinate Y of the vector `v`.
813  * @tparam Vector the type of vector to be managed
814  * @param v the vector with the coordinate Y to be managed
815  * @return an object to manage the coordinate Y of `v`
816  *
817  * The type `Vector` needs to have a `double Y() const` method and a
818  * `auto SetY(auto)` method, where the argument is the type of the managed
819  * coordinate and the return value is unspecified.
820  */
821  template <typename Vector>
822  auto Ycoord(Vector& v)
823  { return bindCoord<Vector>(v, YcoordManager<Vector>); }
824 
825  /**
826  * @brief Returns an object to manage the coordinate Z of the vector `v`.
827  * @tparam Vector the type of vector to be managed
828  * @param v the vector with the coordinate Z to be managed
829  * @return an object to manage the coordinate Z of `v`
830  *
831  * The type `Vector` needs to have a `double Z() const` method and a
832  * `auto SetZ(auto)` method, where the argument is the type of the managed
833  * coordinate and the return value is unspecified.
834  */
835  template <typename Vector>
836  auto Zcoord(Vector& v)
837  { return bindCoord<Vector>(v, ZcoordManager<Vector>); }
838 
839  /**
840  * @brief Returns an object to manage the coordinate T of the vector `v`.
841  * @tparam Vector the type of vector to be managed
842  * @param v the vector with the coordinate T to be managed
843  * @return an object to manage the coordinate T of `v`
844  *
845  * The type `Vector` needs to have a `double T() const` method and a
846  * `auto SetT(auto)` method, where the argument is the type of the managed
847  * coordinate and the return value is unspecified.
848  */
849  template <typename Vector>
850  auto Tcoord(Vector& v)
851  { return bindCoord<Vector>(v, TcoordManager<Vector>); }
852 
853  /**
854  * @brief Returns an object to manage the coordinate `n` of a vector
855  * @tparam Vector the type of vector to be managed
856  * @param v the vector to be managed
857  * @param n the coordinate index: `0` for X, `1` for Y and `2` for Z
858  * @return an object to manage the coordinate `n` of a vector
859  * @see `Xcoord()`, `Ycoord()`, `Zcoord()`
860  *
861  * Result is undefined for any value of `n` other than `0`, `1` and `2`.
862  * See `Xcoord()`, `Ycoord()` and `Zcoord()` for `Vector` type requirements.
863  */
864  template <typename Vector>
865  auto coord(Vector& v, unsigned int n) noexcept;
866 
867 
868  /// Returns an array with all coordinate managers bound to the specified
869  /// vector.
870  template <typename Vector>
871  constexpr auto bindCoordManagers(Vector& v);
872 
873  /// Returns an array with all coordinate readers bound to the specified
874  /// vector.
875  template <typename Vector>
876  constexpr auto bindCoordReaders(Vector const& v);
877 
878 
879  /**
880  * @brief Returns a vector of type `Dest` with the same content as a `Src`.
881  * @tparam Dest target vector type
882  * @tparam Source type of the vector to be converted from
883  * @param v the vector to be converted from
884  * @return a vector with the same content as `v`, but of type `Dest`
885  *
886  * For this to work, both `Src` and `Dest` types must satisfy the
887  * requirements of `Xcoord()`, `Ycoord()`, `Zcoord()` etc.
888  */
889  template <typename Dest, typename Source>
890  Dest convertTo(Source const& v);
891 
892 
893  /**
894  * @brief Returns a vector of type `Dest` with the same content as a `Src`.
895  * @tparam Dest target vector type
896  * @tparam Source type of the vector to be converted from
897  * @param coll the collection of vectors to be converted from
898  * @return a collection of vectors with the same content as `coll`, but of
899  * type `Dest`
900  * @see `convertTo()`
901  *
902  * This version applies `convertTo()` to all the elements of the specified
903  * collection, returning a collection of the same template type
904  * (`std::vector`).
905  *
906  * For the requirements, see `convertTo()`.
907  */
908  template <typename Dest, typename Source>
909  std::vector<Dest> convertCollTo(std::vector<Source> const& coll);
910 
911 
912  /**
913  * @brief Returns a new vector applying a predicate to each component.
914  * @tparam Vector type of the vector in input (and output)
915  * @tparam Pred type of unary predicate to be applied
916  * @param v the vector to be transformed
917  * @param pred the predicate to be applied
918  * @return a vector equivelent to `{ pred(x), pred(y), ... }`
919  *
920  * The predicate is a "functor" type, taking as the single argument the
921  * coordinate to be transformed, and returning the transformed value of it.
922  */
923  template <typename Vector, typename Pred>
924  Vector transformCoords(Vector const& v, Pred&& pred);
925 
926  /// @}
927  // --- END Vector coordinate access abstraction ----------------------------
928 
929 
930  // --- BEGIN Functions for common vector operations ------------------------
931  /// @{
932  /** ************************************************************************
933  * @name Functions for common vector operations.
934  *
935  * This group of template functions are meant to be used with vectors in a
936  * generic way.
937  * The default implementation is for `TVector3`. Specializations can be
938  * easily written for other vector types.
939  *
940  * In addition, two "standard" representations for vectors and points are
941  * provided.
942  *
943  * @note The representations for vector and point objects are currently the
944  * same; this prevents relying on overload resolution to decide which
945  * function to use. For example, defining two functions with signature:
946  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
947  * Vector_t Project(Vector_t const& v);
948  * Point_t Project(Point_t const& v);
949  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
950  * will not compile since these two are exactly the same.
951  * A solution might be to derive two different classes from the common
952  * one:
953  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
954  * struct Vector_t: public VectorBase_t { using VectorBase_t::VectorBase_t; };
955  * struct Point_t: public VectorBase_t { using VectorBase_t::VectorBase_t; };
956  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
957  * This will likely have consequences though (for example, the sum of
958  * two `Vector_t` or `Point_t` will become a `VectorBase_t`).
959  *
960  */
961 
962  /// Returns a vector with all components rounded if close to 0, -1 or +1.
963  template <typename Vector, typename Scalar>
964  Vector rounded01(Vector const& v, Scalar tol)
965  {
966  return transformCoords
967  (v, [tol](auto c){ return extra::roundValue01(c, tol); });
968  }
969 
970  /// Returns a vector with all components rounded if close to 0, -1 or +1.
971  template <typename Vector, typename Scalar>
972  void round01(Vector& v, Scalar tol) { v = rounded01(v, tol); }
973 
974 
975  /// Returns whether all components of the vector are finite.
976  template <typename Vector>
977  bool isfinite(Vector const& v);
978 
979  /// Returns a vector parallel to v and with norm 1
980  template <typename Vector>
981  Vector normalize(Vector const& v) { return v.Unit(); }
982 
983  /// Return cross product of two vectors
984  template <typename Vector>
985  Vector cross(Vector const& a, Vector const& b) { return a.Cross(b); }
986 
987  /// Return cross product of two vectors
988  template <typename Vector>
989  constexpr auto dot(Vector const& a, Vector const& b) { return a.Dot(b); }
990 
991  /// Return norm of the specified vector
992  template <typename Vector>
993  auto mag2(Vector const& v) { return v.Mag2(); }
994 
995  /// Return norm of the specified vector
996  template <typename Vector>
997  auto norm(Vector const& v) { return v.Mag(); }
998 
999  /// Return "mixed" product of three vectors:
1000  /// @f$ \vec{a} \times \vec{b} \cdot \vec{c} @f$
1001  template <typename Vector>
1002  auto mixedProduct(Vector const& a, Vector const& b, Vector const& c)
1003  { return dot(cross(a, b), c); }
1004 
1005 
1006  /// @}
1007  // --- END Functions for common vector operations --------------------------
1008 
1009 
1010  /** ************************************************************************
1011  * @brief Helper class to compute the middle point in a point set.
1012  * @tparam N _(default: `3`)_ dimension of the points
1013  *
1014  * This class accumulates cartesian points and returns their middle point
1015  * when asked.
1016  *
1017  * In the following example, only the points from a list (`points`) which
1018  * have _y_ coordinate larger than 0 are averaged, all with the same weight:
1019  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1020  * std::array<geo::Point_t, 4> const points = {
1021  * geo::Point_t{ 0.0, 1.0, 2.0 },
1022  * geo::Point_t{ 0.0, -1.0, 2.0 },
1023  * geo::Point_t{ 0.0, 1.0, -2.0 },
1024  * geo::Point_t{ 0.0, -1.0, -2.0 }
1025  * };
1026  *
1027  * geo::vect::MiddlePointAccumulatorDim pointsAboveGround;
1028  * for (auto const& point: points)
1029  * if (point.Y() > 0.0) pointsAboveGround.add(point);
1030  *
1031  * if (pointsAboveGround.empty())
1032  * throw std::runtime_error("No point above ground!");
1033  *
1034  * auto middleAboveGround = pointsAboveGround.middlePoint();
1035  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1036  * Note the check to make sure that there are points that fulfil the
1037  * requirement.
1038  *
1039  */
1040  template <unsigned int N = 3U>
1042  static constexpr unsigned int Dim = N; ///< Dimension of the points.
1043  std::array<Length_t, Dim> fSums; ///< Sum of each of the point components.
1044  double fW = 0.0; ///< Total weight.
1045 
1046  public:
1047  /// Default constructor: starts with no accumulated point.
1048  MiddlePointAccumulatorDim() { fSums.fill(0.); }
1049 
1050  /**
1051  * @brief Constructor: starts with accumulating a sequence of points.
1052  * @tparam BeginIter type of iterator to a point type compatible with add()
1053  * @tparam EndIter type of end iterator
1054  * @param begin iterator to the first point to be added
1055  * @param end iterator after the last point to be added
1056  * @see add()
1057  */
1058  template <typename BeginIter, typename EndIter>
1061  { add(begin, end); }
1062 
1063 
1064  // --- BEGIN Result query ------------------------------------------------
1065  /// @{
1066  /// @name Result query
1067 
1068  /// Returns whether the total weight is zero (usually means no points).
1069  bool empty() const { return fW == 0.0; }
1070 
1071  /// Returns the total weight (number of points if all have weight 1).
1072  double weight() const { return fW; }
1073 
1074  /**
1075  * @brief Returns the middle point, NaN components if no point.
1076  * @tparam Point type of the output point
1077  *
1078  * The type of return point must be specified as template argument, e.g.
1079  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1080  * auto mp = accumulator.middlePointAs<TVector3>();
1081  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1082  * The `Point` type is required to have a constructor with the three
1083  * cartesian components as arguments.
1084  */
1085  template <typename Point>
1087  // { return { fSums[0] / fW, fSums[1] / fW, fSums[2] / fW }; }
1088  { return makeWeightedPoint<Point>(1.0 / fW); }
1089 
1090  /// Returns the middle point as a `geo::Point_t`,
1091  /// NaN components if no point.
1093  { return middlePointAs<geo::Point_t>(); }
1094 
1095 
1096  /// @}
1097  // --- END Result query --------------------------------------------------
1098 
1099  // --- BEGIN Addition of points ------------------------------------------
1100  /// @{
1101  /// @name Addition of points
1102 
1103  /**
1104  * @brief Accumulates a point.
1105  * @tparam Point point type, required to have X(), Y() and Z() accessors
1106  * @param p point to be included
1107  *
1108  * The point is added with weight 1.
1109  */
1110  template <typename Point>
1111  void add(Point const& p)
1112  {
1113  std::size_t ic = 0U;
1114  for (auto c: geo::vect::bindCoordManagers(p)) fSums[ic++] += c();
1115  fW += 1.0;
1116  }
1117 
1118  /**
1119  * @brief Accumulates a point.
1120  * @tparam Point point type, required to have X(), Y() and Z() accessors
1121  * @param p point to be included
1122  * @param weight the relative weight of this point
1123  */
1124  template <typename Point>
1125  void add(Point const& p, double weight)
1126  {
1127  std::size_t ic = 0U;
1128  for (auto c: geo::vect::bindCoordManagers(p))
1129  fSums[ic++] += weight * c();
1130  fW += weight;
1131  }
1132 
1133  /**
1134  * @brief Adds a sequence of points.
1135  * @tparam BeginIter type of iterator to a point type compatible with add()
1136  * @tparam EndIter type of end iterator
1137  * @param begin iterator to the first point to be added
1138  * @param end iterator after the last point to be added
1139  *
1140  * Each point is added with weight 1.0.
1141  */
1142  template <typename BeginIter, typename EndIter>
1143  void add(BeginIter begin, EndIter end)
1144  { std::for_each(begin, end, [this](auto const& p){ this->add(p); }); }
1145 
1146  /// Resets the status of the object to no accumulated points.
1147  void clear() { fSums.fill(0.); fW = 0.0; }
1148 
1149  /// @}
1150  // --- END Addition of points --------------------------------------------
1151 
1152  private:
1153  using IndexSequence_t = std::make_index_sequence<Dim>;
1154 
1155  template <typename Point, std::size_t... I>
1156  Point makePointImpl(std::index_sequence<I...>) const
1157  { return { fSums.operator[](I)... }; }
1158 
1159  template <typename Point, std::size_t... I>
1160  Point makeWeightedPointImpl(double w, std::index_sequence<I...>) const
1161  { return { (fSums.operator[](I) * w)... }; }
1162 
1163  /// Converts the internal sums into a `Point`.
1164  template <typename Point>
1166  { return geo::vect::makeFromCoords<Point>(fSums); }
1167 
1168  /// Converts the internal sums into a `Point` with components scaled by
1169  /// `w`.
1170  template <typename Point>
1171  Point makeWeightedPoint(double w) const
1172  { return makeWeightedPointImpl<Point>(w, IndexSequence_t{}); }
1173 
1174 
1175  }; // MiddlePointAccumulatorDim()
1176 
1177 
1178  /// Middle-point accumulator for vectors of dimension 3.
1180 
1181 
1182  // --- BEGIN Middle point functions ----------------------------------------
1183  /// @{
1184  /// @name Middle point functions
1185 
1186  /**
1187  * @brief Returns the middle of the specified points.
1188  * @tparam Point cartesian-represented point type with 3-component constructor
1189  * @tparam BeginIter type of iterator to a point type compatible with add()
1190  * @tparam EndIter type of end iterator
1191  * @param begin iterator to the first point to be averaged
1192  * @param end iterator after the last point to be averaged
1193  * @return an object of type `Point` with the value of the middle point
1194  *
1195  * Example of usage:
1196  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1197  * std::vector<geo::Point_t> points {
1198  * geo::Point_t(1., 2., 3.),
1199  * geo::Point_t(2., 4., 6.),
1200  * geo::Point_t(3., 6., 9.)
1201  * };
1202  *
1203  * auto mp = geo::vect::middlePointAs<geo::Vector_t>(points.begin(), points.end());
1204  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1205  * The variable `mp` of the example will be of type `geo::Vector_t` (converted
1206  * component by components from a `geo::Point_t`).
1207  *
1208  */
1209  template <typename Point, typename BeginIter, typename EndIter>
1210  Point middlePointAs(BeginIter begin, EndIter end)
1211  {
1212  constexpr auto Dim = geo::vect::dimension<Point>();
1214  .template middlePointAs<Point>();
1215  }
1216 
1217  /**
1218  * @brief Returns the middle of the specified points.
1219  * @tparam BeginIter type of iterator to a point type compatible with add()
1220  * @tparam EndIter type of end iterator
1221  * @param begin iterator to the first point to be averaged
1222  * @param end iterator after the last point to be averaged
1223  * @return an object of type `Point_t` with the value of the middle point
1224  *
1225  * Example of usage:
1226  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1227  * std::vector<geo::Point_t> points {
1228  * geo::Point_t(1., 2., 3.),
1229  * geo::Point_t(2., 4., 6.),
1230  * geo::Point_t(3., 6., 9.)
1231  * };
1232  *
1233  * auto mp = geo::vect::middlePoint(points.begin(), points.end());
1234  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1235  * The variable `mp` of the example will be of type `geo::Point_t`.
1236  *
1237  */
1238  template <typename BeginIter, typename EndIter>
1239  geo::Point_t middlePoint(BeginIter begin, EndIter end)
1240  { return middlePointAs<geo::Point_t>(begin, end); }
1241 
1242  /**
1243  * @brief Returns the middle of the specified points.
1244  * @tparam Point cartesian-represented point type with 3-component constructor
1245  * and X(), Y() and Z() accessors.
1246  * @param points the list of points to be included
1247  * @return the value of the middle point
1248  *
1249  * Example of usage:
1250  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1251  * auto mp = geo::vect::middlePoint
1252  * ({ geo::Point_t(1., 2., 3.), geo::Point_t(3., 6., 9.) });
1253  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1254  * The variable `mp` will contain the middle point between the two specified
1255  * in the initializer list.
1256  *
1257  */
1258  template <typename Point>
1259  Point middlePoint(std::initializer_list<Point> points)
1260  {
1261  constexpr auto Dim = geo::vect::dimension<Point>();
1262  return MiddlePointAccumulatorDim<Dim>(points.begin(), points.end())
1263  .template middlePointAs<Point>();
1264  }
1265 
1266  /// @}
1267  // --- END Middle point functions ------------------------------------------
1268 
1269 
1270  // --- BEGIN Support for GArSoft geometry vectors --------------------------
1271  /// @{
1272  /// @name Support for GArSoft geometry vectors
1273 
1274  // import global definitions
1277 
1278  /// Convert the specified point into a `geo::Point_t`.
1279  template <typename Point>
1281  { return geo::vect::convertTo<::geo::Point_t>(p); }
1282 
1283  /// Convert the specified vector into a `geo::Vector_t`.
1284  template <typename Vector>
1286  { return geo::vect::convertTo<::geo::Vector_t>(v); }
1287 
1288 
1289  /// Convert the specified collection of points into a collection of
1290  /// `geo::Point_t`.
1291  template <typename Point>
1292  std::vector<geo::Point_t> convertCollToPoint
1293  (std::vector<Point> const& coll)
1294  { return convertCollTo<geo::Point_t>(coll); }
1295 
1296  /// Convert the specified collection of vectors into a collection of
1297  /// `geo::Vector_t`.
1298  template <typename Vector>
1299  std::vector<geo::Vector_t> convertCollToVector
1300  (std::vector<Vector> const& coll)
1301  { return convertCollTo<geo::Vector_t>(coll); }
1302 
1303 
1304  /// Creates a `geo::Point_t` from its coordinates (see `makeFromCoords()`).
1305  template <typename Coords>
1307  { return makeFromCoords<::geo::Point_t>(std::forward<Coords>(coords)); }
1308 
1309  /// Creates a `geo::Vector_t` from its coordinates (see `makeFromCoords()`).
1310  template <typename Coords>
1312  { return makeFromCoords<::geo::Vector_t>(std::forward<Coords>(coords)); }
1313 
1314  /// @}
1315  // --- END Support for GArSoft geometry vectors ----------------------------
1316 
1317 
1318  } // namespace vect
1319 
1320  /// @}
1321  // END Geometry group --------------------------------------------------------
1322 
1323 } // namespace geo
1324 
1325 
1326 //------------------------------------------------------------------------------
1327 //--- template specializations for standard geometry vectors
1328 //---
1329 namespace geo {
1330  namespace vect {
1331 
1332  //--------------------------------------------------------------------------
1333  template <>
1334  inline auto norm(geo::Vector_t const& v) { return v.R(); }
1335 
1336  //--------------------------------------------------------------------------
1337 
1338  } // namespace vect
1339 } // namespace geo
1340 
1341 
1342 //------------------------------------------------------------------------------
1343 //--- template implementation
1344 
1345 namespace geo {
1346  namespace vect {
1347  namespace details {
1348 
1349  //------------------------------------------------------------------------
1350  template <typename> struct AlwaysFalse: std::false_type {};
1351 
1352 
1353  // constexpr variant of forward (from StackExchange)
1354  template <typename T>
1355  constexpr T&& constexpr_forward(std::remove_reference_t<T>& t)
1356  { return static_cast<T&&>(t); }
1357 
1358  template<typename T>
1359  constexpr T&& constexpr_forward(std::remove_reference_t<T>&& t)
1360  {
1361  static_assert(!std::is_lvalue_reference<T>(),
1362  "template argument substituting T is an lvalue reference type");
1363  return static_cast<T&&>(t);
1364  }
1365 
1366  //------------------------------------------------------------------------
1367  /// Type of sequence of indices up to `Vector` size.
1368  template <typename Vector>
1369  using VectorIndices_t = std::make_index_sequence<dimension<Vector>()>;
1370 
1371  template <typename Vector>
1372  constexpr auto makeVectorIndices() { return VectorIndices_t<Vector>{}; }
1373 
1374  template <typename Vector>
1375  constexpr auto makeVectorIndices(Vector&&)
1376  { return makeVectorIndices<Vector>(); }
1377 
1378 
1379  template <typename T, T... Indices>
1380  constexpr auto makeIndexSeqImpl(std::integer_sequence<T, Indices...>)
1381  // BUG the double brace syntax is required to work around clang bug 21629
1382  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1383  { return std::array<T, sizeof...(Indices)>{{ Indices... }}; }
1384 
1385  // fill a sequence object with the first `N` values of type `T`.
1386  template <typename T, T N>
1387  constexpr auto makeIndexSeq()
1388  { return makeIndexSeqImpl<T>(std::make_integer_sequence<T, N>{}); }
1389 
1390 
1391  //------------------------------------------------------------------------
1392  template <std::size_t I, typename Data>
1393  constexpr auto accessElement(Data&& data) { return data[I]; }
1394 
1395  template <typename Vector, typename Coords, std::size_t... Indices>
1396  constexpr Vector makeFromCoordsImpl
1397  (Coords&& coords, std::index_sequence<Indices...>)
1398  {
1399  return
1400  { accessElement<Indices>(constexpr_forward<Coords>(coords))... };
1401  }
1402 
1403 
1404  //------------------------------------------------------------------------
1405  template <typename Vector>
1406  constexpr CoordManager_t<Vector> NoCoordManager{ nullptr, nullptr };
1407 
1408  template <typename Vector, unsigned int Dim = dimension<Vector>()>
1410 
1411  template <typename Vector>
1412  struct CoordManagerImpl<Vector, 1U> {
1413  static auto get(unsigned int n) noexcept
1414  { return (n == 0)? XcoordManager<Vector>: NoCoordManager<Vector>; }
1415  }; // CoordManagerImpl<1U>
1416 
1417  template <typename Vector>
1418  struct CoordManagerImpl<Vector, 2U> {
1419  static auto get(unsigned int n) noexcept
1420  {
1421  return (n == 1)
1422  ? YcoordManager<Vector>: CoordManagerImpl<Vector, 1U>::get(n);
1423  }
1424  }; // CoordManagerImpl<2U>
1425 
1426  template <typename Vector>
1427  struct CoordManagerImpl<Vector, 3U> {
1428  static auto get(unsigned int n) noexcept
1429  {
1430  return (n == 2)
1431  ? ZcoordManager<Vector>: CoordManagerImpl<Vector, 2U>::get(n);
1432  }
1433  }; // CoordManagerImpl<3U>
1434 
1435  template <typename Vector>
1436  struct CoordManagerImpl<Vector, 4U> {
1437  static auto get(unsigned int n) noexcept
1438  {
1439  return (n == 3)
1440  ? TcoordManager<Vector>: CoordManagerImpl<Vector, 3U>::get(n);
1441  }
1442 
1443  }; // CoordManagerImpl<4U>
1444 
1445 
1446  //------------------------------------------------------------------------
1447  template <typename Vector, unsigned int N>
1449  static constexpr unsigned int Dim = N;
1450 
1451  using Manager_t = decltype(XcoordManager<Vector>);
1452  using Return_t = std::array<Manager_t, Dim>;
1453 
1454  static_assert(dimension<Vector>() == Dim, "Inconsistent vector size.");
1455  }; // CoordManagersImplBase
1456 
1457  template <typename Vector, unsigned int N>
1459 
1460  template <typename Vector>
1462  : private CoordManagersImplBase<Vector, 2U>
1463  {
1465  using typename Base_t::Return_t;
1466  static constexpr Return_t get()
1467  {
1468  // BUG the double brace syntax is required to work around clang bug 21629
1469  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1470  return {{
1471  XcoordManager<Vector>
1472  , YcoordManager<Vector>
1473  }};
1474  }
1475  }; // CoordManagersImpl<2U>
1476 
1477  template <typename Vector>
1479  : private CoordManagersImplBase<Vector, 3U>
1480  {
1482  using typename Base_t::Return_t;
1483  static constexpr Return_t get()
1484  {
1485  // BUG the double brace syntax is required to work around clang bug 21629
1486  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1487  return {{
1488  XcoordManager<Vector>
1489  , YcoordManager<Vector>
1490  , ZcoordManager<Vector>
1491  }};
1492  }
1493  }; // CoordManagersImpl<3U>
1494 
1495  template <typename Vector>
1497  : private CoordManagersImplBase<Vector, 4U>
1498  {
1500  using typename Base_t::Return_t;
1501  static constexpr Return_t get()
1502  {
1503  // BUG the double brace syntax is required to work around clang bug 21629
1504  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1505  return {{
1506  XcoordManager<Vector>
1507  , YcoordManager<Vector>
1508  , ZcoordManager<Vector>
1509  , TcoordManager<Vector>
1510  }};
1511  }
1512  }; // CoordManagersImpl<4U>
1513 
1514 
1515  //------------------------------------------------------------------------
1516  template <typename Vector, unsigned int N>
1518  static constexpr unsigned int Dim = N;
1519 
1520  using Manager_t = decltype(Xcoord(std::declval<Vector>()));
1521  using Return_t = std::array<Manager_t, Dim>;
1522 
1523  static_assert(dimension<Vector>() == Dim, "Inconsistent vector size.");
1524  }; // CoordManagersImplBase
1525 
1526  template <typename Vector, unsigned int N>
1528 
1529  template <typename Vector>
1531  : private BindCoordManagersImplBase<Vector, 2U>
1532  {
1534  using typename Base_t::Return_t;
1535  static Return_t bind(Vector& v)
1536  {
1537  // BUG the double brace syntax is required to work around clang bug 21629
1538  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1539  return {{
1540  Xcoord(v)
1541  , Ycoord(v)
1542  }};
1543  }
1544  }; // BindCoordManagersImpl<2U>
1545 
1546  template <typename Vector>
1548  : private BindCoordManagersImplBase<Vector, 3U>
1549  {
1551  using typename Base_t::Return_t;
1552  static Return_t bind(Vector& v)
1553  {
1554  // BUG the double brace syntax is required to work around clang bug 21629
1555  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1556  return {{
1557  Xcoord(v)
1558  , Ycoord(v)
1559  , Zcoord(v)
1560  }};
1561  }
1562  }; // BindCoordManagersImpl<3U>
1563 
1564  template <typename Vector>
1566  : private BindCoordManagersImplBase<Vector, 4U>
1567  {
1569  using typename Base_t::Return_t;
1570  static Return_t bind(Vector& v)
1571  {
1572  // BUG the double brace syntax is required to work around clang bug 21629
1573  // (https://bugs.llvm.org/show_bug.cgi?id=21629)
1574  return {{
1575  Xcoord(v)
1576  , Ycoord(v)
1577  , Zcoord(v)
1578  , Tcoord(v)
1579  }};
1580  }
1581  }; // BindCoordManagersImpl<4U>
1582 
1583 
1584  //------------------------------------------------------------------------
1585  template<typename Dest, typename Source>
1587  static_assert(dimension<Source>() == dimension<Dest>(),
1588  "Source and destination vectors must have the same dimension.");
1589  }; // struct ConvertToImplBase
1590 
1591 
1592  // special pass-through case
1593  template <typename Dest, typename Source, unsigned int Dim>
1594  struct ConvertToImpl {
1595  // trivial to do: open a feature request!
1596  static_assert(
1598  "This vector dimensionality is not implemented yet."
1599  );
1600  }; // struct ConvertToImpl
1601 
1602  template <typename Dest, typename Source>
1603  struct ConvertToImpl<Dest, Source, 2U>
1604  : private ConvertToImplBase<Dest, Source>
1605  {
1606  static Dest convert(Source const& v)
1607  { return { Xcoord(v)(), Ycoord(v)() }; }
1608  }; // struct ConvertToImpl<2U>
1609 
1610  template <typename Dest, typename Source>
1611  struct ConvertToImpl<Dest, Source, 3U>
1612  : private ConvertToImplBase<Dest, Source>
1613  {
1614  static Dest convert(Source const& v)
1615  { return { Xcoord(v)(), Ycoord(v)(), Zcoord(v)() }; }
1616  }; // struct ConvertToImpl<3U>
1617 
1618  template <typename Dest, typename Source>
1619  struct ConvertToImpl<Dest, Source, 4U>
1620  : private ConvertToImplBase<Dest, Source>
1621  {
1622  static Dest convert(Source const& v)
1623  { return { Xcoord(v)(), Ycoord(v)(), Zcoord(v)(), Tcoord(v)() }; }
1624  }; // struct ConvertToImpl<4U>
1625 
1626 
1627  template
1628  <typename Dest, typename Source, unsigned int Dim = dimension<Source>()>
1630 
1631  // special pass-through case
1632  template <typename Vector, unsigned int Dim>
1634  static_assert
1635  (Dim == dimension<Vector>(), "Inconsistent vector dimension");
1636  static constexpr Vector convert(Vector const& v) { return v; }
1637  }; // struct ConvertToDispatcher<pass through>
1638 
1639 
1640  //------------------------------------------------------------------------
1641  template <typename Point, std::size_t... I>
1642  bool isfiniteImpl(Point const& point, std::index_sequence<I...>)
1643  { return extended_and(std::isfinite(coord(point, I).get())...); }
1644 
1645  //------------------------------------------------------------------------
1646 
1647  } // namespace details
1648  } // namespace vect
1649 } // namespace geo
1650 
1651 
1652 //------------------------------------------------------------------------------
1653 template <typename Vector>
1654 constexpr std::array<std::size_t, geo::vect::dimension<Vector>()>
1656 {
1657  return details::makeIndexSeq<std::size_t, dimension<Vector>()>();
1658 }
1659 
1660 template <typename Vector>
1661 constexpr auto geo::vect::indices(Vector const&) -> decltype(indices<Vector>())
1662  { return indices<Vector>(); }
1663 
1664 
1665 //------------------------------------------------------------------------
1666 template <typename Vector, typename Coords>
1667 constexpr Vector geo::vect::makeFromCoords(Coords&& coords) {
1668  using namespace geo::vect::details;
1669  return makeFromCoordsImpl<Vector>
1670  (constexpr_forward<Coords>(coords), makeVectorIndices<Vector>());
1671 } // geo::vect::makeFromCoords()
1672 
1673 
1674 //------------------------------------------------------------------------------
1675 template <typename Vector>
1676 constexpr auto geo::vect::coordManager(unsigned int n)
1678 
1679 
1680 //------------------------------------------------------------------------------
1681 template <typename Vector>
1682 auto geo::vect::coord(Vector& v, unsigned int n) noexcept {
1683  return vect::bindCoord<Vector>(v, coordManager<Vector>(n));
1684 }
1685 
1686 
1687 //------------------------------------------------------------------------------
1688 template <typename Vector>
1689 constexpr auto geo::vect::coordManagers() {
1690  using PlainVector = std::remove_reference_t<Vector>;
1691  return
1693 } // geo::vect::coordManagers()
1694 
1695 template <typename Vector>
1697  { return coordManagers<Vector>(); }
1698 
1699 
1700 template <typename Vector>
1701 constexpr auto geo::vect::coordReaders() {
1702  using ConstVector = std::add_const_t<std::remove_reference_t<Vector>>;
1703  return
1705 } // geo::vect::coordReaders()
1706 
1707 template <typename Vector>
1709  { return coordReaders<Vector>(); }
1710 
1711 
1712 //------------------------------------------------------------------------------
1713 template <typename Vector>
1716 } // geo::vect::bindCoordManagers()
1717 
1718 
1719 template <typename Vector>
1720 constexpr auto geo::vect::bindCoordReaders(Vector const& v) {
1721  using ConstVector = std::add_const_t<std::remove_reference_t<Vector>>;
1723  ::bind(v);
1724 } // geo::vect::bindCoordReaders()
1725 
1726 
1727 //------------------------------------------------------------------------------
1728 template <typename Dest, typename Source>
1729 Dest geo::vect::convertTo(Source const& v)
1731 
1732 
1733 //----------------------------------------------------------------------------
1734 template <typename Dest, typename Source>
1735 std::vector<Dest> geo::vect::convertCollTo(std::vector<Source> const& coll) {
1736 
1737  std::vector<Dest> dest;
1738  dest.reserve(coll.size());
1739  std::transform(coll.begin(), coll.end(), std::back_inserter(dest),
1740  geo::vect::convertTo<Dest, Source>);
1741  return dest;
1742 
1743 } // geo::vect::convertCollTo()
1744 
1745 
1746 //------------------------------------------------------------------------
1747 template <typename Vector, typename Pred>
1750  unsigned int i = 0;
1751  for (auto c: bindCoordReaders(v)) values[i++] = pred(c());
1752  return makeFromCoords<Vector>(values);
1753 } // geo::vect::transformCoords()
1754 
1755 
1756 //------------------------------------------------------------------------------
1757 template <typename Vector>
1759  { return details::isfiniteImpl(v, details::makeVectorIndices<Vector>()); }
1760 
1761 //------------------------------------------------------------------------------
1762 
1763 
1764 #endif // GARSOFT_UTILITIES_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.
Stored_t & fVector
The vector to manage the coordinate of.
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
vector< T > Vector
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)
static auto compute(Op op, First &&a, Second &&b, Others &&...others) -> decltype(auto)
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()
static constexpr auto XcoordManager
Object that can be bound to a vector to manage its X coordinate.
Point makePointImpl(std::index_sequence< I... >) const
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
GENVECTOR_CONSTEXPR::geo::Vector_t makeVectorFromCoords(Coords &&coords)
Creates a geo::Vector_t from its coordinates (see makeFromCoords()).
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)
typename Vector::Scalar type
Helper class to compute the middle point in a point set.
constexpr auto makeCoordReader(Getter getter)
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >> Point_t
typename Traits_t::Setter_t Setter_t
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()
::geo::Vector_t toVector(Vector const &v)
Convert the specified vector into a geo::Vector_t.
static constexpr auto TcoordManager
std::vector< geo::Vector_t > convertCollToVector(std::vector< Vector > const &coll)
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
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
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.
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.
weight
Definition: test.py:257
void add(Point const &p)
Accumulates a point.
static constexpr auto ZcoordManager< Vector const >
GENVECTOR_CONSTEXPR::geo::Point_t makePointFromCoords(Coords &&coords)
Creates a geo::Point_t from its coordinates (see makeFromCoords()).
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.
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()
constexpr T && constexpr_forward(std::remove_reference_t< T > &t)
T abs(T value)
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.
bool isfinite(Vector const &v)
Returns whether all components of the vector are finite.
typename BaseTypes_t::Vector_t Vector_t
typename Traits_t::Scalar_t Scalar_t
Getter_t fGetter
Member function returning the coordinate value.
void add(BeginIter begin, EndIter end)
Adds a sequence of points.
bool empty() const
Returns whether the total weight is zero (usually means no points).
typename BaseTypes_t::Vector_t Vector_t
void incr(Vector_t &v, Scalar_t c) const
Increments the coordinate by the specified amount.
T roundValue01(T value, T tol)
Returns value, rounded to 0, -1 or +1 if closer than tol.
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)
p
Definition: test.py:223
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(...)
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
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
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()
auto array(Array const &a)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:228
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::vector< geo::Point_t > convertCollToPoint(std::vector< Point > const &coll)
std::make_index_sequence< Dim > IndexSequence_t
static constexpr auto TcoordManager< Vector const >
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.
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.
Setter_t fSetter
Member function setting the coordinate value.
static bool * b
Definition: config.cpp:1043
MiddlePointAccumulatorDim()
Default constructor: starts with no accumulated point.
Helper class for read of a single vector coordinate.
std::array< Length_t, Dim > fSums
Sum of each of the point components.
details::VectorScalar_t< Vector > coordinate_t
Type of coordinate of the specified vector type.
constexpr Vector makeFromCoords(Coords &&coords)
Creates a Vector object with coordinates from coords.
static constexpr bool TestT(...)
std::make_index_sequence< dimension< Vector >()> VectorIndices_t
Type of sequence of indices up to Vector size.
Vector cross(Vector const &a, Vector const &b)
Return cross product of two vectors.
Vector normalize(Vector const &v)
Returns a vector parallel to v and with norm 1.
Dest convertTo(Source const &v)
Returns a vector of type Dest with the same content as a Src.
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.
decltype(details::makeCoordManager(&Vector::X,&Vector::SetX)) CoordManager_t
Type of a coordinate manager for a vector type.
LArSoft geometry interface.
Definition: ChannelGeo.h:16
recob::tracking::Vector_t Vector_t
geo::Point_t middlePoint(BeginIter begin, EndIter end)
Returns the middle of the specified points.
constexpr CoordManager_t< Vector > NoCoordManager
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())*)