12 #include <tracking/trackFindingCDC/utilities/EvalVariadic.h>
14 #include <type_traits>
26 namespace TrackFindingCDC {
34 template<
class... ATypes>
50 friend std::ostream&
operator<<(std::ostream& output,
const Box<>& voidBox __attribute__((unused)))
63 template<
class AFirstType,
class... ASubordinaryTypes>
64 class Box<AFirstType, ASubordinaryTypes...> {
67 using FirstType = AFirstType;
70 using This = Box<AFirstType, ASubordinaryTypes...>;
73 using Point = std::tuple<FirstType, ASubordinaryTypes...>;
76 using Delta = std::tuple < decltype(FirstType() - FirstType()),
77 decltype(ASubordinaryTypes() - ASubordinaryTypes())... >;
80 template<std::
size_t I>
81 using Type =
typename std::tuple_element<I, Point>::type;
92 template<std::
size_t I>
93 using Width =
typename std::tuple_element<I, Delta>::type;
96 static const size_t c_nTypes = std::tuple_size<Point>::value;
99 using Indices = std::make_index_sequence<c_nTypes>;
102 Box(
const std::array<FirstType, 2>& firstBound,
103 const std::array<ASubordinaryTypes, 2>& ... subordinaryBounds)
105 std::min(firstBound[0], firstBound[1]),
106 std::max(firstBound[1], firstBound[0])}}
107 , m_subordinaryBox(subordinaryBounds...)
112 friend std::ostream&
operator<<(std::ostream& output,
const This& box)
121 void setBounds(std::array<FirstType, 2> firstBounds,
122 std::array<ASubordinaryTypes, 2>... subordinaryBounds)
124 m_firstBounds[0] = std::min(firstBounds[0], firstBounds[1]);
125 m_firstBounds[1] = std::max(firstBounds[0], firstBounds[1]);
126 m_subordinaryBox.setBounds(subordinaryBounds...);
130 const Box<ASubordinaryTypes...>& getSubordinaryBox()
const
132 return m_subordinaryBox;
136 template<std::
size_t I>
137 const std::enable_if_t<I == 0, Type<I> >& getLowerBound()
const
139 return m_firstBounds[0];
143 template<std::
size_t I>
144 const std::enable_if_t < I != 0, Type<I> > & getLowerBound()
const
146 static_assert(I < c_nTypes,
147 "Accessed index exceeds number of coordinates");
148 return m_subordinaryBox.template getLowerBound < I - 1 > ();
153 const std::enable_if_t<HasType<T>::value, T>& getLowerBound()
const
155 return getLowerBound<TypeIndex<T>::value>();
159 template <std::
size_t I>
160 const std::enable_if_t<I == 0, Type<I>>& getUpperBound()
const
162 return m_firstBounds[1];
166 template<std::
size_t I>
167 const std::enable_if_t < I != 0, Type<I> > & getUpperBound()
const
169 static_assert(I < c_nTypes,
170 "Accessed index exceeds number of coordinates");
171 return m_subordinaryBox.template getUpperBound < I - 1 > ();
176 const std::enable_if_t<HasType<T>::value, T>& getUpperBound()
const
178 return getUpperBound<TypeIndex<T>::value>();
182 template <std::
size_t I>
183 const std::enable_if_t<I == 0, std::array<Type<I>, 2>>& getBounds()
const
185 return m_firstBounds;
189 template <std::
size_t I>
190 const std::enable_if_t < I != 0, std::array<Type<I>, 2 >>& getBounds()
const
192 static_assert(I < c_nTypes,
"Accessed index exceeds number of coordinates");
193 return m_subordinaryBox.template getBounds < I - 1 > ();
198 const std::enable_if_t<HasType<T>::value, std::array<T, 2>>&
getBounds()
const
200 return getBounds<TypeIndex<T>::value>();
204 template <std::
size_t I>
205 Width<I> getWidth()
const
207 return getUpperBound<I>() - getLowerBound<I>();
212 template<std::
size_t I>
213 Type<I> getDivision(
size_t nDivisions,
size_t iDivision)
const
215 assert(nDivisions >= iDivision);
216 return Type<I>(getLowerBound<I>() + getWidth<I>() * iDivision / nDivisions);
220 template<std::
size_t I>
221 std::array<Type<I>, 2 >
222 getDivisionBounds(
size_t nDivisions,
size_t iDivision)
const
224 assert(nDivisions > iDivision);
225 return {{getDivision<I>(nDivisions, iDivision), getDivision<I>(nDivisions, iDivision + 1)}};
229 template <std::
size_t I>
232 return (getWidth<I>() + (nDivisions - 1) * overlap) / nDivisions;
248 template<std::
size_t I>
250 getLowerDivisionBoundWithOverlap(
const Width<I>& overlap,
252 size_t iDivision)
const
254 assert(nDivisions >= iDivision);
255 return Type<I>(getLowerBound<I>() + (getWidth<I>() - overlap) * iDivision / nDivisions);
271 template<std::
size_t I>
273 getUpperDivisionBoundWithOverlap(
const Width<I>& overlap,
275 size_t iDivision)
const
277 assert(nDivisions >= iDivision);
278 return Type<I>(getUpperBound<I>() - (getWidth<I>() - overlap) * (nDivisions - iDivision - 1) / nDivisions);
295 template<std::
size_t I>
296 std::array<Type<I>, 2 >
297 getDivisionBoundsWithOverlap(
const Width<I>& overlap,
299 size_t iDivision)
const
301 assert(nDivisions > iDivision);
303 getLowerDivisionBoundWithOverlap<I>(overlap, nDivisions, iDivision),
304 getUpperDivisionBoundWithOverlap<I>(overlap, nDivisions, iDivision)
309 template <std::
size_t I>
310 Type<I> getCenter()
const
312 return getDivision<I>(2, 1);
316 template <std::
size_t I>
317 std::array<Type<I>, 2> getLowerHalfBounds()
const
319 return getDivisionBounds(2, 0);
323 template <std::
size_t I>
324 std::array<Type<I>, 2> getUpperHalfBounds()
const
326 return getDivisionBounds(2, 1);
330 template <std::
size_t I,
class ASubordinaryValue>
331 bool isIn(
const ASubordinaryValue& value)
const
333 return getLowerBound<I>() < value and not(getUpperBound<I>() < value);
338 static bool any(
const std::initializer_list<bool>& booleans)
340 return std::accumulate(std::begin(booleans), std::end(booleans),
341 false, [](
const bool & lhs,
const bool & rhs) {
return lhs or rhs;});
346 static bool all(
const std::initializer_list<bool>& booleans)
348 return std::accumulate(std::begin(booleans), std::end(booleans),
349 true, [](
const bool & lhs,
const bool & rhs) {
return lhs and rhs;});
361 template <
size_t... Is>
362 bool intersectsImpl(
const This& box,
363 std::index_sequence<Is...> is __attribute__((unused)))
const
365 return not(any({box.getUpperBound<Is>() < this->getLowerBound<Is>()... }) or
366 any({this->getUpperBound<Is>() < box.getLowerBound<Is>()... }));
373 template <
size_t... Is>
374 bool isInImpl(
const Point& point,
375 std::index_sequence<Is...> is __attribute__((unused)))
const
377 return not all({isIn<Is>(std::get<Is>(point))...});
382 bool intersects(
const This& box)
const
384 return intersectsImpl(box,
Indices());
388 bool isIn(
const Point& point)
const
394 bool isIn(
const FirstType& value,
const ASubordinaryTypes& ... values)
const
401 std::array<FirstType, 2> m_firstBounds;
404 Box<ASubordinaryTypes... > m_subordinaryBox;