Skip to content

Commit

Permalink
Improve Rect class
Browse files Browse the repository at this point in the history
  • Loading branch information
blackwarthog authored and morevnaproject committed Mar 1, 2016
1 parent 37edfa5 commit 6105cae
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 7 deletions.
98 changes: 98 additions & 0 deletions ETL/ETL/_rect.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,104 @@ void set_union(rect<T> &rout, const rect<T> &r1, const rect<T> &r2)
rout = local;*/
}

template<typename List, typename T, typename F>
void rects_subtract(List &list, const rect<T> &r, const F &less)
{
if (!r.valid(less)) return;
for(typename List::iterator i = list.begin(); i != list.end();)
{
if (intersect(*i, r))
{
rect<T> &x = *i;
rect<T> y;
y.minx = std::max(x.minx, r.maxx);
y.maxx = std::min(x.maxx, r.minx);
y.miny = std::max(x.miny, r.maxy);
y.maxy = std::min(x.maxy, r.miny);

T rects[][4] = {
{ x.minx, x.maxx, x.miny, x.maxy },
{ y.minx, r.maxx, x.miny, x.maxy },
{ y.minx, x.maxx, x.miny, y.maxy },
{ y.minx, x.maxx, y.miny, x.maxy }
};

const int count = sizeof(rects)/sizeof(rects[0]);

bool inserted = false;
for(int j = 0; j < count; ++j)
{
if ( less(rects[j][0], rects[j][1])
&& less(rects[j][2], rects[j][3]) )
{
rect<T> rr;
rr.minx = rects[i][0];
rr.maxx = rects[i][1];
rr.miny = rects[i][2];
rr.maxy = rects[i][3];
if (inserted)
i = list.insert(++i, rr);
else
*i = rr, inserted = true;
}
}
if (!inserted) i = list.erase(i); continue;
}
++i;
}
}

template<typename List, typename T>
void rects_subtract(List &list, const rect<T> &r)
{ rects_subtract(list, r, std::less<T>()); }

template<typename List, typename T, typename F>
void rects_add(List &list, const rect<T> &r, const F &less)
{
if (!r.valid(less)) return;
rects_subtract(list, r, less);
list.insert(list.end(), r);
}

template<typename List, typename T>
void rects_add(List &list, const rect<T> &r)
{ rects_add(list, r, std::less<T>()); }

template<typename List, typename F>
void rects_merge(List &list, const F &less)
{
for(typename List::iterator i = list.begin(); i != list.end();)
if (!i->valid(less)) i = list.erase(i); else ++i;

bool merged_any = true;
while(merged_any)
{
merged_any = false;
for(typename List::iterator i = list.begin(); i != list.end();)
{
bool merged_current = false;
for(typename List::iterator j = list.begin(); j != list.end(); ++j)
if ( !less(i->minx, j->minx) && !less(j->minx, i->minx)
&& !less(i->maxy, j->miny) && !less(j->miny, i->maxy) )
{
j->miny = i->miny;
i = list.erase(i);
merged_current = true;
break;
}
if (merged_current) merged_any = true; else ++i;
}
}
}

template<typename List>
void rects_merge(List &list)
{
typedef typename List::value_type R;
typedef typename R::value_type T;
rects_merge(list, std::less<T>());
}

_ETL_END_NAMESPACE

/* === E X T E R N S ======================================================= */
Expand Down
84 changes: 84 additions & 0 deletions synfig-core/src/synfig/real.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,95 @@

