/home/andreas/src/svn/mapnik/include/mapnik/quad_tree.hpp

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * 
00003  * This file is part of Mapnik (c++ mapping toolkit)
00004  *
00005  * Copyright (C) 2006 Artem Pavlenko
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020  *
00021  *****************************************************************************/
00022 //$Id$
00023 
00024 #ifndef QUAD_TREE_HPP
00025 #define QUAD_TREE_HPP
00026 // stl
00027 #include <vector>
00028 // boost
00029 #include <boost/ptr_container/ptr_vector.hpp>
00030 #include <boost/noncopyable.hpp>
00031 // mapnik
00032 #include <mapnik/envelope.hpp>
00033 
00034 namespace mapnik
00035 {
00036    template <typename T>
00037    class quad_tree : boost::noncopyable
00038    {
00039          struct node
00040          {
00041                typedef T value_t;
00042                typedef std::vector<T> cont_t;
00043                typedef typename cont_t::iterator iterator;
00044                typedef typename cont_t::const_iterator const_iterator;
00045                Envelope<double> extent_;
00046                cont_t cont_;
00047                node * children_[4];
00048 
00049                explicit node(Envelope<double> const& ext)
00050                   : extent_(ext)
00051                {
00052                   std::memset(children_,0,4*sizeof(node*));
00053                }
00054    
00055                Envelope<double> const& extent() const
00056                {
00057                   return extent_;
00058                }
00059             
00060                iterator begin() 
00061                {
00062                   return cont_.begin();
00063                }
00064             
00065                const_iterator begin() const 
00066                {
00067                   return cont_.begin();
00068                }
00069             
00070                iterator end() 
00071                {
00072                   return cont_.end();
00073                }
00074             
00075                const_iterator end() const 
00076                {
00077                   return cont_.end();
00078                }
00079                ~node () {}
00080          };
00081         
00082          typedef boost::ptr_vector<node> nodes_t;       
00083          typedef typename node::cont_t cont_t;
00084          typedef typename cont_t::iterator node_data_iterator;
00085         
00086          nodes_t nodes_;
00087          node * root_;  
00088          const double ratio_; 
00089         
00090       public:
00091          typedef typename nodes_t::iterator iterator;
00092          typedef typename nodes_t::const_iterator const_iterator;
00093          typedef typename boost::ptr_vector<T,boost::view_clone_allocator> result_t;    
00094          typedef typename result_t::iterator query_iterator;
00095    
00096          result_t query_result_;
00097         
00098          explicit quad_tree(Envelope<double> const& ext,double ratio=0.55) 
00099             : ratio_(ratio)
00100          {
00101             nodes_.push_back(new node(ext));
00102             root_ = &nodes_[0];
00103          }
00104                 
00105          void insert(T data, Envelope<double> const& box)
00106          {
00107             do_insert_data(data,box,root_);
00108          }
00109         
00110          query_iterator query_in_box(Envelope<double> const& box)
00111          {
00112             query_result_.clear();
00113             query_node(box,query_result_,root_);
00114             return query_result_.begin();
00115          }
00116         
00117          query_iterator query_end()
00118          {
00119             return query_result_.end();
00120          }
00121 
00122          iterator begin()
00123          {
00124             return nodes_.begin();
00125          }
00126         
00127          const_iterator begin() const
00128          {
00129             return nodes_.begin();
00130          }
00131 
00132          iterator end()
00133          {
00134             return  nodes_.end();
00135          }
00136         
00137          const_iterator end() const
00138          {
00139             return  nodes_.end();
00140          }
00141           
00142          void clear () 
00143          {
00144             Envelope<double> ext = root_->extent_;
00145             nodes_.clear();
00146             nodes_.push_back(new node(ext));
00147             root_ = &nodes_[0];
00148          }
00149 
00150       private:
00151          void query_node(Envelope<double> const& box, result_t & result, node * node_) const
00152          {
00153             if (node_)
00154             {
00155                Envelope<double> const& node_extent = node_->extent();
00156                if (box.intersects(node_extent))
00157                {
00158                   node_data_iterator i=node_->begin();
00159                   node_data_iterator end=node_->end();
00160                   while ( i!=end)
00161                   {
00162                      result.push_back(&(*i));
00163                      ++i;
00164                   }
00165                   for (int k = 0; k < 4; ++k)
00166                   {
00167                      query_node(box,result,node_->children_[k]);
00168                   }
00169                }
00170             }
00171          }
00172         
00173          void do_insert_data(T data, Envelope<double> const& box, node * n)
00174          {
00175             if (n)
00176             {
00177                Envelope<double> const& node_extent = n->extent();
00178                Envelope<double> ext[4];
00179                split_box(node_extent,ext);              
00180                for (int i=0;i<4;++i)
00181                {
00182                   if (ext[i].contains(box))
00183                   {
00184                      if (!n->children_[i])
00185                      {
00186                         nodes_.push_back(new node(ext[i]));
00187                         n->children_[i]=&nodes_.back();
00188                      }
00189                      do_insert_data(data,box,n->children_[i]);
00190                      return;
00191                   }
00192                }
00193                n->cont_.push_back(data);
00194             }
00195          }
00196         
00197          void split_box(Envelope<double> const& node_extent,Envelope<double> * ext)
00198          {
00199             coord2d c=node_extent.center();
00200 
00201             double width=node_extent.width();
00202             double height=node_extent.height();
00203             
00204             double lox=node_extent.minx();
00205             double loy=node_extent.miny();
00206             double hix=node_extent.maxx();
00207             double hiy=node_extent.maxy();
00208             
00209             ext[0]=Envelope<double>(lox,loy,lox + width * ratio_,loy + height * ratio_);
00210             ext[1]=Envelope<double>(hix - width * ratio_,loy,hix,loy + height * ratio_);
00211             ext[2]=Envelope<double>(lox,hiy - height*ratio_,lox + width * ratio_,hiy);
00212             ext[3]=Envelope<double>(hix - width * ratio_,hiy - height*ratio_,hix,hiy);
00213          }
00214    };    
00215 } 
00216 
00217 #endif

Generated on Thu Jul 19 17:59:27 2007 for Mapnik by  doxygen 1.4.7