You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
243 lines
6.5 KiB
243 lines
6.5 KiB
#pragma once
|
|
|
|
#include "common.hpp"
|
|
#include "real.hpp"
|
|
#include <cmath>
|
|
#include <array>
|
|
#include <assert.h>
|
|
#include <cstddef>
|
|
#include <ostream>
|
|
#include <vector>
|
|
#include <stdexcept>
|
|
|
|
template <typename Derived, size_t N>
|
|
class VecBase {
|
|
public:
|
|
std::array<real, N> data;
|
|
|
|
VecBase() { data.fill(0); }
|
|
|
|
VecBase(std::initializer_list<real> values) {
|
|
std::copy(values.begin(), values.end(), data.begin());
|
|
}
|
|
|
|
VecBase(real v) : data{v} {}
|
|
|
|
VecBase(const VecBase &v) : data(v.data) {}
|
|
|
|
template <typename... Args>
|
|
explicit VecBase(Args... args) : data{static_cast<real>(args)...} {
|
|
static_assert(sizeof...(args) == N, "Argument count must match vector size.");
|
|
}
|
|
|
|
VecBase &operator=(VecBase v) {
|
|
*this = std::move(v);
|
|
return *this;
|
|
}
|
|
|
|
real &operator[](size_t index) {
|
|
if (index >= N)
|
|
throw std::out_of_range("Index out of range");
|
|
return data[index];
|
|
}
|
|
|
|
const real &operator[](size_t index) const {
|
|
if (index >= N)
|
|
throw std::out_of_range("Index out of range");
|
|
return data[index];
|
|
}
|
|
|
|
Derived operator+(const VecBase &v) const {
|
|
Derived result;
|
|
for (size_t i = 0; i < N; ++i) {
|
|
result[i] = data[i] + v[i];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Derived operator-(const VecBase &v) const {
|
|
Derived result;
|
|
for (size_t i = 0; i < N; ++i) {
|
|
result[i] = data[i] - v[i];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Derived operator*(real s) const {
|
|
Derived result;
|
|
for (size_t i = 0; i < N; ++i) {
|
|
result[i] = data[i] * s;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
friend Derived operator*(real s, const VecBase &v) {
|
|
Derived result;
|
|
for (size_t i = 0; i < N; ++i) {
|
|
result[i] = s * v[i];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
Derived operator/(real s) const {
|
|
Derived result;
|
|
for (size_t i = 0; i < N; ++i) {
|
|
result[i] = data[i] / s;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
real dot(const VecBase &v) const {
|
|
real sum = 0;
|
|
for (size_t i = 0; i < N; ++i) {
|
|
sum += data[i] * v[i];
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
real norm() const { return std::sqrt(dot(*this)); }
|
|
|
|
real l2() const { return dot(*this); }
|
|
|
|
Derived normalize() const { return static_cast<Derived>(*this / norm()); }
|
|
|
|
Derived reflect(const Derived &n) const { return static_cast<Derived>(*this - n * 2 * dot(n)); }
|
|
|
|
bool operator==(const VecBase &v) const {
|
|
for (size_t i = 0; i < N; ++i) {
|
|
if (!isEqual(data[i], v[i]))
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
friend std::ostream& operator<<(std::ostream& os, const VecBase& vec) {
|
|
os << "Vec" << N << "(";
|
|
for (size_t i = 0; i < N; ++i) {
|
|
os<<vec[i];
|
|
if (i<N-1) os<<", ";
|
|
}
|
|
os<<")";
|
|
return os;
|
|
}
|
|
|
|
Derived operator-() const { return static_cast<Derived>(*this * -1); }
|
|
};
|
|
|
|
// Vec<2> 特化
|
|
class Vec2 : public VecBase<Vec2, 2> {
|
|
public:
|
|
Vec2() : VecBase() {}
|
|
Vec2(real x, real y) : VecBase(x, y) {}
|
|
Vec2(const Vec2 &v) : VecBase(v.x(), v.y()) {}
|
|
|
|
Vec2(real v) : VecBase(v) {}
|
|
|
|
Vec2 &operator=(const Vec2 &v) {
|
|
data = v.data;
|
|
return *this;
|
|
}
|
|
|
|
real &x() { return data[0]; }
|
|
real &y() { return data[1]; }
|
|
|
|
[[nodiscard]] const real &x() const { return data[0]; }
|
|
[[nodiscard]] const real &y() const { return data[1]; }
|
|
|
|
real &u() { return data[0]; }
|
|
real &v() { return data[1]; }
|
|
|
|
[[nodiscard]] const real &u() const { return data[0]; }
|
|
[[nodiscard]] const real &v() const { return data[1]; }
|
|
|
|
[[nodiscard]] real cross(const Vec2 &v) const { return x() * v.y() - v.x() * y(); }
|
|
};
|
|
|
|
class Vec3 : public VecBase<Vec3, 3> {
|
|
public:
|
|
Vec3() : VecBase() {}
|
|
Vec3(real x, real y, real z) : VecBase(x, y, z) {}
|
|
Vec3(const Vec3 &v) : VecBase(v.x(), v.y(), v.z()) {}
|
|
|
|
Vec3(real v) : VecBase(v) {}
|
|
|
|
Vec3 &operator=(const Vec3 &v) {
|
|
data = v.data;
|
|
return *this;
|
|
}
|
|
|
|
real &x() { return data[0]; }
|
|
real &y() { return data[1]; }
|
|
real &z() { return data[2]; }
|
|
|
|
[[nodiscard]] real x() const { return data[0]; }
|
|
[[nodiscard]] real y() const { return data[1]; }
|
|
[[nodiscard]] real z() const { return data[2]; }
|
|
|
|
real &u() { return data[0]; }
|
|
real &v() { return data[1]; }
|
|
real &w() { return data[2]; }
|
|
|
|
[[nodiscard]] real u() const { return data[0]; }
|
|
[[nodiscard]] real v() const { return data[1]; }
|
|
[[nodiscard]] real w() const { return data[2]; }
|
|
|
|
[[nodiscard]] Vec3 cross(const Vec3 &v) const {
|
|
return {y() * v.z() - z() * v.y(), z() * v.x() - x() * v.z(), x() * v.y() - y() * v.x()};
|
|
}
|
|
|
|
[[nodiscard]] bool isParallel(const Vec3 &v) const { return cross(v) == 0; }
|
|
};
|
|
|
|
using Pt3Array = std::vector<Vec3>;
|
|
using Pt2Array = std::vector<Vec2>;
|
|
|
|
//class Vec3 {
|
|
//public:
|
|
// real x, y, z;
|
|
// Vec3(): x(0), y(0), z(0) {}
|
|
// Vec3(real x, real y, real z): x(x), y(y), z(z) {}
|
|
// Vec3(const Vec3& v): x(v.x), y(v.y), z(v.z) {}
|
|
// Vec3& operator=(const Vec3& v) {
|
|
// x = v.x;
|
|
// y = v.y;
|
|
// z = v.z;
|
|
// return *this;
|
|
// }
|
|
// Vec3 operator+(const Vec3& v) const {
|
|
// return Vec3(x + v.x, y + v.y, z + v.z);
|
|
// }
|
|
// Vec3 operator-(const Vec3& v) const {
|
|
// return Vec3(x - v.x, y - v.y, z - v.z);
|
|
// }
|
|
// Vec3 operator*(real s) const {
|
|
// return Vec3(x * s, y * s, z * s);
|
|
// }
|
|
// Vec3 operator*(const Vec3& v) const {
|
|
// return Vec3(x * v.x, y * v.y, z * v.z);
|
|
// }
|
|
// Vec3 operator-() const {
|
|
// return Vec3(-x, -y, -z);
|
|
// }
|
|
// friend Vec3 operator*(real s, const Vec3& v) {
|
|
// return Vec3(s * v.x, s * v.y, s * v.z);
|
|
// }
|
|
// Vec3 operator/(real s) const {
|
|
// return Vec3(x / s, y / s, z / s);
|
|
// }
|
|
// real dot(const Vec3& v) const {
|
|
// return x * v.x + y * v.y + z * v.z;
|
|
// }
|
|
// Vec3 cross(const Vec3& v) const {
|
|
// return Vec3(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
|
|
// }
|
|
// real norm() const {
|
|
// return sqrt(x * x + y * y + z * z);
|
|
// }
|
|
// Vec3 normalize() const {
|
|
// return *this / norm();
|
|
// }
|
|
// Vec3 reflect(const Vec3& n) const {
|
|
// return *this - n * 2 * dot(n);
|
|
// }
|
|
//};
|
|
|