From: Mikko Rasa Date: Fri, 17 May 2013 10:55:57 +0000 (+0300) Subject: Redesign the Vector interface X-Git-Url: http://git.tdb.fi/?p=libs%2Fmath.git;a=commitdiff_plain;h=aa47cdf95914ae706b99a48d528260b3261f9882 Redesign the Vector interface The constructors from two and three components are now provided directly by the Vector template, so Vector2 and Vector3 are no longer needed. In addition, two- and three-component vectors now have named members. --- diff --git a/source/geometry/box.h b/source/geometry/box.h index bfcfa2f..40f88dc 100644 --- a/source/geometry/box.h +++ b/source/geometry/box.h @@ -1,7 +1,6 @@ #ifndef MSP_GEOMETRY_BOX_H_ #define MSP_GEOMETRY_BOX_H_ -#include #include "hyperbox.h" namespace Msp { @@ -13,7 +12,7 @@ class Box: public HyperBox public: Box() { } explicit Box(const LinAl::Vector &d): HyperBox(d) { } - Box(T w, T h, T d): HyperBox(LinAl::Vector3(w, h, d)) { } + Box(T w, T h, T d): HyperBox(LinAl::Vector(w, h, d)) { } T get_width() const { return this->get_dimension(0); } T get_height() const { return this->get_dimension(1); } diff --git a/source/geometry/rectangle.h b/source/geometry/rectangle.h index 296ba6c..dbebf8a 100644 --- a/source/geometry/rectangle.h +++ b/source/geometry/rectangle.h @@ -1,7 +1,6 @@ #ifndef MSP_GEOMETRY_RECTANGLE_H_ #define MSP_GEOMETRY_RECTANGLE_H_ -#include #include "hyperbox.h" namespace Msp { @@ -13,7 +12,7 @@ class Rectangle: public HyperBox public: Rectangle() { } explicit Rectangle(const LinAl::Vector &d): HyperBox(d) { } - Rectangle(T w, T h): HyperBox(LinAl::Vector2(w, h)) { } + Rectangle(T w, T h): HyperBox(LinAl::Vector(w, h)) { } T get_width() const { return this->get_dimension(0); } T get_height() const { return this->get_dimension(1); } diff --git a/source/linal/dummy.cpp b/source/linal/dummy.cpp index 25e76a3..05e6ff2 100644 --- a/source/linal/dummy.cpp +++ b/source/linal/dummy.cpp @@ -1,6 +1,4 @@ #include "vector.h" -#include "vector2.h" -#include "vector3.h" #include "matrix.h" #include "squarematrix.h" diff --git a/source/linal/vector.h b/source/linal/vector.h index 392e3a1..11292f7 100644 --- a/source/linal/vector.h +++ b/source/linal/vector.h @@ -8,22 +8,64 @@ namespace Msp { namespace LinAl { /** -A general mathematical vector. +Base class to provide the components of a vector. This is used so that +specializations with individual members can be provided in some dimensions. */ template -class Vector +class VectorComponents { -protected: +private: T data[N]; -public: - Vector(); - Vector(const T *d); - template - Vector(const Vector &v); +protected: + VectorComponents() { } +public: T &operator[](unsigned i) { return data[i]; } const T &operator[](unsigned i) const { return data[i]; } +}; + +template +class VectorComponents +{ +public: + T x, y; + +protected: + VectorComponents() { } + +public: + T &operator[](unsigned i) { return *(&x+i); } + const T &operator[](unsigned i) const { return *(&x+i); } +}; + +template +class VectorComponents +{ +public: + T x, y, z; + +protected: + VectorComponents() { } + +public: + T &operator[](unsigned i) { return *(&x+i); } + const T &operator[](unsigned i) const { return *(&x+i); } +}; + +/** +A general mathematical vector. +*/ +template +class Vector: public VectorComponents +{ +public: + Vector(); + Vector(const T *); + Vector(T, T); + Vector(T, T, T); + template + Vector(const Vector &); Vector &operator*=(T); Vector &operator/=(T); @@ -38,27 +80,47 @@ public: template inline Vector::Vector() { - std::fill(data, data+N, T()); + for(unsigned i=0; i inline Vector::Vector(const T *d) { - std::copy(d, d+N, data); + for(unsigned i=0; i +inline Vector::Vector(T x_, T y_) +{ + this->VectorComponents::x = x_; + this->VectorComponents::y = y_; +} + +template +inline Vector::Vector(T x_, T y_, T z_) +{ + this->VectorComponents::x = x_; + this->VectorComponents::y = y_; + this->VectorComponents::z = z_; } template template inline Vector::Vector(const Vector &v) { - std::copy(v.data, v.data+N, data); + for(unsigned i=0; i inline Vector &Vector::operator*=(T s) { for(unsigned i=0; i inline Vector &Vector::operator/=(T s) { for(unsigned i=0; i inline Vector &Vector::operator+=(const Vector &v) { for(unsigned i=0; i inline Vector &Vector::operator-=(const Vector &v) { for(unsigned i=0; i normalize(const Vector &v) return r.normalize(); } +template +inline T dot(const Vector &v1, const Vector &v2) +{ + return inner_product(v1, v2); +} + +template +inline Vector cross(const Vector &v1, const Vector &v2) +{ + return Vector(v1.y*v2.z-v1.z*v2.y, v1.z*v2.x-v1.x*v2.z, v1.x*v2.y-v1.y*v2.x); +} + } // namespace LinAl } // namespace Msp diff --git a/source/linal/vector2.h b/source/linal/vector2.h deleted file mode 100644 index fed7721..0000000 --- a/source/linal/vector2.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef MSP_LINAL_VECTOR2_H_ -#define MSP_LINAL_VECTOR2_H_ - -#include "vector.h" - -namespace Msp { -namespace LinAl { - -template -class Vector2: public Vector -{ -public: - Vector2() { } - Vector2(const T *d): Vector(d) { } - Vector2(T, T); - template - Vector2(const Vector &v): Vector(v) { } -}; - -template -inline Vector2::Vector2(T x, T y) -{ - this->data[0] = x; - this->data[1] = y; -} - -} // namespace LinAl -} // namespace Msp - -#endif diff --git a/source/linal/vector3.h b/source/linal/vector3.h deleted file mode 100644 index 4a623ca..0000000 --- a/source/linal/vector3.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef MSP_LINAL_VECTOR3_H_ -#define MSP_LINAL_VECTOR3_H_ - -#include "vector.h" - -namespace Msp { -namespace LinAl { - -/** -A three-dimensional vector, applicable for Euclidean space. -*/ -template -class Vector3: public Vector -{ -public: - Vector3() { } - Vector3(const T *d): Vector(d) { } - Vector3(T, T, T); - template - Vector3(const Vector &v): Vector(v) { } -}; - -template -inline Vector3::Vector3(T x, T y, T z) -{ - this->data[0] = x; - this->data[1] = y; - this->data[2] = z; -} - -template -inline T dot(const Vector &v1, const Vector &v2) -{ - return inner_product(v1, v2); -} - -template -inline Vector cross(const Vector &v1, const Vector &v2) -{ - return Vector(v1[1]*v2[2]-v1[2]*v2[1], v1[2]*v2[0]-v1[0]*v2[2], v1[0]*v2[1]-v1[1]*v2[0]); -} - -} // namespace LinAl -} // namespace Msp - -#endif diff --git a/tests/box.cpp b/tests/box.cpp index 860bb4e..4e49927 100644 --- a/tests/box.cpp +++ b/tests/box.cpp @@ -1,5 +1,4 @@ #include -#include #include using namespace Msp; @@ -23,12 +22,12 @@ HyperBoxTests::HyperBoxTests() void HyperBoxTests::ray_intersection() { Geometry::Box box(2, 4, 3); - Geometry::Ray ray(LinAl::Vector3(10, 0, 0), LinAl::Vector3(-1, 0, 0)); + Geometry::Ray ray(LinAl::Vector(10, 0, 0), LinAl::Vector(-1, 0, 0)); EXPECT(box.check_intersection(ray)); - ray = Geometry::Ray(LinAl::Vector3(10, 0, 0), LinAl::Vector3(1, 0, 0)); + ray = Geometry::Ray(LinAl::Vector(10, 0, 0), LinAl::Vector(1, 0, 0)); EXPECT(!box.check_intersection(ray)); - ray = Geometry::Ray(LinAl::Vector3(9, 0, 11.45), LinAl::Vector3(-1, 0, -1)); + ray = Geometry::Ray(LinAl::Vector(9, 0, 11.45), LinAl::Vector(-1, 0, -1)); EXPECT(box.check_intersection(ray)); - ray = Geometry::Ray(LinAl::Vector3(9, 0, 11.55), LinAl::Vector3(-1, 0, -1)); + ray = Geometry::Ray(LinAl::Vector(9, 0, 11.55), LinAl::Vector(-1, 0, -1)); EXPECT(!box.check_intersection(ray)); } diff --git a/tests/sphere.cpp b/tests/sphere.cpp index 7d9a4bb..71754f6 100644 --- a/tests/sphere.cpp +++ b/tests/sphere.cpp @@ -1,5 +1,4 @@ #include -#include #include using namespace Msp; @@ -23,12 +22,12 @@ HyperSphereTests::HyperSphereTests() void HyperSphereTests::ray_intersection() { Geometry::Circle circle(1.5); - Geometry::Ray ray(LinAl::Vector2(2.5, 0), LinAl::Vector2(-1, 0)); + Geometry::Ray ray(LinAl::Vector(2.5, 0), LinAl::Vector(-1, 0)); EXPECT(circle.check_intersection(ray)); - ray = Geometry::Ray(LinAl::Vector2(2.5, 0), LinAl::Vector2(1, 0)); + ray = Geometry::Ray(LinAl::Vector(2.5, 0), LinAl::Vector(1, 0)); EXPECT(!circle.check_intersection(ray)); - ray = Geometry::Ray(LinAl::Vector2(2.5, 0), LinAl::Vector2(-4, 2.95)); + ray = Geometry::Ray(LinAl::Vector(2.5, 0), LinAl::Vector(-4, 2.95)); EXPECT(circle.check_intersection(ray)); - ray = Geometry::Ray(LinAl::Vector2(2.5, 0), LinAl::Vector2(-4, 3.05)); + ray = Geometry::Ray(LinAl::Vector(2.5, 0), LinAl::Vector(-4, 3.05)); EXPECT(!circle.check_intersection(ray)); } diff --git a/tests/transformedshape.cpp b/tests/transformedshape.cpp index 5468a73..540e9b8 100644 --- a/tests/transformedshape.cpp +++ b/tests/transformedshape.cpp @@ -23,10 +23,10 @@ TransformedShapeTests::TransformedShapeTests() void TransformedShapeTests::ray_intersection() { Geometry::TransformedShape shape(Geometry::Rectangle(2, 1), Geometry::AffineTransformation::rotation(Geometry::Angle::from_degrees(45))); - Geometry::Ray ray(LinAl::Vector2(3, 1.05), LinAl::Vector2(-1, 0)); + Geometry::Ray ray(LinAl::Vector(3, 1.05), LinAl::Vector(-1, 0)); EXPECT(shape.check_intersection(ray)); - ray = Geometry::Ray(LinAl::Vector2(2.65, 3.35), LinAl::Vector2(-1, -1)); + ray = Geometry::Ray(LinAl::Vector(2.65, 3.35), LinAl::Vector(-1, -1)); EXPECT(shape.check_intersection(ray)); - ray = Geometry::Ray(LinAl::Vector2(2.6, 3.4), LinAl::Vector2(-1, -1)); + ray = Geometry::Ray(LinAl::Vector(2.6, 3.4), LinAl::Vector(-1, -1)); EXPECT(!shape.check_intersection(ray)); }