Savarese Software Research Corporation
libssrckdtree-j 1.0.2 Java Unit Test Coverage
[all classes][com.savarese.spatial]

COVERAGE SUMMARY FOR SOURCE FILE [NearestNeighbors.java]

nameclass, %method, %block, %line, %
NearestNeighbors.java75%  (3/4)80%  (12/15)92%  (259/280)91%  (60/66)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class NearestNeighbors$10%   (0/1)100% (0/0)100% (0/0)100% (0/0)
     
class NearestNeighbors$EntryComparator100% (1/1)75%  (3/4)72%  (28/39)78%  (7/9)
equals (Object): boolean 0%   (0/1)0%   (0/9)0%   (0/1)
compare (NearestNeighbors$Entry, NearestNeighbors$Entry): int 100% (1/1)90%  (18/20)86%  (6/7)
NearestNeighbors$EntryComparator (NearestNeighbors): void 100% (1/1)100% (6/6)100% (1/1)
NearestNeighbors$EntryComparator (NearestNeighbors, NearestNeighbors$1): void 100% (1/1)100% (4/4)100% (1/1)
     
class NearestNeighbors$NNEntry100% (1/1)80%  (4/5)85%  (35/41)85%  (11/13)
getDistance (): double 0%   (0/1)0%   (0/4)0%   (0/1)
compareTo (NearestNeighbors$Entry): int 100% (1/1)89%  (17/19)83%  (5/6)
NearestNeighbors$NNEntry (NearestNeighbors, double, Map$Entry): void 100% (1/1)100% (12/12)100% (4/4)
getDistance2 (): double 100% (1/1)100% (3/3)100% (1/1)
getNeighbor (): Map$Entry 100% (1/1)100% (3/3)100% (1/1)
     
