// $Header: /home/eschnett/C/carpet/Carpet/Carpet/CarpetLib/src/bbox.cc,v 1.18 2003/11/13 16:03:58 schnetter Exp $ #include #include #include #include "defs.hh" #include "vect.hh" #include "bbox.hh" using namespace std; // Constructors template bbox::bbox (): _lower(T(1)), _upper(T(0)), _stride(T(1)) { } template bbox::bbox (const bbox& b) : _lower(b._lower), _upper(b._upper), _stride(b._stride) { } template bbox& bbox::operator= (const bbox& b) { _lower=b._lower; _upper=b._upper; _stride=b._stride; return *this; } template bbox::bbox (const vect& lower, const vect& upper, const vect& stride) : _lower(lower), _upper(upper), _stride(stride) { assert (all(stride>=1)); assert (all((upper-lower)%stride == T(0))); } // Accessors template T bbox::size () const { if (empty()) return 0; // return prod((shape()+stride()-1)/stride()); const vect sh((shape()+stride()-1)/stride()); T sz = 1, max = numeric_limits::max(); for (int d=0; d bool bbox::contains (const vect& x) const { return all(x>=lower() && x<=upper()); } // Operators template bool bbox::operator== (const bbox& b) const { if (empty() && b.empty()) return true; assert (all(stride()==b.stride())); return all(lower()==b.lower() && upper()==b.upper()); } template bool bbox::operator!= (const bbox& b) const { return ! (*this == b); } template bool bbox::operator< (const bbox& b) const { // An arbitraty order: empty boxes come first, then sorted by lower // bound, then by upper bound, then by coarseness if (b.empty()) return false; if (empty()) return true; for (int d=D-1; d>=0; --d) { if (lower()[d] < b.lower()[d]) return true; if (lower()[d] > b.lower()[d]) return false; } for (int d=D-1; d>=0; --d) { if (upper()[d] < b.upper()[d]) return true; if (upper()[d] > b.upper()[d]) return false; } for (int d=D-1; d>=0; --d) { if (stride()[d] > b.stride()[d]) return true; if (stride()[d] < b.stride()[d]) return false; } return false; } template bool bbox::operator> (const bbox& b) const { return b < *this; } template bool bbox::operator<= (const bbox& b) const { return ! (b > *this); } template bool bbox::operator>= (const bbox& b) const { return b <= *this; } // Intersection template bbox bbox::operator& (const bbox& b) const { assert (all(stride()==b.stride())); vect lo = max(lower(),b.lower()); vect up = min(upper(),b.upper()); return bbox(lo,up,stride()); } // Containment template bool bbox::is_contained_in (const bbox& b) const { if (empty()) return true; // no alignment check return all(lower()>=b.lower() && upper()<=b.upper()); } // Alignment check template bool bbox::is_aligned_with (const bbox& b) const { return all(stride()==b.stride() && (lower()-b.lower()) % stride() == T(0)); } // Expand the bbox a little by multiples of the stride template bbox bbox::expand (const vect& lo, const vect& hi) const { // Allow expansion only into directions where the extent is not negative assert (all(lower()<=upper() || (lo==T(0) && hi==T(0)))); const vect str = stride(); const vect lb = lower() - lo * str; const vect ub = upper() + hi * str; return bbox(lb,ub,str); } // Find the smallest b-compatible box around *this template bbox bbox::expanded_for (const bbox& b) const { if (empty()) return bbox(b.lower(), b.lower()-b.stride(), b.stride()); const vect str = b.stride(); const vect loff = ((lower() - b.lower()) % str + str) % str; const vect uoff = ((upper() - b.lower()) % str + str) % str; const vect lo = lower() - loff; // go outwards const vect up = upper() + (str - uoff) % str; return bbox(lo,up,str); } // Find the largest b-compatible box inside *this template bbox bbox::contracted_for (const bbox& b) const { if (empty()) return bbox(b.lower(), b.lower()-b.stride(), b.stride()); const vect str = b.stride(); const vect loff = ((lower() - b.lower()) % str + str) % str; const vect uoff = ((upper() - b.lower()) % str + str) % str; const vect lo = lower() + (str - loff) % str; // go inwards const vect up = upper() - uoff; return bbox(lo,up,str); } // Smallest bbox containing both boxes template bbox bbox::expanded_containing (const bbox& b) const { if (empty()) return b; if (b.empty()) return *this; assert (is_aligned_with(b)); const vect lo = min(lower(), b.lower()); const vect up = max(upper(), b.upper()); const vect str = min(stride(), b.stride()); return bbox(lo,up,str); } // Iterators template bbox::iterator::iterator (const bbox& box, const vect& pos) : box(box), pos(pos) { if (box.empty()) this->pos=box.upper()+box.stride(); } template bool bbox::iterator::operator!= (const iterator& i) const { return any(pos!=i.pos); } template typename bbox::iterator& bbox::iterator::operator++ () { for (int d=0; d typename bbox::iterator bbox::begin () const { return iterator(*this, lower()); } template typename bbox::iterator bbox::end () const { return iterator(*this, upper()+stride()); } template bbox::iteratorT::iteratorT (const bbox& box, const vect& pos) : box(box), pos(pos) { if (box.empty()) this->pos=box.upper()+box.stride(); } template bool bbox::iteratorT::operator!= (const iteratorT& i) const { return any(pos!=i.pos); } template typename bbox::iteratorT& bbox::iteratorT::operator++ () { for (int d=D-1; d>=0; --d) { pos[d]+=box.stride()[d]; if (pos[d]<=box.upper()[d]) return *this; pos[d]=box.lower()[d]; } pos=box.endT().pos; return *this; } template typename bbox::iteratorT bbox::beginT () const { return iteratorT(*this, lower()); } template typename bbox::iteratorT bbox::endT () const { return iteratorT(*this, upper()+stride()); } // Input template void bbox::input (istream& is) { skipws (is); assert (is.peek() == '('); is.get(); is >> _lower; skipws (is); assert (is.peek() == ':'); is.get(); is >> _upper; skipws (is); assert (is.peek() == ':'); is.get(); is >> _stride; skipws (is); assert (is.peek() == ')'); is.get(); } // Output template void bbox::output (ostream& os) const { os << "(" << lower() << ":" << upper() << ":" << stride() << ")"; } // Note: We need all dimensions all the time. template class bbox; template class bbox; template class bbox; template class bbox;