@@ -192,11 +192,10 @@ class KDTree
192192 value_type out;
193193 int iTask = -1 ;
194194 coord_type minDistSq = std::numeric_limits<coord_type>::max ();
195- m_tasksStack[++iTask] =
196- NearestTask (m_root, m_min, m_max, m_rootDir, minDistSq);
195+ m_tasksStack[++iTask] = NearestTask (m_root, m_min, m_max, m_rootDir);
197196 while (iTask != -1 )
198197 {
199- const NearestTask t = m_tasksStack[iTask--];
198+ const NearestTask& t = m_tasksStack[iTask--];
200199 if (t.distSq > minDistSq)
201200 continue ;
202201 const Node& n = m_nodes[t.node ];
@@ -221,31 +220,31 @@ class KDTree
221220 point_type newMin, newMax;
222221 calcSplitInfo (t.min , t.max , t.dir , mid, newDir, newMin, newMax);
223222
224- const coord_type distToMid = t.dir == NodeSplitDirection::X
225- ? (point.x - mid)
226- : (point.y - mid);
227- const coord_type toMidSq = distToMid * distToMid;
228-
229- const std::size_t iChild = whichChild (point, mid, t.dir );
230223 if (iTask + 2 >= static_cast <int >(m_tasksStack.size ()))
231224 {
232225 m_tasksStack.resize (
233226 m_tasksStack.size () + StackDepthIncrement);
234227 }
235- // node containing point should end up on top of the stack
236- if (iChild == 0 )
237- {
238- m_tasksStack[++iTask] = NearestTask (
239- n.children [1 ], newMin, t.max , newDir, toMidSq);
240- m_tasksStack[++iTask] = NearestTask (
241- n.children [0 ], t.min , newMax, newDir, toMidSq);
242- }
243- else
228+
229+ NearestTask closerTask (n.children [0 ], t.min , newMax, newDir);
230+ NearestTask fartherTask (n.children [1 ], newMin, t.max , newDir);
231+ if (isAfterSplit (point, mid, t.dir ))
232+ std::swap (closerTask, fartherTask);
233+
234+ closerTask.calculateDistanceSquared (point);
235+ if (closerTask.distSq <= minDistSq)
244236 {
245- m_tasksStack[++iTask] = NearestTask (
246- n.children [0 ], t.min , newMax, newDir, toMidSq);
247- m_tasksStack[++iTask] = NearestTask (
248- n.children [1 ], newMin, t.max , newDir, toMidSq);
237+ fartherTask.calculateDistanceSquared (point);
238+ if (fartherTask.distSq <= minDistSq)
239+ {
240+ // put closest node on top of the stack
241+ m_tasksStack[++iTask] = fartherTask;
242+ m_tasksStack[++iTask] = closerTask;
243+ }
244+ else
245+ {
246+ m_tasksStack[++iTask] = closerTask;
247+ }
249248 }
250249 }
251250 }
@@ -261,15 +260,22 @@ class KDTree
261260 return newNodeIndex;
262261 }
263262
263+ static bool isAfterSplit (
264+ const point_type& point,
265+ const coord_type& split,
266+ const NodeSplitDirection::Enum dir)
267+ {
268+ return dir == NodeSplitDirection::X ? point.x > split : point.y > split;
269+ }
270+
264271 // / Test which child point belongs to after the split
265272 // / @returns 0 if first child, 1 if second child
266- std::size_t whichChild (
273+ static std::size_t whichChild (
267274 const point_type& point,
268275 const coord_type& split,
269- const NodeSplitDirection::Enum dir) const
276+ const NodeSplitDirection::Enum dir)
270277 {
271- return static_cast <size_t >(
272- dir == NodeSplitDirection::X ? point.x > split : point.y > split);
278+ return isAfterSplit (point, split, dir);
273279 }
274280
275281 // / Calculate split location, direction, and children boxes
@@ -389,17 +395,24 @@ class KDTree
389395 : dir(NodeSplitDirection::X)
390396 {}
391397 NearestTask (
392- const node_index node_,
393- const point_type& min_,
394- const point_type& max_,
395- const NodeSplitDirection::Enum dir_,
396- const coord_type distSq_)
397- : node(node_)
398- , min(min_)
399- , max(max_)
400- , dir(dir_)
401- , distSq(distSq_)
398+ const node_index node,
399+ const point_type& min,
400+ const point_type& max,
401+ const NodeSplitDirection::Enum dir)
402+ : node(node)
403+ , min(min)
404+ , max(max)
405+ , dir(dir)
406+ , distSq(std::numeric_limits<coord_type>::max())
402407 {}
408+ void calculateDistanceSquared (const point_type& p)
409+ {
410+ const coord_type dx =
411+ std::max (std::max (min.x - p.x , coord_type (0 )), p.x - max.x );
412+ const coord_type dy =
413+ std::max (std::max (min.y - p.y , coord_type (0 )), p.y - max.y );
414+ distSq = dx * dx + dy * dy;
415+ }
403416 };
404417 // allocated in class (not in the 'nearest' method) for better performance
405418 mutable std::vector<NearestTask> m_tasksStack;
0 commit comments