BWAPI
SPAR/AIModule/BWTA/vendors/CGAL/CGAL/Point_container.h
Go to the documentation of this file.
00001 // Copyright (c) 2002 Utrecht University (The Netherlands).
00002 // All rights reserved.
00003 //
00004 // This file is part of CGAL (www.cgal.org); you may redistribute it under
00005 // the terms of the Q Public License version 1.0.
00006 // See the file LICENSE.QPL distributed with CGAL.
00007 //
00008 // Licensees holding a valid commercial license may use this file in
00009 // accordance with the commercial license agreement provided with the software.
00010 //
00011 // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00012 // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00013 //
00014 // $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/CGAL-3.5-branch/Spatial_searching/include/CGAL/Point_container.h $
00015 // $Id: Point_container.h 36901 2007-03-07 19:34:29Z fcacciola $
00016 // 
00017 //
00018 // Author(s)     : Hans Tangelder (<hanst@cs.uu.nl>)
00019 
00020 
00021 // custom point container
00022 #ifndef CGAL_POINT_CONTAINER_H
00023 #define CGAL_POINT_CONTAINER_H
00024 
00025 #include <list>
00026 #include <vector>
00027 #include <functional>
00028 #include <algorithm>
00029 #include <CGAL/Kd_tree_rectangle.h>
00030 
00031 #include <boost/optional.hpp>
00032 
00033 namespace CGAL {
00034 
00035 template <class Traits> 
00036 class Point_container {
00037 
00038 private:
00039   typedef typename Traits::Point_d Point_d;
00040   typedef std::vector<Point_d*> Point_vector;
00041   
00042 public:
00043   typedef typename Traits::FT FT;
00044   
00045   typedef typename Point_vector::iterator iterator;
00046   
00047 private:
00048 
00049   // the iterator range of the Point_container 
00050   boost::optional<iterator> m_b ;
00051   boost::optional<iterator> m_e ;
00052   
00053   int built_coord;    // a coordinate for which the pointer list is built
00054   Kd_tree_rectangle<Traits> bbox;       // bounding box, i.e. rectangle of node
00055   Kd_tree_rectangle<Traits> tbox;       // tight bounding box, 
00056   // i.e. minimal enclosing bounding
00057   // box of points
00058                                     
00059 public:
00060 
00061   inline const Kd_tree_rectangle<Traits>& 
00062   bounding_box() const 
00063   { 
00064     return bbox; 
00065   }
00066   
00067   inline const Kd_tree_rectangle<Traits>&
00068   tight_bounding_box() const 
00069   { 
00070     return tbox; 
00071   }
00072 
00073   inline int 
00074   dimension() const 
00075   { 
00076     return bbox.dimension(); 
00077   } 
00078 
00079   inline int 
00080   built_coordinate() const 
00081   { 
00082     return built_coord; 
00083   } 
00084 
00085   // coordinate of the maximal span
00086   inline int 
00087   max_span_coord() const 
00088   {
00089     return bbox.max_span_coord(); 
00090   }
00091 
00092   // coordinate of the maximal tight span
00093   inline int 
00094   max_tight_span_coord() const 
00095   { 
00096     return tbox.max_span_coord(); 
00097   }
00098 
00099   inline FT  
00100   max_span_lower() const 
00101   { 
00102     return bbox.min_coord(max_span_coord());
00103   }
00104 
00105   inline FT  
00106   max_tight_span_lower() const 
00107   {
00108     return tbox.min_coord(max_tight_span_coord());
00109   }
00110   
00111   inline FT  
00112   max_span_upper() const 
00113   { 
00114     return bbox.max_coord(max_span_coord());
00115   }
00116   
00117   inline FT  
00118   max_tight_span_upper() const 
00119   {
00120     return tbox.max_coord(max_tight_span_coord());
00121   }
00122 
00123   inline FT 
00124   max_spread() const 
00125   { 
00126     return  max_span_upper() -  max_span_lower(); 
00127   }
00128 
00129   inline FT 
00130   max_tight_spread() const 
00131   {
00132     return  max_tight_span_upper() -  max_tight_span_lower(); 
00133   }
00134 
00135 
00136   int 
00137   max_tight_span_coord_balanced(FT Aspect_ratio) const 
00138   {
00139     int cut_dim(-1);
00140     FT max_spread_points(FT(-1));
00141     FT max_length = max_spread();  // length of longest side of box
00142     int dim = dimension();
00143     for (int d=0; d<dim; d++) {
00144       FT length=bbox.max_coord(d)-bbox.min_coord(d);
00145       
00146       if (FT(2)*max_length/length <= Aspect_ratio) {
00147         FT spread=tbox.max_coord(d)-tbox.min_coord(d);
00148         
00149         if (spread > max_spread_points) {
00150           max_spread_points = spread;
00151           cut_dim = d;
00152         }
00153       }
00154     }
00155     // CGAL_assertion(cut_dim >= 0);
00156     return cut_dim;
00157   }
00158 
00159   FT 
00160   max_span_upper_without_dim(int d) const 
00161   {
00162     FT max_span(FT(0));
00163     int dim=dimension();
00164     for (int i=0; i<dim; i++) {
00165       FT span = bbox.max_coord(i)-bbox.min_coord(i);
00166       if (d != i && span > max_span) max_span=span;
00167     }
00168     return max_span;
00169   }
00170 
00171   FT 
00172   balanced_fair(int d, FT Aspect_ratio) 
00173   {
00174     FT small_piece = max_span_upper_without_dim(d) / Aspect_ratio;
00175     FT low_cut = bbox.min_coord(d) + small_piece; // lowest legal cut;
00176     FT high_cut = bbox.max_coord(d) - small_piece; //highest legal cut;
00177     // CGAL_assertion (high_cut >= low_cut);
00178     FT split_value = median(d);
00179     if (split_value < low_cut) split_value = low_cut;
00180     if (split_value > high_cut) split_value = high_cut;
00181     return split_value;
00182   }
00183 
00184   FT 
00185   balanced_sliding_fair(int d, FT Aspect_ratio) 
00186   {
00187     FT small_piece = max_span_upper_without_dim(d) / Aspect_ratio;
00188     FT low_cut = bbox.min_coord(d) + small_piece; // lowest legal cut;
00189     FT high_cut = bbox.max_coord(d) - small_piece; //highest legal cut;
00190     // CGAL_assertion (high_cut >= low_cut);
00191     FT split_value = median(d);
00192     FT max_span_lower = tbox.min_coord(d);
00193     FT max_span_upper = tbox.max_coord(d);
00194     if (split_value < low_cut) split_value= max_span_lower; 
00195     if (split_value > high_cut) split_value = max_span_upper; 
00196     return split_value;
00197   }
00198 
00199   //  points
00200   inline unsigned int 
00201   size() const 
00202   {
00203     return *m_e - *m_b;
00204   }
00205   
00206   inline iterator 
00207   begin() const {
00208     return *m_b;
00209   }
00210   
00211   inline iterator 
00212   end() const 
00213   {
00214     return *m_e;
00215   }
00216      
00217   inline bool 
00218   empty() const
00219   {
00220     return !m_b || !m_e || (*m_b == *m_e ) ;
00221   }
00222 
00223   // building the container from a sequence of Point_d*
00224   Point_container(const int d, iterator begin, iterator end) :
00225     m_b(begin), m_e(end), bbox(d, begin, end), tbox(bbox)  
00226   {
00227     built_coord = max_span_coord();
00228   }
00229 
00230   void 
00231   set_range(iterator begin, iterator end)
00232   {
00233     m_b = begin;
00234     m_e = end;
00235   }
00236 
00237 
00238   // building an empty container 
00239   Point_container(const int d) :
00240     bbox(d), tbox(d)  
00241   {}
00242   
00243   template <class Traits2>   
00244   struct Cmp {
00245     typedef typename Traits2::FT FT;
00246     typedef typename Traits2::Point_d Point_d;
00247     typedef std::vector<Point_d*> Point_vector;
00248     
00249     int split_coord;
00250     FT value;
00251     typename Traits2::Construct_cartesian_const_iterator_d construct_it;
00252     
00253     Cmp(int s, FT c)
00254       : split_coord(s), value(c)
00255     {}
00256     
00257     bool 
00258     operator()(Point_d* pt) const
00259     {
00260       typename Traits2::Cartesian_const_iterator_d ptit;
00261       ptit = construct_it(*pt);
00262       return  *(ptit+split_coord) < value; 
00263     }
00264   };
00265 
00266 
00267   template <class Traits2>   
00268   struct Between {
00269     typedef typename Traits2::FT FT;
00270     typedef typename Traits2::Point_d Point_d;
00271     typedef std::vector<Point_d*> Point_vector;
00272     
00273     int split_coord;
00274     FT low, high;
00275     typename Traits2::Construct_cartesian_const_iterator_d construct_it;
00276     
00277     Between(int s, FT l, FT h)
00278       : split_coord(s), low(l), high(h)
00279     {}
00280     
00281     bool 
00282     operator()(Point_d* pt) const
00283     {
00284       typename Traits2::Cartesian_const_iterator_d ptit;
00285       ptit = construct_it(*pt);
00286       if(! ( *(ptit+split_coord) <= high ) ){
00287         //      std::cerr << "Point " << *pt << " exceeds " << high << " in dimension " << split_coord << std::endl;
00288         return false;
00289       }
00290       if(! ( *(ptit+split_coord) >= low ) ){
00291         //std::cerr << "Point " << *pt << " below " << low << " in dimension " << split_coord << std::endl;
00292         return false;
00293       }
00294       return true;
00295     }
00296   };
00297 
00298 
00299   void recompute_tight_bounding_box() 
00300   {
00301     tbox.update_from_point_pointers(begin(), end());
00302   }
00303   
00304 
00305   bool
00306   is_valid() const
00307   {
00308     if(empty()) return true;
00309     bool b = true;
00310     for (int i = 0; i < dimension(); i++){
00311       CGAL_assertion( b = (b && (bbox.min_coord(i) <= tbox.min_coord(i))));
00312       CGAL_assertion( b = (b && (bbox.max_coord(i) >= tbox.max_coord(i))));
00313 
00314       Between<Traits> between(i,tbox.min_coord(i), tbox.max_coord(i));
00315       for(iterator it = begin(); it != end(); it++){
00316         b = (b && between(*it));
00317       }
00318     }
00319     return b;
00320   }
00321 
00322 
00323   // note that splitting is restricted to the built coordinate
00324   template <class Separator>
00325   void split(Point_container<Traits>& c, Separator& sep,  
00326              bool sliding=false) 
00327   {
00328     CGAL_assertion(dimension()==c.dimension());
00329     CGAL_assertion(is_valid());
00330     c.bbox=bbox;
00331     
00332     const int split_coord = sep.cutting_dimension();
00333     FT cutting_value = sep.cutting_value();
00334 
00335     built_coord=split_coord;
00336     c.built_coord=split_coord;
00337                 
00338         
00339     typename Traits::Construct_cartesian_const_iterator_d construct_it;
00340 
00341     Cmp<Traits> cmp(split_coord, cutting_value);
00342     iterator it = std::partition(begin(), end(), cmp);
00343     // now [begin,it) are lower and [it,end) are upper
00344     if (sliding) { // avoid empty lists 
00345 
00346       if (it == begin()) {
00347         iterator minelt = std::min_element(begin(),end(),comp_coord_val<Traits,int>(split_coord));
00348         if(minelt != it){
00349           std::iter_swap(minelt,it);
00350         }
00351         cutting_value = *(construct_it(**it)+split_coord);
00352         sep.set_cutting_value(cutting_value);
00353         it++;
00354       }
00355       if (it == end()) {
00356         iterator maxelt = std::max_element(begin(),end(),comp_coord_val<Traits,int>(split_coord));
00357         it--;
00358         if(maxelt != it){
00359           std::iter_swap(maxelt,it);
00360         }
00361         cutting_value = *(construct_it(**it)+split_coord);
00362         sep.set_cutting_value(cutting_value);
00363       }
00364     }
00365 
00366     c.set_range(begin(), it);
00367     set_range(it, end());
00368     // adjusting boxes
00369     bbox.set_lower_bound(split_coord, cutting_value);
00370     tbox.update_from_point_pointers(begin(),
00371                                     end());
00372     c.bbox.set_upper_bound(split_coord, cutting_value);
00373     c.tbox.update_from_point_pointers(c.begin(),
00374                                       c.end());
00375     CGAL_assertion(is_valid());
00376     CGAL_assertion(c.is_valid());
00377   }
00378 
00379 
00380 
00381   template <class Traits2, class Value>
00382   struct comp_coord_val {
00383     
00384   private:
00385     Value coord;   
00386     
00387     typedef typename Traits2::Point_d Point_d;
00388   public:
00389     comp_coord_val (const Value& coordinate) 
00390       : coord(coordinate) 
00391     {}
00392     
00393     bool 
00394     operator()(const Point_d *a, const Point_d *b) const
00395     {
00396       typename Traits2::Construct_cartesian_const_iterator_d construct_it;
00397       typename Traits2::Cartesian_const_iterator_d ait = construct_it(*a),
00398         bit = construct_it(*b);
00399       return *(ait+coord) < *(bit+coord);
00400     }
00401   };
00402   
00403 
00404   FT 
00405   median(const int split_coord) 
00406   {
00407     typename Point_vector::iterator mid = begin() + (end() - begin())/2;
00408     std::nth_element(begin(), mid, end(),comp_coord_val<Traits,int>(split_coord));
00409     
00410     typename Traits::Construct_cartesian_const_iterator_d construct_it;
00411     typename Traits::Cartesian_const_iterator_d mpit = construct_it((*(*mid)));
00412     FT val1 = *(mpit+split_coord);
00413     mid++;
00414     mpit = construct_it((*(*mid)));
00415     FT val2 = *(mpit+split_coord);
00416     return (val1+val2)/FT(2); 
00417   }
00418 
00419 
00420 
00421 private:
00422   explicit Point_container() 
00423   {} // disable default constructor
00424   
00425 };
00426 
00427   template <class Point>
00428   std::ostream& 
00429   operator<< (std::ostream& s, Point_container<Point>& c) 
00430   {
00431     s << "Points container of size " << c.size() << "\n cell:";
00432     s << c.bounding_box();
00433     s << "\n minimal box enclosing points:"; s << c.tight_bounding_box(); 
00434     return s;
00435   }
00436 
00437 } // namespace CGAL
00438 
00439 #endif // CGAL_POINT_CONTAINER_H
00440 
00441 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines