Index: uk/me/parabola/mkgmap/build/MapArea.java
===================================================================
--- uk/me/parabola/mkgmap/build/MapArea.java	(revision 3346)
+++ uk/me/parabola/mkgmap/build/MapArea.java	(working copy)
@@ -17,6 +17,7 @@
 package uk.me.parabola.mkgmap.build;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import uk.me.parabola.imgfmt.app.Area;
@@ -35,6 +36,7 @@
 import uk.me.parabola.mkgmap.general.MapPoint;
 import uk.me.parabola.mkgmap.general.MapRoad;
 import uk.me.parabola.mkgmap.general.MapShape;
+import uk.me.parabola.util.GpxCreator;
 import uk.me.parabola.imgfmt.app.net.RoadNetwork;
 
 /**
@@ -98,8 +100,6 @@
 	public MapArea(MapDataSource src, int resolution) {
 		this.areaResolution = 0;
 		this.bounds = src.getBounds();
-		addToBounds(bounds);
-
 		for (MapPoint p : src.getPoints()) {
 			if(bounds.contains(p.getLocation()))
 				addPoint(p);
@@ -119,9 +119,7 @@
 		MapFilterChain chain = new MapFilterChain() {
 			public void doFilter(MapElement element) {
 				MapShape shape = (MapShape) element;
-				shapes.add(shape);
-				addToBounds(shape.getBounds());
-				addSize(element, shape.hasExtendedType()? XT_SHAPE_KIND : SHAPE_KIND);
+				addShape(shape);
 			}
 		};
 
@@ -148,9 +146,7 @@
 		MapFilterChain chain = new MapFilterChain() {
 			public void doFilter(MapElement element) {
 				MapLine line = (MapLine) element;
-				lines.add(line);
-				addToBounds(line.getBounds());
-				addSize(element, line.hasExtendedType()? XT_LINE_KIND : LINE_KIND);
+				addLine(line);
 			}
 		};
 
@@ -173,7 +169,6 @@
 	private MapArea(Area area, int res) {
 		bounds = area;
 		areaResolution = res;
-		addToBounds(area);
 	}
 
 	/**
@@ -193,6 +188,7 @@
 		log.info("Splitting area " + bounds + " into " + nx + "x" + ny + " pieces at resolution " + resolution);
 		boolean useNormalSplit = true;
 		while (true){
+			List<MapArea> largeObjectAreas = new ArrayList<>();
 			for (int i = 0; i < nx * ny; i++) {
 				mapAreas[i] = new MapArea(areas[i], resolution);
 				if (log.isDebugEnabled())
@@ -212,14 +208,29 @@
 				used[pos] = true;
 			}
 
-			
+			final int LARGE_OBJECT_DIM = 1024;
+			int maxWidth = areas[0].getWidth();
+			int maxHeight = areas[0].getHeight();
+			if (nx*ny == 1 || maxWidth < LARGE_OBJECT_DIM|| maxHeight < LARGE_OBJECT_DIM){
+				// don't separate large objects
+				maxWidth = Integer.MAX_VALUE;  
+				maxHeight = Integer.MAX_VALUE; 
+			}
+//			System.out.println(maxHeight + " " + maxWidth);
 			int areaIndex = 0;
 			for (MapLine l : this.lines) {
 				// Drop any zero sized lines.
 				if (l instanceof MapRoad == false && l.getRect().height <= 0 && l.getRect().width <= 0)
 					continue;
-				if (useNormalSplit)
+				if (useNormalSplit){
+					if (l.getBounds().getHeight() > maxHeight || l.getBounds().getWidth() > maxWidth){
+						MapArea largeObjectArea = new MapArea(l.getBounds(), resolution);
+						largeObjectArea.addLine(l);
+						largeObjectAreas.add(largeObjectArea);
+						continue;
+					}
 					areaIndex = pickArea(mapAreas, l, xbase30, ybase30, nx, ny, dx30, dy30);
+				}
 				else 
 					areaIndex = ++areaIndex % mapAreas.length;
 				mapAreas[areaIndex].addLine(l);
@@ -227,8 +238,16 @@
 			}
 
 			for (MapShape e : this.shapes) {
-				if (useNormalSplit)
+				if (useNormalSplit){
+					if (e.getBounds().getHeight() > maxHeight || e.getBounds().getWidth() > maxWidth){
+//						GpxCreator.createGpx("e:/ld/l", e.getPoints(),this.getBounds().toCoords());
+						MapArea largeObjectArea = new MapArea(e.getBounds(), resolution);
+						largeObjectArea.addShape(e);
+						largeObjectAreas.add(largeObjectArea);
+						continue;
+					}
 					areaIndex = pickArea(mapAreas, e, xbase30, ybase30, nx, ny, dx30, dy30);
+				}
 				else 
 					areaIndex = ++areaIndex % mapAreas.length;
 				mapAreas[areaIndex].addShape(e);
@@ -245,6 +264,12 @@
 				useNormalSplit = false;
 				continue;
 			} 
+			if (largeObjectAreas.isEmpty() == false){
+				MapArea[] tmp = Arrays.copyOf(mapAreas, mapAreas.length + largeObjectAreas.size());
+				for (int i = 0; i < largeObjectAreas.size();i++)
+					tmp[i+mapAreas.length] = largeObjectAreas.get(i);
+				mapAreas = tmp;
+			}
 			return mapAreas;
 		}
 	}
@@ -462,7 +487,7 @@
 	 */
 	private void addPoint(MapPoint p) {
 		points.add(p);
-		addToBounds(p.getLocation());
+		addToBounds(p.getLocation()); 
 		addSize(p, p.hasExtendedType()? XT_POINT_KIND : POINT_KIND);
 	}
 
