diff options
Diffstat (limited to 'meowpp/geo')
-rw-r--r-- | meowpp/geo/!readme.asciidoc | 12 | ||||
-rw-r--r-- | meowpp/geo/Vectors.h | 510 |
2 files changed, 522 insertions, 0 deletions
diff --git a/meowpp/geo/!readme.asciidoc b/meowpp/geo/!readme.asciidoc new file mode 100644 index 0000000..7308afc --- /dev/null +++ b/meowpp/geo/!readme.asciidoc @@ -0,0 +1,12 @@ + +計算幾何相關, 算是從math中特化出來的 + +===== Vectors.h + +實作上不是用陣列, 是直接宣告2到3個變數分別存x, y (,z) + +.Classes +* `meow::Vector2D<Scalar>` +* `meow::Vector3D<Scalar>` + + diff --git a/meowpp/geo/Vectors.h b/meowpp/geo/Vectors.h new file mode 100644 index 0000000..8cdafc9 --- /dev/null +++ b/meowpp/geo/Vectors.h @@ -0,0 +1,510 @@ +#ifndef geo_Vectors_H__ +#define geo_Vectors_H__ + +#include "../math/utility.h" +#include "../math/Vector.h" +#include "../math/Matrix.h" + +#include <cmath> + +namespace meow{ + +/*! + * @brief 2D's vector + * + * @author cat_leopard + */ +template<class Scalar> +class Vector2D { +private: + Scalar x_, y_; +public: + //! @brief consturctor (0, 0) + Vector2D(): x_(0), y_(0) { + } + + //! @brief consturctor (from another Vector2D) + Vector2D(Vector2D const& v): x_(v.x_), y_(v.y_) { + } + + //! @brief constructor (s, s) + Vector2D(Scalar const& s): x_(s), y_(s) { + } + + //! @brief constructor (sx, sy) + Vector2D(Scalar const& sx, Scalar const& sy): x_(sx), y_(sy) { + } + + //! @brief constructor (from another Vector) + Vector2D(Vector<Scalar> const& v): x_(v(0)), y_(v(1)) { + } + + //! @brief constructor (from another Vector, i-th) + Vector2D(Vector<Scalar> const& v, size_t i): x_(v(i)), y_(v(i + 1)) { + } + + //! @brief destructor + ~Vector2D() { + } + + //! @brief copy + Vector2D& copyFrom(Vector2D const& v) { + return xy(v.x(), v.y()); + } + + //! @brief access x + Scalar const& x() const { + return x_; + } + + //! @brief access x with non constant reference + Scalar& xGet() { + return x_; + } + + //! @brief access y with non constant reference + Scalar& yGet() { + return y_; + } + + //! @brief access y + Scalar const& y() const { + return y_; + } + + //! @brief modify x + Scalar const& x(Scalar const& s) { + x_ = s; + return x(); + } + + //! @brief modify y + Scalar const& y(Scalar const& s) { + y_ = s; + return y(); + } + + //! @brief modify x and y + Vector2D& xy(Scalar const& sx, Scalar const& sy){ + x(sx); + y(sy); + return *this; + } + + //! @brief return \a +(*this) + Vector2D positive() const { + return *this; + } + + //! @brief return \a -(*this) + Vector2D negative() const { + return Vector2D(-x(), -y()); + } + + //! @brief return \a count-clockwise \a rotate \a 90 \a degree of itself + Vector2D right()const{ + return Vector2D(-y(), x()); + } + + //! @brief return \a (*this)+v + Vector2D add(Vector2D const& v) const { + return Vector2D(x() + v.x(), y() + v.y()); + } + + //! @brief Let itself add v + Vector2D& added(Vector2D const& v) { + return xy(x() + v.x(), y() + v.y()); + } + + //! @brief return \a (*this)-v + Vector2D sub(Vector2D const& v) const { + return Vector2D(x() - v.x(), y() - v.y()); + } + + //! @brief Let itself substract v + Vector2D& subed(Vector2D const& v) { + return xy(x() - v.x(), y() - v.y()); + } + + //! @brief return \a (*this)*s , where s is a scalar + Vector2D mul(Scalar const& s) const { + return Vector2D(x() * s, y() * s); + } + + //! @brief Let itself mulitple s + Vector2D& muled(Scalar const& s) { + return xy(x() * s, y() * s); + } + + //! @brief return \a (*this)/s , where s is a scalar + Vector2D div(Scalar const& s) const { + return Vector2D(x() / s, y() / s); + } + + //! @brief Let itself divide s + Vector2D& dived(Scalar const& s) { + return xy(x() / s, y() / s); + } + + //! @brief same as dot(v) + Scalar mul(Vector2D const& v) const { + return dot(v); + } + + //! @brief dot + Scalar dot(Vector2D const& v) const { + return x() * v.x() + y() * v.y(); + } + + //! @brief cross + Scalar cross(Vector2D const& v) const { + return x() * v.y() - y() * v.x(); + } + + //! @brief sqrt of length2 + Scalar length() const { + return Scalar(sqrt(double(length2()))); + } + + //! @brief same as \a dot(*this) + Scalar length2() const { + return dot(*this); + } + + //! @brief return normalize form of itself + Vector2D normalize() const { + return div(length()); + } + + //! @brief normalize itself + Vector2D& normalized() { + return dived(length()); + } + + //! @brief return rotate \a theta degree of itself + Vector2D rotate(Scalar const& theta) const { + Scalar cs(cos(-double(theta))); + Scalar sn(sin(-double(theta))); + Vector2D<Scalar> new_x(cs, sn); + return Vector2D(new_x.dot(*this), new_x.cross(*this)); + } + + //! @brief Let itself rotate \a theta degree + Vector2D& rotated(Scalar const& theta) { + return copyFrom(rotate(theta)); + } + + //! @brief return reflect from given vector \a v + Vector2D reflect(Vector2D const& v) const { + return v.mul(v.dot(*this) * 2 / v.length2()).sub(*this); + } + + //! @brief reflect itself given vector \a v + Vector2D& reflected(Vector2D const& v) { + return copyFrom(reflecte(v)); + } + + //! @brief return a 2x1 matrix form of itself + Matrix<Scalar> matrix() const { + static Matrix<Scalar> ret(2, 1, Scalar(0)); + ret(0, 0, x()); + ret(1, 0, y()); + return ret; + } + + //! @brief return a 3x1 matrix form of itself + Matrix<Scalar> matrix(Scalar const& homo) const { + static Matrix<Scalar> ret(3, 1, Scalar(0)); + ret(0, 0, x()); + ret(1, 0, y()); + ret(2, 0, homo); + return ret; + } + + Scalar const& operator()(size_t n) const { + return (n == 0 ? x() : y()); + } + + Vector2D& operator()(Scalar const& sx, Scalar const& sy) { + return xy(sx, sy); + } + + Vector2D operator+() const { return positive(); } + Vector2D operator-() const { return negative(); } + Vector2D operator~() const { return right (); } + + Vector2D operator+(Vector2D const& v) const { return add(v); } + Vector2D operator-(Vector2D const& v) const { return sub(v); } + Vector2D operator*(Scalar const& s) const { return mul(s); } + Vector2D operator/(Scalar const& s) const { return div(s); } + Scalar operator*(Vector2D const& v) const { return mul(v); } + + Vector2D& operator=(Vector2D const& v) { return copyFrom(v); } + Vector2D& operator+=(Vector2D const& v) { return added(v); } + Vector2D& operator-=(Vector2D const& v) { return subed(v); } + Vector2D& operator*=(Scalar const& s) { return muled(s); } + Vector2D& operator/=(Scalar const& s) { return dived(s); } +}; + +/*! + * @brief 3D's vector + * + * @author cat_leopard + */ +template<class Scalar> +class Vector3D{ +private: + Scalar x_, y_, z_; +public: + //! @brief consturctor (0, 0) + Vector3D(): x_(0), y_(0), z_(0) { + } + + //! @brief consturctor (from another Vector3D) + Vector3D(Vector3D const& v): x_(v.x_), y_(v.y_), z_(v.z_) { + } + + //! @brief constructor (s, s) + Vector3D(Scalar const& s): x_(s), y_(s), z_(s) { + } + + //! @brief constructor (sx, sy) + Vector3D(Scalar const& sx, + Scalar const& sy, + Scalar const& sz): x_(sx), y_(sy), z_(sz) { + } + + //! @brief constructor (from another Vector) + Vector3D(Vector<Scalar> const& v): x_(v(0)), y_(v(1)), z_(v(2)) { + } + + //! @brief constructor (from another Vector, i-th) + Vector3D(Vector<Scalar> const& v, size_t i): x_(v(i)), y_(v(i+1)), z_(v(i+2)){ + } + + //! @brief destructor + ~Vector3D(){ + } + + //! @brief copy + Vector3D& copyFrom(Vector3D const& v){ + return xyz(v.x(), v.y(), v.z()); + } + + //! @brief access x + Scalar const& x() const{ + return x_; + } + + //! @brief access y + Scalar const& y() const{ + return y_; + } + + //! @brief access z + Scalar const& z() const{ + return z_; + } + + //! @brief access x with non constant reference + Scalar& xGet() { + return x_; + } + + //! @brief access y with non constant reference + Scalar& yGet() { + return y_; + } + + //! @brief access z with non constant reference + Scalar& zGet() { + return z_; + } + + //! @brief modify x + Scalar const& x(Scalar const& s) { + x_ = s; + return x(); + } + + //! @brief modify y + Scalar const& y(Scalar const& s) { + y_ = s; + return y(); + } + + //! @brief modify z + Scalar const& z(Scalar const& s) { + z_ = s; + return z(); + } + + //! @brief modify x and y + Vector3D& xyz(Scalar const& sx, Scalar const& sy, Scalar const& sz) { + x(sx); + y(sy); + z(sz); + return *this; + } + + //! @brief return \a +(*this) + Vector3D positive() const { + return *this; + } + + //! @brief return \a -(*this) + Vector3D negative() const { + return Vector3D(-x(), -y(), -z()); + } + + //! @brief return \a (*this)+v + Vector3D add(Vector3D const& v) const { + return Vector3D(x() + v.x(), y() + v.y(), z() + v.z()); + } + + //! @brief Let itself add v + Vector3D& added(Vector3D const& v) { + return xyz(x() + v.x(), y() + v.y(), z() + v.z()); + } + + //! @brief return \a (*this)-v + Vector3D sub(Vector3D const& v) const { + return Vector3D(x() - v.x(), y() - v.y(), z() - v.z()); + } + + //! @brief Let itself substract v + Vector3D& subed(Vector3D const& v) { + return xyz(x() - v.x(), y() - v.y(), z() - v.z()); + } + + //! @brief return \a (*this)*s , where s is a scalar + Vector3D mul(Scalar const& s) const { + return Vector3D(x() * s, y() * s, z() * s); + } + + //! @brief Let itself mulitple s + Vector3D& muled(Scalar const& s) { + return xyz(x() * s, y() * s, z() * s); + } + + //! @brief return \a (*this)/s , where s is a scalar + Vector3D div(Scalar const& s) const { + return Vector3D(x() / s, y() / s, z() / s); + } + + //! @brief Let itself divide s + Vector3D& dived(Scalar const& s) { + return xyz(x() / s, y() / s, z() / s); + } + + //! @brief same as dot(v) + Scalar mul(Vector3D const& v) const { + return dot(v); + } + + //! @brief dot + Scalar dot(Vector3D const& v) const { + return x() * v.x() + y() * v.y() + z() * v.z(); + } + + //! @brief cross + Vector3D cross(Vector3D const& v) const { + return Vector3D(y() * v.z() - z() * v.y(), + z() * v.x() - x() * v.z(), + x() * v.y() - y() * v.x()); + } + + //! @brief crossed + Vector3D& crossed(Vector3D const& v) { + return copyFrom(cross(v)); + } + + //! @brief sqrt of length2 + Scalar length() const { + return Scalar(sqrt(double(length2()))); + } + + //! @brief same as \a dot(*this) + Scalar length2() const { + return dot(*this); + } + + //! @brief return normalize form of itself + Vector3D normalize() const { + return div(length()); + } + + //! @brief normalize itself + Vector3D& normalized() { + return dived(length()); + } + + //! @brief return rotate \a theta degree by \a axis of itself + Vector3D rotate(Vector3D const& axis, double theta) const { + Vector3D a(axis.normalize()); + Vector3D xx(sub(a) .mul(cos(theta))); + Vector3D yy(a.cross(*this).mul(sin(theta))); + return a.mul(a.dot(*this)).add(xx).add(yy); + } + + //! @brief Let itself rotate \a theta degree + Vector3D& rotated(Vector3D const& axis, double theta) { + return copyFrom(rotate(axis, theta)); + } + + //! @brief return reflect from given vector \a v + Vector3D reflect(Vector3D const& v) const { + return v.mul(v.dot(*this) * 2 / v.length2()).sub(*this); + } + + //! @brief reflect itself given vector \a v + Vector3D& reflected(Vector3D const& v) { + return copyFrom(reflecte(v)); + } + + //! @brief return a 3x1 matrix form of itself + Matrix<Scalar> matrix() const { + static Matrix<Scalar> ret(3, 1, Scalar(0)); + ret(0, 0, x()); + ret(1, 0, y()); + ret(2, 0, z()); + return ret; + } + + //! @brief return a 3x1 matrix form of itself + Matrix<Scalar> matrix(Scalar const& homo) const { + static Matrix<Scalar> ret(4, 1, Scalar(0)); + ret(0, 0, x()); + ret(1, 0, y()); + ret(2, 0, z()); + ret(3, 0, homo); + return ret; + } + + Scalar const& operator()(size_t n) const { + return (n == 0 ? x() : (n == 1 ? y() : z())); + } + + Vector3D& operator()(Scalar const& sx, Scalar const& sy, Scalar const& sz) { + return xyz(sx, sy, sz); + } + + Vector3D operator+() const { return positive(); } + Vector3D operator-() const { return negative(); } + + Vector3D operator+(Vector3D const& v) const { return add(v); } + Vector3D operator-(Vector3D const& v) const { return sub(v); } + Vector3D operator*(Scalar const& s) const { return mul(s); } + Vector3D operator/(Scalar const& s) const { return div(s); } + Scalar operator*(Vector3D const& v) const { return mul(v); } + + Vector3D& operator=(Vector3D const& v) { return copyFrom(v); } + Vector3D& operator+=(Vector3D const& v) { return added(v); } + Vector3D& operator-=(Vector3D const& v) { return subed(v); } + Vector3D& operator*=(Scalar const& s) { return muled(s); } + Vector3D& operator/=(Scalar const& s) { return dived(s); } +}; + +} + +#endif // geo_Vectors_H__ |