120 lines
2.6 KiB
Java
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);
|
|
}
|
|
|
|
}
|