2// ********************************************************************
3// * License and Disclaimer *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
27// Author: Mathieu Karamitros (kara (AT) cenbg . in2p3 . fr)
31// 10 Oct 2011 M.Karamitros created
33// -------------------------------------------------------------------
35 * Based on ``kdtree'', a library for working with kd-trees.
36 * Copyright (C) 2007-2009 John Tsiombikas <nuclear@siggraph.org>
37 * The original open-source version of this code
38 * may be found at http://code.google.com/p/kdtree/
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions are
43 * 1. Redistributions of source code must retain the above copyright
45 * list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
48 * this list of conditions and the following disclaimer in the
50 * and/or other materials provided with the distribution.
51 * 3. The name of the author may not be used to endorse or promote products
52 * derived from this software without specific prior written permission.
54 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
55 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
56 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
57 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
58 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
59 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
60 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
61 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
62 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64/* single nearest neighbor search written by Tamas Nepusz
65 * <tamas@cs.rhul.ac.uk>
68template<typename PointT>
69 G4KDNode_Base* G4KDTree::InsertMap(PointT* point)
71 G4KDNode<PointT>* node = new G4KDNode<PointT>(this, point, 0);
72 this->__InsertMap(node);
76template<typename PointT>
77 G4KDNode_Base* G4KDTree::Insert(PointT* pos)
79 G4KDNode_Base* node = 0;
82 fRoot = new G4KDNode<PointT>(this, pos, 0);
90 if ((node = fRoot->Insert<PointT>(pos)))
99 fRect = new HyperRect(fDim);
100 fRect->SetMinMax(*pos, *pos);
110template<typename PointT>
111 G4KDNode_Base* G4KDTree::Insert(const PointT& pos)
113 G4KDNode_Base* node = 0;
116 fRoot = new G4KDNodeCopy<PointT>(this, pos, 0);
124 if ((node = fRoot->Insert<PointT>(pos)))
133 fRect = new HyperRect(fDim);
134 fRect->SetMinMax(pos, pos);
144//__________________________________________________________________
145template<typename Position>
146 int G4KDTree::__NearestInRange(G4KDNode_Base* node,
148 const double& range_sq,
150 G4KDTreeResult& list,
152 G4KDNode_Base *source_node)
156 double dist_sq(DBL_MAX), dx(DBL_MAX);
157 int ret(-1), added_res(0);
159 if (node->IsValid() && node != source_node)
161 bool do_break = false;
163 for (size_t i = 0; i < fDim; i++)
165 dist_sq += sqr((*node)[i] - pos[i]);
166 if (dist_sq > range_sq)
172 if (!do_break && dist_sq <= range_sq)
174 list.Insert(dist_sq, node);
179 dx = pos[node->GetAxis()] - (*node)[node->GetAxis()];
181 ret = __NearestInRange(dx <= 0.0 ? node->GetLeft() : node->GetRight(), pos,
182 range_sq, range, list, ordered, source_node);
183 if (ret >= 0 && std::fabs(dx) <= range)
186 ret = __NearestInRange(dx <= 0.0 ? node->GetRight() : node->GetLeft(),
187 pos, range_sq, range, list, ordered, source_node);
199//__________________________________________________________________
200template<typename Position>
201 void G4KDTree::__NearestToPosition(G4KDNode_Base *node,
203 G4KDNode_Base *&result,
204 double *result_dist_sq,
207 int dir = node->GetAxis();
208 double dummy(0.), dist_sq(-1.);
209 G4KDNode_Base* nearer_subtree(0), *farther_subtree(0);
210 double *nearer_hyperrect_coord(0), *farther_hyperrect_coord(0);
212 /* Decide whether to go left or right in the tree */
213 dummy = pos[dir] - (*node)[dir];
216 nearer_subtree = node->GetLeft();
217 farther_subtree = node->GetRight();
219 nearer_hyperrect_coord = rect->GetMax() + dir;
220 farther_hyperrect_coord = rect->GetMin() + dir;
224 nearer_subtree = node->GetRight();
225 farther_subtree = node->GetLeft();
226 nearer_hyperrect_coord = rect->GetMin() + dir;
227 farther_hyperrect_coord = rect->GetMax() + dir;
232 /* Slice the hyperrect to get the hyperrect of the nearer subtree */
233 dummy = *nearer_hyperrect_coord;
234 *nearer_hyperrect_coord = (*node)[dir];
235 /* Recurse down into nearer subtree */
236 __NearestToPosition(nearer_subtree, pos, result, result_dist_sq, rect);
238 *nearer_hyperrect_coord = dummy;
241 /* Check the distance of the point at the current node, compare it
242 * with our best so far */
243 if (node->IsValid()) // TODO
246 bool do_break = false;
247 for (size_t i = 0; i < fDim; i++)
249 dist_sq += sqr((*node)[i] - pos[i]);
250 if (dist_sq > *result_dist_sq)
256 if (!do_break && dist_sq < *result_dist_sq)
259 *result_dist_sq = dist_sq;
265 /* Get the hyperrect of the farther subtree */
266 dummy = *farther_hyperrect_coord;
267 *farther_hyperrect_coord = (*node)[dir];
268 /* Check if we have to recurse down by calculating the closest
269 * point of the hyperrect and see if it's closer than our
270 * minimum distance in result_dist_sq. */
271 if (rect->CompareDistSqr(pos, result_dist_sq))
273 /* Recurse down into farther subtree */
274 __NearestToPosition(farther_subtree, pos, result, result_dist_sq, rect);
276 /* Undo the slice on the hyperrect */
277 *farther_hyperrect_coord = dummy;
281template<typename Position>
282 G4KDTreeResultHandle G4KDTree::Nearest(const Position& pos)
284 // G4cout << "Nearest(pos)" << G4endl ;
286 if (!fRect) return 0;
288 G4KDNode_Base *result(0);
289 double dist_sq = DBL_MAX;
291 /* Duplicate the bounding hyperrectangle, we will work on the copy */
292 HyperRect* newrect = new HyperRect(*fRect);
294 /* Our first estimate is the root node */
295 /* Search for the nearest neighbour recursively */
296 __NearestToPosition(fRoot, pos, result, &dist_sq, newrect);
298 /* Free the copy of the hyperrect */
301 /* Store the result */
304 G4KDTreeResultHandle rset = new G4KDTreeResult(this);
305 rset->Insert(dist_sq, result);
315//__________________________________________________________________
316template<typename Position>
317 void G4KDTree::__NearestToNode(G4KDNode_Base* source_node,
320 std::vector<G4KDNode_Base*>& result,
321 double *result_dist_sq,
325 int dir = node->GetAxis();
326 double dummy, dist_sq;
327 G4KDNode_Base *nearer_subtree(0), *farther_subtree(0);
328 double *nearer_hyperrect_coord(0), *farther_hyperrect_coord(0);
330 /* Decide whether to go left or right in the tree */
331 dummy = pos[dir] - (*node)[dir];
334 nearer_subtree = node->GetLeft();
335 farther_subtree = node->GetRight();
336 nearer_hyperrect_coord = rect->GetMax() + dir;
337 farther_hyperrect_coord = rect->GetMin() + dir;
341 nearer_subtree = node->GetRight();
342 farther_subtree = node->GetLeft();
343 nearer_hyperrect_coord = rect->GetMin() + dir;
344 farther_hyperrect_coord = rect->GetMax() + dir;
349 /* Slice the hyperrect to get the hyperrect of the nearer subtree */
350 dummy = *nearer_hyperrect_coord;
351 *nearer_hyperrect_coord = (*node)[dir];
352 /* Recurse down into nearer subtree */
353 __NearestToNode(source_node, nearer_subtree, pos, result, result_dist_sq,
356 *nearer_hyperrect_coord = dummy;
359 /* Check the distance of the point at the current node, compare it
360 * with our best so far */
361 if (node->IsValid() && node != source_node)
364 bool do_break = false;
365 for (size_t i = 0; i < fDim; i++)
367 dist_sq += sqr((*node)[i] - pos[i]);
368 if (dist_sq > *result_dist_sq)
376 if (dist_sq < *result_dist_sq)
380 result.push_back(node);
381 *result_dist_sq = dist_sq;
383 else if (dist_sq == *result_dist_sq)
385 result.push_back(node);
393 /* Get the hyperrect of the farther subtree */
394 dummy = *farther_hyperrect_coord;
395 *farther_hyperrect_coord = (*node)[dir];
396 /* Check if we have to recurse down by calculating the closest
397 * point of the hyperrect and see if it's closer than our
398 * minimum distance in result_dist_sq. */
399 // if (hyperrect_dist_sq(rect, pos) < *result_dist_sq)
400 if (rect->CompareDistSqr(pos, result_dist_sq))
402 /* Recurse down into farther subtree */
403 __NearestToNode(source_node, farther_subtree, pos, result,
404 result_dist_sq, rect, nbresult);
406 /* Undo the slice on the hyperrect */
407 *farther_hyperrect_coord = dummy;
411template<typename Position>
412 G4KDTreeResultHandle G4KDTree::NearestInRange(const Position& pos,
417 const double range_sq = sqr(range);
419 G4KDTreeResultHandle rset = new G4KDTreeResult(this);
420 if ((ret = __NearestInRange(fRoot, pos, range_sq, range, *(rset()), 0)) == -1)