Hi Ivan,

It took me a little longer than expected (as I decided to revamp what
was there) but I have a patch for you to try (attached).

This limits the size of the extended type elements to 32KB for each of
the points/lines/shapes. I have no idea if that is a sensible limit but
you can alter it by changing these lines in MapSplitter.java:

        // maximum allowed amounts of points/lines/shapes with extended types
        private static final int MAX_XT_POINTS_SIZE = 0x8000;
        private static final int MAX_XT_LINES_SIZE  = 0x8000;
        private static final int MAX_XT_SHAPES_SIZE = 0x8000;

I hope it solves the problem.

Mark
diff --git a/src/uk/me/parabola/mkgmap/build/MapArea.java b/src/uk/me/parabola/mkgmap/build/MapArea.java
index d668cda..d562fdb 100644
--- a/src/uk/me/parabola/mkgmap/build/MapArea.java
+++ b/src/uk/me/parabola/mkgmap/build/MapArea.java
@@ -51,9 +51,13 @@ public class MapArea implements MapDataSource {
 	private static final int INITIAL_CAPACITY = 100;
 	private static final int MAX_RESOLUTION = 24;
 
-	public static final int POINT_KIND = 0;
-	public static final int LINE_KIND = 1;
-	public 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;
+	public static final int XT_POINT_KIND = 3;
+	public static final int XT_LINE_KIND  = 4;
+	public static final int XT_SHAPE_KIND = 5;
+	public static final int NUM_KINDS     = 6;
 
 	// This is the initial area.
 	private final Area bounds;
@@ -70,11 +74,8 @@ public class MapArea implements MapDataSource {
 	private final List<MapLine> lines = new ArrayList<MapLine>(INITIAL_CAPACITY);
 	private final List<MapShape> shapes = new ArrayList<MapShape>(INITIAL_CAPACITY);
 
-	// Counts of features available at different resolutions.
-	private final int[] pointSize = new int[MAX_RESOLUTION+1];
-	private final int[] lineSize = new int[MAX_RESOLUTION+1];
-	private final int[] shapeSize = new int[MAX_RESOLUTION+1];
-	private final int[] elemCounts = new int[MAX_RESOLUTION+1];
+	// amount of space required for the contents
+	private final int[] sizes = new int[NUM_KINDS];
 
 	private int nActivePoints;
 	private int nActiveIndPoints;
@@ -99,7 +100,7 @@ public class MapArea implements MapDataSource {
 
 		for (MapPoint p : src.getPoints()) {
 			points.add(p);
-			addSize(p, pointSize, POINT_KIND);
+			addSize(p, p.hasExtendedType()? XT_POINT_KIND : POINT_KIND);
 		}
 		addLines(src, resolution);
 		addPolygons(src, resolution);
@@ -116,7 +117,7 @@ public class MapArea implements MapDataSource {
 				MapShape shape = (MapShape) element;
 
 				shapes.add(shape);
-				addSize(element, shapeSize, SHAPE_KIND);
+				addSize(element, shape.hasExtendedType()? XT_SHAPE_KIND : SHAPE_KIND);
 			}
 
 			public void addElement(MapElement element) {
@@ -149,7 +150,7 @@ public class MapArea implements MapDataSource {
 				MapLine line = (MapLine) element;
 
 				lines.add(line);
-				addSize(element, lineSize, LINE_KIND);
+				addSize(element, line.hasExtendedType()? XT_LINE_KIND : LINE_KIND);
 			}
 
 			public void addElement(MapElement element) {
@@ -240,24 +241,12 @@ public class MapArea implements MapDataSource {
 
 	/**
 	 * Get an estimate of the size of the RGN space that will be required to
-	 * hold the points in this area.  For points we can be fairly accurate, but
-	 * we just guess an upper bound for lines and shapes since we don't know the
-	 * exact size until later.
+	 * hold the elements
 	 *
-	 * @param res The resolution to test for.  At lower resolutions, there are
-	 * less elements so less room is needed.
-	 * @return An estimate of the max size that will be needed in the RGN file
-	 * for this sub-division.
+	 * @return Estimates of the max size that will be needed in the RGN file
+	 * for the points/lines/shapes in this sub-division.
 	 */
-	public int[] getSizeAtResolution(int res) {
-		int[] sizes = new int[3];
-		
-		for (int i = 0; i <= res; i++) {
-			sizes[POINT_KIND] += pointSize[i];
-			sizes[LINE_KIND] += lineSize[i];
-			sizes[SHAPE_KIND] += shapeSize[i];
-		}
-
+	public int[] getEstimatedSizes() {
 		return sizes;
 	}
 
@@ -383,65 +372,64 @@ public class MapArea implements MapDataSource {
 	 *
 	 * @param p The element containing the minimum resolution that it will be
 	 * displayed at.
-	 * @param sizes An array of sizes, this routine updates the correct one.
 	 * @param kind What kind of element this is KIND_POINT etc.
 	 */
-	private void addSize(MapElement p, int[] sizes, int kind) {
-
-		if(p.hasExtendedType()) {
-			// not applicable for elements with extended types
-			return;
-		}
+	private void addSize(MapElement p, int kind) {
 
 		int res = p.getMinResolution();
 		if (res > MAX_RESOLUTION)
 			return;
 
-		int s;
 		int numPoints;
 		int numElements;
 
 		switch (kind) {
 		case POINT_KIND:
-			if (res <= areaResolution) {
-				if(((MapPoint) p).isCity())
-					nActiveIndPoints++;
-				else
-					nActivePoints++;
+		case XT_POINT_KIND:
+			if(res <= areaResolution) {
+				// Points are predictibly less than 9 bytes.
+				sizes[kind] += 9;
+				if(!p.hasExtendedType()) {
+					if(((MapPoint) p).isCity())
+						nActiveIndPoints++;
+					else
+						nActivePoints++;
+				}
 			}
-
-			// Points are predictibly less than 9 bytes.
-			s = 9;
 			break;
 
 		case LINE_KIND:
-			// Estimate the size taken by lines and shapes as a constant plus
-			// a factor based on the number of points.
-			numPoints = ((MapLine) p).getPoints().size();
-			numElements = 1 + ((numPoints - 1) / LineSplitterFilter.MAX_POINTS_IN_LINE);
-			s = numElements * 11 + numPoints * 4;
-			if (res <= areaResolution)
-				nActiveLines += numElements;
+		case XT_LINE_KIND:
+			if(res <= areaResolution) {
+				// Estimate the size taken by lines and shapes as a constant plus
+				// a factor based on the number of points.
+				numPoints = ((MapLine) p).getPoints().size();
+				numElements = 1 + ((numPoints - 1) / LineSplitterFilter.MAX_POINTS_IN_LINE);
+				sizes[kind] += numElements * 11 + numPoints * 4;
+				if (!p.hasExtendedType())
+					nActiveLines += numElements;
+			}
 			break;
+
 		case SHAPE_KIND:
-			// Estimate the size taken by lines and shapes as a constant plus
-			// a factor based on the number of points.
-			numPoints = ((MapLine) p).getPoints().size();
-			numElements = 1 + ((numPoints - 1) / PolygonSplitterFilter.MAX_POINT_IN_ELEMENT);
-			s = numElements * 11 + numPoints * 4;
-			if (res <= areaResolution)
-				nActiveShapes += numElements;
+		case XT_SHAPE_KIND:
+			if(res <= areaResolution) {
+				// Estimate the size taken by lines and shapes as a constant plus
+				// a factor based on the number of points.
+				numPoints = ((MapLine) p).getPoints().size();
+				numElements = 1 + ((numPoints - 1) / PolygonSplitterFilter.MAX_POINT_IN_ELEMENT);
+				sizes[kind] += numElements * 11 + numPoints * 4;
+				if (!p.hasExtendedType())
+					nActiveShapes += numElements;
+			}
 			break;
 
 		default:
 			log.error("should not be here");
 			assert false;
-			s = 0;
 			break;
 		}
 
-		sizes[res] += s;
-		elemCounts[res]++;
 	}
 
 	/**
@@ -452,7 +440,7 @@ public class MapArea implements MapDataSource {
 	private void addPoint(MapPoint p) {
 		points.add(p);
 		addToBounds(p.getBounds());
-		addSize(p, pointSize, POINT_KIND);
+		addSize(p, p.hasExtendedType()? XT_POINT_KIND : POINT_KIND);
 	}
 
 	/**
@@ -463,7 +451,7 @@ public class MapArea implements MapDataSource {
 	private void addLine(MapLine l) {
 		lines.add(l);
 		addToBounds(l.getBounds());
-		addSize(l, lineSize, LINE_KIND);
+		addSize(l, l.hasExtendedType()? XT_LINE_KIND : LINE_KIND);
 	}
 
 	/**
@@ -474,7 +462,7 @@ public class MapArea implements MapDataSource {
 	private void addShape(MapShape s) {
 		shapes.add(s);
 		addToBounds(s.getBounds());
-		addSize(s, shapeSize, SHAPE_KIND);
+		addSize(s, s.hasExtendedType()? XT_SHAPE_KIND : SHAPE_KIND);
 	}
 
 	/**
diff --git a/src/uk/me/parabola/mkgmap/build/MapSplitter.java b/src/uk/me/parabola/mkgmap/build/MapSplitter.java
index 0032307..3796507 100644
--- a/src/uk/me/parabola/mkgmap/build/MapSplitter.java
+++ b/src/uk/me/parabola/mkgmap/build/MapSplitter.java
@@ -52,6 +52,11 @@ class MapSplitter {
 
 	private static final int MAX_NUM_POINTS = 0xff;
 
+	// maximum allowed amounts of points/lines/shapes with extended types
+	private static final int MAX_XT_POINTS_SIZE = 0x8000;
+	private static final int MAX_XT_LINES_SIZE  = 0x8000;
+	private static final int MAX_XT_SHAPES_SIZE = 0x8000;
+
 	private final Zoom zoom;
 
 	/**
@@ -110,7 +115,7 @@ class MapSplitter {
 		int res = zoom.getResolution();
 		for (MapArea area : areas) {
 			Area bounds = area.getBounds();
-			int[] sizes = area.getSizeAtResolution(res);
+			int[] sizes = area.getEstimatedSizes();
 			if(log.isInfoEnabled()) {
 				String padding = depth + "                                            ";
 				log.info(padding.substring(0, (depth + 1) * 2) + 
@@ -126,7 +131,10 @@ class MapSplitter {
 				(sizes[MapArea.POINT_KIND] > MAX_RGN_SIZE &&
 				 (area.hasIndPoints() || area.hasLines() || area.hasShapes())) ||
 				(((sizes[MapArea.POINT_KIND] + sizes[MapArea.LINE_KIND]) > MAX_RGN_SIZE) &&
-				 area.hasShapes())) {
+				 area.hasShapes()) ||
+				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) {
 				if (area.getBounds().getMaxDimention() > 100) {
 					if (log.isDebugEnabled())
 						log.debug("splitting area", area);
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to