HerdSoftware  0.1.1
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 
141  float PolarAngle() const { return M_PI - std::acos((*this)[RefFrame::Coo::Z] / Mag()); }
142 
148  float AzimuthAngle() const { return std::atan2((*this)[RefFrame::Coo::Y], (*this)[RefFrame::Coo::X]); }
149 
154  Vec3D &operator+=(Vec3D const &right) {
155  (*this)[RefFrame::Coo::X] += right[RefFrame::Coo::X];
156  (*this)[RefFrame::Coo::Y] += right[RefFrame::Coo::Y];
157  (*this)[RefFrame::Coo::Z] += right[RefFrame::Coo::Z];
158 
159  return *this;
160  };
161  Vec3D &operator+=(Vec3D &&right) {
162  (*this)[RefFrame::Coo::X] += right[RefFrame::Coo::X];
163  (*this)[RefFrame::Coo::Y] += right[RefFrame::Coo::Y];
164  (*this)[RefFrame::Coo::Z] += right[RefFrame::Coo::Z];
165 
166  return *this;
167  };
168 
173  Vec3D operator-(Vec3D const &right) const {
174  Vec3D retValue;
175  retValue[RefFrame::Coo::X] = (*this)[RefFrame::Coo::X] - right[RefFrame::Coo::X];
176  retValue[RefFrame::Coo::Y] = (*this)[RefFrame::Coo::Y] - right[RefFrame::Coo::Y];
177  retValue[RefFrame::Coo::Z] = (*this)[RefFrame::Coo::Z] - right[RefFrame::Coo::Z];
178 
179  return retValue;
180  };
181 
186  Vec3D &operator-=(Vec3D const &right) {
187  (*this)[RefFrame::Coo::X] -= right[RefFrame::Coo::X];
188  (*this)[RefFrame::Coo::Y] -= right[RefFrame::Coo::Y];
189  (*this)[RefFrame::Coo::Z] -= right[RefFrame::Coo::Z];
190 
191  return *this;
192  };
193  Vec3D &operator-=(Vec3D &&right) {
194  (*this)[RefFrame::Coo::X] -= right[RefFrame::Coo::X];
195  (*this)[RefFrame::Coo::Y] -= right[RefFrame::Coo::Y];
196  (*this)[RefFrame::Coo::Z] -= right[RefFrame::Coo::Z];
197 
198  return *this;
199  };
200 
205  // This neat trick restricts the rhs type to be a number (bool is also viable
206  // but nothing is perfect, right?)
207  template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
208  Vec3D &operator*=(T const &right) {
209  (*this)[RefFrame::Coo::X] *= right;
210  (*this)[RefFrame::Coo::Y] *= right;
211  (*this)[RefFrame::Coo::Z] *= right;
212 
213  return *this;
214  }
215 
216  template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
217  Vec3D &operator*=(T &&right) {
218  (*this)[RefFrame::Coo::X] *= right;
219  (*this)[RefFrame::Coo::Y] *= right;
220  (*this)[RefFrame::Coo::Z] *= right;
221 
222  return *this;
223  }
224 
229  // This neat trick restricts the rhs type to be a number (bool is also viable
230  // but nothing is perfect, right?)
231  template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
232  Vec3D &operator/=(T const &right) {
233  (*this)[RefFrame::Coo::X] /= right;
234  (*this)[RefFrame::Coo::Y] /= right;
235  (*this)[RefFrame::Coo::Z] /= right;
236 
237  return *this;
238  }
239 
240  template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
241  Vec3D &operator/=(T &&right) {
242  (*this)[RefFrame::Coo::X] /= right;
243  (*this)[RefFrame::Coo::Y] /= right;
244  (*this)[RefFrame::Coo::Z] /= right;
245 
246  return *this;
247  }
248 
254  bool operator==(const Vec3D &right) const {
255  return (((*this)[RefFrame::Coo::X] == right[RefFrame::Coo::X]) &&
256  ((*this)[RefFrame::Coo::Y] == right[RefFrame::Coo::Y]) &&
257  ((*this)[RefFrame::Coo::Z] == right[RefFrame::Coo::Z]));
258  }
259 };
260 
265 // VF: Check here for this neat trick to enable move semantics:
266 // https://stackoverflow.com/questions/9851188/does-it-make-sense-to-use-move-semantics-for-operator-and-or-operator
267 inline Vec3D operator+(Vec3D left, Vec3D const &right) {
268  left += right;
269  return left;
270 }
271 inline Vec3D operator+(const Vec3D &left, Vec3D &&right) {
272  right += left;
273  return std::move(right);
274 }
275 
280 // This neat trick restricts the rhs type to be a number (bool is also viable
281 // but nothing is perfect, right?)
282 template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
283 inline Vec3D operator*(Vec3D left, T const &right) {
284  left *= right;
285  return left;
286 }
287 
288 // symmetrization
289 template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
290 inline Vec3D operator*(T const &right, Vec3D left) {
291  return left * right;
292 }
293 
298 // This neat trick restricts the rhs type to be a number (bool is also viable
299 // but nothing is perfect, right?)
300 template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
301 inline Vec3D operator/(Vec3D left, T const &right) {
302  left /= right;
303  return left;
304 }
305 
306 // symmetrization
307 template <typename T, typename std::enable_if<std::is_arithmetic<T>::value>::type * = nullptr>
308 inline Vec3D operator/(T const &right, Vec3D left) {
309  return left / right;
310 }
311 
316 inline float operator*(const Vec3D left, const Vec3D right) {
317  return (left[RefFrame::Coo::X] * right[RefFrame::Coo::X] + left[RefFrame::Coo::Y] * right[RefFrame::Coo::Y] +
318  left[RefFrame::Coo::Z] * right[RefFrame::Coo::Z]);
319 }
320 
323 std::ostream &operator<<(std::ostream &os, const Vec3D &vec) {
324  os << "( " << vec[RefFrame::Coo::X] << ", " << vec[RefFrame::Coo::Y] << ", " << vec[RefFrame::Coo::Z] << " )";
325  return os;
326 }
327 } // namespace Herd
328 
329 #endif
CssGeoParams.h CssGeoParams class declaration.
Definition: CaloPDCalibrationAlgo.h:24
Vec3D & operator-=(Vec3D &&right)
Definition: Vec3D.h:193
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:323
float operator*(const Vec3D left, const Vec3D right)
Compute the dot-product between two vectors.
Definition: Vec3D.h:316
Vec3D & operator*=(T &&right)
Definition: Vec3D.h:217
Vec3D & operator*=(T const &right)
Multiply a vector by a number.
Definition: Vec3D.h:208
Vec3D & operator+=(Vec3D &&right)
Definition: Vec3D.h:161
Vec3D & operator+=(Vec3D const &right)
Add a vector to this one.
Definition: Vec3D.h:154
Vec3D & operator/=(T &&right)
Definition: Vec3D.h:241
float PolarAngle() const
Compute the polar angle.
Definition: Vec3D.h:141
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:148
Vec3D operator/(Vec3D left, T const &right)
Divide a vector by a number.
Definition: Vec3D.h:301
Vec3D operator-(Vec3D const &right) const
Subtract two vectors.
Definition: Vec3D.h:173
float Mag() const
Compute the vector magnitude.
Definition: Vec3D.h:118
Vec3D(std::array< float, 3 > arr)
Constructor.
Definition: Vec3D.h:58
Vec3D & operator-=(Vec3D const &right)
Subtract a vector from this one.
Definition: Vec3D.h:186
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:232
bool operator==(const Vec3D &right) const
Comparison operator.
Definition: Vec3D.h:254
Vec3D operator+(Vec3D left, Vec3D const &right)
Add two vectors.
Definition: Vec3D.h:267
Direction
Aliases for the six axis directions. RefFrame.h common/RefFrame.h.
Definition: RefFrame.h:52