Last active
October 29, 2020 15:47
-
-
Save Midi12/a2d024f0e3340860ec28ffa5af6f36af to your computer and use it in GitHub Desktop.
Geometry vector class example with metaprogramming
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Geometry vector class example with metaprogramming | |
#include <iostream> | |
#include <string> | |
#include <cmath> | |
namespace utils { | |
template <typename type> | |
class property { | |
public: | |
property() = delete; | |
property(type& reference) : _reference(reference) {} | |
property(const property<type>& copy) : _reference(copy._reference) {} | |
property<type>& operator = (const property<type>& other) { | |
return other; | |
} | |
property<type>& operator = (const type& reference) { | |
_reference = reference; | |
return *this; | |
} | |
operator const type& () const { | |
return _reference; | |
} | |
typedef type element_type; | |
private: | |
type& _reference; | |
}; | |
} | |
namespace math { | |
namespace geometry { | |
template <typename type, int size> | |
class basic_vector { | |
public: | |
basic_vector() = default; | |
typedef type element_type; | |
static const int vector_size = size; | |
virtual basic_vector* clone(void) const = 0; | |
virtual bool operator == (const basic_vector& vec) const = 0; | |
virtual basic_vector* operator + (const basic_vector& vec) const = 0; | |
virtual basic_vector* operator - (const basic_vector& vec) const = 0; | |
virtual basic_vector* operator * (const basic_vector& vec) const = 0; | |
virtual basic_vector* operator / (const basic_vector& vec) const = 0; | |
virtual basic_vector& operator += (const basic_vector& vec) = 0; | |
virtual basic_vector& operator -= (const basic_vector& vec) = 0; | |
virtual basic_vector& operator *= (const basic_vector& vec) = 0; | |
virtual basic_vector& operator /= (const basic_vector& vec) = 0; | |
virtual basic_vector* operator + (type value) const = 0; | |
virtual basic_vector* operator - (type value) const = 0; | |
virtual basic_vector* operator * (type value) const = 0; | |
virtual basic_vector* operator / (type value) const = 0; | |
virtual basic_vector& operator += (type value) = 0; | |
virtual basic_vector& operator -= (type value) = 0; | |
virtual basic_vector& operator *= (type value) = 0; | |
virtual basic_vector& operator /= (type value) = 0; | |
virtual void normalize(void) = 0; | |
virtual basic_vector* normalized(void) const = 0; | |
virtual void rotate(type rotation) = 0; | |
virtual basic_vector* rotated(type rotation) const = 0; | |
virtual type length(void) const = 0; | |
virtual basic_vector* orthogonal(void) const = 0; | |
virtual type distance(const basic_vector& vec) const = 0; | |
virtual type dot_product(const basic_vector& vec) = 0; | |
virtual type cross_product(const basic_vector& vec) = 0; | |
protected: | |
element_type _data[size]; | |
}; | |
template<typename type> | |
class vector2 : public basic_vector<type, 2> { | |
public: | |
vector2(type _x, type _y) : x(this->_data[0]), y(this->_data[1]) { | |
this->_data[0] = _x; | |
this->_data[1] = _y; | |
} | |
utils::property<type> x; | |
utils::property<type> y; | |
basic_vector<type, 2>* clone(void) const override { | |
return new vector2<type>(this->x, this->y); | |
} | |
bool operator == (const basic_vector<type, 2>& vec) const override { | |
const vector2 *v = dynamic_cast<const vector2 *>(&vec); | |
return x == v->x && y == v->y; | |
} | |
basic_vector<type, 2>* operator + (const basic_vector<type, 2>& vec) const override { | |
vector2 *tmp = dynamic_cast<vector2 *>(this->clone()); | |
*tmp += vec; | |
return tmp; | |
} | |
basic_vector<type, 2>* operator - (const basic_vector<type, 2>& vec) const override { | |
vector2 *tmp = dynamic_cast<vector2 *>(this->clone()); | |
*tmp -= vec; | |
return tmp; | |
} | |
basic_vector<type, 2>* operator * (const basic_vector<type, 2>& vec) const override { | |
vector2 *tmp = dynamic_cast<vector2 *>(this->clone()); | |
*tmp *= vec; | |
return tmp; | |
} | |
basic_vector<type, 2>* operator / (const basic_vector<type, 2>& vec) const override { | |
vector2 *tmp = dynamic_cast<vector2 *>(this->clone()); | |
*tmp /= vec; | |
return tmp; | |
} | |
basic_vector<type, 2>& operator += (const basic_vector<type, 2>& vec) override { | |
const vector2 *v = dynamic_cast<const vector2 *>(&vec); | |
x = x + v->x; | |
y = y + v->y; | |
return *this; | |
} | |
basic_vector<type, 2>& operator -= (const basic_vector<type, 2>& vec) override { | |
const vector2 *v = dynamic_cast<const vector2 *>(&vec); | |
x = x - v->x; | |
y = y - v->y; | |
return *this; | |
} | |
basic_vector<type, 2>& operator *= (const basic_vector<type, 2>& vec) override { | |
const vector2 *v = dynamic_cast<const vector2 *>(&vec); | |
x = x * v->x; | |
y = y * v->y; | |
return *this; | |
} | |
basic_vector<type, 2>& operator /= (const basic_vector<type, 2>& vec) override { | |
const vector2 *v = dynamic_cast<const vector2 *>(&vec); | |
x = x / v->x; | |
y = y / v->y; | |
return *this; | |
} | |
basic_vector<type, 2>* operator + (type value) const override { | |
vector2 *tmp = dynamic_cast<vector2 *>(this->clone()); | |
*tmp += value; | |
return tmp; | |
} | |
basic_vector<type, 2>* operator - (type value) const override { | |
vector2 *tmp = dynamic_cast<vector2 *>(this->clone()); | |
*tmp -= value; | |
return tmp; | |
} | |
basic_vector<type, 2>* operator * (type value) const override { | |
vector2 *tmp = dynamic_cast<vector2 *>(this->clone()); | |
*tmp *= value; | |
return tmp; | |
} | |
basic_vector<type, 2>* operator / (type value) const override { | |
vector2 *tmp = dynamic_cast<vector2 *>(this->clone()); | |
*tmp /= value; | |
return tmp; | |
} | |
basic_vector<type, 2>& operator += (type value) override { | |
x = x + value; | |
y = y + value; | |
return *this; | |
} | |
basic_vector<type, 2>& operator -= (type value) override { | |
x = x - value; | |
y = y - value; | |
return *this; | |
} | |
basic_vector<type, 2>& operator *= (type value) override { | |
x = x * value; | |
y = y * value; | |
return *this; | |
} | |
basic_vector<type, 2>& operator /= (type value) override { | |
x = x / value; | |
y = y / value; | |
return *this; | |
} | |
void normalize(void) override { | |
if (x == 0 || y == 0) | |
return; | |
type len = length(); | |
x = x / len; | |
y = y / len; | |
} | |
basic_vector<type, 2>* normalized(void) const override { | |
if (x == 0 || y == 0) | |
return new vector2(0, 0); | |
type len = length(); | |
return new vector2<type>(x / len, y / len); | |
} | |
void rotate(type rotation) override { | |
type x1 = x; | |
x = (x * std::cos(rotation)) - (y * std::sin(rotation)); | |
y = (x1 * std::sin(rotation)) + (y * std::cos(rotation)); | |
} | |
basic_vector<type, 2>* rotated(type rotation) const override { | |
return new vector2<type>((x * std::cos(rotation)) - (y * std::sin(rotation)), (x * std::sin(rotation)) + (y * std::cos(rotation))); | |
} | |
type length(void) const override { | |
return std::sqrt(std::pow(x, 2) + std::pow(y, 2)); | |
} | |
virtual basic_vector<type, 2>* orthogonal(void) const override { | |
return new vector2<type>(y, -x); | |
} | |
virtual type distance(const basic_vector<type, 2>& vec) const override { | |
const vector2 *v = dynamic_cast<const vector2 *>(&vec); | |
vector2<type> tmp(v->x - x, v->y - y); | |
return tmp.length(); | |
} | |
type dot_product(const basic_vector<type, 2>& vec) override { | |
const vector2 *v = dynamic_cast<const vector2 *>(&vec); | |
return x * v->x + y * v->y; | |
} | |
type cross_product(const basic_vector<type, 2>& vec) override { | |
const vector2 *v = dynamic_cast<const vector2 *>(&vec); | |
return (x * v->y) - (y * v->x); | |
} | |
}; | |
} | |
} | |
int main() | |
{ | |
math::geometry::vector2<double> vec0(1.0f, -1.0f); | |
std::cout << "vector2<double> vec0(" << vec0.x << ", " << vec0.y << ")" << std::endl; | |
math::geometry::vector2<double> vec1(1.0f, -1.0f); | |
std::cout << "vector2<double> vec1(" << vec1.x << ", " << vec1.y << ")" << std::endl; | |
math::geometry::vector2<double> vec2(2.0f, -2.0f); | |
std::cout << "vector2<double> vec2(" << vec2.x << ", " << vec2.y << ")" << std::endl; | |
std::cout << "vec0 == vec1 " << std::boolalpha << (vec0 == vec1) << std::endl; | |
std::cout << "vec0 == vec2 " << std::boolalpha << (vec0 == vec2) << std::endl; | |
math::geometry::vector2<double> *vec3 = reinterpret_cast<math::geometry::vector2<double> *>(vec0 + static_cast<double>(2.0f)); | |
std::cout << "vector2<double> vec3(" << vec3->x << ", " << vec3->y << ")" << std::endl; | |
vec0 += vec1; | |
std::cout << "vector2<double> vec0(" << vec0.x << ", " << vec0.y << ")" << std::endl; | |
std::cout << "vec0 length : " << vec0.length() << std::endl; | |
std::cout << "vec0 to vec1 distance : " << vec0.distance(vec1) << std::endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment