@@ -26,7 +26,6 @@ public class KdTree<T extends KdTree.XYZPoint> {
26
26
private KdNode root = null ;
27
27
28
28
private static final Comparator <XYZPoint > X_COMPARATOR = new Comparator <XYZPoint >() {
29
-
30
29
/**
31
30
* {@inheritDoc}
32
31
*/
@@ -41,7 +40,6 @@ public int compare(XYZPoint o1, XYZPoint o2) {
41
40
};
42
41
43
42
private static final Comparator <XYZPoint > Y_COMPARATOR = new Comparator <XYZPoint >() {
44
-
45
43
/**
46
44
* {@inheritDoc}
47
45
*/
@@ -56,7 +54,6 @@ public int compare(XYZPoint o1, XYZPoint o2) {
56
54
};
57
55
58
56
private static final Comparator <XYZPoint > Z_COMPARATOR = new Comparator <XYZPoint >() {
59
-
60
57
/**
61
58
* {@inheritDoc}
62
59
*/
@@ -77,8 +74,7 @@ public int compare(XYZPoint o1, XYZPoint o2) {
77
74
/**
78
75
* Default constructor.
79
76
*/
80
- public KdTree () {
81
- }
77
+ public KdTree () { }
82
78
83
79
/**
84
80
* Constructor for creating a more balanced tree. It uses the
@@ -91,6 +87,19 @@ public KdTree(List<XYZPoint> list) {
91
87
root = createNode (list , k , 0 );
92
88
}
93
89
90
+ /**
91
+ * Constructor for creating a more balanced tree. It uses the
92
+ * "median of points" algorithm.
93
+ *
94
+ * @param list
95
+ * of XYZPoints.
96
+ * @param k
97
+ * of the tree.
98
+ */
99
+ public KdTree (List <XYZPoint > list , int k ) {
100
+ root = createNode (list , k , 0 );
101
+ }
102
+
94
103
/**
95
104
* Create node from list of XYZPoints.
96
105
*
@@ -115,40 +124,32 @@ else if (axis == Y_AXIS)
115
124
Collections .sort (list , Z_COMPARATOR );
116
125
117
126
KdNode node = null ;
127
+ List <XYZPoint > less = new ArrayList <XYZPoint >(list .size ());
128
+ List <XYZPoint > more = new ArrayList <XYZPoint >(list .size ());
118
129
if (list .size () > 0 ) {
119
130
int medianIndex = list .size () / 2 ;
120
- node = new KdNode (k , depth , list .get (medianIndex ));
121
- List <XYZPoint > less = new ArrayList <XYZPoint >(list .size () - 1 );
122
- List <XYZPoint > more = new ArrayList <XYZPoint >(list .size () - 1 );
131
+ node = new KdNode (list .get (medianIndex ), k , depth );
123
132
// Process list to see where each non-median point lies
124
133
for (int i = 0 ; i < list .size (); i ++) {
125
134
if (i == medianIndex )
126
135
continue ;
127
136
XYZPoint p = list .get (i );
137
+ // Cannot assume points before the median are less since they could be equal
128
138
if (KdNode .compareTo (depth , k , p , node .id ) <= 0 ) {
129
139
less .add (p );
130
140
} else {
131
141
more .add (p );
132
142
}
133
143
}
134
- if ((medianIndex - 1 ) >= 0 ) {
135
- // Cannot assume points before the median are less since they
136
- // could be equal
137
- // List<XYZPoint> less = list.subList(0, mediaIndex);
138
- if (less .size () > 0 ) {
139
- node .lesser = createNode (less , k , depth + 1 );
140
- node .lesser .parent = node ;
141
- }
144
+
145
+ if ((medianIndex - 1 ) >= 0 && less .size () > 0 ) {
146
+ node .lesser = createNode (less , k , depth + 1 );
147
+ node .lesser .parent = node ;
142
148
}
143
- if ((medianIndex + 1 ) <= (list .size () - 1 )) {
144
- // Cannot assume points after the median are less since they
145
- // could be equal
146
- // List<XYZPoint> more = list.subList(mediaIndex + 1,
147
- // list.size());
148
- if (more .size () > 0 ) {
149
- node .greater = createNode (more , k , depth + 1 );
150
- node .greater .parent = node ;
151
- }
149
+
150
+ if ((medianIndex + 1 ) <= (list .size () - 1 ) && more .size () > 0 ) {
151
+ node .greater = createNode (more , k , depth + 1 );
152
+ node .greater .parent = node ;
152
153
}
153
154
}
154
155
@@ -176,7 +177,7 @@ public boolean add(T value) {
176
177
if (KdNode .compareTo (node .depth , node .k , value , node .id ) <= 0 ) {
177
178
// Lesser
178
179
if (node .lesser == null ) {
179
- KdNode newNode = new KdNode (k , node .depth + 1 , value );
180
+ KdNode newNode = new KdNode (value , k , node .depth + 1 );
180
181
newNode .parent = node ;
181
182
node .lesser = newNode ;
182
183
break ;
@@ -185,7 +186,7 @@ public boolean add(T value) {
185
186
} else {
186
187
// Greater
187
188
if (node .greater == null ) {
188
- KdNode newNode = new KdNode (k , node .depth + 1 , value );
189
+ KdNode newNode = new KdNode (value , k , node .depth + 1 );
189
190
newNode .parent = node ;
190
191
node .greater = newNode ;
191
192
break ;
@@ -205,7 +206,7 @@ public boolean add(T value) {
205
206
* @return True if tree contains value.
206
207
*/
207
208
public boolean contains (T value ) {
208
- if (value == null )
209
+ if (value == null || root == null )
209
210
return false ;
210
211
211
212
KdNode node = getNode (this , value );
@@ -253,7 +254,7 @@ private static final <T extends KdTree.XYZPoint> KdNode getNode(KdTree<T> tree,
253
254
* @return True if value was removed from the tree.
254
255
*/
255
256
public boolean remove (T value ) {
256
- if (value == null )
257
+ if (value == null || root == null )
257
258
return false ;
258
259
259
260
KdNode node = getNode (this , value );
@@ -327,12 +328,12 @@ private static final List<XYZPoint> getTree(KdNode root) {
327
328
* last nodes are equal distances.
328
329
* @param value
329
330
* to find neighbors of.
330
- * @return unmodifiable collection of T neighbors.
331
+ * @return Collection of T neighbors.
331
332
*/
332
333
@ SuppressWarnings ("unchecked" )
333
334
public Collection <T > nearestNeighbourSearch (int K , T value ) {
334
- if (value == null )
335
- return null ;
335
+ if (value == null || root == null )
336
+ return Collections . EMPTY_LIST ;
336
337
337
338
// Map used for results
338
339
TreeSet <KdNode > results = new TreeSet <KdNode >(new EuclideanComparator (value ));
@@ -370,11 +371,10 @@ public Collection<T> nearestNeighbourSearch(int K, T value) {
370
371
Collection <T > collection = new ArrayList <T >(K );
371
372
for (KdNode kdNode : results )
372
373
collection .add ((T ) kdNode .id );
373
- return Collections . unmodifiableCollection ( collection ) ;
374
+ return collection ;
374
375
}
375
376
376
- private static final <T extends KdTree .XYZPoint > void searchNode (T value , KdNode node , int K ,
377
- TreeSet <KdNode > results , Set <KdNode > examined ) {
377
+ private static final <T extends KdTree .XYZPoint > void searchNode (T value , KdNode node , int K , TreeSet <KdNode > results , Set <KdNode > examined ) {
378
378
examined .add (node );
379
379
380
380
// Search node
@@ -457,7 +457,7 @@ public String toString() {
457
457
458
458
protected static class EuclideanComparator implements Comparator <KdNode > {
459
459
460
- private XYZPoint point = null ;
460
+ private final XYZPoint point ;
461
461
462
462
public EuclideanComparator (XYZPoint point ) {
463
463
this .point = point ;
@@ -480,19 +480,22 @@ else if (d2.compareTo(d1) < 0)
480
480
481
481
public static class KdNode implements Comparable <KdNode > {
482
482
483
- private int k = 3 ;
484
- private int depth = 0 ;
485
- private XYZPoint id = null ;
483
+ private final XYZPoint id ;
484
+ private final int k ;
485
+ private final int depth ;
486
+
486
487
private KdNode parent = null ;
487
488
private KdNode lesser = null ;
488
489
private KdNode greater = null ;
489
490
490
491
public KdNode (XYZPoint id ) {
491
492
this .id = id ;
493
+ this .k = 3 ;
494
+ this .depth = 0 ;
492
495
}
493
496
494
- public KdNode (int k , int depth , XYZPoint id ) {
495
- this ( id ) ;
497
+ public KdNode (XYZPoint id , int k , int depth ) {
498
+ this . id = id ;
496
499
this .k = k ;
497
500
this .depth = depth ;
498
501
}
@@ -553,9 +556,9 @@ public String toString() {
553
556
554
557
public static class XYZPoint implements Comparable <XYZPoint > {
555
558
556
- double x = Double . NEGATIVE_INFINITY ;
557
- double y = Double . NEGATIVE_INFINITY ;
558
- double z = Double . NEGATIVE_INFINITY ;
559
+ private final double x ;
560
+ private final double y ;
561
+ private final double z ;
559
562
560
563
public XYZPoint (double x , double y ) {
561
564
this .x = x ;
@@ -569,6 +572,16 @@ public XYZPoint(double x, double y, double z) {
569
572
this .z = z ;
570
573
}
571
574
575
+ public double getX () {
576
+ return x ;
577
+ }
578
+ public double getY () {
579
+ return y ;
580
+ }
581
+ public double getZ () {
582
+ return z ;
583
+ }
584
+
572
585
/**
573
586
* Computes the Euclidean distance from this point to the other.
574
587
*
0 commit comments