HerdSoftware  0.4.0
Vec3D.h
Go to the documentation of this file.
1 /*
2  * Vec3D.h
3  *
4  * Created on: 18 Mar 2019
5  * Author: Valerio Formato
6  */
7 
9 #ifndef HERD_VEC3D_H_
10 #define HERD_VEC3D_H_
11 
14 
15 #include <array>
16 #include <cmath>
17 #include <iostream>
18 #include <limits>
19 #include <type_traits>
20 
21 namespace Herd {
22 
23 class Vec3D;
24 inline float operator*(const Vec3D left, const Vec3D right);
25 
33 class Vec3D : public CooArray<float> {
34 public:
35  friend inline std::ostream &operator<<(std::ostream &os, const Vec3D &vec);
36 
42  constexpr Vec3D()
43  : CooArray<float>(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(),
44  std::numeric_limits<float>::max()) {}
45 
51  constexpr Vec3D(float x, float y, float z) : CooArray<float>(x, y, z) {}
52 
58  constexpr Vec3D(std::array<float, 3> arr) : CooArray(std::forward<std::array<float, 3>>(arr)) {}
59 
64  constexpr Vec3D(RefFrame::Direction direction) : CooArray<float>(0, 0, 0) {
65  switch (direction) {
67  (*this)[RefFrame::Coo::X] = 1;
68  break;
70  (*this)[RefFrame::Coo::X] = -1;
71  break;
73  (*this)[RefFrame::Coo::Y] = 1;
74  break;
76  (*this)[RefFrame::Coo::Y] = -1;
77  break;
79  (*this)[RefFrame::Coo::Z] = 1;
80  break;
82  (*this)[RefFrame::Coo::Z] = -1;
83  break;
85  (*this)[RefFrame::Coo::X] = 1;
86  (*this)[RefFrame::Coo::Y] = 1;
87  (*this) /= this->Mag();
88  break;
90  (*this)[RefFrame::Coo::X] = 1;
91  (*this)[RefFrame::Coo::Y] = -1;
92  (*this) /= this->Mag();
93  break;
95  (*this)[RefFrame::Coo::X] = -1;
96  (*this)[RefFrame::Coo::Y] = 1;
97  (*this) /= this->Mag();
98  break;
100  (*this)[RefFrame::Coo::X] = -1;
101  (*this)[RefFrame::Coo::Y] = -1;
102  (*this) /= this->Mag();
103  break;
104  default:
105  break;
106  }
107  }
108 
111  void Dump() const { std::cout << *this << std::endl; }
112 
118  [[nodiscard]] float Mag() const { return std::sqrt((*this) * (*this)); }
119 
124  [[nodiscard]] Vec3D UnitVector() const {
125  Vec3D result = *this;
126  return result /= Mag();
127  }
128 
137  [[nodiscard]] constexpr Vec3D CrossProduct(const Vec3D &rhs) const {
138  float a = (*this)[RefFrame::Coo::Y] * rhs[RefFrame::Coo::Z] - (*this)[RefFrame::Coo::Z] * rhs[RefFrame::Coo::Y];
139  float b = (*this)[RefFrame::Coo::Z] * rhs[RefFrame::Coo::X] - (*this)[RefFrame::Coo::X] * rhs[RefFrame::Coo::Z];
140  float c = (*this)[RefFrame::Coo::X] * rhs[RefFrame::Coo::Y] - (*this)[RefFrame::Coo::Y] * rhs[RefFrame::Coo::X];
141  Vec3D product(a, b, c);
142  return product;
143  }
144 
146  class UndefinedAngle : public Exception {
147  public:
148  using Exception::Exception;
149  };
150 
156  [[nodiscard]] float PolarAngle() const {
157  // polar is always defined in the [0, M_PI) range
158  return M_PI - std::acos(static_cast<double>((*this)[RefFrame::Coo::Z] / Mag()));
159  }
160 
166  [[nodiscard]] float AzimuthAngle() const {
167  if (PolarAngle() == 0.0f || std::fabs(PolarAngle() - M_PI) < std::numeric_limits<float>::epsilon())
168  throw UndefinedAngle("Vec3D::AzimuthAngle is undefined when polar == 0 or pi");
169  return std::atan2((*this)[RefFrame::Coo::Y], (*this)[RefFrame::Coo::X]);
170  }
171 
176  Vec3D &operator+=(Vec3D const &right) {
177  (*this)[RefFrame::Coo::X] += right[RefFrame::Coo::X];
178  (*this)[RefFrame::Coo::Y] += right[RefFrame::Coo::Y];
179  (*this)[RefFrame::Coo::Z] += right[RefFrame::Coo::Z];
180 
181  return *this;
182  };
183  Vec3D &operator+=(Vec3D &&right) {
184  (*this)[RefFrame::Coo::X] += right[RefFrame::Coo::X];
185  (*this)[RefFrame::Coo::Y] += right[RefFrame::Coo::Y];
186  (*this)[RefFrame::Coo::Z] += right[RefFrame::Coo::Z];
187 
188  return *this;
189  };
190 
195  Vec3D operator-(Vec3D const &right) const {
196  Vec3D retValue;
197  retValue[RefFrame::Coo::X] = (*this)[RefFrame::Coo::X] - right[RefFrame::Coo::X];
198  retValue[RefFrame::Coo::Y] = (*this)[RefFrame::Coo::Y] - right[RefFrame::Coo::Y];
199  retValue[RefFrame::Coo::Z] = (*this)[RefFrame::Coo::Z] - right[RefFrame::Coo::Z];
200 
201  return retValue;
202  };
203 
208  Vec3D &operator-=(Vec3D const &right) {
209  (*this)[RefFrame::Coo::X] -= right[RefFrame::Coo::X];
210  (*this)[RefFrame::Coo::Y] -= right[RefFrame::Coo::Y];
211  (*this)[RefFrame::Coo::Z] -= right[RefFrame::Coo::Z];
212 
213  return *this;
214  };
215  Vec3D &operator-=(Vec3D &&right) {
216  (*this)[RefFrame::Coo::X] -= right[RefFrame::Coo::X];
217  (*this)[RefFrame::Coo::Y] -= right[RefFrame::Coo::Y];
218  (*this)[RefFrame::Coo::Z] -= right[RefFrame::Coo::Z];
219 
220  return *this;
221  };
222 
227  // This neat trick restricts the rhs type to be a number (bool is also viable
228  // but nothing is perfect, right?)
229  template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
230  Vec3D &operator*=(T const &right) {
231  (*this)[RefFrame::Coo::X] *= right;
232  (*this)[RefFrame::Coo::Y] *= right;
233  (*this)[RefFrame::Coo::Z] *= right;
234 
235  return *this;
236  }
237 
238  template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
239  Vec3D &operator*=(T &&right) {
240  (*this)[RefFrame::Coo::X] *= right;
241  (*this)[RefFrame::Coo::Y] *= right;
242  (*this)[RefFrame::Coo::Z] *= right;
243 
244  return *this;
245  }
246 
251  // This neat trick restricts the rhs type to be a number (bool is also viable
252  // but nothing is perfect, right?)
253  template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
254  Vec3D &operator/=(T const &right) {
255  (*this)[RefFrame::Coo::X] /= right;
256  (*this)[RefFrame::Coo::Y] /= right;
257  (*this)[RefFrame::Coo::Z] /= right;
258 
259  return *this;
260  }
261 
262  template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
263  Vec3D &operator/=(T &&right) {
264  (*this)[RefFrame::Coo::X] /= right;
265  (*this)[RefFrame::Coo::Y] /= right;
266  (*this)[RefFrame::Coo::Z] /= right;
267 
268  return *this;
269  }
270 
276  bool operator==(const Vec3D &right) const {
277  return (((*this)[RefFrame::Coo::X] == right[RefFrame::Coo::X]) &&
278  ((*this)[RefFrame::Coo::Y] == right[RefFrame::Coo::Y]) &&
279  ((*this)[RefFrame::Coo::Z] == right[RefFrame::Coo::Z]));
280  }
281 };
282 
287 // VF: Check here for this neat trick to enable move semantics:
288 // https://stackoverflow.com/questions/9851188/does-it-make-sense-to-use-move-semantics-for-operator-and-or-operator
289 inline Vec3D operator+(Vec3D left, Vec3D const &right) {
290  left += right;
291  return left;
292 }
293 inline Vec3D operator+(const Vec3D &left, Vec3D &&right) {
294  right += left;
295  return std::move(right);
296 }
297 
302 // This neat trick restricts the rhs type to be a number (bool is also viable
303 // but nothing is perfect, right?)
304 template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
305 inline Vec3D operator*(Vec3D left, T const &right) {
306  left *= right;
307  return left;
308 }
309 
310 // symmetrization
311 template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
312 inline Vec3D operator*(T const &right, Vec3D left) {
313  return left * right;
314 }
315 
320 // This neat trick restricts the rhs type to be a number (bool is also viable
321 // but nothing is perfect, right?)
322 template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
323 inline Vec3D operator/(Vec3D left, T const &right) {
324  left /= right;
325  return left;
326 }
327 
328 // symmetrization
329 template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
330 inline Vec3D operator/(T const &right, Vec3D left) {
331  return left / right;
332 }
333 
338 inline float operator*(const Vec3D left, const Vec3D right) {
339  return (left[RefFrame::Coo::X] * right[RefFrame::Coo::X] + left[RefFrame::Coo::Y] * right[RefFrame::Coo::Y] +
340  left[RefFrame::Coo::Z] * right[RefFrame::Coo::Z]);
341 }
342 
345 std::ostream &operator<<(std::ostream &os, const Vec3D &vec) {
346  os << "( " << vec[RefFrame::Coo::X] << ", " << vec[RefFrame::Coo::Y] << ", " << vec[RefFrame::Coo::Z] << " )";
347  return os;
348 }
349 } // namespace Herd
350 
351 #endif
Herd::Vec3D::Mag
float Mag() const
Compute the vector magnitude.
Definition: Vec3D.h:118
Herd::RefFrame::Coo::Y
@ Y
Herd::Vec3D::operator+=
Vec3D & operator+=(Vec3D const &right)
Add a vector to this one.
Definition: Vec3D.h:176
Herd::RefFrame::Direction::Yneg
@ Yneg
Herd::operator*
float operator*(const Vec3D left, const Vec3D right)
Compute the dot-product between two vectors.
Definition: Vec3D.h:338
Herd::Vec3D
A class describing a vector in 3D space.
Definition: Vec3D.h:33
Herd::Vec3D::Dump
void Dump() const
Dumps the vector components.
Definition: Vec3D.h:111
Herd::RefFrame::Coo::X
@ X
Herd::CooArray
An array that accepts coordinates as subscripts.
Definition: CooArray.h:22
Herd::RefFrame::Direction::Zneg
@ Zneg
Herd::RefFrame::Direction::XposYpos
@ XposYpos
Herd::RefFrame::Direction::Xneg
@ Xneg
Herd::Vec3D::Vec3D
constexpr Vec3D(RefFrame::Direction direction)
Constructs a 3D vector from a given direction.
Definition: Vec3D.h:64
Herd::Vec3D::Vec3D
constexpr Vec3D()
Default constructor.
Definition: Vec3D.h:42
Herd::Vec3D::operator/=
Vec3D & operator/=(T &&right)
Definition: Vec3D.h:263
Herd::Vec3D::AzimuthAngle
float AzimuthAngle() const
Compute the azimuth angle.
Definition: Vec3D.h:166
Herd::RefFrame::Direction::XnegYpos
@ XnegYpos
Herd::Vec3D::operator-=
Vec3D & operator-=(Vec3D &&right)
Definition: Vec3D.h:215
Herd::RefFrame::Direction
Direction
Aliases for the six axis directions.
Definition: RefFrame.h:55
Herd::Exception::Exception
Exception(std::string msg="")
Definition: Exception.h:30
Herd
CssGeoParams.h CssGeoParams class declaration.
Definition: CaloPDCalibrationAlgo.h:22
Herd::RefFrame::Direction::Zpos
@ Zpos
Herd::operator<<
std::ostream & operator<<(std::ostream &os, const Vec3D &vec)
Write coordinates to stream.
Definition: Vec3D.h:345
Herd::RefFrame::Direction::Xpos
@ Xpos
Herd::Vec3D::operator<<
friend std::ostream & operator<<(std::ostream &os, const Vec3D &vec)
Write coordinates to stream.
Definition: Vec3D.h:345
CooArray.h
Herd::Vec3D::CrossProduct
constexpr Vec3D CrossProduct(const Vec3D &rhs) const
Compute the cross product of two vectors.
Definition: Vec3D.h:137
Herd::Vec3D::PolarAngle
float PolarAngle() const
Compute the polar angle.
Definition: Vec3D.h:156
RefFrame.h
Herd::Vec3D::UndefinedAngle
Exception class for invalid operations on a undefined angle.
Definition: Vec3D.h:146
Herd::RefFrame::Direction::Ypos
@ Ypos
Herd::Vec3D::operator*=
Vec3D & operator*=(T &&right)
Definition: Vec3D.h:239
Herd::RefFrame::Direction::XnegYneg
@ XnegYneg
Herd::RefFrame::Coo::Z
@ Z
Herd::Vec3D::operator==
bool operator==(const Vec3D &right) const
Comparison operator.
Definition: Vec3D.h:276
Herd::Vec3D::Vec3D
constexpr Vec3D(float x, float y, float z)
Constructor.
Definition: Vec3D.h:51
Herd::Vec3D::operator-=
Vec3D & operator-=(Vec3D const &right)
Subtract a vector from this one.
Definition: Vec3D.h:208
Herd::Exception
Definition: Exception.h:24
Herd::RefFrame::Direction::XposYneg
@ XposYneg
Herd::Vec3D::operator*=
Vec3D & operator*=(T const &right)
Multiply a vector by a number.
Definition: Vec3D.h:230
Herd::Vec3D::UnitVector
Vec3D UnitVector() const
Return this vector, but normalized to unit length.
Definition: Vec3D.h:124
Herd::operator/
Vec3D operator/(Vec3D left, T const &right)
Divide a vector by a number.
Definition: Vec3D.h:323
Herd::Vec3D::operator/=
Vec3D & operator/=(T const &right)
Divide a vector by a number.
Definition: Vec3D.h:254
Herd::Vec3D::Vec3D
constexpr Vec3D(std::array< float, 3 > arr)
Constructor.
Definition: Vec3D.h:58
Herd::Vec3D::operator+=
Vec3D & operator+=(Vec3D &&right)
Definition: Vec3D.h:183
Herd::operator+
Vec3D operator+(Vec3D left, Vec3D const &right)
Add two vectors.
Definition: Vec3D.h:289
Herd::Vec3D::operator-
Vec3D operator-(Vec3D const &right) const
Subtract two vectors.
Definition: Vec3D.h:195