@@ -511,18 +536,26 @@
 			maxLon = l;
 	}
 
+	/**
+	 * Add to bounds considering high precision values. 
+	 * @param co
+	 */
 	private void addToBounds(Coord co) {
-		int l = co.getLatitude();
-		if (l < minLat)
-			minLat = l;
-		if (l > maxLat)
-			maxLat = l;
-
-		l = co.getLongitude();
-		if (l < minLon)
-			minLon = l;
-		if (l > maxLon)
-			maxLon = l;
+		int lat30 = co.getHighPrecLat();
+		int latLower  = lat30 >> Coord.DELTA_SHIFT;
+		int latUpper  = (latLower << Coord.DELTA_SHIFT) < lat30 ? latLower + 1 : latLower;
+		if (latLower < minLat)
+			minLat = latLower;
+		if (latUpper > maxLat)
+			maxLat = latUpper;
+		
+		int lon30 = co.getHighPrecLon();
+		int lonLeft = lon30 >> Coord.DELTA_SHIFT;
+		int lonRight = (lonLeft << Coord.DELTA_SHIFT) < lon30 ? lonLeft + 1 : lonLeft;
+		if (lonLeft < minLon)
+			minLon = lonLeft;
+		if (lonRight > maxLon)
+			maxLon = lonRight;
 	}
 
 	
Index: uk/me/parabola/mkgmap/build/MapSplitter.java
===================================================================
--- uk/me/parabola/mkgmap/build/MapSplitter.java	(revision 3346)
+++ uk/me/parabola/mkgmap/build/MapSplitter.java	(working copy)
@@ -117,9 +117,14 @@
 	 */
 	private void addAreasToList(MapArea[] areas, List<MapArea> alist, int depth) {
 		int res = zoom.getResolution();
+		int wantedSize = MAX_RGN_SIZE / 10; // smaller values result in more sub divs
 		for (MapArea area : areas) {
 			Area bounds = area.getBounds();
 			int[] sizes = area.getEstimatedSizes();
+			if (area.getPoints().size() == 0 && area.getLines().size() == 0 && area.getShapes().size()==0){
+				continue;
+//				System.out.println(area.getPoints().size() + " " + area.getLines().size() + " " + area.getShapes().size());
+			}
 			if(log.isInfoEnabled()) {
 				String padding = depth + "                                                                      ";
 				log.info(padding.substring(0, (depth + 1) * 2) + 
@@ -129,7 +134,8 @@
 						 ", lines = " + area.getNumLines() + "/" + sizes[MapArea.LINE_KIND] +
 						 ", shapes = " + area.getNumShapes() + "/" + sizes[MapArea.SHAPE_KIND]);
 			}
-
+			boolean doSplit = false;
+			
 			if (area.getNumLines() > MAX_NUM_LINES ||
 				area.getNumPoints() > MAX_NUM_POINTS ||
 				(sizes[MapArea.POINT_KIND] +
@@ -137,7 +143,19 @@
 				 sizes[MapArea.SHAPE_KIND]) > MAX_RGN_SIZE ||
 				sizes[MapArea.XT_POINT_KIND] > MAX_XT_POINTS_SIZE ||
 				sizes[MapArea.XT_LINE_KIND] > MAX_XT_LINES_SIZE ||
-				sizes[MapArea.XT_SHAPE_KIND] > MAX_XT_SHAPES_SIZE) {
+				sizes[MapArea.XT_SHAPE_KIND] > MAX_XT_SHAPES_SIZE)
+				doSplit = true; // we must split
+			else if (bounds.getMaxDimension() > MIN_DIMENSION) {
+				int sumSize = 0;
+				for (int s:sizes)
+					sumSize += s;
+				if (sumSize > wantedSize ){
+					if (area.getLines().size() + area.getShapes().size() >= 2){
+						doSplit = true;
+					}
+				}
+			}
+			if (doSplit){
 				if (bounds.getMaxDimension() > MIN_DIMENSION) {
 					if (log.isDebugEnabled())
 						log.debug("splitting area", area);
