00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef QUAD_TREE_HPP
00025 #define QUAD_TREE_HPP
00026
00027 #include <vector>
00028
00029 #include <boost/ptr_container/ptr_vector.hpp>
00030 #include <boost/noncopyable.hpp>
00031
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