HerdSoftware  0.3.2
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 
12 #include "common/CooArray.h"
13 #include "common/RefFrame.h"
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 
43  : CooArray<float>(std::numeric_limits<float>::max(), std::numeric_limits<float>::max(),
44  std::numeric_limits<float>::max()) {}
45 
51  Vec3D(float x, float y, float z) : CooArray<float>(x, y, z) {}
52 
58  Vec3D(std::array<float, 3> arr) : CooArray(std::forward<std::array<float, 3>>(arr)) {}
59 
64  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  float Mag() const { return std::sqrt((*this) * (*this)); }
119 
128  Vec3D CrossProduct(const Vec3D &rhs) {
129  float a = (*this)[RefFrame::Coo::Y] * rhs[RefFrame::Coo::Z] - (*this)[RefFrame::Coo::Z] * rhs[RefFrame::Coo::Y];
130  float b = (*this)[RefFrame::Coo::Z] * rhs[RefFrame::Coo::X] - (*this)[RefFrame::Coo::X] * rhs[RefFrame::Coo::Z];
131  float c = (*this)[RefFrame::Coo::X] * rhs[RefFrame::Coo::Y] - (*this)[RefFrame::Coo::Y] * rhs[RefFrame::Coo::X];
132  Vec3D product(a, b, c);
133  return product;
134  }
135 
137  class UndefinedAngle : public Exception {
138  public:
139  using Exception::Exception;
140  };
141 
147  float PolarAngle() const {
148  // polar is always defined in the [0, M_PI) range
149  return M_PI - std::acos(static_cast<double>((*this)[RefFrame::Coo::Z] / Mag()));
150  }
151 
157  float AzimuthAngle() const {
158  if (PolarAngle() == 0.0f || std::fabs(PolarAngle() - M_PI) < std::numeric_limits<float>::epsilon())
159  throw UndefinedAngle("Vec3D::AzimuthAngle is undefined when polar == 0 or pi");
160  return std::atan2((*this)[RefFrame::Coo::Y], (*this)[RefFrame::Coo::X]);
161  }
162 
167  Vec3D &operator+=(Vec3D const &right) {
168  (*this)[RefFrame::Coo::X] += right[RefFrame::Coo::X];
169  (*this)[RefFrame::Coo::Y] += right[RefFrame::Coo::Y];
170  (*this)[RefFrame::Coo::Z] += right[RefFrame::Coo::Z];
171 
172  return *this;
173  };
174  Vec3D &operator+=(Vec3D &&right) {
175  (*this)[RefFrame::Coo::X] += right[RefFrame::Coo::X];
176  (*this)[RefFrame::Coo::Y] += right[RefFrame::Coo::Y];
177  (*this)[RefFrame::Coo::Z] += right[RefFrame::Coo::Z];
178 
179  return *this;
180  };
181 
186  Vec3D operator-(Vec3D const &right) const {
187  Vec3D retValue;
188  retValue[RefFrame::Coo::X] = (*this)[RefFrame::Coo::X] - right[RefFrame::Coo::X];
189  retValue[RefFrame::Coo::Y] = (*this)[RefFrame::Coo::Y] - right[RefFrame::Coo::Y];
190  retValue[RefFrame::Coo::Z] = (*this)[RefFrame::Coo::Z] - right[RefFrame::Coo::Z];
191 
192  return retValue;
193  };
194 
199  Vec3D &operator-=(Vec3D const &right) {
200  (*this)[RefFrame::Coo::X] -= right[RefFrame::Coo::X];
201  (*this)[RefFrame::Coo::Y] -= right[RefFrame::Coo::Y];
202  (*this)[RefFrame::Coo::Z] -= right[RefFrame::Coo::Z];
203 
204  return *this;
205  };
206  Vec3D &operator-=(Vec3D &&right) {
207  (*this)[RefFrame::Coo::X] -= right[RefFrame::Coo::X];
208  (*this)[RefFrame::Coo::Y] -= right[RefFrame::Coo::Y];
209  (*this)[RefFrame::Coo::Z] -= right[RefFrame::Coo::Z];
210 
211  return *this;
212  };
213 
218  // This neat trick restricts the rhs type to be a number (bool is also viable
219  // but nothing is perfect, right?)
220  template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
221  Vec3D &operator*=(T const &right) {
222  (*this)[RefFrame::Coo::X] *= right;
223  (*this)[RefFrame::Coo::Y] *= right;
224  (*this)[RefFrame::Coo::Z] *= right;
225 
226  return *this;
227  }
228 
229  template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
230  Vec3D &operator*=(T &&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 
242  // This neat trick restricts the rhs type to be a number (bool is also viable
243  // but nothing is perfect, right?)
244  template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
245  Vec3D &operator/=(T const &right) {
246  (*this)[RefFrame::Coo::X] /= right;
247  (*this)[RefFrame::Coo::Y] /= right;
248  (*this)[RefFrame::Coo::Z] /= right;
249 
250  return *this;
251  }
252 
253  template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
254  Vec3D &operator/=(T &&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 
267  bool operator==(const Vec3D &right) const {
268  return (((*this)[RefFrame::Coo::X] == right[RefFrame::Coo::X]) &&
269  ((*this)[RefFrame::Coo::Y] == right[RefFrame::Coo::Y]) &&
270  ((*this)[RefFrame::Coo::Z] == right[RefFrame::Coo::Z]));
271  }
272 };
273 
278 // VF: Check here for this neat trick to enable move semantics:
279 // https://stackoverflow.com/questions/9851188/does-it-make-sense-to-use-move-semantics-for-operator-and-or-operator
280 inline Vec3D operator+(Vec3D left, Vec3D const &right) {
281  left += right;
282  return left;
283 }
284 inline Vec3D operator+(const Vec3D &left, Vec3D &&right) {
285  right += left;
286  return std::move(right);
287 }
288 
293 // This neat trick restricts the rhs type to be a number (bool is also viable
294 // but nothing is perfect, right?)
295 template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
296 inline Vec3D operator*(Vec3D left, T const &right) {
297  left *= right;
298  return left;
299 }
300 
301 // symmetrization
302 template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
303 inline Vec3D operator*(T const &right, Vec3D left) {
304  return left * right;
305 }
306 
311 // This neat trick restricts the rhs type to be a number (bool is also viable
312 // but nothing is perfect, right?)
313 template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
314 inline Vec3D operator/(Vec3D left, T const &right) {
315  left /= right;
316  return left;
317 }
318 
319 // symmetrization
320 template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
321 inline Vec3D operator/(T const &right, Vec3D left) {
322  return left / right;
323 }
324 
329 inline float operator*(const Vec3D left, const Vec3D right) {
330  return (left[RefFrame::Coo::X] * right[RefFrame::Coo::X] + left[RefFrame::Coo::Y] * right[RefFrame::Coo::Y] +
331  left[RefFrame::Coo::Z] * right[RefFrame::Coo::Z]);
332 }
333 
336 std::ostream &operator<<(std::ostream &os, const Vec3D &vec) {
337  os << "( " << vec[RefFrame::Coo::X] << ", " << vec[RefFrame::Coo::Y] << ", " << vec[RefFrame::Coo::Z] << " )";
338  return os;
339 }
340 } // namespace Herd
341 
342 #endif
CssGeoParams.h CssGeoParams class declaration.
Definition: CaloPDCalibrationAlgo.h:24
Vec3D & operator-=(Vec3D &&right)
Definition: Vec3D.h:206
An array that accepts coordinates as subscripts.
Definition: CooArray.h:22
friend std::ostream & operator<<(std::ostream &os, const Vec3D &vec)
Write coordinates to stream.
Definition: Vec3D.h:336
Exception(std::string msg="")
Definition: Exception.h:30
float operator*(const Vec3D left, const Vec3D right)
Compute the dot-product between two vectors.
Definition: Vec3D.h:329
Vec3D & operator*=(T &&right)
Definition: Vec3D.h:230
Vec3D & operator*=(T const &right)
Multiply a vector by a number.
Definition: Vec3D.h:221
Vec3D & operator+=(Vec3D &&right)
Definition: Vec3D.h:174
Vec3D & operator+=(Vec3D const &right)
Add a vector to this one.
Definition: Vec3D.h:167
Vec3D & operator/=(T &&right)
Definition: Vec3D.h:254
float PolarAngle() const
Compute the polar angle.
Definition: Vec3D.h:147
A class describing a vector in 3D space.
Definition: Vec3D.h:33
Vec3D(float x, float y, float z)
Constructor.
Definition: Vec3D.h:51
Vec3D()
Default constructor.
Definition: Vec3D.h:42
Vec3D CrossProduct(const Vec3D &rhs)
Compute the cross product of two vectors.
Definition: Vec3D.h:128
Vec3D(RefFrame::Direction direction)
Constructs a 3D vector from a given direction.
Definition: Vec3D.h:64
float AzimuthAngle() const
Compute the azimuth angle.
Definition: Vec3D.h:157
Vec3D operator/(Vec3D left, T const &right)
Divide a vector by a number.
Definition: Vec3D.h:314
Vec3D operator-(Vec3D const &right) const
Subtract two vectors.
Definition: Vec3D.h:186
float Mag() const
Compute the vector magnitude.
Definition: Vec3D.h:118
Vec3D(std::array< float, 3 > arr)
Constructor.
Definition: Vec3D.h:58
Definition: Exception.h:24
Vec3D & operator-=(Vec3D const &right)
Subtract a vector from this one.
Definition: Vec3D.h:199
void Dump() const
Dumps the vector components.
Definition: Vec3D.h:111
Vec3D & operator/=(T const &right)
Divide a vector by a number.
Definition: Vec3D.h:245
bool operator==(const Vec3D &right) const
Comparison operator.
Definition: Vec3D.h:267
Exception class for invalid operations on a undefined angle.
Definition: Vec3D.h:137
Vec3D operator+(Vec3D left, Vec3D const &right)
Add two vectors.
Definition: Vec3D.h:280
Direction
Aliases for the six axis directions. RefFrame.h common/RefFrame.h.
Definition: RefFrame.h:57