Skip to content

Commit 2be2176

Browse files
committed
BallTree WIP
1 parent 7984b73 commit 2be2176

File tree

9 files changed

+65
-428
lines changed

9 files changed

+65
-428
lines changed

src/main/java/org/tinspin/index/PointMap.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package org.tinspin.index;
1919

2020
import org.tinspin.index.array.PointArray;
21+
import org.tinspin.index.balltree.BallTree;
2122
import org.tinspin.index.covertree.CoverTree;
2223
import org.tinspin.index.kdtree.KDTree;
2324
import org.tinspin.index.phtree.PHTreeP;
@@ -130,11 +131,22 @@ static <T> PointMap<T> createArray(int dims, int size) {
130131
}
131132

132133
/**
133-
* Create a COverTree.
134+
* Create a BallTree.
134135
*
135136
* @param dims Number of dimensions.
136137
* @param <T> Value type
137-
* @return New PH-Tree
138+
* @return New BallTree
139+
*/
140+
static <T> PointMap<T> createBallTree(int dims) {
141+
return BallTree.create(dims);
142+
}
143+
144+
/**
145+
* Create a CoverTree.
146+
*
147+
* @param dims Number of dimensions.
148+
* @param <T> Value type
149+
* @return New CoverTree
138150
*/
139151
static <T> PointMap<T> createCoverTree(int dims) {
140152
return CoverTree.create(dims);

src/main/java/org/tinspin/index/balltree/QIterator0.java renamed to src/main/java/org/tinspin/index/balltree/BTIterator.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2017 Tilmann Zaeschke
2+
* Copyright 2016-2024 Tilmann Zaeschke
33
*
44
* This file is part of TinSpin.
55
*
@@ -28,7 +28,7 @@
2828
*
2929
* @param <T> Value type
3030
*/
31-
public class QIterator0<T> implements PointIterator<T> {
31+
public class BTIterator<T> implements PointIterator<T> {
3232

3333
private class IteratorStack {
3434
private final ArrayList<StackEntry<T>> stack;
@@ -73,18 +73,20 @@ public void clear() {
7373

7474
private static class StackEntry<T> {
7575
int pos;
76-
BTNode<T>[] subs;
76+
BTNode<T> left;
77+
BTNode<T> right;
7778
ArrayList<PointEntry<T>> vals;
7879
int len;
7980

8081
void set(BTNode<T> node) {
8182
this.pos = 0;
8283
this.vals = node.getEntries();
83-
this.subs = node.getChildNodes();
84+
this.left = node.getLeftChild();
85+
this.right = node.getRightChild();
8486
if (this.vals != null) {
8587
len = this.vals.size();
8688
} else {
87-
len = this.subs.length;
89+
len = 2;
8890
}
8991
}
9092

@@ -94,7 +96,7 @@ public boolean isLeaf() {
9496
}
9597

9698

97-
QIterator0(BallTree<T> tree, double[] min, double[] max) {
99+
BTIterator(BallTree<T> tree, double[] min, double[] max) {
98100
this.stack = new IteratorStack();
99101
this.tree = tree;
100102
reset(min, max);
@@ -112,9 +114,8 @@ private void findNext() {
112114
return;
113115
}
114116
} else {
115-
BTNode<T> node = se.subs[pos];
116-
if (node != null &&
117-
BTUtil.overlap(min, max, node.getCenter(), node.getRadius())) {
117+
BTNode<T> node = pos == 0 ? se.left : se.right;
118+
if (BTUtil.overlap(min, max, node.getCenter(), node.getRadius())) {
118119
se = stack.prepareAndPush(node);
119120
}
120121
}

src/main/java/org/tinspin/index/balltree/QIteratorKnn.java renamed to src/main/java/org/tinspin/index/balltree/BTIteratorKnn.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2009-2023 Tilmann Zaeschke. All rights reserved.
2+
* Copyright 2016-2024 Tilmann Zaeschke. All rights reserved.
33
*
44
* This file is part of TinSpin.
55
*
@@ -25,7 +25,7 @@
2525

2626
import static org.tinspin.index.Index.*;
2727

28-
public class QIteratorKnn<T> implements PointIteratorKnn<T> {
28+
public class BTIteratorKnn<T> implements PointIteratorKnn<T> {
2929

3030
private final BTNode<T> root;
3131
private final PointDistance distFn;
@@ -38,7 +38,7 @@ public class QIteratorKnn<T> implements PointIteratorKnn<T> {
3838
private double[] center;
3939
private double currentDistance;
4040

41-
QIteratorKnn(BTNode<T> root, int minResults, double[] center, PointDistance distFn, PointFilterKnn<T> filterFn) {
41+
BTIteratorKnn(BTNode<T> root, int minResults, double[] center, PointDistance distFn, PointFilterKnn<T> filterFn) {
4242
this.filterFn = filterFn;
4343
this.distFn = distFn;
4444
this.root = root;
@@ -124,13 +124,15 @@ private void findNextElement() {
124124
}
125125
}
126126
} else {
127-
for (BTNode<T> subnode : node.getChildNodes()) {
128-
if (subnode != null) {
129-
double dist = distFn.dist(center, subnode.getCenter()) - subnode.getRadius();
130-
if (dist <= maxNodeDist) {
131-
queueN.push(new NodeDistT(dist, subnode));
132-
}
133-
}
127+
BTNode leftChild = node.getLeftChild();
128+
double distL = distFn.dist(center, leftChild.getCenter()) - leftChild.getRadius();
129+
if (distL <= maxNodeDist) {
130+
queueN.push(new NodeDistT(distL, leftChild));
131+
}
132+
BTNode rightChild = node.getLeftChild();
133+
double distR = distFn.dist(center, rightChild.getCenter()) - rightChild.getRadius();
134+
if (distR <= maxNodeDist) {
135+
queueN.push(new NodeDistT(distR, rightChild));
134136
}
135137
}
136138
}

src/main/java/org/tinspin/index/balltree/BTNode.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2017 Tilmann Zaeschke
2+
* Copyright 2016-2024 Tilmann Zaeschke
33
*
44
* This file is part of TinSpin.
55
*
@@ -41,7 +41,6 @@ public class BTNode<T> {
4141
private double radius;
4242
// null indicates that we have sub-node i.o. values
4343
private ArrayList<PointEntry<T>> values;
44-
private BTNode<T>[] subs;
4544
private BTNode<T> left;
4645
private BTNode<T> right;
4746

@@ -89,7 +88,6 @@ BTNode<T> tryPut(PointEntry<T> e, int maxNodeSize, boolean enforceLeaf) {
8988
//split
9089
ArrayList<PointEntry<T>> vals = values;
9190
values = null;
92-
subs = new BTNode[2];
9391
PointEntry<T> start = vals.get(0);
9492
int dims = start.point().length;
9593
double[][] ordered = BTUtil.orderCoordinates(vals);
@@ -395,7 +393,7 @@ void checkNode(BallTree.BTStats s, BTNode<T> parent, int depth) {
395393
throw new IllegalStateException();
396394
}
397395
}
398-
if (subs != null) {
396+
if (left != null || right != null) {
399397
throw new IllegalStateException();
400398
}
401399
} else {
@@ -409,8 +407,12 @@ boolean isLeaf() {
409407
return values != null;
410408
}
411409

412-
BTNode<T>[] getChildNodes() {
413-
return subs;
410+
BTNode<T> getLeftChild() {
411+
return left;
412+
}
413+
414+
BTNode<T> getRightChild() {
415+
return right;
414416
}
415417

416418
// TODO add radii as argument

src/main/java/org/tinspin/index/balltree/BTUtil.java

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2017 Tilmann Zaeschke
2+
* Copyright 2016-2024 Tilmann Zaeschke
33
*
44
* This file is part of TinSpin.
55
*
@@ -23,8 +23,6 @@
2323
import java.util.ArrayList;
2424
import java.util.Arrays;
2525

26-
import static org.tinspin.index.Index.BoxEntry;
27-
2826
class BTUtil {
2927

3028
static final double EPS_MUL = 1.000000001;
@@ -81,12 +79,19 @@ public static boolean isPointEqual(double[] p1, double[] p2) {
8179
// }
8280

8381
public static boolean overlap(double[] min, double[] max, double[] center, double radius) {
82+
double[] p = new double[min.length];
8483
for (int d = 0; d < min.length; d++) {
85-
if (max[d] < center[d] - radius || min[d] > center[d] + radius) {
86-
return false;
84+
if (center[d] <= min[d]) {
85+
p[d] = min[d];
86+
} else if (center[d] >= max[d]) {
87+
p[d] = max[d];
88+
} else {
89+
p[d] = center[d];
8790
}
91+
8892
}
89-
return true;
93+
// TODO sqr-dist?
94+
return PointDistance.l2(p, center) <= radius;
9095
}
9196

9297
// public static boolean isRectEnclosed(double[] minEnclosed, double[] maxEnclosed, double[] minOuter, double[] maxOuter) {

src/main/java/org/tinspin/index/balltree/BallTree.java

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2016-2017 Tilmann Zaeschke
2+
* Copyright 2016-2024 Tilmann Zaeschke
33
*
44
* This file is part of TinSpin.
55
*
@@ -306,7 +306,7 @@ public PointIterator<T> queryExactPoint(double[] point) {
306306
@Override
307307
public PointIterator<T> query(double[] min, double[] max) {
308308
//This does not use min/max but is really very basic.
309-
return new QIterator0<>(this, min, max);
309+
return new BTIterator<>(this, min, max);
310310
//return new QIterator<>(this, min, max);
311311
}
312312

@@ -325,7 +325,7 @@ public PointEntryKnn<T> query1nn(double[] center) {
325325
*/
326326
@Override
327327
public PointIteratorKnn<T> queryKnn(double[] center, int k, PointDistance dist) {
328-
return new QIteratorKnn<>(root, k, center, dist, (e, d) -> true);
328+
return new BTIteratorKnn<>(root, k, center, dist, (e, d) -> true);
329329
}
330330

331331
/**
@@ -349,13 +349,11 @@ private void toStringTree(StringBuilderLn sb, BTNode<T> node, int depth, int pos
349349
sb.append(" " + Arrays.toString(node.getCenter()));
350350
sb.appendLn("/" + node.getRadius());
351351
prefix += " ";
352-
if (node.getChildNodes() != null) {
353-
for (int i = 0; i < node.getChildNodes().length; i++) {
354-
BTNode<T> sub = node.getChildNodes()[i];
355-
if (sub != null) {
356-
toStringTree(sb, sub, depth+1, i);
357-
}
358-
}
352+
if (node.getLeftChild() != null) {
353+
toStringTree(sb, node.getLeftChild(), depth+1, 0);
354+
}
355+
if (node.getRightChild() != null) {
356+
toStringTree(sb, node.getRightChild(), depth+1, 1);
359357
}
360358
if (node.getEntries() != null) {
361359
for (int i = 0; i < node.getEntries().size(); i++) {

0 commit comments

Comments
 (0)