Skip to content

Instantly share code, notes, and snippets.

@Midi12
Last active October 29, 2020 15:47
Show Gist options
  • Save Midi12/a2d024f0e3340860ec28ffa5af6f36af to your computer and use it in GitHub Desktop.
Save Midi12/a2d024f0e3340860ec28ffa5af6f36af to your computer and use it in GitHub Desktop.
Geometry vector class example with metaprogramming
// 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