// Copyright (C) 2010 Aleksandr Dobkin, Michael Choi, and Christopher Mills. // // This file is part of BusRadar <https://github.com/orgs/busradar/>. // // BusRadar is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 3 of the License, or // (at your option) any later version. // // BusRadar is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. package busradar.madison; import java.util.ArrayList; import java.io.DataOutputStream; import java.io.DataInputStream; import java.io.IOException; import java.util.Collections; import java.util.Comparator; public class QuadTree { public static class Element { public int lat; public int lon; public char dir; public int id; public int[] routes; public Element() {} public void write(DataOutputStream s) throws IOException { s.writeInt(lat); s.writeInt(lon); s.writeChar(dir); s.writeInt(id); s.writeInt(routes.length); for(int i = 0; i < routes.length; i++) s.writeInt(routes[i]); } public Element(DataInputStream s) throws IOException { lat = s.readInt(); lon = s.readInt(); dir = s.readChar(); id = s.readInt(); routes = new int[s.readInt()]; for(int i = 0; i < routes.length; i++) routes[i] = s.readInt(); } } final static int maxchild = 20; Element[] items; QuadTree nw, ne, sw, se; int midx, midy; public void write(DataOutputStream s) throws IOException { if (items != null) { s.writeBoolean(true); s.writeInt(items.length); for (int i = 0; i < items.length; i++) items[i].write(s); } else { s.writeBoolean(false); nw.write(s); ne.write(s); sw.write(s); se.write(s); s.writeInt(midx); s.writeInt(midy); } } public QuadTree(DataInputStream s) throws IOException { if (s.readBoolean() == true) { int x = s.readInt(); items = new Element[x]; for (int i = 0; i < items.length; i++) { items[i] = new Element(s); } } else { nw = new QuadTree(s); ne = new QuadTree(s); sw = new QuadTree(s); se = new QuadTree(s); midx = s.readInt(); midy = s.readInt(); } } public QuadTree(ArrayList<Element> points) { if (points.size() <= maxchild) { items = points.toArray(new Element[0]); return; } Collections.sort(points, new Comparator<Element>() { public int compare(Element a, Element 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<Element>() { public int compare(Element a, Element b) { return a.lat - b.lat; } public boolean equals(Object o) { return false; } }); midy = points.get(points.size()/2+1).lat; ArrayList<Element> nwl = new ArrayList<Element>(); ArrayList<Element> nel = new ArrayList<Element>(); ArrayList<Element> swl = new ArrayList<Element>(); ArrayList<Element> sel = new ArrayList<Element>(); for (Element 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<Element> get(int xboundmin, int yboundmin, int xboundmax, int yboundmax) { ArrayList<Element> l = new ArrayList<Element>(); if (items != null) // we're a leaf { for (Element p : items) { 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)); } if (xboundmax >= midx) { // include east l.addAll(se.get(xboundmin, yboundmin, xboundmax, yboundmax)); } } if (yboundmax >= midy) { // include north if (xboundmin < midx) { // include west l.addAll(nw.get(xboundmin, yboundmin, xboundmax, yboundmax)); } if (xboundmax >= midx) { // include east l.addAll(ne.get(xboundmin, yboundmin, xboundmax, yboundmax)); } } return l; } } }