Blob Blame Raw
#ifndef VECTOR_H
#define VECTOR_H


#include <cmath>
#include "real.h"


class Vector {
public:
	union {
		struct { Real x, y; };
		struct { Real coords[2]; };
	};
	
	explicit Vector(const Real &x = Real(), const Real &y = Real()): x(x), y(y) { }
	
	const Real& operator[] (int i) const { return coords[i]; }
	Real& operator[] (int i) { return coords[i]; }

	bool operator< (const Vector &a) const { return less(x, a.x) || (!less(a.x, x) && less(y, a.y)); }
	bool operator== (const Vector &a) const { return equal(x, a.x) && equal(y, a.y); }
	bool operator!= (const Vector &a) const { return !(*this == a); }

	Vector operator+ (const Vector &a) const { return Vector(x + a.x, y + a.y); }
	Vector operator- (const Vector &a) const { return Vector(x - a.x, y - a.y); }
	Vector operator* (const Real &a) const { return Vector(x*a, y*a); }
	Vector operator/ (const Real &a) const { return *this * (Real(1)/a); }
	
	Vector& operator+= (const Vector &a) { x += a.x; y += a.y; return *this; }
	Vector& operator-= (const Vector &a) { x -= a.x; y -= a.y; return *this; }
	Vector& operator*= (const Real &a) { x *= a; y *= a; return *this; }
	Vector& operator/= (const Real &a) { return *this *= (Real(1)/a); }

	friend inline Vector operator*(const Real &a, const Vector &b) { return b*a; }
	friend inline Real dot(const Vector &a, const Vector &b) { return a.x*b.x + a.y*b.y; }

	bool iszero() const { return *this == Vector(); }
	void reset() { *this = Vector(); }

	Real lensqr() const { return dot(*this, *this); }
	Real len() const { return sqrt(lensqr()); }

	Vector norm() const { return iszero() ? Vector() : *this/len(); }
	Vector perp() const { return Vector(-y, x); }
	Vector scale(const Vector &a) const { return Vector(x*a.x, y*a.y); }
	Vector rotate(const Real &angle) const {
		Vector a = from_angle(angle);
		return Vector(x*a.x - y*a.y, x*a.y + y*a.x);
	}
	
	static Vector from_angle(Real angle)
		{ return Vector(cos(angle), sin(angle)); }
};


class Segment {
public:
	Vector p0, p1, t0, t1;

	explicit Segment(
		const Vector &p0 = Vector(),
		const Vector &p1 = Vector(),
		const Vector &t0 = Vector(),
		const Vector &t1 = Vector()
	):
		p0(p0), p1(p1), t0(t0), t1(t1) { }

	bool operator< (const Segment &a) const {
		return p0 < a.p0 ? true : a.p0 < p0 ? false
			 : p1 < a.p1 ? true : a.p1 < p1 ? false
			 : t0 < a.t0 ? true : a.t0 < t0 ? false
			 : t1 < a.t1;
	}
	bool operator> (const Segment &a) const { return a < *this; }
	bool operator== (const Segment &a) const { return p0 == a.p0 && p1 == a.p1 && t0 == a.t0 && t1 == a.t1; }
	bool operator!= (const Segment &a) const { return !(*this == a); }

	Vector p(const Real &l) const {
		return p0*((( 2.0*l - 3.0)*l      )*l + 1.0)
			 + p1*(((-2.0*l + 3.0)*l      )*l      )
			 + t0*(((     l - 2.0)*l + 1.0)*l      )
			 + t1*(((     l - 1.0)*l      )*l      );
	}

	Vector t(const Real &l) const {
		return p0*(( 6.0*l - 6.0)*l      )
			 + p1*((-6.0*l + 6.0)*l      )
			 + t0*(( 3.0*l - 4.0)*l + 1.0)
			 + t1*(( 3.0*l - 2.0)*l      );
	}

	Vector operator() (const Real &l) const  { return p(l); }
	Segment sub(const Real &a, const Real &b) const { return Segment(p(a), p(b), t(a), t(b)); }
};


#endif