BucketKdTree?.java
package de._4geeks.robots.guns.DC;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class BucketKdTree<T extends Info> {
private int dim;
private int bucketSize;
private int entries;
private Bucket buckets;
public BucketKdTree(int dim, int bucketSize) {
this.dim = dim;
this.bucketSize = bucketSize;
this.buckets = new Bucket(bucketSize, 0);
this.entries = 0;
}
public void addInfo(T info) {
buckets.addInfo(this, info);
entries += 1;
}
public void clear() {
this.buckets = new Bucket(bucketSize, 0);
this.entries = 0;
}
public void balance() {
ArrayList<T> l = collect();
this.buckets = new Bucket(bucketSize, 0);
this.buckets.balance(l, this);
}
public ArrayList<T> collect() {
ArrayList<T> l = new ArrayList<T>();
buckets.collect(l);
return l;
}
public ArrayList<T> getBucket(double[] features) {
return buckets.getBucket(features);
}
class Bucket {
ArrayList<T> b;
int dim;
Bucket top;
Bucket bottom;
double border;
public Bucket(int bucketSize, int dim) {
this.dim = dim;
b = new ArrayList<T>(bucketSize);
}
public ArrayList<T> getBucket(double[] features) {
if (b != null) {
return b;
} else {
if (features[dim] >= border) {
return top.getBucket(features);
} else {
return bottom.getBucket(features);
}
}
}
public void addInfo(BucketKdTree<T> tree, T info) {
if (b != null) {
if (b.size() >= tree.bucketSize) {
subdivide(tree);
if (info.getFeature(dim) >= border) {
top.addInfo(tree, info);
} else {
bottom.addInfo(tree, info);
}
} else {
b.add(info);
}
} else {
if (info.getFeature(dim) >= border) {
top.addInfo(tree, info);
} else {
bottom.addInfo(tree, info);
}
}
}
private void subdivide(BucketKdTree<T> tree) {
// This calculates the median for the bucket.
Collections.sort(b, new InfoComparator(dim));
border = b.get(b.size() / 2).getFeature(dim);
//System.out.println(String.format("Subdivide: %d %f", dim, border));
top = new Bucket(bucketSize, (dim+1) % tree.getDim());
bottom = new Bucket(bucketSize, (dim+1) % tree.getDim());
for (T i : b) {
if (i.getFeature(dim) >= border) {
top.addInfo(tree, i);
} else {
bottom.addInfo(tree, i);
}
}
b = null;
}
public void collect(ArrayList<T> l) {
if(b != null) {
l.addAll(b);
} else {
top.collect(l);
bottom.collect(l);
}
}
public void balance(ArrayList<T> l, BucketKdTree<T> tree) {
if(l.size() >= tree.bucketSize) {
Collections.sort(l, new InfoComparator(dim));
border = l.get(l.size() / 2).getFeature(dim);
top = new Bucket(bucketSize, (dim+1) % tree.getDim());
bottom = new Bucket(bucketSize, (dim+1) % tree.getDim());
ArrayList<T> topList = new ArrayList<T>();
ArrayList<T> bottomList = new ArrayList<T>();
for(T i : l) {
if (i.getFeature(dim) >= border) {
topList.add(i);
} else {
bottomList.add(i);
}
}
top.balance(topList, tree);
bottom.balance(bottomList, tree);
b = null;
} else {
b = l;
}
}
public int size() {
return b.size();
}
class InfoComparator implements Comparator<T> {
int i;
public InfoComparator(int i) {
this.i = i;
}
public int compare(T o1, T o2) {
return Double.compare(o1.getFeature(i), o2.getFeature(i));
}
}
}
public int getDim() {
return dim;
}
public int getBucketSize() {
return bucketSize;
}
public int getEntries() {
return entries;
}
}
Info.java
package de._4geeks.robots.guns.DC;
public interface Info {
public double getFeature(int i);
}