Index: uk/me/parabola/mkgmap/reader/osm/boundary/BoundaryQuadTree.java
===================================================================
--- uk/me/parabola/mkgmap/reader/osm/boundary/BoundaryQuadTree.java	(revision 0)
+++ uk/me/parabola/mkgmap/reader/osm/boundary/BoundaryQuadTree.java	(working copy)
@@ -0,0 +1,157 @@
+package uk.me.parabola.mkgmap.reader.osm.boundary;
+
+import java.awt.geom.Area;
+import java.util.Arrays;
+import java.util.List;
+import uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.util.Java2DConverter;
+
+/**
+ * A simple quadtree implementation that stores the areas formed by boundaries. 
+ * @author GerdP
+ *
+ */
+public class BoundaryQuadTree {
+	private BoundaryQuadTree [] childs;
+
+	// bounding box of this part of the tree
+	private Area bbox;
+	private uk.me.parabola.imgfmt.app.Area bounds;
+
+	// boundaries that intersect with the bbox of this part of the tree
+	private Boundary[] boundaries;
+	// the intersections of the boundaries with the bbox of the tree
+	private Area[] areas;
+	
+	private short depth;
+	private short numAreas;
+	private boolean isLeaf; 
+	
+	/**
+	 * Create a quadtree for a given bounding box and a list of boundaries.
+	 */
+	public BoundaryQuadTree (uk.me.parabola.imgfmt.app.Area bbox, List<Boundary> boundaries){
+		this.bounds = bbox;
+		this.bbox = Java2DConverter.createBoundsArea(bbox);
+		for (int i = 0;i < boundaries.size(); i++){
+			Boundary b = boundaries.get(i);
+			add (b.getArea(), b);
+		}
+		isLeaf = true;
+		split();
+	}	
+	
+	/**
+	 * Return a boundary that contains the point referenced by Coord 
+	 * @param co the point
+	 * @return a boundary reference or null 
+	 */
+	public Boundary get(Coord co){
+		if (this.bounds.contains(co) == false)
+			return null;
+		if (isLeaf){
+			if (areas == null)
+				return null;
+			for (int i=0; i < numAreas; i++){
+				Area area = areas[i]; 
+				if (area.contains(co.getLongitude(), co.getLatitude())) 
+					return boundaries[i];
+			}
+		}
+		else {
+			for (int i = 0; i < 4; i++){
+				Boundary res = childs[i].get(co);
+				if (res != null) 
+					return res; 
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * Constructor that is used by the split method. The parameters give the corners of a bounding box.
+	 * @param minLat
+	 * @param minLong
+	 * @param maxLat
+	 * @param maxLong
+	 */
+	private BoundaryQuadTree (int minLat, int minLong, int maxLat, int maxLong){
+		this.bounds = new uk.me.parabola.imgfmt.app.Area (minLat, minLong, maxLat, maxLong);
+		this.bbox = Java2DConverter.createBoundsArea(bounds);
+		this.isLeaf = true;
+		numAreas = 0;
+	}
+	
+	/**
+	 * Add a boundary to the tree. 
+	 * @param area the part of the boundary area that should be added to the tree.    
+	 * @param boundary the boundary reference
+	 */
+	private void add(Area area, Boundary boundary){
+		Area a = new Area(area);
+		a.intersect(this.bbox);
+		if (a.isEmpty() == false){
+			if (numAreas == 0){
+				areas = new Area[4];
+				boundaries = new Boundary[4];
+			}
+			if (numAreas >= areas.length){
+				Area[] tmpAreas = Arrays.copyOf(areas, numAreas+4);
+				areas = tmpAreas;
+				Boundary[] tmpIds = Arrays.copyOf(boundaries, numAreas+4);
+				boundaries = tmpIds;
+			}
+			areas[numAreas] = a;
+			boundaries[numAreas] = boundary;
+			++numAreas;
+		}
+	}
+	
+	/**
+	 * Split the tree into 4 equally sized parts.
+	 */
+	private void split(){
+		if  (isLeaf == false 
+				|| areas == null 
+				|| depth >= 6 // subject to tuning
+				||	 numAreas <= 1) // subject to tuning
+			return ;
+		
+		childs = new BoundaryQuadTree[4];
+		int halfLat = (bounds.getMinLat() + bounds.getMaxLat()) / 2;
+		int halfLong = (bounds.getMinLong() + bounds.getMaxLong()) / 2;
+		if (bounds.getHeight() < 10 || bounds.getWidth() < 10 ){ 
+			// area would be too small 
+			return;
+		}
+		
+		childs[0] = new BoundaryQuadTree(bounds.getMinLat(), bounds.getMinLong(),
+				halfLat, halfLong);
+		childs[1] = new BoundaryQuadTree(halfLat, bounds.getMinLong(),
+				bounds.getMaxLat(), halfLong);
+		childs[2] = new BoundaryQuadTree(bounds.getMinLat(), halfLong, halfLat,
+				bounds.getMaxLong());
+		childs[3] = new BoundaryQuadTree(halfLat, halfLong, bounds.getMaxLat(),
+				bounds.getMaxLong());
+		for (int i = 0; i < 4; i++){
+			childs[i].depth = (short) (this.depth + 1);
+			for (int j = 0; j < numAreas; j++){
+				// this is performance critical: we don't add the area of the boundary, just the intersection 
+				// of the boundaries area with the the current tree area. 
+				if (Java2DConverter.createBbox(areas[j]).intersects(childs[i].bounds) )
+					childs[i].add(areas[j],boundaries[j]);
+			}
+		}
+		numAreas = 0;
+		isLeaf = false;
+		// return memory to GC
+		areas = null;
+		boundaries = null;
+		// finally try splitting the sub trees
+		for (int i = 0; i < 4; i++){
+			childs[i].split();
+		}
+
+	}
+	
+}
\ No newline at end of file
