OsmAnd/OsmAnd-java/src/main/java/net/osmand/data/QuadTree.java
2018-06-15 15:24:05 +02:00

120 lines
2.6 KiB
Java

package net.osmand.data;
import java.util.ArrayList;
import java.util.List;
public class QuadTree<T> {
private static class Node<T> {
List<T> data = null;
Node<T>[] children = null;
QuadRect bounds;
@SuppressWarnings("unchecked")
private Node(QuadRect b) {
bounds = new QuadRect(b.left, b.top, b.right, b.bottom);
children = new Node[4];
}
}
private float ratio;
private int maxDepth;
private Node<T> root;
public QuadTree(QuadRect r, int depth/* =8 */, float ratio /* = 0.55 */) {
this.ratio = ratio;
this.root = new Node<T>(r);
this.maxDepth = depth;
}
public void insert(T data, QuadRect box) {
int depth = 0;
doInsertData(data, box, root, depth);
}
public void clear() {
clear(root);
}
private void clear(Node<T> rt) {
if(rt != null ){
if(rt.data != null) {
rt.data.clear();
}
if(rt.children != null) {
for(Node<T> c : rt.children) {
clear(c);
}
}
}
}
public void insert(T data, float x, float y) {
insert(data, new QuadRect(x, y, x, y));
}
public List<T> queryInBox(QuadRect box, List<T> result) {
result.clear();
queryNode(box, result, root);
return result;
}
private void queryNode(QuadRect box, List<T> result, Node<T> node) {
if (node != null) {
if (QuadRect.intersects(box, node.bounds)) {
if (node.data != null) {
result.addAll(node.data);
}
for (int k = 0; k < 4; ++k) {
queryNode(box, result, node.children[k]);
}
}
}
}
private void doInsertData(T data, QuadRect box, Node<T> n, int depth) {
if (++depth >= maxDepth) {
if (n.data == null) {
n.data = new ArrayList<T>();
}
n.data.add(data);
} else {
QuadRect[] ext = new QuadRect[4];
splitBox(n.bounds, ext);
for (int i = 0; i < 4; ++i) {
if (ext[i].contains(box)) {
if (n.children[i] == null) {
n.children[i] = new Node<T>(ext[i]);
}
doInsertData(data, box, n.children[i], depth);
return;
}
}
if (n.data == null) {
n.data = new ArrayList<T>();
}
n.data.add(data);
}
}
void splitBox(QuadRect node_extent, QuadRect[] n) {
// coord2d c=node_extent.center();
double width = node_extent.width();
double height = node_extent.height();
double lox = node_extent.left;
double loy = node_extent.top;
double hix = node_extent.right;
double hiy = node_extent.bottom;
n[0] = new QuadRect(lox, loy, lox + width * ratio, loy + height * ratio);
n[1] = new QuadRect(hix - width * ratio, loy, hix, loy + height * ratio);
n[2] = new QuadRect(lox, hiy - height * ratio, lox + width * ratio, hiy);
n[3] = new QuadRect(hix - width * ratio, hiy - height * ratio, hix, hiy);
}
}