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 // ********************************************************************
 
   26 // $Id: G4KDTree.icc 87443 2014-12-04 12:26:31Z gunter $
 
   28 // Author: Mathieu Karamitros (kara (AT) cenbg . in2p3 . fr) 
 
   32 // 10 Oct 2011 M.Karamitros created
 
   34 // -------------------------------------------------------------------
 
   36  * Based on ``kdtree'', a library for working with kd-trees.
 
   37  * Copyright (C) 2007-2009 John Tsiombikas <nuclear@siggraph.org>
 
   38  * The original open-source version of this code
 
   39  * may be found at http://code.google.com/p/kdtree/
 
   41  * Redistribution and use in source and binary forms, with or without
 
   42  * modification, are permitted provided that the following conditions are
 
   44  * 1. Redistributions of source code must retain the above copyright
 
   46  * list of conditions and the following disclaimer.
 
   47  * 2. Redistributions in binary form must reproduce the above copyright
 
   49  *  this list of conditions and the following disclaimer in the
 
   51  *  and/or other materials provided with the distribution.
 
   52  * 3. The name of the author may not be used to endorse or promote products
 
   53  *  derived from this software without specific prior written permission.
 
   55  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
   56  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
   57  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
   58  * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 
   59  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 
   60  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
   61  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 
   62  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 
   63  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
   65 /* single nearest neighbor search written by Tamas Nepusz
 
   66  * <tamas@cs.rhul.ac.uk>
 
   69 template<typename PointT>
 
   70   G4KDNode_Base* G4KDTree::InsertMap(PointT* point)
 
   72     G4KDNode<PointT>* node = new G4KDNode<PointT>(this, point, 0);
 
   73     this->__InsertMap(node);
 
   77 template<typename PointT>
 
   78   G4KDNode_Base* G4KDTree::Insert(PointT* pos)
 
   80     G4KDNode_Base* node = 0;
 
   83       fRoot = new G4KDNode<PointT>(this, pos, 0);
 
   91       if ((node = fRoot->Insert<PointT>(pos)))
 
  100       fRect = new HyperRect(fDim);
 
  101       fRect->SetMinMax(*pos, *pos);
 
  111 //__________________________________________________________________
 
  112 template<typename Position>
 
  113   int G4KDTree::__NearestInRange(G4KDNode_Base* node,
 
  115                                  const double& range_sq,
 
  117                                  G4KDTreeResult& list,
 
  119                                  G4KDNode_Base *source_node)
 
  123     double dist_sq(DBL_MAX), dx(DBL_MAX);
 
  124     int ret(-1), added_res(0);
 
  126     if (node->IsValid() && node != source_node)
 
  128       bool do_break = false;
 
  130       for (size_t i = 0; i < fDim; i++)
 
  132         dist_sq += sqr((*node)[i] - pos[i]);
 
  133         if (dist_sq > range_sq)
 
  139       if (!do_break && dist_sq <= range_sq)
 
  141         list.Insert(dist_sq, node);
 
  146     dx = pos[node->GetAxis()] - (*node)[node->GetAxis()];
 
  148     ret = __NearestInRange(dx <= 0.0 ? node->GetLeft() : node->GetRight(), pos,
 
  149                            range_sq, range, list, ordered, source_node);
 
  150     if (ret >= 0 && std::fabs(dx) <= range)
 
  153       ret = __NearestInRange(dx <= 0.0 ? node->GetRight() : node->GetLeft(),
 
  154                              pos, range_sq, range, list, ordered, source_node);
 
  166 //__________________________________________________________________
 
  167 template<typename Position>
 
  168   void G4KDTree::__NearestToPosition(G4KDNode_Base *node,
 
  170                                      G4KDNode_Base *&result,
 
  171                                      double *result_dist_sq,
 
  174     int dir = node->GetAxis();
 
  175     double dummy(0.), dist_sq(-1.);
 
  176     G4KDNode_Base* nearer_subtree(0), *farther_subtree(0);
 
  177     double *nearer_hyperrect_coord(0), *farther_hyperrect_coord(0);
 
  179     /* Decide whether to go left or right in the tree */
 
  180     dummy = pos[dir] - (*node)[dir];
 
  183       nearer_subtree = node->GetLeft();
 
  184       farther_subtree = node->GetRight();
 
  186       nearer_hyperrect_coord = rect->GetMax() + dir;
 
  187       farther_hyperrect_coord = rect->GetMin() + dir;
 
  191       nearer_subtree = node->GetRight();
 
  192       farther_subtree = node->GetLeft();
 
  193       nearer_hyperrect_coord = rect->GetMin() + dir;
 
  194       farther_hyperrect_coord = rect->GetMax() + dir;
 
  199       /* Slice the hyperrect to get the hyperrect of the nearer subtree */
 
  200       dummy = *nearer_hyperrect_coord;
 
  201       *nearer_hyperrect_coord = (*node)[dir];
 
  202       /* Recurse down into nearer subtree */
 
  203       __NearestToPosition(nearer_subtree, pos, result, result_dist_sq, rect);
 
  205       *nearer_hyperrect_coord = dummy;
 
  208     /* Check the distance of the point at the current node, compare it
 
  209      * with our best so far */
 
  210     if (node->IsValid()) // TODO
 
  213       bool do_break = false;
 
  214       for (size_t i = 0; i < fDim; i++)
 
  216         dist_sq += sqr((*node)[i] - pos[i]);
 
  217         if (dist_sq > *result_dist_sq)
 
  223       if (!do_break && dist_sq < *result_dist_sq)
 
  226         *result_dist_sq = dist_sq;
 
  232       /* Get the hyperrect of the farther subtree */
 
  233       dummy = *farther_hyperrect_coord;
 
  234       *farther_hyperrect_coord = (*node)[dir];
 
  235       /* Check if we have to recurse down by calculating the closest
 
  236        * point of the hyperrect and see if it's closer than our
 
  237        * minimum distance in result_dist_sq. */
 
  238       if (rect->CompareDistSqr(pos, result_dist_sq))
 
  240         /* Recurse down into farther subtree */
 
  241         __NearestToPosition(farther_subtree, pos, result, result_dist_sq, rect);
 
  243       /* Undo the slice on the hyperrect */
 
  244       *farther_hyperrect_coord = dummy;
 
  248 template<typename Position>
 
  249   G4KDTreeResultHandle G4KDTree::Nearest(const Position& pos)
 
  251     //    G4cout << "Nearest(pos)" << G4endl ;
 
  253     if (!fRect) return 0;
 
  255     G4KDNode_Base *result(0);
 
  256     double dist_sq = DBL_MAX;
 
  258     /* Duplicate the bounding hyperrectangle, we will work on the copy */
 
  259     HyperRect* newrect = new HyperRect(*fRect);
 
  261     /* Our first guesstimate is the root node */
 
  262     /* Search for the nearest neighbour recursively */
 
  263     __NearestToPosition(fRoot, pos, result, &dist_sq, newrect);
 
  265     /* Free the copy of the hyperrect */
 
  268     /* Store the result */
 
  271       G4KDTreeResultHandle rset = new G4KDTreeResult(this);
 
  272       rset->Insert(dist_sq, result);
 
  282 //__________________________________________________________________
 
  283 template<typename Position>
 
  284   void G4KDTree::__NearestToNode(G4KDNode_Base* source_node,
 
  287                                  std::vector<G4KDNode_Base*>& result,
 
  288                                  double *result_dist_sq,
 
  292     int dir = node->GetAxis();
 
  293     double dummy, dist_sq;
 
  294     G4KDNode_Base *nearer_subtree(0), *farther_subtree(0);
 
  295     double *nearer_hyperrect_coord(0), *farther_hyperrect_coord(0);
 
  297     /* Decide whether to go left or right in the tree */
 
  298     dummy = pos[dir] - (*node)[dir];
 
  301       nearer_subtree = node->GetLeft();
 
  302       farther_subtree = node->GetRight();
 
  303       nearer_hyperrect_coord = rect->GetMax() + dir;
 
  304       farther_hyperrect_coord = rect->GetMin() + dir;
 
  308       nearer_subtree = node->GetRight();
 
  309       farther_subtree = node->GetLeft();
 
  310       nearer_hyperrect_coord = rect->GetMin() + dir;
 
  311       farther_hyperrect_coord = rect->GetMax() + dir;
 
  316       /* Slice the hyperrect to get the hyperrect of the nearer subtree */
 
  317       dummy = *nearer_hyperrect_coord;
 
  318       *nearer_hyperrect_coord = (*node)[dir];
 
  319       /* Recurse down into nearer subtree */
 
  320       __NearestToNode(source_node, nearer_subtree, pos, result, result_dist_sq,
 
  323       *nearer_hyperrect_coord = dummy;
 
  326     /* Check the distance of the point at the current node, compare it
 
  327      * with our best so far */
 
  328     if (node->IsValid() && node != source_node)
 
  331       bool do_break = false;
 
  332       for (size_t i = 0; i < fDim; i++)
 
  334         dist_sq += sqr((*node)[i] - pos[i]);
 
  335         if (dist_sq > *result_dist_sq)
 
  343         if (dist_sq < *result_dist_sq)
 
  347           result.push_back(node);
 
  348           *result_dist_sq = dist_sq;
 
  350         else if (dist_sq == *result_dist_sq)
 
  352           result.push_back(node);
 
  360       /* Get the hyperrect of the farther subtree */
 
  361       dummy = *farther_hyperrect_coord;
 
  362       *farther_hyperrect_coord = (*node)[dir];
 
  363       /* Check if we have to recurse down by calculating the closest
 
  364        * point of the hyperrect and see if it's closer than our
 
  365        * minimum distance in result_dist_sq. */
 
  366       //        if (hyperrect_dist_sq(rect, pos) < *result_dist_sq)
 
  367       if (rect->CompareDistSqr(pos, result_dist_sq))
 
  369         /* Recurse down into farther subtree */
 
  370         __NearestToNode(source_node, farther_subtree, pos, result,
 
  371                         result_dist_sq, rect, nbresult);
 
  373       /* Undo the slice on the hyperrect */
 
  374       *farther_hyperrect_coord = dummy;
 
  378 template<typename Position>
 
  379   G4KDTreeResultHandle G4KDTree::NearestInRange(const Position& pos,
 
  384     const double range_sq = sqr(range);
 
  386     G4KDTreeResultHandle rset = new G4KDTreeResult(this);
 
  387     if ((ret = __NearestInRange(fRoot, pos, range_sq, range, *(rset()), 0)) == -1)