namespace synfig {


/*! \typedef Real
** \todo writeme
*/
typedef double Real;


template<typename T = Real>
inline T real_low_precision()
{ return T(1e-6); }
template<typename T = Real>
inline T real_precision()
{ return T(1e-8); }
template<typename T = Real>
inline T real_high_precision()
{ return T(1e-10); }


// comparison should be symmetric
// approximate_equal(a, b) absolutely identical to approximate_equal(b, a)
// this code should be equal to code of functions less and less_or_equal
template<typename T>
inline bool approximate_equal_custom(const T &a, const T &b, const T &precision)
{ return a < b ? b - a < precision : a - b < precision; }
template<typename T>
inline bool approximate_less_custom(const T &a, const T &b, const T &precision)
{ return a < b && b - a >= precision; }
template<typename T>
inline bool approximate_greater_custom(const T &a, const T &b, const T &precision)
{ return approximate_less(b, a, precision); }
template<typename T>
inline bool approximate_less_or_equal_custom(const T &a, const T &b, const T &precision)
{ return a < b || a - b < precision; }
template<typename T>
inline bool approximate_greater_or_equal_custom(const T &a, const T &b, const T &precision)
{ return approximate_less_or_equal(b, a, precision); }


template< typename T, T func() = real_precision<T> >
inline bool approximate_equal(const T &a, const T &b)
{ return approximate_equal_custom(a, b, func()); }
template< typename T, T func() = real_precision<T> >
inline bool approximate_less(const T &a, const T &b)
{ return approximate_less_custom(a, b, func()); }
template< typename T, T func() = real_precision<T> >
inline bool approximate_greater(const T &a, const T &b)
{ return approximate_greater_custom(a, b, func()); }
template< typename T, T func() = real_precision<T> >
inline bool approximate_less_or_equal(const T &a, const T &b)
{ return approximate_less_or_equal_custom(a, b, func()); }
template< typename T, T func() = real_precision<T> >
inline bool approximate_greater_or_equal(const T &a, const T &b)
{ return approximate_greater_or_equal_custom(a, b, func()); }


template<typename T>
inline bool approximate_equal_lp(const T &a, const T &b)
{ return approximate_equal_custom(a, b, real_low_precision<T>()); }
template<typename T>
inline bool approximate_less_lp(const T &a, const T &b)
{ return approximate_less_custom(a, b, real_low_precision()); }
template<typename T>
inline bool approximate_greater_lp(const T &a, const T &b)
{ return approximate_greater_custom(a, b, real_low_precision()); }
template<typename T>
inline bool approximate_less_or_equal_lp(const T &a, const T &b)
{ return approximate_less_or_equal_custom(a, b, real_low_precision()); }
template<typename T>
inline bool approximate_greater_or_equal_lp(const T &a, const T &b)
{ return approximate_greater_or_equal_custom(a, b, real_low_precision()); }


template<typename T>
inline bool approximate_equal_hp(const T &a, const T &b)
{ return approximate_equal_custom(a, b, real_high_precision<T>()); }
template<typename T>
inline bool approximate_less_hp(const T &a, const T &b)
{ return approximate_less_custom(a, b, real_high_precision()); }
template<typename T>
inline bool approximate_greater_hp(const T &a, const T &b)
{ return approximate_greater_custom(a, b, real_high_precision()); }
template<typename T>
inline bool approximate_less_or_equal_hp(const T &a, const T &b)
{ return approximate_less_or_equal_custom(a, b, real_high_precision()); }
template<typename T>
inline bool approximate_greater_or_equal_hp(const T &a, const T &b)
{ return approximate_greater_or_equal_custom(a, b, real_high_precision()); }


}; // END of namespace synfig

/* === E N D =============================================================== */
Expand Down
26 changes: 26 additions & 0 deletions synfig-core/src/synfig/rect.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,22 @@ class RectInt : public etl::rect<int>

bool operator!=(const RectInt &rhs)const { return get_min() != rhs.get_min() || get_max() != rhs.get_max(); }

bool contains(const RectInt &x) { return etl::contains(*this, x); }

bool is_valid()const { return valid(); }

template<typename List>
static void merge(List &list)
{ etl::rects_merge(list); }

template<typename List>
void list_add(List &list)
{ etl::rects_add(list, *this); merge(list); }

template<typename List>
void list_subtract(List &list)
{ etl::rects_subtract(list, *this); merge(list); }

RectInt multiply_coords(const VectorInt &rhs) const
{ return RectInt(minx*rhs[0], miny*rhs[1], maxx*rhs[0], maxy*rhs[1]); }
RectInt divide_coords(const VectorInt &rhs) const
Expand Down Expand Up @@ -330,6 +344,18 @@ class Rect : public etl::rect<Real>
|| std::isinf(maxy);
}

template<typename List>
static void merge(List &list)
{ etl::rects_merge(list, approximate_less<Real>); }

template<typename List>
void list_add(List &list)
{ etl::rects_add(list, *this, approximate_less<Real>); merge(list); }

template<typename List>
void list_subtract(List &list)
{ etl::rects_subtract(list, *this, approximate_less<Real>); merge(list); }

Rect multiply_coords(const Vector &rhs) const
{ return Rect(minx*rhs[0], miny*rhs[1], maxx*rhs[0], maxy*rhs[1]); }
Rect divide_coords(const Vector &rhs) const
Expand Down
10 changes: 3 additions & 7 deletions synfig-core/src/synfig/vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,11 +258,11 @@ class Vector

bool
operator==(const Vector &rhs)const
{ return _x==rhs._x && _y==rhs._y; }
{ return is_equal_to(rhs); }

bool
operator!=(const Vector &rhs)const
{ return _y!=rhs._y || _x!=rhs._x; }
{ return !(*this == rhs); }

//! Returns the squared magnitude of the vector
value_type mag_squared()const
Expand All @@ -288,11 +288,7 @@ class Vector
{ return Angle::rad(atan2(_y, _x)); }

bool is_equal_to(const Vector& rhs)const
{
static const value_type epsilon(0.0000000000001);
// return (_x>rhs._x)?_x-rhs._x<=epsilon:rhs._x-_x<=epsilon && (_y>rhs._y)?_y-rhs._y<=epsilon:rhs._y-_y<=epsilon;
return (*this-rhs).mag_squared()<=epsilon;
}
{ return approximate_equal((*this-rhs).mag_squared(), value_type(0.0)); }

static Vector zero() { return Vector(0,0); }

Expand Down

0 comments on commit 6105cae

Please sign in to comment.