2022-10-28 09:31:13 +02:00
|
|
|
#include "common/vector3d.h"
|
2022-11-11 14:27:43 +01:00
|
|
|
#include "common/common.h"
|
|
|
|
#include <algorithm>
|
2022-10-28 09:31:13 +02:00
|
|
|
#include <cassert>
|
|
|
|
|
|
|
|
// Access operators ////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
float &Vector3d::operator[](int const dimension) {
|
|
|
|
assert(0 <= dimension && dimension < 3);
|
|
|
|
switch (dimension) {
|
|
|
|
case Dimension::X:
|
|
|
|
return this->x;
|
|
|
|
case Dimension::Y:
|
|
|
|
return this->y;
|
|
|
|
case Dimension::Z:
|
|
|
|
return this->z;
|
|
|
|
default: // This must never happen
|
|
|
|
return this->x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
float const &Vector3d::operator[](int const dimension) const {
|
|
|
|
assert(0 <= dimension && dimension < 3);
|
|
|
|
switch (dimension) {
|
|
|
|
case Dimension::X:
|
|
|
|
return this->x;
|
|
|
|
case Dimension::Y:
|
|
|
|
return this->y;
|
|
|
|
case Dimension::Z:
|
|
|
|
return this->z;
|
|
|
|
default: // This must never happen
|
|
|
|
return this->x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Comparison operators ////////////////////////////////////////////////////////
|
|
|
|
|
2022-11-11 14:27:43 +01:00
|
|
|
bool operator==(Vector3d const &left, Vector3d const &right) { return (left.x == right.x && left.y == right.y && left.z == right.z); }
|
2022-10-28 09:31:13 +02:00
|
|
|
|
|
|
|
bool operator!=(Vector3d const &left, Vector3d const &right) { return !(left == right); }
|
|
|
|
|
|
|
|
// Arithmetic operators ////////////////////////////////////////////////////////
|
|
|
|
|
2022-11-11 14:27:43 +01:00
|
|
|
Vector3d operator+(Vector3d const &left, Vector3d const &right) { return Vector3d(left.x + right.x, left.y + right.y, left.z + right.z); }
|
2022-10-28 09:31:13 +02:00
|
|
|
|
|
|
|
Vector3d operator-(Vector3d const &right) { return Vector3d(-right.x, -right.y, -right.z); }
|
|
|
|
|
2022-11-11 14:27:43 +01:00
|
|
|
Vector3d operator-(Vector3d const &left, Vector3d const &right) { return Vector3d(left.x - right.x, left.y - right.y, left.z - right.z); }
|
2022-10-28 09:31:13 +02:00
|
|
|
|
2022-11-11 14:27:43 +01:00
|
|
|
Vector3d operator*(Vector3d const &left, float right) { return Vector3d(left.x * right, left.y * right, left.z * right); }
|
2022-10-28 09:31:13 +02:00
|
|
|
|
2022-11-11 14:27:43 +01:00
|
|
|
Vector3d operator*(float left, Vector3d const &right) { return Vector3d(left * right.x, left * right.y, left * right.z); }
|
2022-10-28 09:31:13 +02:00
|
|
|
|
2022-11-11 14:27:43 +01:00
|
|
|
Vector3d operator*(Vector3d const &left, Vector3d const &right) { return Vector3d(left.x * right.x, left.y * right.y, left.z * right.z); }
|
|
|
|
|
|
|
|
Vector3d operator/(Vector3d const &left, float right) { return Vector3d(left.x / right, left.y / right, left.z / right); }
|
|
|
|
|
|
|
|
Vector3d operator/(Vector3d const &left, Vector3d const &right) { return Vector3d(left.x / right.x, left.y / right.y, left.z / right.z); }
|
2022-10-28 09:31:13 +02:00
|
|
|
|
|
|
|
// Assignment operators ////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
Vector3d &operator+=(Vector3d &left, Vector3d const &right) {
|
|
|
|
left.x += right.x;
|
|
|
|
left.y += right.y;
|
|
|
|
left.z += right.z;
|
|
|
|
return left;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector3d &operator-=(Vector3d &left, Vector3d const &right) {
|
|
|
|
left.x -= right.x;
|
|
|
|
left.y -= right.y;
|
|
|
|
left.z -= right.z;
|
|
|
|
return left;
|
|
|
|
}
|
|
|
|
|
|
|
|
Vector3d &operator*=(Vector3d &left, float right) {
|
|
|
|
left.x *= right;
|
|
|
|
left.y *= right;
|
|
|
|
left.z *= right;
|
|
|
|
return left;
|
|
|
|
}
|
|
|
|
|
2022-11-11 14:27:43 +01:00
|
|
|
Vector3d &operator*=(Vector3d &left, Vector3d const &right) {
|
|
|
|
left.x *= right.x;
|
|
|
|
left.y *= right.y;
|
|
|
|
left.z *= right.z;
|
|
|
|
return left;
|
|
|
|
}
|
|
|
|
|
2022-10-28 09:31:13 +02:00
|
|
|
Vector3d &operator/=(Vector3d &left, float right) {
|
|
|
|
left.x /= right;
|
|
|
|
left.y /= right;
|
|
|
|
left.z /= right;
|
|
|
|
return left;
|
|
|
|
}
|
|
|
|
|
2022-11-11 14:27:43 +01:00
|
|
|
Vector3d &operator/=(Vector3d &left, Vector3d const &right) {
|
|
|
|
left.x /= right.x;
|
|
|
|
left.y /= right.y;
|
|
|
|
left.z /= right.z;
|
|
|
|
return left;
|
|
|
|
}
|
|
|
|
|
2022-10-28 09:31:13 +02:00
|
|
|
// Useful functions ////////////////////////////////////////////////////////////
|
|
|
|
|
2022-11-11 14:27:43 +01:00
|
|
|
Vector3d componentProduct(const Vector3d &left, const Vector3d &right) { return Vector3d(left.x * right.x, left.y * right.y, left.z * right.z); }
|
2022-10-28 09:31:13 +02:00
|
|
|
|
2022-11-11 14:27:43 +01:00
|
|
|
Vector3d componentQuotient(const Vector3d &left, const Vector3d &right) { return Vector3d(left.x / right.x, left.y / right.y, left.z / right.z); }
|
2022-10-28 09:31:13 +02:00
|
|
|
|
2022-11-11 14:27:43 +01:00
|
|
|
Vector3d crossProduct(Vector3d const &left, Vector3d const &right) { return Vector3d(left.y * right.z - left.z * right.y, left.z * right.x - left.x * right.z, left.x * right.y - left.y * right.x); }
|
2022-10-28 09:31:13 +02:00
|
|
|
|
2022-11-11 14:27:43 +01:00
|
|
|
float dotProduct(Vector3d const &left, Vector3d const &right) { return left.x * right.x + left.y * right.y + left.z * right.z; }
|
2022-10-28 09:31:13 +02:00
|
|
|
|
|
|
|
float length(Vector3d const &v) { return std::sqrt(dotProduct(v, v)); }
|
|
|
|
|
2022-11-11 14:27:43 +01:00
|
|
|
Vector3d normalized(Vector3d const &v) { return v / std::max(length(v), NORM_EPS); }
|
2022-10-28 09:31:13 +02:00
|
|
|
|
|
|
|
void normalize(Vector3d *v) { *v = normalized(*v); }
|
2022-11-11 14:27:43 +01:00
|
|
|
|
|
|
|
std::tuple<Vector3d, Vector3d, Vector3d> orthoNormalized(Vector3d const &u, Vector3d const &v, Vector3d const &w) {
|
|
|
|
// using gram-schmidt orthonormalization
|
|
|
|
auto ret_u = normalized(u);
|
|
|
|
auto ret_v = normalized(v - dotProduct(ret_u, v) * ret_u);
|
|
|
|
auto ret_w = normalized(w - dotProduct(ret_u, w) * ret_u - dotProduct(ret_v, w) * ret_v);
|
|
|
|
|
|
|
|
return std::make_tuple(ret_u, ret_v, ret_w);
|
|
|
|
}
|