// Copyright (c) 2002,2011 Utrecht University (The Netherlands). // All rights reserved. // // This file is part of CGAL (www.cgal.org). // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Spatial_searching/include/CGAL/Kd_tree_rectangle.h $ // $Id: Kd_tree_rectangle.h 2e180ac 2020-03-26T19:29:44+01:00 Sébastien Loriot // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Hans Tangelder () #ifndef CGAL_KD_TREE_RECTANGLE_H #define CGAL_KD_TREE_RECTANGLE_H #include #include #include #include #include #include #include namespace CGAL { template struct set_bounds_from_pointer : public CGAL::cpp98::unary_function { int dim; T *lower; T *upper; Construct_cartesian_const_iterator_d construct_it; set_bounds_from_pointer(int d, T *l, T *u,Construct_cartesian_const_iterator_d construct_it_) : dim(d), lower(l), upper(u), construct_it(construct_it_) {} void operator()(P p) { T h; typename Construct_cartesian_const_iterator_d::result_type pit = construct_it(*p); for (int i = 0; i < dim; ++i, ++pit) { h=(*pit); if (h < lower[i]) lower[i] = h; if (h > upper[i]) upper[i] = h; } } }; template class Kd_tree_rectangle { public: typedef FT_ FT; typedef FT T; private: //int dim; std::array lower_; std::array upper_; int max_span_coord_; public: inline void set_upper_bound(int i, const FT& x) { CGAL_assertion(i >= 0 && i < D::value); CGAL_assertion(x >= lower_[i]); upper_[i] = x; set_max_span(); } inline void set_lower_bound(int i, const FT& x) { CGAL_assertion(i >= 0 && i < D::value); CGAL_assertion(x <= upper_[i]); lower_[i] = x; set_max_span(); } inline void set_max_span() { FT span = upper_[0]-lower_[0]; max_span_coord_ = 0; for (int i = 1; i < D::value; ++i) { FT tmp = upper_[i] - lower_[i]; if (span < tmp) { span = tmp; max_span_coord_ = i; } } } Kd_tree_rectangle(int) : max_span_coord_(0) { lower_.fill(FT(0)); upper_.fill(FT(0)); } Kd_tree_rectangle() : max_span_coord_(-1) {} explicit Kd_tree_rectangle(const Kd_tree_rectangle& r) : max_span_coord_(r.max_span_coord_) { lower_ = r.lower_; upper_ = r.upper_; } template void update_from_point_pointers(PointPointerIter begin, PointPointerIter end, const Construct_cartesian_const_iterator_d& construct_it ) { if (begin ==end) return; // initialize with values of first point typename Construct_cartesian_const_iterator_d::result_type bit = construct_it(**begin); for (int i=0; i < D::value; ++i, ++bit) { lower_[i]= *bit; upper_[i]=lower_[i]; } begin++; typedef typename std::iterator_traits::value_type P; std::for_each(begin, end,set_bounds_from_pointer(D::value, &(lower_[0]), &(upper_[0]), construct_it)); set_max_span(); } template // was PointIter Kd_tree_rectangle(int, PointPointerIter begin, PointPointerIter end,const Construct_cartesian_const_iterator_d& construct_it) : max_span_coord_(-1) { update_from_point_pointers(begin,end,construct_it); } inline int max_span_coord() const { return max_span_coord_; } inline FT max_span() const { return upper_[max_span_coord_] - lower_[max_span_coord_]; } inline FT min_coord(int i) const { CGAL_assume(i(s," ")); s << "\n upper: "; for (int j=0; j < D::value; ++j) s << upper_[j] << " "; // std::copy(upper_, upper_ + D, // 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* void split(Kd_tree_rectangle& r, int d, FT value) { CGAL_assertion(d >= 0 && d < D::value); CGAL_assertion(lower_[d] <= value && value <= upper_[d]); //Kd_tree_rectangle* r = new Kd_tree_rectangle(*this); upper_[d]=value; r.lower_[d]=value; //return r; } int dimension() const { return D::value; } T* lower() {return lower_.data();} T* upper() {return upper_.data();} const T* lower() const {return lower_.data();} const T* upper() const {return upper_.data();} Kd_tree_rectangle& operator=(const Kd_tree_rectangle& r) { CGAL_assertion(dimension() == r.dimension()); if (this != &r) { lower_ = r.lower_; upper_ = r.upper_; set_max_span(); } return *this; } }; // of class Kd_tree_rectangle // Partial specialization for dynamic dimension, which means dimension at runtime template class Kd_tree_rectangle { public: typedef FT_ FT; typedef FT T; private: T* coords_; int dim; int max_span_coord_; public: inline void set_upper_bound(int i, const FT& x) { CGAL_assertion(i >= 0 && i < dim); CGAL_assertion(x >= lower()[i]); upper()[i] = x; set_max_span(); } inline void set_lower_bound(int i, const FT& x) { CGAL_assertion(i >= 0 && i < dim); CGAL_assertion(x <= upper()[i]); lower()[i] = x; set_max_span(); } inline void set_max_span() { FT span = upper()[0]-lower()[0]; max_span_coord_ = 0; for (int i = 1; i < dim; ++i) { FT tmp = upper()[i] - lower()[i]; if (span < tmp) { span = tmp; max_span_coord_ = i; } } } Kd_tree_rectangle(int d) : coords_(new FT[2*d]), dim(d), max_span_coord_(0) { std::fill(coords_, coords_ + 2*dim, FT(0)); } Kd_tree_rectangle() : coords_(0), dim(0), max_span_coord_(-1) { } explicit Kd_tree_rectangle(const Kd_tree_rectangle& r) : coords_(new FT[2*r.dim]), dim(r.dim), max_span_coord_(r.max_span_coord_) { std::copy(r.coords_, r.coords_+2*dim, lower()); } template void update_from_point_pointers(PointPointerIter begin, PointPointerIter end, const Construct_cartesian_const_iterator_d& construct_it ) { if (begin ==end) return; // initialize with values of first point typename Construct_cartesian_const_iterator_d::result_type bit = construct_it(**begin); for (int i=0; i < dim; ++i, ++bit) { lower()[i]= *bit; 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(),construct_it)); set_max_span(); } template // was PointIter Kd_tree_rectangle(int d, PointPointerIter begin, PointPointerIter end,const Construct_cartesian_const_iterator_d& construct_it) : coords_(new FT[2*d]), dim(d), max_span_coord_(-1) { update_from_point_pointers(begin,end,construct_it); } inline int max_span_coord() const { return max_span_coord_; } inline FT max_span() const { return upper()[max_span_coord_] - lower()[max_span_coord_]; } inline FT min_coord(int i) const { CGAL_assertion(coords_ != nullptr); return lower()[i]; } inline FT max_coord(int i) const { return upper()[i]; } std::ostream& print(std::ostream& s) const { 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* void split(Kd_tree_rectangle& r, int d, FT value) { CGAL_assertion(d >= 0 && d < dim); CGAL_assertion(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 (coords_) delete [] coords_; } } int dimension() const { return dim; } T* lower() {return coords_;} T* upper() {return coords_ + dim;} const T* lower() const {return coords_;} const T* upper() const {return coords_ + dim;} Kd_tree_rectangle& operator=(const Kd_tree_rectangle& r) { CGAL_assertion(dimension() == r.dimension()); if (this != &r) { std::copy(r.coords_, r.coords_+2*dim, coords_); set_max_span(); } return *this; } }; // of partial specialization of class Kd_tree_rectangle template std::ostream& operator<<(std::ostream& s, const Kd_tree_rectangle& r) { return r.print(s); } } // namespace CGAL #endif // CGAL_KD_TREE_RECTANGLE_H