class NearestNeighbors100% (1/1)83%  (5/6)98%  (196/200)95%  (42/44)
setDistance (Distance): void 0%   (0/1)0%   (0/4)0%   (0/2)
NearestNeighbors (): void 100% (1/1)100% (6/6)100% (2/2)
NearestNeighbors (Distance): void 100% (1/1)100% (6/6)100% (3/3)
find (KDTree$KDNode): void 100% (1/1)100% (128/128)100% (23/23)
get (KDTree, Point, int): NearestNeighbors$Entry [] 100% (1/1)100% (7/7)100% (1/1)
get (KDTree, Point, int, boolean): NearestNeighbors$Entry [] 100% (1/1)100% (49/49)100% (13/13)

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 
17package com.savarese.spatial;
18 
19import java.util.PriorityQueue;
20import java.util.Map;
21import java.util.Arrays;
22import java.util.Comparator;
23 
24/**
25 * NearestNeighbors implements an algorithm for finding the k-nearest
26 * neighbors to a query point within the set of points contained by a
27 * {@link KDTree} instance.  The algorithm can be specialized with a custom
28 * distance-finding function by passing a {@link Distance} instance to its
29 * constructor.
30 */
31public class NearestNeighbors<Coord extends Number & Comparable<? super Coord>,
32                               P extends Point<Coord>, V>
33{
34  /**
35   * The Entry interface makes accessible the results of a
36   * {@link NearestNeighbors} search.  An Entry exposes both the
37   * point-value mapping and its distance from the query point.
38   */
39  public interface Entry<Coord extends Number & Comparable<? super Coord>,
40                         P extends Point<Coord>, V>
41  {
42    /**
43     * Returns the distance from result to the query point.  This
44     * will usually be implemented by dynamically taking the square root
45     * of {@link #getDistance2}.  Therefore, repeated calls may be
46     * expensive.
47     *
48     * @return The distance from result to the query point.
49     */
50    public double getDistance();
51 
52    /**
53     * Returns the square of the distance from result to the query point.
54     * This will usually be implemented as returning a cached value used
55     * during the nearest neighbors search.
56     *
57     * @return The square of the distance from result to the query point.
58     */
59    public double getDistance2();
60 
61    /**
62     * Returns the point-value mapping stored in this query result.
63     *
64     * @return The point-value mapping stored in this query result.
65     */
66    public Map.Entry<P,V> getNeighbor();
67  }
68 
69  private final class NNEntry
70    implements Entry<Coord, P, V>, Comparable<Entry<Coord, P, V>>
71  {
72    double _distance2;
73    Map.Entry<P,V> _neighbor;
74 
75    NNEntry(double distance2, Map.Entry<P,V> neighbor) {
76      _distance2 = distance2;
77      _neighbor = neighbor;
78    }
79 
80    public double getDistance() {
81      return StrictMath.sqrt(_distance2);
82    }
83 
84    public double getDistance2() {
85      return _distance2;
86    }
87 
88    public Map.Entry<P,V> getNeighbor() {
89      return _neighbor;
90    }
91 
92    public int compareTo(Entry<Coord, P, V> obj) {
93      final double d = obj.getDistance2();
94 
95      if(_distance2 < d)
96        return -1;
97      else if(_distance2 > d)
98        return 1;
99 
100      return 0;
101    }
102  }
103 
104  private final class EntryComparator
105    implements Comparator<Entry<Coord, P, V>>
106  {
107    // Invert relationship so priority queue keeps highest on top.
108    public int compare(Entry<Coord, P, V> n1, Entry<Coord, P, V> n2) {
109      final double d1 = n1.getDistance2();
110      final double d2 = n2.getDistance2();
111 
112      if(d1 < d2)
113        return 1;
114      else if(d1 > d2)
115        return -1;
116 
117      return 0;
118    }
119 
120    public boolean equals(Object obj) {
121      return (obj != null && obj == this);
122    }
123  }
124 
125  private boolean __omitQueryPoint;
126  private int __numNeighbors;
127  private double __minDistance;
128  private Distance<Coord, P> __distance;
129  private PriorityQueue<Entry<Coord, P, V>> __pq;
130  private P __query;
131 
132  private void find(KDTree<Coord,P,V>.KDNode node) {
133    if(node == null)
134      return;
135 
136    final int discriminator = node._discriminator;
137    final P point = node.getKey();
138    double d2 = __distance.distance2(__query, point);
139 
140    if(d2 < __minDistance && (d2 != 0.0 || !__omitQueryPoint)) {
141      if(__pq.size() == __numNeighbors) {
142        __pq.poll();
143        __pq.add(new NNEntry(d2, node));
144        __minDistance = __pq.peek().getDistance2();
145      } else {
146        __pq.add(new NNEntry(d2, node));
147        if(__pq.size() == __numNeighbors) {
148          __minDistance = __pq.peek().getDistance2();
149        }
150      }
151    }
152 
153    double dp =
154      __query.getCoord(discriminator).doubleValue() -
155      point.getCoord(discriminator).doubleValue();
156 
157    d2 = dp*dp;
158 
159    if(dp < 0) {
160      find(node._low);
161      if(d2 < __minDistance) {
162        find(node._high);
163      }
164    } else {
165      find(node._high);
166      if(d2 < __minDistance) {
167        find(node._low);
168      }
169    }
170  }
171 
172  /**
173   * Constructs a new NearestNeighbors instance, using the specified
174   * distance-finding functor to calculate distances during searches.
175   *
176   * @param distance A distance-finding functor implementing
177   *                 the {@link Distance} interface.
178   */
179  public NearestNeighbors(Distance<Coord, P> distance) {
180    __distance = distance;
181  }
182 
183  /**
184   * Constructs a NearestNeighbors instance using a {@link EuclideanDistance}
185   * instance to calculate distances between points.
186   */
187  public NearestNeighbors() {
188    this(new EuclideanDistance<Coord, P>());
189  }
190 
191  /**
192   * Sets the distance-finding functor used to calculate distances during
193   * searches.
194   *
195   * @param distance The distance-finding functor to use for distance
196   *                 calculations.
197   */
198  public void setDistance(Distance<Coord, P> distance) {
199    __distance = distance;
200  }
201 
202  /**
203   * Finds the k-nearest neighbors to a query point withina KDTree instance.
204   * The neighbors are returned as an array of {@link Entry} instances, sorted
205   * from nearest to farthest.
206   *
207   * @param tree The KDTree to search.
208   * @param queryPoint The query point.
209   * @param numNeighbors The number of nearest neighbors to find.  This should
210   *        be a positive value.  Non-positive values result in no neighbors
211   *        being found.
212   * @param omitQueryPoint If true, point-value mappings at a distance of
213   *        zero are omitted from the result.  If false, mappings at a
214   *        distance of zero are included.
215   * @return An array containing the nearest neighbors and their distances
216   *         sorted by least distance to greatest distance.  If no neighbors
217   *         are found, the array will have a length of zero.
218   */
219  public Entry<Coord,P,V>[] get(KDTree<Coord,P,V> tree,
220                                P queryPoint,
221                                int numNeighbors,
222                                boolean omitQueryPoint)
223  {
224    __omitQueryPoint = omitQueryPoint;
225    __numNeighbors = numNeighbors;
226    __query = queryPoint;
227    __minDistance = Double.POSITIVE_INFINITY;
228 
229    __pq = new PriorityQueue<Entry<Coord, P, V>>(numNeighbors,
230                                                 new EntryComparator());
231 
232    if(numNeighbors > 0) {
233      find(tree._root);
234    }
235 
236    Entry<Coord,P,V>[] neighbors = new Entry[__pq.size()];
237 
238    __pq.toArray(neighbors);
239    Arrays.sort(neighbors);
240 
241    __pq = null;
242    __query = null;
243 
244    return neighbors;
245  }
246 
247  /**
248   * Same as {@link #get get(tree, queryPoint, numNeighbors, true)}.
249   */
250  public Entry<Coord,P,V>[]
251    get(KDTree<Coord,P,V> tree, P queryPoint, int numNeighbors)
252  {
253    return get(tree, queryPoint, numNeighbors, true);
254  }
255}

[all classes][com.savarese.spatial]
Savarese Software Research Corporation