diff --git a/src/uk/me/parabola/mkgmap/build/MapArea.java b/src/uk/me/parabola/mkgmap/build/MapArea.java
index 137de17..7fd0da0 100644
--- a/src/uk/me/parabola/mkgmap/build/MapArea.java
+++ b/src/uk/me/parabola/mkgmap/build/MapArea.java
@@ -24,8 +24,10 @@ import uk.me.parabola.imgfmt.app.trergn.Overview;
 import uk.me.parabola.log.Logger;
 import uk.me.parabola.mkgmap.filters.FilterConfig;
 import uk.me.parabola.mkgmap.filters.LineSizeSplitterFilter;
+import uk.me.parabola.mkgmap.filters.LineSplitterFilter;
 import uk.me.parabola.mkgmap.filters.MapFilterChain;
 import uk.me.parabola.mkgmap.filters.PolygonSizeSplitterFilter;
+import uk.me.parabola.mkgmap.filters.PolygonSplitterFilter;
 import uk.me.parabola.mkgmap.general.MapDataSource;
 import uk.me.parabola.mkgmap.general.MapElement;
 import uk.me.parabola.mkgmap.general.MapLine;
@@ -49,9 +51,9 @@ public class MapArea implements MapDataSource {
 	private static final int INITIAL_CAPACITY = 100;
 	private static final int MAX_RESOLUTION = 24;
 
-	private static final int POINT_KIND = 0;
-	private static final int LINE_KIND = 1;
-	private static final int SHAPE_KIND = 2;
+	public static final int POINT_KIND = 0;
+	public static final int LINE_KIND = 1;
+	public static final int SHAPE_KIND = 2;
 
 	// This is the initial area.
 	private final Area bounds;
@@ -247,27 +249,16 @@ public class MapArea implements MapDataSource {
 	 * @return An estimate of the max size that will be needed in the RGN file
 	 * for this sub-division.
 	 */
-	public int getSizeAtResolution(int res) {
-		int psize = 0;
-		int lsize = 0;
-		int ssize = 0;
+	public int[] getSizeAtResolution(int res) {
+		int[] sizes = new int[3];
 		
 		for (int i = 0; i <= res; i++) {
-
-			psize += pointSize[i];
-			lsize += lineSize[i];
-			ssize += shapeSize[i];
+			sizes[POINT_KIND] += pointSize[i];
+			sizes[LINE_KIND] += lineSize[i];
+			sizes[SHAPE_KIND] += shapeSize[i];
 		}
 
-		// Return the largest one as an overflow of any means that we have to
-		// split the area.
-		int size = psize;
-		if (lsize > size)
-			size = lsize;
-		if (ssize > size)
-			size = ssize;
-
-		return size;
+		return sizes;
 	}
 
 	/**
@@ -359,6 +350,13 @@ public class MapArea implements MapDataSource {
 	}
 
 	/**
+	 * Return number of shapes in this area.
+	 */
+	public int getNumShapes() {
+		return nActiveShapes;
+	}
+
+	/**
 	 * Return number of points in this area.
 	 */
 	public int getNumPoints() {
@@ -416,22 +414,20 @@ public class MapArea implements MapDataSource {
 			break;
 
 		case LINE_KIND:
-			if (res <= areaResolution)
-				nActiveLines++;
-
 			// Estimate the size taken by lines and shapes as a constant plus
 			// a factor based on the number of points.
 			n = ((MapLine) p).getPoints().size();
 			s = 11 + n * 2;
+			if (res <= areaResolution)
+				nActiveLines += 1 + ((n - 1) / LineSplitterFilter.MAX_POINTS_IN_LINE);
 			break;
 		case SHAPE_KIND:
-			if (res <= areaResolution)
-				nActiveShapes++;
-
 			// Estimate the size taken by lines and shapes as a constant plus
 			// a factor based on the number of points.
 			n = ((MapLine) p).getPoints().size();
 			s = 11 + n * 2;
+			if (res <= areaResolution)
+				nActiveShapes += 1 + ((n - 1) / PolygonSplitterFilter.MAX_POINT_IN_ELEMENT);
 			break;
 
 		default:
diff --git a/src/uk/me/parabola/mkgmap/build/MapSplitter.java b/src/uk/me/parabola/mkgmap/build/MapSplitter.java
index ac490df..487497d 100644
--- a/src/uk/me/parabola/mkgmap/build/MapSplitter.java
+++ b/src/uk/me/parabola/mkgmap/build/MapSplitter.java
@@ -43,15 +43,12 @@ class MapSplitter {
 
 	// The maximum region size.  Note that the offset to the start of a section
 	// has to fit into 16 bits, the end of the last section could be beyond the
-	// 16 bit limit, but we make sure that everything fits into under half the
-	// allowed space.  Really I'm not sure what the max actually is on real
-	// devices.
-	private static final int MAX_RGN_SIZE = 30 * 1024;
+	// 16 bit limit. Leave a little room for the region pointers
+	private static final int MAX_RGN_SIZE = 0xfff8;
 
 	// The maximum number of lines. NET points to lines in subdivision
 	// using bytes.
-	// Theoretical maximum about 0x100, which still gives errors.
-	private static final int MAX_NUM_LINES = 0xf0;
+	private static final int MAX_NUM_LINES = 0xff;
 
 	private static final int MAX_NUM_POINTS = 0xff;
 
@@ -94,7 +91,7 @@ class MapSplitter {
 		// in them.  For those that do, we further split them.  This is done
 		// recursively until everything fits.
 		List<MapArea> alist = new ArrayList<MapArea>();
-		addAreasToList(areas, alist);
+		addAreasToList(areas, alist, 0);
 
 		MapArea[] results = new MapArea[alist.size()];
 		return alist.toArray(results);
@@ -109,17 +106,38 @@ class MapSplitter {
 	 * @param alist The list that will finally contain the complete list of
 	 * map areas.
 	 */
-	private void addAreasToList(MapArea[] areas, List<MapArea> alist) {
+	private void addAreasToList(MapArea[] areas, List<MapArea> alist, int depth) {
 		int res = zoom.getResolution();
 		for (MapArea area : areas) {
-			if (area.getSizeAtResolution(res) > MAX_RGN_SIZE
-			    || area.getNumLines() > MAX_NUM_LINES
-			    || area.getNumPoints() > MAX_NUM_POINTS) {
+			Area bounds = area.getBounds();
+			int[] sizes = area.getSizeAtResolution(res);
+			if(log.isInfoEnabled()) {
+				String padding = "                                            ";
+				log.info(padding.substring(0, depth * 2) + 
+						 bounds.getWidth() + "x" + bounds.getHeight() +
+						 ", res = " + res +
+						 ", depth = " + depth +
+						 ", size = (" + sizes[0] + "," + sizes[1] + "," + sizes[2] + ")" +
+						 ", points = " + area.getNumPoints() +
+						 ", lines = " + area.getNumLines() +
+						 ", shapes = " + area.getNumShapes());
+			}
+
+			if ((sizes[MapArea.POINT_KIND] > MAX_RGN_SIZE &&
+				 (area.hasLines() || area.hasShapes())) ||
+				(((sizes[MapArea.POINT_KIND] + sizes[MapArea.LINE_KIND]) > MAX_RGN_SIZE) &&
+				 area.hasShapes()) ||
+			    area.getNumLines() > MAX_NUM_LINES ||
+			    area.getNumPoints() > MAX_NUM_POINTS) {
 				if (area.getBounds().getMaxDimention() > 100) {
 					if (log.isDebugEnabled())
 						log.debug("splitting area", area);
-					MapArea[] sublist = area.split(2, 2, res);
-					addAreasToList(sublist, alist);
+					MapArea[] sublist;
+					if(bounds.getWidth() > bounds.getHeight())
+						sublist = area.split(2, 1, res);
+					else
+						sublist = area.split(1, 2, res);
+					addAreasToList(sublist, alist, depth + 1);
 					continue;
 				} else {
 					log.warn("area too small to split", area);
diff --git a/src/uk/me/parabola/mkgmap/filters/LineSplitterFilter.java b/src/uk/me/parabola/mkgmap/filters/LineSplitterFilter.java
index 3ba4a74..921d9d4 100644
--- a/src/uk/me/parabola/mkgmap/filters/LineSplitterFilter.java
+++ b/src/uk/me/parabola/mkgmap/filters/LineSplitterFilter.java
@@ -35,7 +35,7 @@ public class LineSplitterFilter implements MapFilter {
 	private static final Logger log = Logger.getLogger(LineSplitterFilter.class);
 	
 	// Not sure of the value, probably 255.  Say 250 here.
-	private static final int MAX_POINTS_IN_LINE = 250;
+	public static final int MAX_POINTS_IN_LINE = 250;
 
 	public void init(FilterConfig config) {
 	}
diff --git a/src/uk/me/parabola/mkgmap/filters/PolygonSplitterFilter.java b/src/uk/me/parabola/mkgmap/filters/PolygonSplitterFilter.java
index 6cf397b..71be5b1 100644
--- a/src/uk/me/parabola/mkgmap/filters/PolygonSplitterFilter.java
+++ b/src/uk/me/parabola/mkgmap/filters/PolygonSplitterFilter.java
@@ -37,7 +37,7 @@ import java.util.List;
  * @author Steve Ratcliffe
  */
 public class PolygonSplitterFilter extends PolygonSplitterBase implements MapFilter {
-	private static final int MAX_POINT_IN_ELEMENT = 250;
+	public static final int MAX_POINT_IN_ELEMENT = 250;
 
 	/**
 	 * Split up polygons that have more than the max allowed number of points.
diff --git a/src/uk/me/parabola/mkgmap/general/MapLine.java b/src/uk/me/parabola/mkgmap/general/MapLine.java
index a30352b..d34d3be 100644
--- a/src/uk/me/parabola/mkgmap/general/MapLine.java
+++ b/src/uk/me/parabola/mkgmap/general/MapLine.java
@@ -64,9 +64,11 @@ public class MapLine extends MapElement {
 		Coord last = null;
 		for (Coord co : points) {
 			if (last != null && last.equals(co))
-				log.info("Line " + getName() + " has consecutive identical points at ", co.toDegreeString());
-			addToBounds(co);
-			last = co;
+				log.info("Line " + getName() + " has consecutive identical points at " + co.toDegreeString() + " (discarding)");
+			else {
+				addToBounds(co);
+				last = co;
+			}
 		}
 	}
 
