Physical Quantities  v1.0.0
C++ library of physical quantities, physical models, and units of measure for scientific computing. https://github.com/acodcha/phq
PlanarVector.hpp
Go to the documentation of this file.
1 // Copyright © 2020-2024 Alexandre Coderre-Chabot
2 //
3 // This file is part of Physical Quantities (PhQ), a C++ library of physical quantities, physical
4 // models, and units of measure for scientific computing.
5 //
6 // Physical Quantities is hosted at:
7 // https://github.com/acodcha/phq
8 //
9 // Physical Quantities is licensed under the MIT License:
10 // https://mit-license.org
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
13 // associated documentation files (the "Software"), to deal in the Software without restriction,
14 // including without limitation the rights to use, copy, modify, merge, publish, distribute,
15 // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 // - The above copyright notice and this permission notice shall be included in all copies or
18 // substantial portions of the Software.
19 // - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
20 // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 #ifndef PHQ_PLANAR_VECTOR_HPP
26 #define PHQ_PLANAR_VECTOR_HPP
27 
28 #include <array>
29 #include <cmath>
30 #include <cstddef>
31 #include <functional>
32 #include <ostream>
33 #include <string>
34 #include <type_traits>
35 
36 #include "Base.hpp"
37 
38 namespace PhQ {
39 
40 // Forward declarations for class PhQ::PlanarVector.
41 template <typename NumericType>
42 class Angle;
43 
44 // Forward declaration for class PhQ::PlanarVector.
45 template <typename>
46 class Dyad;
47 
48 // Forward declaration for class PhQ::PlanarVector.
49 template <typename NumericType>
50 class PlanarDirection;
51 
52 // Forward declaration for class PhQ::PlanarVector.
53 template <typename NumericType>
54 class Vector;
55 
56 /// \brief Two-dimensional Euclidean vector in the XY plane. Contains two components in Cartesian
57 /// coordinates: x and y. For a three-dimensional Euclidean vector, see PhQ::Vector. For a
58 /// three-dimensional Euclidean dyadic tensor, see PhQ::Dyad. For a three-dimensional symmetric
59 /// Euclidean dyadic tensor, see PhQ::SymmetricDyad.
60 /// \tparam NumericType Floating-point numeric type: float, double, or long double. Defaults to
61 /// double if unspecified.
62 template <typename NumericType = double>
63 class PlanarVector {
64  static_assert(std::is_floating_point<NumericType>::value,
65  "The NumericType template parameter of PhQ::PlanarVector<NumericType> must be a "
66  "numeric floating-point type: float, double, or long double.");
67 
68 public:
69  /// \brief Default constructor. Constructs a two-dimensional planar vector with uninitialized x
70  /// and y Cartesian components.
71  PlanarVector() = default;
72 
73  /// \brief Constructor. Constructs a two-dimensional planar vector from the given x and y
74  /// Cartesian components.
75  constexpr PlanarVector(const NumericType x, const NumericType y) : x_y_({x, y}) {}
76 
77  /// \brief Constructor. Constructs a two-dimensional planar vector from a given array representing
78  /// its x and y Cartesian components.
79  explicit constexpr PlanarVector(const std::array<NumericType, 2>& x_y) : x_y_(x_y) {}
80 
81  /// \brief Constructor. Constructs a two-dimensional planar vector from a given three-dimensional
82  /// vector. Projects the three-dimensional vector onto the XY plane.
83  explicit constexpr PlanarVector(const Vector<NumericType>& vector);
84 
85  /// \brief Constructor. Constructs a two-dimensional planar vector given a magnitude and a planar
86  /// direction.
87  constexpr PlanarVector(NumericType magnitude, const PlanarDirection<NumericType>& direction);
88 
89  /// \brief Destructor. Destroys this two-dimensional planar vector.
90  ~PlanarVector() noexcept = default;
91 
92  /// \brief Copy constructor. Constructs a two-dimensional planar vector by copying another one.
93  constexpr PlanarVector(const PlanarVector<NumericType>& other) = default;
94 
95  /// \brief Copy constructor. Constructs a two-dimensional planar vector by copying another one.
96  template <typename OtherNumericType>
97  explicit constexpr PlanarVector(const PlanarVector<OtherNumericType>& other)
98  : x_y_({static_cast<NumericType>(other.x()), static_cast<NumericType>(other.y())}) {}
99 
100  /// \brief Move constructor. Constructs a two-dimensional planar vector by moving another one.
101  constexpr PlanarVector(PlanarVector<NumericType>&& other) noexcept = default;
102 
103  /// \brief Copy assignment operator. Assigns this two-dimensional planar vector by copying another
104  /// one.
106 
107  /// \brief Copy assignment operator. Assigns this two-dimensional planar vector by copying another
108  /// one.
109  template <typename OtherNumericType>
111  x_y_[0] = static_cast<NumericType>(other.x());
112  x_y_[1] = static_cast<NumericType>(other.y());
113  return *this;
114  }
115 
116  /// \brief Move assignment operator. Assigns this two-dimensional planar vector by moving another
117  /// one.
119  PlanarVector<NumericType>&& other) noexcept = default;
120 
121  /// \brief Assignment operator. Assigns this two-dimensional planar vector by copying a given
122  /// array representing its x and y Cartesian components.
123  constexpr PlanarVector<NumericType>& operator=(const std::array<NumericType, 2>& x_y) {
124  x_y_ = x_y;
125  return *this;
126  }
127 
128  /// \brief Statically creates a two-dimensional planar vector with its x and y Cartesian
129  /// components initialized to zero.
130  [[nodiscard]] static constexpr PlanarVector<NumericType> Zero() {
132  std::array<NumericType, 2>{static_cast<NumericType>(0), static_cast<NumericType>(0)}
133  };
134  }
135 
136  /// \brief Returns this two-dimensional planar vector's x and y Cartesian components as an array.
137  [[nodiscard]] constexpr const std::array<NumericType, 2>& x_y() const noexcept {
138  return x_y_;
139  }
140 
141  /// \brief Returns this two-dimensional planar vector's x Cartesian component.
142  [[nodiscard]] constexpr NumericType x() const noexcept {
143  return x_y_[0];
144  }
145 
146  /// \brief Returns this two-dimensional planar vector's y Cartesian component.
147  [[nodiscard]] constexpr NumericType y() const noexcept {
148  return x_y_[1];
149  }
150 
151  /// \brief Returns this two-dimensional planar vector's x and y Cartesian components as a mutable
152  /// array.
153  [[nodiscard]] constexpr std::array<NumericType, 2>& Mutable_x_y() noexcept {
154  return x_y_;
155  }
156 
157  /// \brief Returns this two-dimensional planar vector's x Cartesian component as a mutable value.
158  [[nodiscard]] constexpr NumericType& Mutable_x() noexcept {
159  return x_y_[0];
160  }
161 
162  /// \brief Returns this two-dimensional planar vector's y Cartesian component as a mutable value.
163  [[nodiscard]] constexpr NumericType& Mutable_y() noexcept {
164  return x_y_[1];
165  }
166 
167  /// \brief Sets this two-dimensional planar vector's x and y Cartesian components to the given
168  /// values.
169  constexpr void Set_x_y(const std::array<NumericType, 2>& x_y) noexcept {
170  x_y_ = x_y;
171  }
172 
173  /// \brief Sets this two-dimensional planar vector's x and y Cartesian components to the given
174  /// values.
175  constexpr void Set_x_y(const NumericType x, const NumericType y) noexcept {
176  x_y_[0] = x;
177  x_y_[1] = y;
178  }
179 
180  /// \brief Sets this two-dimensional planar vector's x Cartesian component to a given value.
181  constexpr void Set_x(const NumericType x) noexcept {
182  x_y_[0] = x;
183  }
184 
185  /// \brief Sets this two-dimensional planar vector's y Cartesian component to a given value.
186  constexpr void Set_y(const NumericType y) noexcept {
187  x_y_[1] = y;
188  }
189 
190  /// \brief Returns the square of the magnitude of this two-dimensional planar vector.
191  [[nodiscard]] constexpr NumericType MagnitudeSquared() const noexcept {
192  return x_y_[0] * x_y_[0] + x_y_[1] * x_y_[1];
193  }
194 
195  /// \brief Returns the magnitude (also known as the L2 norm) of this two-dimensional planar
196  /// vector.
197  [[nodiscard]] NumericType Magnitude() const noexcept {
198  return std::sqrt(MagnitudeSquared());
199  }
200 
201  /// \brief Returns the planar direction of this two-dimensional planar vector.
203 
204  /// \brief Returns the dot product (also known as the inner product or scalar product) of this
205  /// two-dimensional planar vector and another one.
206  [[nodiscard]] constexpr NumericType Dot(const PlanarVector<NumericType>& other) const noexcept {
207  return x_y_[0] * other.x_y_[0] + x_y_[1] * other.x_y_[1];
208  }
209 
210  /// \brief Returns the dot product (also known as the inner product or scalar product) of this
211  /// two-dimensional planar vector and a given planar direction.
212  [[nodiscard]] constexpr NumericType Dot(
213  const PhQ::PlanarDirection<NumericType>& planar_direction) const noexcept;
214 
215  /// \brief Returns the cross product (also known as the vector product) of this two-dimensional
216  /// planar vector and another one.
217  [[nodiscard]] constexpr Vector<NumericType> Cross(const PlanarVector<NumericType>& other) const;
218 
219  /// \brief Returns the cross product (also known as the vector product) of this two-dimensional
220  /// planar vector and a given planar direction.
221  [[nodiscard]] constexpr Vector<NumericType> Cross(
222  const PhQ::PlanarDirection<NumericType>& planar_direction) const;
223 
224  /// \brief Returns the dyadic tensor product (also known as the outer product) of this
225  /// two-dimensional planar vector and another one.
226  [[nodiscard]] constexpr Dyad<NumericType> Dyadic(const PlanarVector<NumericType>& other) const;
227 
228  /// \brief Returns the dyadic tensor product (also known as the outer product) of this
229  /// two-dimensional planar vector and a given planar direction.
230  [[nodiscard]] constexpr Dyad<NumericType> Dyadic(
231  const PhQ::PlanarDirection<NumericType>& planar_direction) const;
232 
233  /// \brief Returns the angle between this two-dimensional planar vector and another one.
234  [[nodiscard]] PhQ::Angle<NumericType> Angle(const PlanarVector<NumericType>& other) const;
235 
236  /// \brief Returns the angle between this two-dimensional planar vector and a given planar
237  /// direction.
238  [[nodiscard]] PhQ::Angle<NumericType> Angle(
239  const PhQ::PlanarDirection<NumericType>& planar_direction) const;
240 
241  /// \brief Prints this two-dimensional planar vector as a string.
242  [[nodiscard]] std::string Print() const {
243  return "(" + PhQ::Print(x_y_[0]) + ", " + PhQ::Print(x_y_[1]) + ")";
244  }
245 
246  /// \brief Serializes this two-dimensional planar vector as a JSON message.
247  [[nodiscard]] std::string JSON() const {
248  return "{\"x\":" + PhQ::Print(x_y_[0]) + ",\"y\":" + PhQ::Print(x_y_[1]) + "}";
249  }
250 
251  /// \brief Serializes this two-dimensional planar vector as an XML message.
252  [[nodiscard]] std::string XML() const {
253  return "<x>" + PhQ::Print(x_y_[0]) + "</x><y>" + PhQ::Print(x_y_[1]) + "</y>";
254  }
255 
256  /// \brief Serializes this two-dimensional planar vector as a YAML message.
257  [[nodiscard]] std::string YAML() const {
258  return "{x:" + PhQ::Print(x_y_[0]) + ",y:" + PhQ::Print(x_y_[1]) + "}";
259  }
260 
261  /// \brief Adds another two-dimensional planar vector to this one.
262  constexpr void operator+=(const PlanarVector<NumericType>& other) noexcept {
263  x_y_[0] += other.x_y_[0];
264  x_y_[1] += other.x_y_[1];
265  }
266 
267  /// \brief Subtracts another two-dimensional planar vector from this one.
268  constexpr void operator-=(const PlanarVector<NumericType>& other) noexcept {
269  x_y_[0] -= other.x_y_[0];
270  x_y_[1] -= other.x_y_[1];
271  }
272 
273  /// \brief Multiplies this two-dimensional planar vector by the given number.
274  /// \tparam OtherNumericType Floating-point numeric type of the given number. Deduced
275  /// automatically.
276  template <typename OtherNumericType>
277  constexpr void operator*=(const OtherNumericType number) noexcept {
278  x_y_[0] *= static_cast<NumericType>(number);
279  x_y_[1] *= static_cast<NumericType>(number);
280  }
281 
282  /// \brief Divides this two-dimensional planar vector by the given number.
283  /// \tparam OtherNumericType Floating-point numeric type of the given number. Deduced
284  /// automatically.
285  template <typename OtherNumericType>
286  constexpr void operator/=(const OtherNumericType number) noexcept {
287  x_y_[0] /= static_cast<NumericType>(number);
288  x_y_[1] /= static_cast<NumericType>(number);
289  }
290 
291 private:
292  /// \brief Cartesian components of this two-dimensional planar vector.
293  std::array<NumericType, 2> x_y_;
294 };
295 
296 template <typename NumericType>
297 inline constexpr bool operator==(
298  const PlanarVector<NumericType>& left, const PlanarVector<NumericType>& right) noexcept {
299  return left.x() == right.x() && left.y() == right.y();
300 }
301 
302 template <typename NumericType>
303 inline constexpr bool operator!=(
304  const PlanarVector<NumericType>& left, const PlanarVector<NumericType>& right) noexcept {
305  return left.x() != right.x() || left.y() != right.y();
306 }
307 
308 template <typename NumericType>
309 inline constexpr bool operator<(
310  const PlanarVector<NumericType>& left, const PlanarVector<NumericType>& right) noexcept {
311  if (left.x() != right.x()) {
312  return left.x() < right.x();
313  }
314  return left.y() < right.y();
315 }
316 
317 template <typename NumericType>
318 inline constexpr bool operator>(
319  const PlanarVector<NumericType>& left, const PlanarVector<NumericType>& right) noexcept {
320  if (left.x() != right.x()) {
321  return left.x() > right.x();
322  }
323  return left.y() > right.y();
324 }
325 
326 template <typename NumericType>
327 inline constexpr bool operator<=(
328  const PlanarVector<NumericType>& left, const PlanarVector<NumericType>& right) noexcept {
329  return !(left > right);
330 }
331 
332 template <typename NumericType>
333 inline constexpr bool operator>=(
334  const PlanarVector<NumericType>& left, const PlanarVector<NumericType>& right) noexcept {
335  return !(left < right);
336 }
337 
338 template <typename NumericType>
340  const PlanarVector<NumericType>& left, const PlanarVector<NumericType>& right) {
341  return PlanarVector<NumericType>{left.x() + right.x(), left.y() + right.y()};
342 }
343 
344 template <typename NumericType>
346  const PlanarVector<NumericType>& left, const PlanarVector<NumericType>& right) {
347  return PlanarVector<NumericType>{left.x() - right.x(), left.y() - right.y()};
348 }
349 
350 template <typename NumericType, typename OtherNumericType>
352  const PlanarVector<NumericType>& planar_vector, const OtherNumericType number) {
353  return PlanarVector<NumericType>{planar_vector.x() * static_cast<NumericType>(number),
354  planar_vector.y() * static_cast<NumericType>(number)};
355 }
356 
357 template <typename NumericType, typename OtherNumericType>
359  const OtherNumericType number, const PlanarVector<NumericType>& planar_vector) {
360  return PlanarVector<NumericType>{planar_vector * number};
361 }
362 
363 template <typename NumericType, typename OtherNumericType>
365  const PlanarVector<NumericType>& planar_vector, const OtherNumericType number) {
366  return PlanarVector<NumericType>{planar_vector.x() / static_cast<NumericType>(number),
367  planar_vector.y() / static_cast<NumericType>(number)};
368 }
369 
370 template <typename NumericType>
371 inline std::ostream& operator<<(
372  std::ostream& stream, const PlanarVector<NumericType>& planar_vector) {
373  stream << planar_vector.Print();
374  return stream;
375 }
376 
377 } // namespace PhQ
378 
379 namespace std {
380 
381 template <typename NumericType>
382 struct hash<PhQ::PlanarVector<NumericType>> {
383  inline size_t operator()(const PhQ::PlanarVector<NumericType>& planar_vector) const {
384  size_t result{17};
385  result = static_cast<size_t>(31) * result + hash<NumericType>()(planar_vector.x());
386  result = static_cast<size_t>(31) * result + hash<NumericType>()(planar_vector.y());
387  return result;
388  }
389 };
390 
391 } // namespace std
392 
393 #endif // PHQ_PLANAR_VECTOR_HPP
Plane angle between two lines or dihedral angle between two planes.
Definition: Angle.hpp:130
Three-dimensional Euclidean dyadic tensor. Contains nine components in Cartesian coordinates: xx,...
Definition: Dyad.hpp:51
two-dimensional Euclidean direction vector in the XY plane. Contains two components in Cartesian coor...
Two-dimensional Euclidean vector in the XY plane. Contains two components in Cartesian coordinates: x...
constexpr Vector< NumericType > Cross(const PlanarVector< NumericType > &other) const
Returns the cross product (also known as the vector product) of this two-dimensional planar vector an...
Definition: Vector.hpp:411
constexpr const std::array< NumericType, 2 > & x_y() const noexcept
Returns this two-dimensional planar vector's x and y Cartesian components as an array.
constexpr PlanarVector(const NumericType x, const NumericType y)
Constructor. Constructs a two-dimensional planar vector from the given x and y Cartesian components.
std::string YAML() const
Serializes this two-dimensional planar vector as a YAML message.
constexpr NumericType x() const noexcept
Returns this two-dimensional planar vector's x Cartesian component.
constexpr void operator*=(const OtherNumericType number) noexcept
Multiplies this two-dimensional planar vector by the given number.
constexpr void operator-=(const PlanarVector< NumericType > &other) noexcept
Subtracts another two-dimensional planar vector from this one.
constexpr void Set_x_y(const NumericType x, const NumericType y) noexcept
Sets this two-dimensional planar vector's x and y Cartesian components to the given values.
constexpr NumericType & Mutable_x() noexcept
Returns this two-dimensional planar vector's x Cartesian component as a mutable value.
constexpr void operator+=(const PlanarVector< NumericType > &other) noexcept
Adds another two-dimensional planar vector to this one.
constexpr void Set_y(const NumericType y) noexcept
Sets this two-dimensional planar vector's y Cartesian component to a given value.
constexpr PlanarVector< NumericType > & operator=(PlanarVector< NumericType > &&other) noexcept=default
Move assignment operator. Assigns this two-dimensional planar vector by moving another one.
PlanarVector()=default
Default constructor. Constructs a two-dimensional planar vector with uninitialized x and y Cartesian ...
constexpr PlanarVector< NumericType > & operator=(const PlanarVector< NumericType > &other)=default
Copy assignment operator. Assigns this two-dimensional planar vector by copying another one.
static constexpr PlanarVector< NumericType > Zero()
Statically creates a two-dimensional planar vector with its x and y Cartesian components initialized ...
constexpr void Set_x(const NumericType x) noexcept
Sets this two-dimensional planar vector's x Cartesian component to a given value.
PhQ::PlanarDirection< NumericType > PlanarDirection() const
Returns the planar direction of this two-dimensional planar vector.
constexpr NumericType Dot(const PlanarVector< NumericType > &other) const noexcept
Returns the dot product (also known as the inner product or scalar product) of this two-dimensional p...
NumericType Magnitude() const noexcept
Returns the magnitude (also known as the L2 norm) of this two-dimensional planar vector.
constexpr PlanarVector(PlanarVector< NumericType > &&other) noexcept=default
Move constructor. Constructs a two-dimensional planar vector by moving another one.
PhQ::Angle< NumericType > Angle(const PlanarVector< NumericType > &other) const
Returns the angle between this two-dimensional planar vector and another one.
Definition: Angle.hpp:394
std::string JSON() const
Serializes this two-dimensional planar vector as a JSON message.
std::string XML() const
Serializes this two-dimensional planar vector as an XML message.
std::array< NumericType, 2 > x_y_
Cartesian components of this two-dimensional planar vector.
constexpr PlanarVector(const std::array< NumericType, 2 > &x_y)
Constructor. Constructs a two-dimensional planar vector from a given array representing its x and y C...
constexpr void Set_x_y(const std::array< NumericType, 2 > &x_y) noexcept
Sets this two-dimensional planar vector's x and y Cartesian components to the given values.
constexpr NumericType & Mutable_y() noexcept
Returns this two-dimensional planar vector's y Cartesian component as a mutable value.
constexpr void operator/=(const OtherNumericType number) noexcept
Divides this two-dimensional planar vector by the given number.
constexpr PlanarVector< NumericType > & operator=(const PlanarVector< OtherNumericType > &other)
Copy assignment operator. Assigns this two-dimensional planar vector by copying another one.
constexpr Dyad< NumericType > Dyadic(const PlanarVector< NumericType > &other) const
Returns the dyadic tensor product (also known as the outer product) of this two-dimensional planar ve...
Definition: Dyad.hpp:722
std::string Print() const
Prints this two-dimensional planar vector as a string.
constexpr std::array< NumericType, 2 > & Mutable_x_y() noexcept
Returns this two-dimensional planar vector's x and y Cartesian components as a mutable array.
constexpr PlanarVector< NumericType > & operator=(const std::array< NumericType, 2 > &x_y)
Assignment operator. Assigns this two-dimensional planar vector by copying a given array representing...
constexpr NumericType y() const noexcept
Returns this two-dimensional planar vector's y Cartesian component.
constexpr NumericType MagnitudeSquared() const noexcept
Returns the square of the magnitude of this two-dimensional planar vector.
~PlanarVector() noexcept=default
Destructor. Destroys this two-dimensional planar vector.
Three-dimensional Euclidean vector. Contains three components in Cartesian coordinates: x,...
Definition: Vector.hpp:60
Angle
Angle units.
Definition: Angle.hpp:53
Namespace that encompasses all of the Physical Quantities library's content.
constexpr bool operator<(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr bool operator<=(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr Acceleration< NumericType > operator*(const NumericType number, const Acceleration< NumericType > &acceleration)
constexpr bool operator>(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr bool operator==(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr Dyad< NumericType > operator+(const Dyad< NumericType > &left, const Dyad< NumericType > &right)
Definition: Dyad.hpp:568
constexpr Dyad< NumericType > operator-(const Dyad< NumericType > &left, const Dyad< NumericType > &right)
Definition: Dyad.hpp:576
constexpr bool operator>=(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
constexpr Dyad< NumericType > operator/(const Dyad< NumericType > &dyad, const OtherNumericType number)
Definition: Dyad.hpp:696
constexpr bool operator!=(const Acceleration< NumericType > &left, const Acceleration< NumericType > &right) noexcept
std::ostream & operator<<(std::ostream &stream, const Acceleration< NumericType > &acceleration)
std::string Print(const NumericType value)
Prints a given floating-point number as a string. Prints enough digits to represent the number exactl...
Definition: Base.hpp:170