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 93883 2015-11-03 08:25:04Z gcosmo $
 
   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 template<typename PointT>
 
  112   G4KDNode_Base* G4KDTree::Insert(const PointT& pos)
 
  114     G4KDNode_Base* node = 0;
 
  117       fRoot = new G4KDNodeCopy<PointT>(this, pos, 0);
 
  125       if ((node = fRoot->Insert<PointT>(pos)))
 
  134       fRect = new HyperRect(fDim);
 
  135       fRect->SetMinMax(pos, pos);
 
  145 //__________________________________________________________________
 
  146 template<typename Position>
 
  147   int G4KDTree::__NearestInRange(G4KDNode_Base* node,
 
  149                                  const double& range_sq,
 
  151                                  G4KDTreeResult& list,
 
  153                                  G4KDNode_Base *source_node)
 
  157     double dist_sq(DBL_MAX), dx(DBL_MAX);
 
  158     int ret(-1), added_res(0);
 
  160     if (node->IsValid() && node != source_node)
 
  162       bool do_break = false;
 
  164       for (size_t i = 0; i < fDim; i++)
 
  166         dist_sq += sqr((*node)[i] - pos[i]);
 
  167         if (dist_sq > range_sq)
 
  173       if (!do_break && dist_sq <= range_sq)
 
  175         list.Insert(dist_sq, node);
 
  180     dx = pos[node->GetAxis()] - (*node)[node->GetAxis()];
 
  182     ret = __NearestInRange(dx <= 0.0 ? node->GetLeft() : node->GetRight(), pos,
 
  183                            range_sq, range, list, ordered, source_node);
 
  184     if (ret >= 0 && std::fabs(dx) <= range)
 
  187       ret = __NearestInRange(dx <= 0.0 ? node->GetRight() : node->GetLeft(),
 
  188                              pos, range_sq, range, list, ordered, source_node);
 
  200 //__________________________________________________________________
 
  201 template<typename Position>
 
  202   void G4KDTree::__NearestToPosition(G4KDNode_Base *node,
 
  204                                      G4KDNode_Base *&result,
 
  205                                      double *result_dist_sq,
 
  208     int dir = node->GetAxis();
 
  209     double dummy(0.), dist_sq(-1.);
 
  210     G4KDNode_Base* nearer_subtree(0), *farther_subtree(0);
 
  211     double *nearer_hyperrect_coord(0), *farther_hyperrect_coord(0);
 
  213     /* Decide whether to go left or right in the tree */
 
  214     dummy = pos[dir] - (*node)[dir];
 
  217       nearer_subtree = node->GetLeft();
 
  218       farther_subtree = node->GetRight();
 
  220       nearer_hyperrect_coord = rect->GetMax() + dir;
 
  221       farther_hyperrect_coord = rect->GetMin() + dir;
 
  225       nearer_subtree = node->GetRight();
 
  226       farther_subtree = node->GetLeft();
 
  227       nearer_hyperrect_coord = rect->GetMin() + dir;
 
  228       farther_hyperrect_coord = rect->GetMax() + dir;
 
  233       /* Slice the hyperrect to get the hyperrect of the nearer subtree */
 
  234       dummy = *nearer_hyperrect_coord;
 
  235       *nearer_hyperrect_coord = (*node)[dir];
 
  236       /* Recurse down into nearer subtree */
 
  237       __NearestToPosition(nearer_subtree, pos, result, result_dist_sq, rect);
 
  239       *nearer_hyperrect_coord = dummy;
 
  242     /* Check the distance of the point at the current node, compare it
 
  243      * with our best so far */
 
  244     if (node->IsValid()) // TODO
 
  247       bool do_break = false;
 
  248       for (size_t i = 0; i < fDim; i++)
 
  250         dist_sq += sqr((*node)[i] - pos[i]);
 
  251         if (dist_sq > *result_dist_sq)
 
  257       if (!do_break && dist_sq < *result_dist_sq)
 
  260         *result_dist_sq = dist_sq;
 
  266       /* Get the hyperrect of the farther subtree */
 
  267       dummy = *farther_hyperrect_coord;
 
  268       *farther_hyperrect_coord = (*node)[dir];
 
  269       /* Check if we have to recurse down by calculating the closest
 
  270        * point of the hyperrect and see if it's closer than our
 
  271        * minimum distance in result_dist_sq. */
 
  272       if (rect->CompareDistSqr(pos, result_dist_sq))
 
  274         /* Recurse down into farther subtree */
 
  275         __NearestToPosition(farther_subtree, pos, result, result_dist_sq, rect);
 
  277       /* Undo the slice on the hyperrect */
 
  278       *farther_hyperrect_coord = dummy;
 
  282 template<typename Position>
 
  283   G4KDTreeResultHandle G4KDTree::Nearest(const Position& pos)
 
  285     //    G4cout << "Nearest(pos)" << G4endl ;
 
  287     if (!fRect) return 0;
 
  289     G4KDNode_Base *result(0);
 
  290     double dist_sq = DBL_MAX;
 
  292     /* Duplicate the bounding hyperrectangle, we will work on the copy */
 
  293     HyperRect* newrect = new HyperRect(*fRect);
 
  295     /* Our first estimate is the root node */
 
  296     /* Search for the nearest neighbour recursively */
 
  297     __NearestToPosition(fRoot, pos, result, &dist_sq, newrect);
 
  299     /* Free the copy of the hyperrect */
 
  302     /* Store the result */
 
  305       G4KDTreeResultHandle rset = new G4KDTreeResult(this);
 
  306       rset->Insert(dist_sq, result);
 
  316 //__________________________________________________________________
 
  317 template<typename Position>
 
  318   void G4KDTree::__NearestToNode(G4KDNode_Base* source_node,
 
  321                                  std::vector<G4KDNode_Base*>& result,
 
  322                                  double *result_dist_sq,
 
  326     int dir = node->GetAxis();
 
  327     double dummy, dist_sq;
 
  328     G4KDNode_Base *nearer_subtree(0), *farther_subtree(0);
 
  329     double *nearer_hyperrect_coord(0), *farther_hyperrect_coord(0);
 
  331     /* Decide whether to go left or right in the tree */
 
  332     dummy = pos[dir] - (*node)[dir];
 
  335       nearer_subtree = node->GetLeft();
 
  336       farther_subtree = node->GetRight();
 
  337       nearer_hyperrect_coord = rect->GetMax() + dir;
 
  338       farther_hyperrect_coord = rect->GetMin() + dir;
 
  342       nearer_subtree = node->GetRight();
 
  343       farther_subtree = node->GetLeft();
 
  344       nearer_hyperrect_coord = rect->GetMin() + dir;
 
  345       farther_hyperrect_coord = rect->GetMax() + dir;
 
  350       /* Slice the hyperrect to get the hyperrect of the nearer subtree */
 
  351       dummy = *nearer_hyperrect_coord;
 
  352       *nearer_hyperrect_coord = (*node)[dir];
 
  353       /* Recurse down into nearer subtree */
 
  354       __NearestToNode(source_node, nearer_subtree, pos, result, result_dist_sq,
 
  357       *nearer_hyperrect_coord = dummy;
 
  360     /* Check the distance of the point at the current node, compare it
 
  361      * with our best so far */
 
  362     if (node->IsValid() && node != source_node)
 
  365       bool do_break = false;
 
  366       for (size_t i = 0; i < fDim; i++)
 
  368         dist_sq += sqr((*node)[i] - pos[i]);
 
  369         if (dist_sq > *result_dist_sq)
 
  377         if (dist_sq < *result_dist_sq)
 
  381           result.push_back(node);
 
  382           *result_dist_sq = dist_sq;
 
  384         else if (dist_sq == *result_dist_sq)
 
  386           result.push_back(node);
 
  394       /* Get the hyperrect of the farther subtree */
 
  395       dummy = *farther_hyperrect_coord;
 
  396       *farther_hyperrect_coord = (*node)[dir];
 
  397       /* Check if we have to recurse down by calculating the closest
 
  398        * point of the hyperrect and see if it's closer than our
 
  399        * minimum distance in result_dist_sq. */
 
  400       //        if (hyperrect_dist_sq(rect, pos) < *result_dist_sq)
 
  401       if (rect->CompareDistSqr(pos, result_dist_sq))
 
  403         /* Recurse down into farther subtree */
 
  404         __NearestToNode(source_node, farther_subtree, pos, result,
 
  405                         result_dist_sq, rect, nbresult);
 
  407       /* Undo the slice on the hyperrect */
 
  408       *farther_hyperrect_coord = dummy;
 
  412 template<typename Position>
 
  413   G4KDTreeResultHandle G4KDTree::NearestInRange(const Position& pos,
 
  418     const double range_sq = sqr(range);
 
  420     G4KDTreeResultHandle rset = new G4KDTreeResult(this);
 
  421     if ((ret = __NearestInRange(fRoot, pos, range_sq, range, *(rset()), 0)) == -1)