From aa47cdf95914ae706b99a48d528260b3261f9882 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 17 May 2013 13:55:57 +0300 Subject: [PATCH] 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. --- source/geometry/box.h | 3 +- source/geometry/rectangle.h | 3 +- source/linal/dummy.cpp | 2 - source/linal/vector.h | 104 ++++++++++++++++++++++++++++++------ source/linal/vector2.h | 30 ----------- source/linal/vector3.h | 46 ---------------- tests/box.cpp | 9 ++-- tests/sphere.cpp | 9 ++-- tests/transformedshape.cpp | 6 +-- 9 files changed, 102 insertions(+), 110 deletions(-) delete mode 100644 source/linal/vector2.h delete mode 100644 source/linal/vector3.h 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)); } -- 2.43.0