/*************************************************************************** bbox.cc - Bounding boxes ------------------- begin : Sun Jun 11 2000 copyright : (C) 2000 by Erik Schnetter email : schnetter@astro.psu.edu $Header: /home/eschnett/C/carpet/Carpet/Carpet/CarpetLib/src/bbox.cc,v 1.6 2001/03/27 22:26:31 eschnett Exp $ ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include #include "defs.hh" #include "vect.hh" #if !defined(TMPL_IMPLICIT) || !defined(BBOX_HH) # include "bbox.hh" #endif using namespace std; // Constructors template bbox::bbox (): _lower(1), _upper(0), _stride(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==0)); } // Accessors template T bbox::size () const { if (empty()) return 0; return prod(shape()); } template T bbox::num_points () const { if (empty()) return 0; return prod((shape()+stride()-1)/stride()); } // Queries template 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 { // 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() == 0); } // Expand the bbox a little by multiples of the stride template bbox bbox::expand (const vect& lo, const vect& hi) const { 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 { 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 { 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 bbox::iterator& bbox::iterator::operator++ () { for (int d=0; d bbox::iterator bbox::begin () const { return iterator(*this, lower()); } template bbox::iterator bbox::end () const { return iterator(*this, upper()+stride()); } // Output template void bbox::output (ostream& os) const { os << "(" << lower() << ":" << upper() << ":" << stride() << ")"; } #if defined(TMPL_EXPLICIT) template class bbox; template class bbox; template class bbox; #endif