115 lines
3.9 KiB
C++
115 lines
3.9 KiB
C++
#ifndef FESA_MATH_VECTOR3_H_
|
|
#define FESA_MATH_VECTOR3_H_ // NOLINT(readability-identifier-naming)
|
|
|
|
#include <array>
|
|
#include <cmath>
|
|
#include <cstddef>
|
|
#include <optional>
|
|
|
|
namespace fesa {
|
|
|
|
/// @brief Represents an owning fixed-size three-dimensional value vector.
|
|
class Vector3 {
|
|
public:
|
|
/// @brief Constructs the zero vector.
|
|
constexpr Vector3() noexcept = default;
|
|
|
|
/// @brief Constructs a vector from three Cartesian components.
|
|
/// @param x First component in the caller-defined coordinate system.
|
|
/// @param y Second component in the caller-defined coordinate system.
|
|
/// @param z Third component in the caller-defined coordinate system.
|
|
constexpr Vector3(double x, double y, double z) noexcept
|
|
: components_{{x, y, z}} {}
|
|
|
|
/// @brief Copies components from an existing array-backed carrier.
|
|
explicit constexpr Vector3(const std::array<double, 3>& components) noexcept
|
|
: components_{components} {}
|
|
|
|
/// @brief Returns the first component.
|
|
constexpr double X() const noexcept { return components_[0]; }
|
|
|
|
/// @brief Returns the second component.
|
|
constexpr double Y() const noexcept { return components_[1]; }
|
|
|
|
/// @brief Returns the third component.
|
|
constexpr double Z() const noexcept { return components_[2]; }
|
|
|
|
/// @brief Returns a component by zero-based index.
|
|
/// @pre index is less than three.
|
|
constexpr double operator[](std::size_t index) const noexcept {
|
|
return components_[index];
|
|
}
|
|
|
|
/// @brief Returns the immutable array-backed component carrier.
|
|
constexpr const std::array<double, 3>& Components() const noexcept {
|
|
return components_;
|
|
}
|
|
|
|
/// @brief Adds corresponding vector components.
|
|
constexpr Vector3 operator+(const Vector3& rhs) const noexcept {
|
|
return Vector3{X() + rhs.X(), Y() + rhs.Y(), Z() + rhs.Z()};
|
|
}
|
|
|
|
/// @brief Subtracts corresponding vector components.
|
|
constexpr Vector3 operator-(const Vector3& rhs) const noexcept {
|
|
return Vector3{X() - rhs.X(), Y() - rhs.Y(), Z() - rhs.Z()};
|
|
}
|
|
|
|
/// @brief Multiplies every component by a scalar.
|
|
constexpr Vector3 operator*(double scalar) const noexcept {
|
|
return Vector3{X() * scalar, Y() * scalar, Z() * scalar};
|
|
}
|
|
|
|
/// @brief Divides every component by a scalar.
|
|
constexpr Vector3 operator/(double scalar) const noexcept {
|
|
return Vector3{X() / scalar, Y() / scalar, Z() / scalar};
|
|
}
|
|
|
|
/// @brief Multiplies every component with the scalar as the left operand.
|
|
friend constexpr Vector3 operator*(double scalar,
|
|
const Vector3& rhs) noexcept {
|
|
return Vector3{scalar * rhs.X(), scalar * rhs.Y(), scalar * rhs.Z()};
|
|
}
|
|
|
|
/// @brief Compares every component exactly.
|
|
constexpr bool operator==(const Vector3& rhs) const noexcept {
|
|
return X() == rhs.X() && Y() == rhs.Y() && Z() == rhs.Z();
|
|
}
|
|
|
|
/// @brief Computes the Euclidean dot product with rhs.
|
|
double Dot(const Vector3& rhs) const noexcept {
|
|
return X() * rhs.X() + Y() * rhs.Y() + Z() * rhs.Z();
|
|
}
|
|
|
|
/// @brief Computes the right-handed cross product with rhs.
|
|
Vector3 Cross(const Vector3& rhs) const noexcept {
|
|
return Vector3{Y() * rhs.Z() - Z() * rhs.Y(), Z() * rhs.X() - X() * rhs.Z(),
|
|
X() * rhs.Y() - Y() * rhs.X()};
|
|
}
|
|
|
|
/// @brief Computes the Euclidean norm.
|
|
double Norm() const noexcept { return std::hypot(X(), Y(), Z()); }
|
|
|
|
/// @brief Returns a unit vector when the norm is usable.
|
|
/// @return Empty when the norm is exactly zero or nonfinite.
|
|
std::optional<Vector3> Normalized() const noexcept {
|
|
const double norm = Norm(); // NOLINT(readability-identifier-naming)
|
|
if (norm == 0.0 || !std::isfinite(norm)) {
|
|
return std::nullopt;
|
|
}
|
|
return Vector3{X() / norm, Y() / norm, Z() / norm};
|
|
}
|
|
|
|
/// @brief Reports whether all components are finite.
|
|
bool IsFinite() const noexcept {
|
|
return std::isfinite(X()) && std::isfinite(Y()) && std::isfinite(Z());
|
|
}
|
|
|
|
private:
|
|
std::array<double, 3> components_{};
|
|
};
|
|
|
|
} // namespace fesa
|
|
|
|
#endif // FESA_MATH_VECTOR3_H_
|