#include #include #include #include #include #include #include "defs.hh" #include "bboxset.hh" using namespace std; // Constructors template bboxset::bboxset () { assert (invariant()); } template bboxset::bboxset (const box& b) { if (!b.empty()) bs.insert(b); assert (invariant()); } template bboxset::bboxset (const bboxset& s): bs(s.bs) { assert (invariant()); } template bboxset::bboxset (const bset& bs_): bs(bs_) { assert (invariant()); } // Invariant template bool bboxset::invariant () const { // This is very slow when there are many bboxes #if 0 for (const_iterator bi=begin(); bi!=end(); ++bi) { if ((*bi).empty()) return false; if (! (*bi).is_aligned_with(*bs.begin())) return false; // check for overlap (quadratic -- expensive) for (const_iterator bi2=begin(); bi2!=bi; ++bi2) { if (! ((*bi2) & (*bi)).empty()) return false; } } #endif return true; } // Normalisation template void bboxset::normalize () { assert (invariant()); bboxset const oldbs = * this; int const oldsize = this->size(); // Split all bboxes into small pieces which have all their // boundaries aligned. for (int d=0; d sbnds; for (typename bset::const_iterator si = bs.begin(); si != bs.end(); ++ si) { box const & b = * si; int const bstr = b.stride()[d]; int const blo = b.lower()[d]; int const bhi = b.upper()[d] + bstr; sbnds.insert (blo); sbnds.insert (bhi); } // Split bboxes bset nbs; for (typename bset::const_iterator si = bs.begin(); si != bs.end(); ++ si) { box const & b = * si; int const bstr = b.stride()[d]; int const blo = b.lower()[d]; int const bhi = b.upper()[d] + bstr; typename set::const_iterator const ilo = find (sbnds.begin(), sbnds.end(), blo); typename set::const_iterator const ihi = find (sbnds.begin(), sbnds.end(), bhi); assert (ilo != sbnds.end()); assert (ihi != sbnds.end()); assert (* ilo == blo); assert (* ihi == bhi); // Split one bbox for (typename set::const_iterator curr = ilo; curr != ihi; ++ curr) { typename set::const_iterator next = curr; advance (next, 1); int const nblo = * curr; int const nbhi = * next; box nb (b.lower().replace(d, nblo), b.upper().replace(d, nbhi - bstr), b.stride()); nbs.insert (nb); } } // Replace old set bs.swap (nbs); assert (invariant()); } // Combine bboxes if possible for (int d=0; dsize(); assert (*this == oldbs); assert (newsize <= oldsize); } // Accessors template T bboxset::size () const { T s=0; for (const_iterator bi=begin(); bi!=end(); ++bi) { const T bsz = (*bi).size(); assert (numeric_limits::max() - bsz >= s); s += bsz; } return s; } // Add (bboxes that don't overlap) template bboxset& bboxset::operator+= (const box& b) { if (b.empty()) return *this; // check for overlap for (const_iterator bi=begin(); bi!=end(); ++bi) { assert ((*bi & b).empty()); } bs.insert(b); assert (invariant()); return *this; } template bboxset& bboxset::operator+= (const bboxset& s) { for (const_iterator bi=s.begin(); bi!=s.end(); ++bi) { *this += *bi; } assert (invariant()); return *this; } template bboxset bboxset::operator+ (const box& b) const { bboxset r(*this); r += b; assert (r.invariant()); return r; } template bboxset bboxset::operator+ (const bboxset& s) const { bboxset r(*this); r += s; assert (r.invariant()); return r; } template bboxset bboxset::plus (const bbox& b1, const bbox& b2) { return bboxset(b1) + b2; } template bboxset bboxset::plus (const bbox& b, const bboxset& s) { return s + b; } // Union template bboxset& bboxset::operator|= (const box& b) { *this += b - *this; assert (invariant()); return *this; } template bboxset& bboxset::operator|= (const bboxset& s) { *this += s - *this; assert (invariant()); return *this; } template bboxset bboxset::operator| (const box& b) const { bboxset r(*this); r |= b; assert (r.invariant()); return r; } template bboxset bboxset::operator| (const bboxset& s) const { bboxset r(*this); r |= s; assert (r.invariant()); return r; } // Intersection template bboxset bboxset::operator& (const box& b) const { // start with an empty set bboxset r; // walk all my elements for (const_iterator bi=begin(); bi!=end(); ++bi) { // insert the intersection with the bbox r += *bi & b; } assert (r.invariant()); return r; } template bboxset bboxset::operator& (const bboxset& s) const { // start with an empty set bboxset r; // walk all the bboxes for (const_iterator bi=s.begin(); bi!=s.end(); ++bi) { // insert the intersection with this bbox r += *this & *bi; } assert (r.invariant()); return r; } template bboxset& bboxset::operator&= (const box& b) { *this = *this & b; assert (invariant()); return *this; } template bboxset& bboxset::operator&= (const bboxset& s) { *this = *this & s; assert (invariant()); return *this; } // Difference template bboxset bboxset::minus (const bbox& b1, const bbox& b2) { assert (b1.is_aligned_with(b2)); if (b1.empty()) return bboxset(); if (b2.empty()) return bboxset(b1); const vect str = b1.stride(); bboxset r; for (int d=0; d lb, ub; bbox b; for (int dd=0; ddd) { lb[dd] = b1.lower()[dd]; ub[dd] = b1.upper()[dd]; } } lb[d] = b1.lower()[d]; ub[d] = b2.lower()[d] - str[d]; b = bbox(lb,ub,str) & b1; r += b; lb[d] = b2.upper()[d] + str[d]; ub[d] = b1.upper()[d]; b = bbox(lb,ub,str) & b1; r += b; } assert (r.invariant()); return r; } template bboxset bboxset::operator- (const box& b) const { // start with an empty set bboxset r; // walk all my elements for (const_iterator bi=begin(); bi!=end(); ++bi) { // insert the difference with the bbox r += *bi - b; } assert (r.invariant()); return r; } template bboxset& bboxset::operator-= (const box& b) { *this = *this - b; assert (invariant()); return *this; } template bboxset& bboxset::operator-= (const bboxset& s) { for (const_iterator bi=s.begin(); bi!=s.end(); ++bi) { *this -= *bi; } assert (invariant()); return *this; } template bboxset bboxset::operator- (const bboxset& s) const { bboxset r(*this); r -= s; assert (r.invariant()); return r; } template bboxset bboxset::minus (const bbox& b, const bboxset& s) { bboxset r = bboxset(b) - s; assert (r.invariant()); return r; } // Equality template bool bboxset::operator<= (const bboxset& s) const { return (*this - s).empty(); } template bool bboxset::operator< (const bboxset& s) const { return (*this - s).empty() && ! (s - *this).empty(); } template bool bboxset::operator>= (const bboxset& s) const { return s <= *this; } template bool bboxset::operator> (const bboxset& s) const { return s < *this; } template bool bboxset::operator== (const bboxset& s) const { return (*this <= s) && (*this >= s); } template bool bboxset::operator!= (const bboxset& s) const { return ! (*this == s); } // Output template void bboxset::output (ostream& os) const { T Tdummy; os << "bboxset<" << typestring(Tdummy) << "," << D << ">:" << "size=" << size() << "," << "setsize=" << setsize() << "," << "set=" << bs; } template class bboxset;