package busradar.madison;
import java.util.ArrayList;
import java.io.Serializable;
import java.util.Collections;
import java.util.Comparator;
@SuppressWarnings("serial")
public class QuadTree<E extends QuadTree.Element> implements Serializable
{
public static class Element implements Serializable {
public int lat;
public int lon;
}
public static class BusStop extends Element {
public char dir;
public int id;
}
public static class RoutePoint extends Element {
public int lat2, lon2;
public int id;
}
static int maxchild = 20;
Object[] items;
QuadTree nw, ne, sw, se;
int midx, midy;
public QuadTree(ArrayList<E> points)
{
if (points.size() <= maxchild) {
items = points.toArray();
return;
}
Collections.sort(points, new Comparator<E>() {
public int compare(E a, E b) { return a.lon - b.lon; }
public boolean equals(Object o) { return false; }
});
midx = points.get(points.size()/2+1).lon;
Collections.sort(points, new Comparator<E>() {
public int compare(E a, E b) { return a.lat - b.lat; }
public boolean equals(Object o) { return false; }
});
midy = points.get(points.size()/2+1).lat;
ArrayList<E> nwl = new ArrayList<E>();
ArrayList<E> nel = new ArrayList<E>();
ArrayList<E> swl = new ArrayList<E>();
ArrayList<E> sel = new ArrayList<E>();
for (E p : points)
{
if (p.lat >= midy) { // north
if (p.lon >= midx) { // east
nel.add(p);
}
else { //west
nwl.add(p);
}
}
else { // south
if (p.lon >= midx) { // east
sel.add(p);
}
else { //west
swl.add(p);
}
}
}
nw = new QuadTree(nwl);
ne = new QuadTree(nel);
sw = new QuadTree(swl);
se = new QuadTree(sel);
}
public ArrayList<E>
get(int xboundmin, int yboundmin, int xboundmax, int yboundmax, int span)
{
ArrayList<E> l = new ArrayList<E>();
if (items != null) // we're a leaf
{
for (Object _p : items) {
E p = (E)_p;
if (p.lon >= xboundmin && p.lon <= xboundmax &&
p.lat >= yboundmin && p.lat <= yboundmax )
l.add(p);
}
return l;
}
else {
if (yboundmin < midy) { // include south
if (xboundmin < midx) { // include west
l.addAll(sw.get(xboundmin, yboundmin, xboundmax, yboundmax, span));
}
if (xboundmax >= midx) { // include east
l.addAll(se.get(xboundmin, yboundmin, xboundmax, yboundmax, span));
}
}
if (yboundmax >= midy) { // include north
if (xboundmin < midx) { // include west
l.addAll(nw.get(xboundmin, yboundmin, xboundmax, yboundmax, span));
}
if (xboundmax >= midx) { // include east
l.addAll(ne.get(xboundmin, yboundmin, xboundmax, yboundmax, span));
}
}
return l;
}
}
}