libssrckdtree 1.0.8 C++ Unit Test Coverage
Current view: top level - ssrc/spatial/detail - kd_tree_nearest_neighbors.h (source / functions) Hit Total Coverage
Test: libssrckdtree 1.0.8 C++ Unit Tests Lines: 55 55 100.0 %
Date: 2011-06-03 Functions: 30 30 100.0 %
Branches: 114 174 65.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright 2010 Savarese Software Research Corporation
       3                 :            :  *
       4                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :            :  * you may not use this file except in compliance with the License.
       6                 :            :  * You may obtain a copy of the License at
       7                 :            :  *
       8                 :            :  *     https://www.savarese.com/software/ApacheLicense-2.0
       9                 :            :  *
      10                 :            :  * Unless required by applicable law or agreed to in writing, software
      11                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :            :  * See the License for the specific language governing permissions and
      14                 :            :  * limitations under the License.
      15                 :            :  */
      16                 :            : 
      17                 :            : #ifndef __SSRC_SPATIAL_DETAIL_KDTREE_NEAREST_NEIGHBORS_H
      18                 :            : #define __SSRC_SPATIAL_DETAIL_KDTREE_NEAREST_NEIGHBORS_H
      19                 :            : 
      20                 :            : #include <ssrc/spatial/detail/coordinate_limits.h>
      21                 :            : #include <ssrc/spatial/distance.h>
      22                 :            : 
      23                 :            : #include <vector>
      24                 :            : #include <algorithm>
      25                 :            : 
      26                 :            : #include <boost/shared_ptr.hpp>
      27                 :            : #include <boost/shared_container_iterator.hpp>
      28                 :            : #include <boost/iterator/transform_iterator.hpp>
      29                 :            : 
      30                 :            : __BEGIN_NS_SSRC_SPATIAL
      31                 :            : 
      32                 :            : namespace detail {
      33                 :            : 
      34                 :            :   template<typename TreeTraits, typename Distance>
      35                 :        988 :   struct kd_tree_nn_pq_value {
      36                 :            :     typedef TreeTraits traits;
      37                 :            :     typedef Distance distance_type;
      38                 :            :     typedef typename traits::node_type node_type;
      39                 :            : 
      40                 :            :     distance_type distance;
      41                 :            :     node_type *node;
      42                 :            : 
      43                 :       1342 :     kd_tree_nn_pq_value(const distance_type distance = distance_type(0),
      44                 :            :                         node_type * const node = 0) :
      45                 :       1342 :       distance(distance), node(node)
      46                 :       1342 :     { }
      47                 :            : 
      48                 :       4093 :     friend bool operator<(const kd_tree_nn_pq_value & v1,
      49                 :            :                           const kd_tree_nn_pq_value & v2)
      50                 :            :     {
      51                 :       4093 :       return (v1.distance < v2.distance);
      52                 :            :     }
      53                 :            :   };
      54                 :            : 
      55                 :            :   template<typename TreeTraits, typename Distance>
      56                 :            :   class kd_tree_nearest_neighbors {
      57                 :            :     typedef TreeTraits traits;
      58                 :            :     typedef typename traits::key_type key_type;
      59                 :            :     typedef typename traits::node_type node_type;
      60                 :            :     typedef typename traits::discriminator_type discriminator_type;
      61                 :            :     typedef Distance distance_type;
      62                 :            :     typedef kd_tree_nn_pq_value<traits, distance_type> pq_value_type;
      63                 :            :     typedef std::vector<pq_value_type> pq_type;
      64                 :            :     typedef boost::shared_container_iterator<pq_type> shared_iterator;
      65                 :            : 
      66                 :            :     mutable bool _omit_query_point;
      67                 :            :     mutable unsigned int _num_neighbors;
      68                 :            :     mutable distance_type _min_distance;
      69                 :            :     mutable pq_type *_pq;
      70                 :            :     mutable key_type _query;
      71                 :            : 
      72                 :            :     struct get_node_pair {
      73                 :            :       typedef
      74                 :            :       typename kd_tree_nearest_neighbors::traits::const_reference result_type;
      75                 :            :       typedef kd_tree_nearest_neighbors::pq_value_type pq_value_type;
      76                 :            : 
      77                 :        350 :       result_type operator()(const pq_value_type  & v) const {
      78                 :        350 :         return v.node->pair();
      79                 :            :       }
      80                 :            :     };
      81                 :            : 
      82                 :       1342 :     void push(const pq_value_type & v) const {
      83                 :       1342 :       _pq->push_back(v);
      84                 :       1342 :       std::push_heap(_pq->begin(), _pq->end());
      85                 :       1342 :     }
      86                 :            : 
      87                 :        988 :     void pop() const {
      88                 :        988 :       std::pop_heap(_pq->begin(), _pq->end());
      89                 :        988 :       _pq->pop_back();
      90                 :        988 :     }
      91                 :            : 
      92                 :       1070 :     const pq_value_type & top() const {
      93                 :       1070 :       return _pq->front();
      94                 :            :     }
      95                 :            : 
      96                 :       3836 :     void find(node_type * const node) const {
      97 [ +  + ][ +  + ]:       3836 :       if(node == 0)
                 [ +  + ]
      98                 :       3836 :         return;
      99                 :            : 
     100                 :       2628 :       const discriminator_type discriminator = node->discriminator;
     101                 :       2628 :       const key_type & point = node->point();
     102                 :       2628 :       distance_type d2 = euclidean_distance<key_type>::d2(_query, point);
     103                 :            : 
     104 [ +  + ][ +  + ]:       2628 :       if(d2 < _min_distance && (d2 != 0 || !_omit_query_point)) {
           [ +  +  +  + ]
                 [ +  + ]
           [ +  +  +  + ]
         [ +  + ][ +  + ]
     105 [ +  + ][ +  + ]:       1342 :         if(_pq->size() == _num_neighbors) {
                 [ +  + ]
     106                 :        988 :           pop();
     107                 :        988 :           push(pq_value_type(d2, node));
     108                 :        988 :           _min_distance = top().distance;
     109                 :            :         } else {
     110                 :        354 :           push(pq_value_type(d2, node));
     111   [ +  +  +  +  :        354 :           if(_pq->size() == _num_neighbors) {
                   +  + ]
     112                 :         82 :             _min_distance = top().distance;
     113                 :            :           }
     114                 :            :         }
     115                 :            :       }
     116                 :            : 
     117                 :            :       // Distance to partition plane.
     118                 :            :       const distance_type dp =
     119                 :            :         static_cast<distance_type>(_query[discriminator]) -
     120                 :       2628 :         static_cast<distance_type>(point[discriminator]);
     121                 :            : 
     122                 :       2628 :       d2 = dp*dp;
     123                 :            : 
     124   [ +  +  +  +  :       2628 :       if(dp < 0) {
                   +  + ]
     125                 :        708 :         find(node->child_low);
     126   [ +  +  +  +  :        708 :         if(d2 < _min_distance) {
                   +  + ]
     127                 :        158 :           find(node->child_high);
     128                 :            :         }
     129                 :            :       } else {
     130                 :       1920 :         find(node->child_high);
     131   [ +  +  +  +  :       1920 :         if(d2 < _min_distance) {
                   +  + ]
     132                 :        968 :           find(node->child_low);
     133                 :            :         }
     134                 :            :       }
     135                 :            :     }
     136                 :            : 
     137                 :            :   public:
     138                 :            :     typedef
     139                 :            :     boost::transform_iterator<get_node_pair, shared_iterator>
     140                 :            :     iterator;
     141                 :            : 
     142                 :         82 :     kd_tree_nearest_neighbors() { }
     143                 :            : 
     144                 :         82 :     std::pair<iterator,iterator> find(node_type * const root,
     145                 :            :                                       const key_type & query,
     146                 :            :                                       const unsigned int num_neighbors,
     147                 :            :                                       const bool omit_query_point) const
     148                 :            :     {
     149 [ +  - ][ +  - ]:        164 :       boost::shared_ptr<pq_type> neighbors(new pq_type());
                 [ +  - ]
     150                 :         82 :       _pq = neighbors.get();
     151   [ +  -  +  -  :         82 :       _pq->reserve(num_neighbors);
                   +  - ]
     152                 :            : 
     153                 :         82 :       _omit_query_point = omit_query_point;
     154                 :         82 :       _num_neighbors = num_neighbors;
     155                 :         82 :       _min_distance = coordinate_limits<distance_type>::highest();
     156                 :         82 :       _query = query;
     157                 :            : 
     158   [ +  -  +  -  :         82 :       if(num_neighbors > 0) {
                   +  - ]
     159 [ +  - ][ +  - ]:         82 :         find(root);
                 [ +  - ]
     160                 :            :       }
     161                 :            : 
     162 [ +  - ][ +  - ]:         82 :       std::sort_heap(_pq->begin(), _pq->end());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     163                 :         82 :       _pq = 0;
     164                 :            : 
     165                 :            :      
     166                 :            :       return
     167                 :            :         std::pair<iterator,iterator>(
     168                 :            :                   iterator(shared_iterator(neighbors->begin(), neighbors),
     169                 :            :                            get_node_pair()),
     170                 :            :                   iterator(shared_iterator(neighbors->end(), neighbors),
     171 [ +  - ][ +  - ]:        164 :                            get_node_pair()));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     172                 :            : 
     173                 :            :     }
     174                 :            :   };
     175                 :            : 
     176                 :            : }
     177                 :            : 
     178                 :            : __END_NS_SSRC_SPATIAL
     179                 :            : 
     180                 :            : #endif