|
|
faaf7d |
/*
|
|
|
faaf7d |
......... 2015 Ivan Mahonin
|
|
|
faaf7d |
|
|
|
faaf7d |
This program is free software: you can redistribute it and/or modify
|
|
|
faaf7d |
it under the terms of the GNU General Public License as published by
|
|
|
faaf7d |
the Free Software Foundation, either version 3 of the License, or
|
|
|
faaf7d |
(at your option) any later version.
|
|
|
faaf7d |
|
|
|
faaf7d |
This program is distributed in the hope that it will be useful,
|
|
|
faaf7d |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
faaf7d |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
faaf7d |
GNU General Public License for more details.
|
|
|
faaf7d |
|
|
|
faaf7d |
You should have received a copy of the GNU General Public License
|
|
|
faaf7d |
along with this program. If not, see <http: licenses="" www.gnu.org="">.</http:>
|
|
|
faaf7d |
*/
|
|
|
faaf7d |
|
|
|
faaf7d |
#ifndef _VECTOR_H_
|
|
|
faaf7d |
#define _VECTOR_H_
|
|
|
faaf7d |
|
|
|
faaf7d |
#include <cmath></cmath>
|
|
|
faaf7d |
|
|
|
faaf7d |
class Vector {
|
|
|
faaf7d |
public:
|
|
|
faaf7d |
typedef float float;
|
|
|
faaf7d |
|
|
|
faaf7d |
private:
|
|
|
faaf7d |
float _x, _y;
|
|
|
faaf7d |
|
|
|
faaf7d |
public:
|
|
|
faaf7d |
Vector(): _x(0.0), _y(0.0) { };
|
|
|
faaf7d |
Vector(const float &x, const float &y):_x(x),_y(y) { };
|
|
|
faaf7d |
Vector(const float &radius, const Angle &angle):
|
|
|
faaf7d |
_x(radius*Angle::cos(angle).get()),
|
|
|
faaf7d |
_y(radius*Angle::sin(angle).get())
|
|
|
faaf7d |
{ };
|
|
|
faaf7d |
|
|
|
faaf7d |
bool is_valid()const { return !(isnan(_x) || isnan(_y)); }
|
|
|
faaf7d |
bool is_nan_or_inf()const { return isnan(_x) || isnan(_y) || isinf(_x) || isinf(_y); }
|
|
|
faaf7d |
|
|
|
faaf7d |
float &
|
|
|
faaf7d |
operator[](const int& i)
|
|
|
faaf7d |
{ return i?_y:_x; }
|
|
|
faaf7d |
|
|
|
faaf7d |
const float &
|
|
|
faaf7d |
operator[](const int& i) const
|
|
|
faaf7d |
{ return i?_y:_x; }
|
|
|
faaf7d |
|
|
|
faaf7d |
const Vector &
|
|
|
faaf7d |
operator+=(const Vector &rhs)
|
|
|
faaf7d |
{
|
|
|
faaf7d |
_x+=rhs._x;
|
|
|
faaf7d |
_y+=rhs._y;
|
|
|
faaf7d |
return *this;
|
|
|
faaf7d |
}
|
|
|
faaf7d |
|
|
|
faaf7d |
const Vector &
|
|
|
faaf7d |
operator-=(const Vector &rhs)
|
|
|
faaf7d |
{
|
|
|
faaf7d |
_x-=rhs._x;
|
|
|
faaf7d |
_y-=rhs._y;
|
|
|
faaf7d |
return *this;
|
|
|
faaf7d |
}
|
|
|
faaf7d |
|
|
|
faaf7d |
const Vector &
|
|
|
faaf7d |
operator*=(const float &rhs)
|
|
|
faaf7d |
{
|
|
|
faaf7d |
_x*=rhs;
|
|
|
faaf7d |
_y*=rhs;
|
|
|
faaf7d |
return *this;
|
|
|
faaf7d |
}
|
|
|
faaf7d |
|
|
|
faaf7d |
const Vector &
|
|
|
faaf7d |
operator/=(const float &rhs)
|
|
|
faaf7d |
{
|
|
|
faaf7d |
float tmp=1.0/rhs;
|
|
|
faaf7d |
_x*=tmp;
|
|
|
faaf7d |
_y*=tmp;
|
|
|
faaf7d |
return *this;
|
|
|
faaf7d |
}
|
|
|
faaf7d |
|
|
|
faaf7d |
Vector
|
|
|
faaf7d |
operator+(const Vector &rhs)const
|
|
|
faaf7d |
{ return Vector(*this)+=rhs; }
|
|
|
faaf7d |
|
|
|
faaf7d |
Vector
|
|
|
faaf7d |
operator-(const Vector &rhs)const
|
|
|
faaf7d |
{ return Vector(*this)-=rhs; }
|
|
|
faaf7d |
|
|
|
faaf7d |
Vector
|
|
|
faaf7d |
operator*(const float &rhs)const
|
|
|
faaf7d |
{ return Vector(*this)*=rhs; }
|
|
|
faaf7d |
|
|
|
faaf7d |
Vector
|
|
|
faaf7d |
operator/(const float &rhs)const
|
|
|
faaf7d |
{ return Vector(*this)/=rhs; }
|
|
|
faaf7d |
|
|
|
faaf7d |
Vector
|
|
|
faaf7d |
operator-()const
|
|
|
faaf7d |
{ return Vector(-_x,-_y); }
|
|
|
faaf7d |
|
|
|
faaf7d |
float
|
|
|
faaf7d |
operator*(const Vector &rhs)const
|
|
|
faaf7d |
{ return _x*rhs._x+_y*rhs._y; }
|
|
|
faaf7d |
|
|
|
faaf7d |
bool
|
|
|
faaf7d |
operator==(const Vector &rhs)const
|
|
|
faaf7d |
{ return _x==rhs._x && _y==rhs._y; }
|
|
|
faaf7d |
|
|
|
faaf7d |
bool
|
|
|
faaf7d |
operator!=(const Vector &rhs)const
|
|
|
faaf7d |
{ return _y!=rhs._y || _x!=rhs._x; }
|
|
|
faaf7d |
|
|
|
faaf7d |
//! Returns the squared magnitude of the vector
|
|
|
faaf7d |
float mag_squared()const
|
|
|
faaf7d |
{ return _x*_x+_y*_y; }
|
|
|
faaf7d |
|
|
|
faaf7d |
//! Returns the magnitude of the vector
|
|
|
faaf7d |
float mag()const
|
|
|
faaf7d |
{ return sqrt(mag_squared()); }
|
|
|
faaf7d |
|
|
|
faaf7d |
//! Returns the reciprocal of the magnitude of the vector
|
|
|
faaf7d |
float inv_mag()const
|
|
|
faaf7d |
{ return 1.0/sqrt(mag_squared()); }
|
|
|
faaf7d |
|
|
|
faaf7d |
//! Returns a normalized version of the vector
|
|
|
faaf7d |
Vector norm()const
|
|
|
faaf7d |
{ return (*this)*inv_mag(); }
|
|
|
faaf7d |
|
|
|
faaf7d |
//! Returns a perpendicular version of the vector
|
|
|
faaf7d |
Vector perp()const
|
|
|
faaf7d |
{ return Vector(_y,-_x); }
|
|
|
faaf7d |
|
|
|
faaf7d |
Angle angle()const
|
|
|
faaf7d |
{ return Angle::rad(atan2(_y, _x)); }
|
|
|
faaf7d |
|
|
|
faaf7d |
bool is_equal_to(const Vector& rhs)const
|
|
|
faaf7d |
{
|
|
|
faaf7d |
static const float epsilon(0.0000000000001);
|
|
|
faaf7d |
// return (_x>rhs._x)?_x-rhs._x<=epsilon:rhs._x-_x<=epsilon && (_y>rhs._y)?_y-rhs._y<=epsilon:rhs._y-_y<=epsilon;
|
|
|
faaf7d |
return (*this-rhs).mag_squared()<=epsilon;
|
|
|
faaf7d |
}
|
|
|
faaf7d |
|
|
|
faaf7d |
static const Vector zero() { return Vector(0,0); }
|
|
|
faaf7d |
|
|
|
faaf7d |
Vector multiply_coords(const Vector &rhs) const
|
|
|
faaf7d |
{ return Vector(_x*rhs._x, _y*rhs._y); }
|
|
|
faaf7d |
Vector divide_coords(const Vector &rhs) const
|
|
|
faaf7d |
{ return Vector(_x/rhs._x, _y/rhs._y); }
|
|
|
faaf7d |
Vector one_divide_coords() const
|
|
|
faaf7d |
{ return Vector(1.0/_x, 1.0/_y); }
|
|
|
faaf7d |
Vector rotate(const Angle &rhs) const
|
|
|
faaf7d |
{
|
|
|
faaf7d |
float s = Angle::sin(rhs).get();
|
|
|
faaf7d |
float c = Angle::cos(rhs).get();
|
|
|
faaf7d |
return Vector(c*_x - s*_y, s*_x + c*_y);
|
|
|
faaf7d |
}
|
|
|
faaf7d |
};
|
|
|
faaf7d |
|
|
|
faaf7d |
/*! \typedef Point
|
|
|
faaf7d |
** \todo writeme
|
|
|
faaf7d |
*/
|
|
|
faaf7d |
typedef Vector Point;
|
|
|
faaf7d |
|
|
|
faaf7d |
|
|
|
faaf7d |
|
|
|
faaf7d |
}; // END of namespace synfig
|
|
|
faaf7d |
|
|
|
faaf7d |
namespace std {
|
|
|
faaf7d |
|
|
|
faaf7d |
inline synfig::Vector::float
|
|
|
faaf7d |
abs(const synfig::Vector &rhs)
|
|
|
faaf7d |
{ return rhs.mag(); }
|
|
|
faaf7d |
|
|
|
faaf7d |
}; // END of namespace std
|
|
|
faaf7d |
|
|
|
faaf7d |
#include <etl bezier=""></etl>
|
|
|
faaf7d |
|
|
|
faaf7d |
_ETL_BEGIN_NAMESPACE
|
|
|
faaf7d |
|
|
|
faaf7d |
template <>
|
|
|
faaf7d |
class bezier_base<synfig::vector,float> : public std::unary_function<float,synfig::vector></float,synfig::vector></synfig::vector,float>
|
|
|
faaf7d |
{
|
|
|
faaf7d |
public:
|
|
|
faaf7d |
typedef synfig::Vector float;
|
|
|
faaf7d |
typedef float time_type;
|
|
|
faaf7d |
private:
|
|
|
faaf7d |
|
|
|
faaf7d |
bezier_base<synfig::vector::float,time_type> bezier_x,bezier_y;</synfig::vector::float,time_type>
|
|
|
faaf7d |
|
|
|
faaf7d |
float a,b,c,d;
|
|
|
faaf7d |
|
|
|
faaf7d |
protected:
|
|
|
faaf7d |
affine_combo<float,time_type> affine_func;</float,time_type>
|
|
|
faaf7d |
|
|
|
faaf7d |
public:
|
|
|
faaf7d |
bezier_base() { }
|
|
|
faaf7d |
bezier_base(
|
|
|
faaf7d |
const float &a, const float &b, const float &c, const float &d,
|
|
|
faaf7d |
const time_type &r=0.0, const time_type &s=1.0):
|
|
|
faaf7d |
a(a),b(b),c(c),d(d) { set_rs(r,s); sync(); }
|
|
|
faaf7d |
|
|
|
faaf7d |
void sync()
|
|
|
faaf7d |
{
|
|
|
faaf7d |
bezier_x[0]=a[0],bezier_y[0]=a[1];
|
|
|
faaf7d |
bezier_x[1]=b[0],bezier_y[1]=b[1];
|
|
|
faaf7d |
bezier_x[2]=c[0],bezier_y[2]=c[1];
|
|
|
faaf7d |
bezier_x[3]=d[0],bezier_y[3]=d[1];
|
|
|
faaf7d |
bezier_x.sync();
|
|
|
faaf7d |
bezier_y.sync();
|
|
|
faaf7d |
}
|
|
|
faaf7d |
|
|
|
faaf7d |
float
|
|
|
faaf7d |
operator()(time_type t)const
|
|
|
faaf7d |
{
|
|
|
faaf7d |
return synfig::Vector(bezier_x(t),bezier_y(t));
|
|
|
faaf7d |
}
|
|
|
faaf7d |
|
|
|
faaf7d |
void evaluate(time_type t, float &f, float &df) const
|
|
|
faaf7d |
{
|
|
|
faaf7d |
t=(t-get_r())/get_dt();
|
|
|
faaf7d |
|
|
|
faaf7d |
const float p1 = affine_func(
|
|
|
faaf7d |
affine_func(a,b,t),
|
|
|
faaf7d |
affine_func(b,c,t)
|
|
|
faaf7d |
,t);
|
|
|
faaf7d |
const float p2 = affine_func(
|
|
|
faaf7d |
affine_func(b,c,t),
|
|
|
faaf7d |
affine_func(c,d,t)
|
|
|
faaf7d |
,t);
|
|
|
faaf7d |
|
|
|
faaf7d |
f = affine_func(p1,p2,t);
|
|
|
faaf7d |
df = (p2-p1)*3;
|
|
|
faaf7d |
}
|
|
|
faaf7d |
|
|
|
faaf7d |
void set_rs(time_type new_r, time_type new_s) { bezier_x.set_rs(new_r,new_s); bezier_y.set_rs(new_r,new_s); }
|
|
|
faaf7d |
void set_r(time_type new_r) { bezier_x.set_r(new_r); bezier_y.set_r(new_r); }
|
|
|
faaf7d |
void set_s(time_type new_s) { bezier_x.set_s(new_s); bezier_y.set_s(new_s); }
|
|
|
faaf7d |
const time_type &get_r()const { return bezier_x.get_r(); }
|
|
|
faaf7d |
const time_type &get_s()const { return bezier_x.get_s(); }
|
|
|
faaf7d |
time_type get_dt()const { return bezier_x.get_dt(); }
|
|
|
faaf7d |
|
|
|
faaf7d |
float &
|
|
|
faaf7d |
operator[](int i)
|
|
|
faaf7d |
{ return (&a)[i]; }
|
|
|
faaf7d |
|
|
|
faaf7d |
const float &
|
|
|
faaf7d |
operator[](int i) const
|
|
|
faaf7d |
{ return (&a)[i]; }
|
|
|
faaf7d |
|
|
|
faaf7d |
//! Bezier curve intersection function
|
|
|
faaf7d |
time_type intersect(const bezier_base<float,time_type> &/*x*/, time_type /*near*/=0.0)const</float,time_type>
|
|
|
faaf7d |
{
|
|
|
faaf7d |
return 0;
|
|
|
faaf7d |
}
|
|
|
faaf7d |
};
|
|
|
faaf7d |
|
|
|
faaf7d |
#endif
|