diff --git a/toonz/sources/common/tgeometry/tgeometry.cpp b/toonz/sources/common/tgeometry/tgeometry.cpp index bef8959..882bc68 100644 --- a/toonz/sources/common/tgeometry/tgeometry.cpp +++ b/toonz/sources/common/tgeometry/tgeometry.cpp @@ -355,6 +355,8 @@ TAffine4 TAffine4::rotationZ(double angle) { //================================================================================================== +const TAngleRangeSet::Type TAngleRangeSet::Iterator::m_blank = TAngleRangeSet::Type(); + int TAngleRangeSet::find(Type a) const { assert(!m_angles.empty()); @@ -373,7 +375,7 @@ void TAngleRangeSet::insert(Type a) { int i = find(a); if (m_angles[i] == a) m_angles.erase(m_angles.begin() + i); else if (a < m_angles[0]) m_angles.insert(m_angles.begin(), a); else - m_angles.insert(m_angles.begin()+1, a); + m_angles.insert(m_angles.begin()+i+1, a); } bool TAngleRangeSet::doAdd(Type a0, Type a1) { @@ -444,7 +446,7 @@ void TAngleRangeSet::set(Type a0, Type a1) { } } -void TAngleRangeSet::set(const TAngleRangeSet &x, bool flip = false) { +void TAngleRangeSet::set(const TAngleRangeSet &x, bool flip) { if (&x == this) return; m_flip = (x.isFlipped() != flip); m_angles = x.angles(); @@ -478,11 +480,8 @@ void TAngleRangeSet::add(const TAngleRangeSet &x) { if (&x == this || isFull() || x.isEmpty()) return; if (isEmpty()) { set(x); return; } if (x.isFull()) { fill(); return; } - bool f = x.isFlipped(); - Type prev = x.angles().back(); - for(List::const_iterator i = x.angles().begin(); i != x.angles().end(); ++i) - if (f && doAdd(prev, *i)) return; - else { prev = *i; f = !f; } + for(Iterator i(x); i; ++i) + if (doAdd(i.a0(), i.a1())) return; } void TAngleRangeSet::subtract(Type a0, Type a1) { @@ -499,11 +498,8 @@ void TAngleRangeSet::subtract(const TAngleRangeSet &x) { // a - b = !(!a + b) invert(); - bool f = x.isFlipped(); - Type prev = x.angles().back(); - for(List::const_iterator i = x.angles().begin(); i != x.angles().end(); ++i) - if (f && doAdd(prev, *i)) return; - else { prev = *i; f = !f; } + for(Iterator i(x); i; ++i) + if (doAdd(i.a0(), i.a1())) return; invert(); } @@ -520,13 +516,9 @@ void TAngleRangeSet::intersect(const TAngleRangeSet &x) { if (x.isEmpty()) { clear(); return; } if (isFull()) { set(x); return; } - // a & b = !(!a + b) + // a & b = !(!a + !b) invert(); - bool f = !x.isFlipped(); - Type prev = x.angles().back(); - for(List::const_iterator i = x.angles().begin(); i != x.angles().end(); ++i) - if (f && doAdd(prev, *i)) return; - else { prev = *i; f = !f; } + for(Iterator i(x, true); i; ++i) + if (doAdd(i.a0(), i.a1())) return; invert(); } - diff --git a/toonz/sources/include/tgeometry.h b/toonz/sources/include/tgeometry.h index aab04ec..d22a047 100644 --- a/toonz/sources/include/tgeometry.h +++ b/toonz/sources/include/tgeometry.h @@ -1327,6 +1327,137 @@ public: inline Range flip() const { return Range(a1, a0); } }; + struct Iterator { + private: + bool m_flip; + List::const_iterator m_prebegin; + List::const_iterator m_begin; + List::const_iterator m_end; + List::const_iterator m_current; + bool m_lapped; + static const Type m_blank; + + public: + inline Iterator(): m_flip(), m_lapped(true) + { reset(); } + inline explicit Iterator(const List &list, bool flip = false, bool reverse = false) + { set(list, flip, reverse); } + inline explicit Iterator(const TAngleRangeSet &ranges, bool flip = false, bool reverse = false) + { set(ranges, flip, reverse); } + + inline Iterator& set(bool full) { + m_flip = full; m_lapped = !m_flip; + m_current = m_prebegin = m_begin = m_end = List::const_iterator(); + return *this; + } + + inline Iterator& reset() + { return set(false); } + + inline Iterator& set(const List &list, bool flip = false, bool reverse = false) { + assert(list.size()%2 == 0); + if (list.empty()) { + set(flip); + } else { + m_flip = flip; + m_lapped = false; + if (flip) { + m_prebegin = list.end() - 1; + m_begin = list.begin(); + m_end = m_prebegin - 1; + } else { + m_prebegin = list.begin(); + m_begin = m_prebegin + 1; + m_end = list.end() - 1; + } + } + m_current = reverse ? m_end : m_begin; + return *this; + } + + inline Iterator& set(const TAngleRangeSet &ranges, bool flip = false, bool reverse = false) + { return set(ranges.angles(), ranges.isFlipped() != flip, reverse); } + + inline const Type& a0() const + { return valid() ? *(m_current == m_begin ? m_prebegin : m_current - 1) : m_blank; } + inline const Type& a1() const + { return valid() ? *m_current : m_blank; } + inline double d0() const + { return toDouble(a0()); } + inline double d1() const + { return toDouble(a1()); } + inline double d1greater() const { + return !valid() ? (m_flip ? M_PI : -M_PI) + : m_current == m_begin && m_prebegin > m_begin + ? toDouble(*m_current) + M_2PI : toDouble(*m_current); + } + inline Range range() const + { return Range(a0(), a1()); } + inline int size() const + { return (m_end - m_begin)/2 + 1; } + inline int index() const + { return (m_current - m_begin)/2; } + inline int reverseIndex() const + { int i = index(); return i == 0 ? 0 : size() - i; } + inline bool lapped() const + { return m_lapped; } + inline bool valid() const + { return m_prebegin != m_begin; } + inline bool isFull() const + { return !valid() && m_flip; } + inline bool isEmpty() const + { return !valid() && !m_flip; } + + inline operator bool() const + { return !m_lapped; } + + inline Iterator& operator++() { + if (!valid()) { m_lapped = true; return *this; } + m_lapped = (m_current == m_end); + if (m_lapped) m_current = m_begin; else m_current += 2; + return *this; + } + + inline Iterator& operator--() { + if (!valid()) { m_lapped = true; return *this; } + m_lapped = (m_current == m_end); + if (m_lapped) m_current = m_end; else m_current -= 2; + return *this; + } + + inline Iterator& operator += (int i) { + if (i == 0) { m_lapped = isEmpty(); return *this; } + if (!valid()) { m_lapped = true; return *this; } + int ii = index(); + int s = size(); + if (ii + i >= 0 && ii + i < s) { + m_current += i*2; + m_lapped = false; + } else { + m_current = m_begin + ((ii + s + i%s)%s)*2; + m_lapped = true; + } + return *this; + } + + inline int operator-(const Iterator &i) const { + assert(m_flip == i.m_flip && m_begin == i.m_begin && m_end == i.m_end && m_prebegin == i.m_prebegin); + int ii = m_current - i.m_current; + return ii < 0 ? ii + size() : ii; + } + + inline Iterator operator++() const + { Iterator copy(*this); ++(*this); return copy; } + inline Iterator operator--() const + { Iterator copy(*this); --(*this); return copy; } + inline Iterator& operator -= (int i) + { return (*this) += -i; } + inline Iterator operator+(int i) const + { Iterator ii(*this); return ii += i; } + inline Iterator operator-(int i) const + { Iterator ii(*this); return ii -= i; } + }; + private: bool m_flip; List m_angles;