// $Header:$ #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 { 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; } } return true; } // Normalisation template void bboxset::normalize () { assert (invariant()); const int num_initial_boxes = bs.size(); int num_combined_boxes = 0; stack todo, done; for (typename set::const_iterator elt = bs.begin(); elt != bs.end(); ++elt) { done.push (*elt); } // TODO: This will not catch all cases where bboxes can be combined. for (int d=0; d(); while (! todo.empty()) { restart:; box item = todo.top(); todo.pop(); stack work = done; done = stack(); while (! work.empty()) { box comp = work.top(); work.pop(); { assert (all(comp.stride() == item.stride())); if (comp.upper()[d] + item.stride()[d] == item.lower()[d]) { if (all((comp.lower() == item.lower() && comp.upper() == item.upper()).replace (d, true))) { box newbox = box(comp.lower(), item.upper(), item.stride()); todo.push (newbox); while (! work.empty()) { done.push (work.top()); work.pop(); } ++num_combined_boxes; goto restart; } } if (item.upper()[d] + item.stride()[d] == comp.lower()[d]) { if (all((comp.lower() == item.lower() && comp.upper() == item.upper()).replace (d, true))) { box newbox = box(item.lower(), comp.upper(), item.stride()); todo.push (newbox); while (! work.empty()) { done.push (work.top()); work.pop(); } ++num_combined_boxes; goto restart; } } } done.push (comp); } // while work done.push (item); } // while todo } // for d bs.clear(); while (! done.empty()) { bs.insert (done.top()); done.pop(); } const int num_final_boxes = bs.size(); assert (num_initial_boxes - num_combined_boxes == num_final_boxes); assert (invariant()); } // Accessors template T bboxset::size () const { T s=0; for (const_iterator bi=begin(); bi!=end(); ++bi) { const T bs = (*bi).size(); assert (numeric_limits::max() - bs >= s); s += bs; } 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;