#ifndef TJG_BASIC_VECTOR_H #define TJG_BASIC_VECTOR_H #pragma once #include #include #include #include namespace tjg_basic { template class Vector; template struct Point { typedef Rep value_type; value_type x, y, z; typedef Vector vector_type; Point() : x(), y(), z() { } Point(value_type x_, value_type y_, value_type z_ = value_type()) : x(x_), y(y_), z(z_) { } template value_type get() const; template<> value_type get<0>() const { return x; } template<> value_type get<1>() const { return y; } template<> value_type get<2>() const { return z; } template void set(value_type v); template<> void set<0>(value_type v) { x = v; } template<> void set<1>(value_type v) { y = v; } template<> void set<2>(value_type v) { z = v; } Point& operator+=(const vector_type& v); Point& operator-=(const vector_type& v); friend bool operator==(const Point& lhs, const Point& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z; } friend bool operator!=(const Point& lhs, const Point& rhs) { return !(lhs == rhs); } }; // Point template struct Vector { typedef Rep value_type; typedef Point point_type; value_type x, y, z; Vector() : x(), y(), z() { } Vector(value_type dx, value_type dy, value_type dz = value_type()) : x(dx), y(dy), z(dz) { } Vector(const point_type& from_, const point_type& to_) : x(to_.x - from_.x), y(to_.y - from_.y), z(to_.z - from_.z) { } template value_type get() const; template<> value_type get<0>() const { return x; } template<> value_type get<1>() const { return y; } template<> value_type get<2>() const { return z; } template void set(value_type v); template<> void set<0>(value_type v) { x = v; } template<> void set<1>(value_type v) { y = v; } template<> void set<2>(value_type v) { z = v; } Vector& operator+=(const Vector& rhs) { x += rhs.x; y += rhs.y; z += rhs.z; return *this; } Vector& operator-=(const Vector& rhs) { x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this; } Vector& operator*=(const value_type& rhs) { x *= rhs; y *= rhs; z *= rhs; return *this; } Vector& operator/=(const value_type& rhs) { x /= rhs; y /= rhs; z /= rhs; return *this; } friend Vector operator+(Vector lhs, const Vector& rhs) { return lhs += rhs; } friend Vector operator-(Vector lhs, const Vector& rhs) { return lhs -= rhs; } friend Vector operator*(Vector lhs, const value_type& rhs) { return lhs *= rhs; } friend Vector operator/(Vector lhs, const value_type& rhs) { return lhs /= rhs; } // dot product friend value_type operator*(const Vector& lhs, const Vector& rhs) { return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z + rhs.z; } friend Vector cross_product(const Vector& lhs, const Vector& rhs) { return Vector(lhs.y * rhs.z - lhs.z * rhs.y, lhs.z * rhs.x - lhs.x * rhs.z, lhs.x * rhs.y - lhs.y * rhs.x); } // cross_product friend point_type operator+(point_type lhs, const Vector& rhs) { lhs.x += rhs.x; lhs.y += rhs.y; lhs.z += rhs.z; return lhs; } friend point_type operator+(const Vector& lhs, point_type rhs) { return rhs + lhs; } friend bool operator==(const Vector& lhs, const Vector& rhs) { return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z; } friend bool operator!=(const Vector& lhs, const Vector& rhs) { return !(lhs == rhs); } friend value_type abs_squared(const Vector& v) { return v.x * v.x + v.y * v.y + v.z * v.z; } friend value_type abs(const Vector& v) { using namespace std; return sqrt(abs_squared(v)); } // Is it a good idea to order Vectors based on their magnitude? friend bool operator<(const Vector& lhs, const Vector& rhs) { return abs_squared(lhs) < abs_squared(rhs); } friend bool operator>(const Vector& lhs, const Vector& rhs) { return rhs < lhs; } friend bool operator>=(const Vector& lhs, const Vector& rhs) { return !(lhs < rhs); } friend bool operator<=(const Vector& lhs, const Vector& rhs) { return !(rhs < lhs); } }; // Vector template inline Point& Point::operator+=(const Vector& rhs) { x += rhs.x; y += rhs.y; z += rhs.z; return *this; } template inline Point& Point::operator-=(const Vector& rhs) { x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this; } template inline Vector operator-(const Point& lhs, const Point& rhs) { return Vector(rhs, lhs); } // boost::units support template inline boost::units::quantity operator*(const boost::units::quantity >& x, const boost::units::quantity >& y) { typedef boost::units::quantity return_type; return return_type::from_value(x.value() * y.value()); } template inline boost::units::quantity > cross_product(const boost::units::quantity >& x, const boost::units::quantity >& y) { typedef boost::units::quantity > return_type; return return_type::from_value(cross_product(x.value(), y.value())); } template inline boost::units::quantity abs(const boost::units::quantity >& v) { return boost::units::quantity::from_value(abs(v.value())); } template inline typename boost::units::power_typeof_helper< boost::units::quantity, boost::units::static_rational<2> > ::type abs_squared(const boost::units::quantity >& v) { typedef typename boost::units::power_typeof_helper< quantity, static_rational<2> >::type return_type; return return_type::from_value(abs_squared(v.value())); } // abs_squared // ostream support template inline std::basic_ostream& operator<<(std::basic_ostream& os, const Point& p) { return os << '(' << p.x << ' ' << p.y << ' ' << p.z << ')'; } template inline std::basic_ostream& operator<<(std::basic_ostream& os, const Vector& v) { return os << '<' << v.x << ' ' << v.y << ' ' << v.z << '>'; } } // tjg_basic #endif