cheshirekow  v0.1.0
Node.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2012 Josh Bialkowski (jbialk@mit.edu)
3  *
4  * This file is part of mpblocks.
5  *
6  * mpblocks is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * mpblocks is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with mpblocks. If not, see <http://www.gnu.org/licenses/>.
18  */
27 #ifndef MPBLOCKS_KD_TREE_NODE_HPP_
28 #define MPBLOCKS_KD_TREE_NODE_HPP_
29 
30 #include <limits>
31 
32 
33 namespace mpblocks {
34 namespace kd_tree {
35 
36 
37 template <class Traits>
39 {
40  m_parent = 0;
41  m_i = 0;
42  m_smallerChild = 0;
43  m_greaterChild = 0;
44 }
45 
46 template <class Traits>
48  Node_t* parent, unsigned int i )
49 {
50  m_parent = parent;
51  m_i = i;
52  m_smallerChild = 0;
53  m_greaterChild = 0;
54  m_this = static_cast<Node_t*>(this);
55 }
56 
57 template <class Traits>
59 {
60  m_point = p;
61 }
62 
63 template <class Traits>
64 const typename Node<Traits>::Point_t&
66 {
67  return m_point;
68 }
69 
70 template <class Traits>
72 {
73  Node_t** ptrChild = 0;
74 
75  // first, grab a pointer to which child pointer we should recurse
76  // into
77  if(static_cast<This_t*>(node)->m_point[m_i] <= m_point[m_i])
78  ptrChild = &m_smallerChild;
79  else
80  ptrChild = &m_greaterChild;
81 
82  // dereference the pointer
83  Node_t*& child = *ptrChild;
84 
85  // if the child exists (is not null) then recurse, otherwise
86  // create it and we're done
87  if(child)
88  return static_cast<This_t*>(child)->insert(node);
89  else
90  {
91  child = node;
92  static_cast<This_t*>(node)->construct( m_this,(m_i+1) % m_point.rows());
93  }
94 }
95 
96 
97 
98 template <class Traits>
100  const Point_t& q,
101  HyperRect_t& rect,
102  NNIface_t& search)
103 {
104  Node_t* nearerNode;
105  Node_t* fartherNode;
106  Format_t* nearerHyperCoord;
107  Format_t* fartherHyperCoord;
108 
109  // first, check to see if the left child or the right child is a
110  // would-be-ancester if the point were incerted in the graph
111  Format_t diff = q[m_i] - m_point[m_i];
112  if (diff <= 0.0)
113  {
114  nearerNode = m_smallerChild;
115  fartherNode = m_greaterChild;
116 
117  nearerHyperCoord = &(rect.maxExt[m_i]);
118  fartherHyperCoord = &(rect.minExt[m_i]);
119  }
120 
121  else
122  {
123  nearerNode = m_greaterChild;
124  fartherNode = m_smallerChild;
125 
126  nearerHyperCoord = &(rect.minExt[m_i]);
127  fartherHyperCoord = &(rect.maxExt[m_i]);
128  }
129 
130  // now, whichever child is the would-be-ancestor, recurse into them
131  // also, refine the hyperrectangle that contains the node by
132  // splitting it along the split-plane of this node
133  if (nearerNode)
134  {
135  // copy out the old extent of they hyper-rectangle
136  Format_t oldHyperVal = *nearerHyperCoord;
137 
138  // split the hyperrectangle by updating the extent with the
139  // value of this nodes split plane
140  *nearerHyperCoord = m_point[m_i];
141 
142  // recurse into the nearer node
143  static_cast<This_t*>(nearerNode)->findNearest(q,rect,search);
144 
145  // now that we've stepped back up into this node, restore the
146  // hyperrectangle
147  *nearerHyperCoord = oldHyperVal;
148  }
149 
150  // evaluate this node and add it to the result set if necessary
151  search.evaluate(q,m_point,m_this);
152 
153  // if the farther node exists, we might need to also check it's
154  // children
155  if (fartherNode)
156  {
157  // refine the hyper-rectangle of the farther subtree
158  Format_t oldHyperVal = *fartherHyperCoord;
159  *fartherHyperCoord = m_point[m_i];
160 
161  // check if we have to recurse into the farther subtree
162  if( search.shouldRecurse(q,rect) )
163  static_cast<This_t*>(fartherNode)->findNearest(q,rect,search);
164 
165  // undo refinement of the hyperrectangle
166  *fartherHyperCoord = oldHyperVal;
167  }
168 }
169 
170 
171 
172 
173 
174 
175 
176 template <class Traits>
178 {
179  // evaluate this node and add it to the result set if
180  // it lies inside the range
181  search.evaluate(m_point,m_this);
182 
183  // now evaluate the two children and recurse if necessary
184  {
185  // copy out the old extent of they hyper-rectangle
186  Node_t* child = m_smallerChild;
187  Format_t* hyperCoord = &(rect.maxExt[m_i]);
188  Format_t oldHyperVal = *hyperCoord;
189 
190  // split the hyperrectangle by updating the extent with the
191  // value of this nodes split plane
192  *hyperCoord = m_point[m_i];
193 
194  // recurse into the nearer node
195  if(child && search.shouldRecurse(rect) )
196  static_cast<This_t*>(child)->findRange(search,rect);
197 
198  // now that we've stepped back up into this node, restore the
199  // hyperrectangle
200  *hyperCoord = oldHyperVal;
201  }
202 
203  {
204  // copy out the old extent of they hyper-rectangle
205  Node_t* child = m_greaterChild;
206  Format_t* hyperCoord = &(rect.minExt[m_i]);
207  Format_t oldHyperVal = *hyperCoord;
208 
209  // split the hyperrectangle by updating the extent with the
210  // value of this nodes split plane
211  *hyperCoord = m_point[m_i];
212 
213  // recurse into the nearer node
214  if(child && search.shouldRecurse(rect) )
215  static_cast<This_t*>(child)->findRange(search,rect);
216 
217  // now that we've stepped back up into this node, restore the
218  // hyperrectangle
219  *hyperCoord = oldHyperVal;
220  }
221 }
222 
223 
224 template <class Traits>
225 template <typename BackInserter >
227  HyperRect_t& container, BackInserter bs )
228 {
229  if( m_greaterChild )
230  {
231  Pair_t* pair= new Pair_t();
232  container.copyTo(pair->container);
233  pair->container.minExt[m_i] = m_point[m_i];
234  pair->node = m_greaterChild;
235  bs = pair;
236  }
237 
238  if( m_smallerChild )
239  {
240  Pair_t* pair= new Pair_t();
241  container.copyTo(pair->container);
242  pair->container.maxExt[m_i] = m_point[m_i];
243  pair->node = m_smallerChild;
244  bs = pair;
245  }
246 }
247 
248 
249 
250 
251 
252 
253 
254 
255 
256 
257 } // namespace kd_tree
258 } // mpblocks
259 
260 #endif
void insert(Node_t *)
recursively inserts point as a new node in the tree
Definition: Node.hpp:71
void construct(Node_t *parent, unsigned int i)
construct a new node
Definition: Node.hpp:47
__host__ __device__ __forceinline__ void construct(SturmSequence2< Scalar, Spec > &sturm, const Exp &exp)
construct a sturm sequence
virtual bool shouldRecurse(const HyperRect_t &h)=0
return true if the hyper rectangle intersects the range
Vector_t Point_t
Definition: Node.h:69
void enumerate(HyperRect_t &container, BackInserter bs)
Definition: Node.hpp:226
Point_t maxExt
maximum extent of hyper-rectangle
Definition: HyperRect.h:30
pairs nodes of the Kd tree along with a hyperrectangle that is the bounding volume for the subtree ro...
Definition: ListPair.h:37
virtual bool shouldRecurse(const Point_t &q, const HyperRect_t &h)=0
evaluate the hyper rectangle and return true if it is possible that we must recurse into it ...
const Point_t & getPoint()
returns a Point_t of the point stored at this node
Definition: Node.hpp:65
Interface for nearest node type searches.
Definition: NearestSearch.h:38
void findNearest(const Point &query, int k, SearchQueue &q, ResultSet &r, const QueueMinKeyFn &minKey, const QueuePopMinFn &popMin, const QueueInsertFn &enqueue, const QueueSizeFn &queueSize, const SetMaxKeyFn &maxKey, const SetPopMaxFn &popMax, const SetInsertFn &insert, const SetSizeFn &size, const PointDistanceFn &pointDist, const CellDistanceFn &cellDist, const IsLeafFn &isLeaf, const ChildrenFn &children, const SitesFn &sites, const CellFn &getCell, const NodeFn &getNode)
Definition: findNearest.h:62
Node()
does nothing, see construct
Definition: Node.hpp:38
Traits::Format_t Format_t
Definition: Node.h:63
virtual void evaluate(const Point_t &q, const Point_t &p, Node_t *n)=0
evaluate the current point, and add the corresponding node to the result set if necessary ...
void setPoint(const Point_t &p)
fill point data (convenience method)
Definition: Node.hpp:58
the node class must be defined in traits since it uses the CTRP, it must derive from kd_tree::Node<Tr...
Definition: Traits.h:49
virtual void evaluate(const Point_t &q, Node_t *n)=0
evalute if p is inside the range, and add n to the result set if it is
Base class for nodes in the kd tree.
Definition: Node.h:58
void insert(NodeRef node, PointRef point, const IsLeafFn &isLeaf, const LeafInsertFn &leafInsert, const IdxFn &idx, const ValueFn &value, const ChildFn &child, const PointGetFn &pointGet)
Definition: insert.h:46
Point_t minExt
minimum extent of hyper-rectangle
Definition: HyperRect.h:29
void findRange(RangeIface_t &search, HyperRect_t &rect)
find all nodes in the tree that lie inside the specified range ( can be arbitrary volume...
Definition: Node.hpp:177
void findNearest(const Point_t &q, HyperRect_t &rect, NNIface_t &search)
perform a generic Nearest Neighbor query, different queries provide different implementations of the ...
Definition: Node.hpp:99
an NDim dimensional hyperrectangle, represented as a min and max extent
Definition: HyperRect.h:23