// ====================================================================== // Copyright (c) 2002 The CGAL Consortium // // This software and related documentation is part of an INTERNAL release // of the Computational Geometry Algorithms Library (CGAL). It is not // intended for general use. // // ---------------------------------------------------------------------- // // release : // release_date : // // file : include/CGAL/Kd_tree_rectangle.h // package : ASPAS // revision : 2.4 // revision_date : 2003/02/01 // authors : Hans Tangelder () // maintainer : Hans Tangelder () // coordinator : Utrecht University // // ====================================================================== #ifndef CGAL_KD_TREE_RECTANGLE_H #define CGAL_KD_TREE_RECTANGLE_H #include #include #include #include #include namespace CGAL { template struct set_bounds : public std::unary_function { int dim; T *lower; T *upper; set_bounds(int d, T *l, T *u) : dim(d), lower(l), upper(u) {} void operator() (Point& p) { T h; for (int i = 0; i < dim; ++i) { h=p[i]; if (h < lower[i]) lower[i] = h; if (h > upper[i]) upper[i] = h; } } }; template struct set_bounds_from_pointer : public std::unary_function { int dim; T *lower; T *upper; set_bounds_from_pointer(int d, T *l, T *u) : dim(d), lower(l), upper(u) {} void operator() (P p) { T h; for (int i = 0; i < dim; ++i) { h=(*p)[i]; if (h < lower[i]) lower[i] = h; if (h > upper[i]) upper[i] = h; } } }; template class Kd_tree_rectangle { public: typedef T NT; private: int dim; T *lower_; T *upper_; int max_span_coord_; public: inline void set_upper_bound(const int i, const NT& x) { // assert(i >= 0 && i < dim); // assert(x >= lower_[i]); upper_[i] = x; set_max_span(); } inline void set_lower_bound(const int i, const NT& x) { // assert(i >= 0 && i < dim); // assert(x <= upper_[i]); lower_[i] = x; set_max_span(); } inline void set_max_span() { NT span = upper_[0]-lower_[0]; max_span_coord_ = 0; for (int i = 1; i < dim; ++i) { NT tmp = upper_[i] - lower_[i]; if (span < tmp) { span = tmp; max_span_coord_ = i; } } } Kd_tree_rectangle(const int d) : dim(d), lower_(new NT[d]), upper_(new NT[d]) { std::fill(lower_, lower_ + dim, 0); std::fill(upper_, upper_ + dim, 0); set_max_span(); } Kd_tree_rectangle() : dim(0), lower_(0), upper_(0) {} template Kd_tree_rectangle(const int d, Iter begin_lower, Iter end_lower, Iter begin_upper, Iter end_upper) : dim(d) { lower_ = new NT[d]; upper_ = new NT[d]; std::copy(begin_lower, end_lower, lower_); std::copy(begin_upper, end_upper, upper_); set_max_span(); } explicit Kd_tree_rectangle(const Kd_tree_rectangle& r) : dim(r.dim), lower_(new NT[dim]), upper_(new NT[dim]) { std::copy(r.lower_, r.lower_+dim, lower_); std::copy(r.upper_, r.upper_+dim, upper_); set_max_span(); } template Kd_tree_rectangle(const int d, PointIter begin, PointIter end) : dim(d), lower_(new NT[d]), upper_(new NT[d]) { // initialize with values of first point for (int i=0; i < dim; ++i) { lower_[i]=(*begin)[i]; upper_[i]=lower_[i]; } begin++; typedef typename std::iterator_traits::value_type P; std::for_each(begin, end, set_bounds(dim, lower_, upper_)); set_max_span(); } template void update_from_point_pointers(PointPointerIter begin, PointPointerIter end, bool empty) { if (empty) { // no points for (int i=0; i < dim; ++i) { lower_[i]= NT(1); upper_[i]= NT(-1); } } else { // initialize with values of first point for (int i=0; i < dim; ++i) { lower_[i]= (*(*begin))[i]; upper_[i]=lower_[i]; } begin++; typedef typename std::iterator_traits::value_type P; std::for_each(begin, end, set_bounds_from_pointer(dim, lower_, upper_)); } set_max_span(); } inline int max_span_coord() const { return max_span_coord_; } inline NT max_span() const { return upper_[max_span_coord_] - lower_[max_span_coord_]; } inline NT min_coord(int i) const { return lower_[i]; } inline NT max_coord(int i) const { return upper_[i]; } std::ostream& print(std::ostream& s) { s << "Rectangle dimension = " << dim; s << "\n lower: "; for (int i=0; i < dim; ++i) s << lower_[i] << " "; // std::copy(lower_, lower_ + dim, // std::ostream_iterator(s," ")); s << "\n upper: "; for (int j=0; j < dim; ++j) s << upper_[j] << " "; // std::copy(upper_, upper_ + dim, // std::ostream_iterator(s," ")); s << "\n maximum span " << max_span() << " at coordinate " << max_span_coord() << std::endl; return s; } // Splits rectangle by modifying itself to lower half // and returns upper half Kd_tree_rectangle* split(int d, NT value) { // assert(d >= 0 && d < dim); // assert(lower_[d] <= value && value <= upper_[d]); Kd_tree_rectangle* r = new Kd_tree_rectangle(*this); upper_[d]=value; r->lower_[d]=value; return r; } ~Kd_tree_rectangle() { if (dim) { if (lower_) delete [] lower_; if (upper_) delete [] upper_; } } int dimension() const {return dim;} /* template bool has_on_bounded_side(const Point& p) { NT h; for (int i = 0; i < dimension(); ++i) { h=p[i]; if ( (h < min_coord(i)) || (h > max_coord(i)) ) return 0; } return 1; } */ // checks whether an epsilon eroded iso rectangle r // intersects the kd_tree rectangle template inline bool intersects_eroded_rectangle( const Iso_rectangle_d& r, const NT eps) { for (int i = 0; i < dim; ++i) { if ( (r.max_coord(i)-eps < lower_[i]) || (r.min_coord(i)+eps > upper_[i]) ) return 0; } return 1; } // checks whether an epsilon dilated iso rectangle r // encloses the kd_tree rectangle template inline bool is_enclosed_by_dilated_rectangle( const Iso_rectangle_d& r, const NT eps) { for (int i = 0; i < dim; ++i) { if ( (r.max_coord(i)+eps < upper_[i]) || (r.min_coord(i)-eps > lower_[i]) ) return 0; } return 1; } Kd_tree_rectangle& operator= (const Kd_tree_rectangle& r) { if (this != &r) { std::copy(r.lower_, r.lower_+dim, lower_); std::copy(r.upper_, r.upper_+dim, upper_); set_max_span(); } return *this; } template bool min_squared_Euclidean_distance_to_point_is_at_most( const Point& p, const NT d) { NT distance = NT(0); for (int i = 0; (i < dim) && (distance <= d); ++i) { if (p[i] < lower_[i]) distance += (lower_[i]-p[i])*(lower_[i]-p[i]); if (p[i] > upper_[i]) distance += (p[i]-upper_[i])*(p[i]-upper_[i]); } return (distance <= d); } template bool max_squared_Euclidean_distance_to_point_is_at_most (const Point& p, const NT d) { NT distance=NT(0); for (int i = 0; (i < dim) && (distance <= d) ; ++i) { if (p[i] <= (lower_[i]+upper_[i])/NT(2)) distance += (upper_[i]-p[i])*(upper_[i]-p[i]); else distance += (p[i]-lower_[i])*(p[i]-lower_[i]); } return (distance <= d); } }; // of class Kd_tree_rectangle template std::ostream& operator<< (std::ostream& s, Kd_tree_rectangle& r) { return r.print(s); } } // namespace CGAL #endif // CGAL_KD_TREE_RECTANGLE_H