Just an idea that struck me, not a real solution, but a quick improvement:
At the moment mkgamp drops all the data in the area when it cannot be
subdivided. It would be at least some improvement if it would just drop some
data that exceeds the maximum content of an area instead of everything.
bye
Nop
Generally yes.
But most of the problems I have seen were caused by one polygon that
exceeds the limits without any other element in the subdivision.
I have an idea an will post a first patch within the next hour. This is
a first workaround only but should do it for now.
WanMil
Please try attached patch.
This is far from the optimal solution but I was able to remove the
errors with it.
@Nop: Unfortunately I could not reproduce the problems at your
problematic area so I wasn't able to see a real difference. Please test
the patch. If it works for you some more work has to be done so that
also the line filters checks against the subdivision size. It's not very
probable that a single line exceeds the limits but who knows....
WanMil
Index: src/uk/me/parabola/mkgmap/filters/PolygonSubdivSizeSplitterFilter.java
===================================================================
--- src/uk/me/parabola/mkgmap/filters/PolygonSubdivSizeSplitterFilter.java (revision 0)
+++ src/uk/me/parabola/mkgmap/filters/PolygonSubdivSizeSplitterFilter.java (revision 0)
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2007 Steve Ratcliffe
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program 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.
+ *
+ *
+ * Author: Steve Ratcliffe
+ * Create date: Dec 2, 2007
+ */
+package uk.me.parabola.mkgmap.filters;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import uk.me.parabola.log.Logger;
+import uk.me.parabola.mkgmap.build.MapSplitter;
+import uk.me.parabola.mkgmap.general.MapElement;
+import uk.me.parabola.mkgmap.general.MapShape;
+
+/**
+ * Split polygons so that it does not exceed the limits of a subdivision. The plan
+ * here is simple, if its too big, then cut it in half. As we always cut the largest
+ * dimension, then we will soon enough have cut it down to be small enough.
+ *
+ * @author Steve Ratcliffe
+ */
+public class PolygonSubdivSizeSplitterFilter extends PolygonSplitterBase implements MapFilter {
+ private static final Logger log = Logger.getLogger(PolygonSubdivSizeSplitterFilter.class);
+
+ private int shift;
+
+ /**
+ * Get the scale factor so that we don't over split.
+ *
+ * @param config Configuration information, giving parameters of the map level
+ * that is being produced through this filter.
+ */
+ public void init(FilterConfig config) {
+ shift = config.getShift();
+ if (shift > 15)
+ shift = 16;
+ }
+
+ /**
+ * Split up polygons that are too big.
+ *
+ * @param element A map element, only polygons will be processed.
+ * @param next This is used to pass the possibly transformed element onward.
+ */
+ public void doFilter(MapElement element, MapFilterChain next) {
+ assert element instanceof MapShape;
+ MapShape shape = (MapShape) element;
+
+ int maxSize = MAX_SIZE << shift;
+ if (isSizeOk(shape, maxSize)) {
+ // This is ok let it through and return.
+ next.doFilter(element);
+ return;
+ }
+
+ List<MapShape> outputs = new ArrayList<MapShape>();
+
+ // Do an initial split
+ split(shape, outputs);
+
+ // Now check that all the resulting parts are also small enough.
+ // NOTE: the end condition is changed from within the loop.
+ for (int i = 0; i < outputs.size(); i++) {
+ MapShape s = outputs.get(i);
+ if (!isSizeOk(s, maxSize)) {
+ // Not small enough, so remove it and split it again. The resulting
+ // pieces will be placed at the end of the list and will be
+ // picked up later on.
+ outputs.set(i, null);
+ split(s, outputs);
+ }
+ }
+
+ // Now add all to the chain.
+ boolean first = true;
+ for (MapShape s : outputs) {
+ if (s == null)
+ continue;
+ if (first) {
+ first = false;
+ next.doFilter(s);
+ } else
+ next.addElement(s);
+ }
+ }
+
+ private boolean isSizeOk(MapShape shape, int maxSize) {
+ // do not cut the background shape
+ if (shape.getType() == 0x4a)
+ return true;
+
+
+ // Estimate the size taken by lines and shapes as a constant plus
+ // a factor based on the number of points.
+ int numPoints = shape.getPoints().size();
+ int numElements = 1 + ((numPoints - 1) / PolygonSplitterFilter.MAX_POINT_IN_ELEMENT);
+ int size = numElements * 11 + numPoints * 4;
+// if (!shape.hasExtendedType())
+// nActiveShapes += numElements;
+
+ if (shape.hasExtendedType()) {
+ if (size > MapSplitter.MAX_XT_SHAPES_SIZE) {
+ log.error("XTSize larger than "+ MapSplitter.MAX_XT_SHAPES_SIZE);
+ return false;
+ }
+ } else if (size > MapSplitter.MAX_RGN_SIZE) {
+ log.error("RGN Size larger than "+ MapSplitter.MAX_RGN_SIZE);
+ return false;
+ }
+
+ return shape.getBounds().getMaxDimension() < Math.min(maxSize, 0x7fff);
+ }
+
+}
Index: src/uk/me/parabola/mkgmap/build/MapArea.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/MapArea.java (revision 1970)
+++ src/uk/me/parabola/mkgmap/build/MapArea.java (working copy)
@@ -26,8 +26,8 @@
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.filters.PolygonSubdivSizeSplitterFilter;
import uk.me.parabola.mkgmap.general.MapDataSource;
import uk.me.parabola.mkgmap.general.MapElement;
import uk.me.parabola.mkgmap.general.MapLine;
@@ -133,7 +133,9 @@
}
};
- PolygonSizeSplitterFilter filter = new PolygonSizeSplitterFilter();
+ PolygonSubdivSizeSplitterFilter filter = new PolygonSubdivSizeSplitterFilter();
+// PolygonSizeSplitterFilter filter = new PolygonSizeSplitterFilter();
+
FilterConfig config = new FilterConfig();
config.setResolution(resolution);
config.setBounds(bounds);
Index: src/uk/me/parabola/mkgmap/build/MapSplitter.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/MapSplitter.java (revision 1970)
+++ src/uk/me/parabola/mkgmap/build/MapSplitter.java (working copy)
@@ -32,32 +32,32 @@
*
* @author Steve Ratcliffe
*/
-class MapSplitter {
+public class MapSplitter {
private static final Logger log = Logger.getLogger(MapSplitter.class);
private final MapDataSource mapSource;
// There is an absolute largest size as offsets are in 16 bits, we are
// staying safely inside it however.
- private static final int MAX_DIVISION_SIZE = 0x7fff;
+ public static final int MAX_DIVISION_SIZE = 0x7fff;
// 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. Leave a little room for the region pointers
- private static final int MAX_RGN_SIZE = 0xfff8;
+ public static final int MAX_RGN_SIZE = 0xfff8;
// The maximum number of lines. NET points to lines in subdivision
// using bytes.
- private static final int MAX_NUM_LINES = 0xff;
+ public static final int MAX_NUM_LINES = 0xff;
- private static final int MAX_NUM_POINTS = 0xff;
+ public static final int MAX_NUM_POINTS = 0xff;
// maximum allowed amounts of points/lines/shapes with extended types
// real limits are not known but if these values are too large, data
// goes missing (lines disappear, etc.)
- private static final int MAX_XT_POINTS_SIZE = 0xff00;
- private static final int MAX_XT_LINES_SIZE = 0xff00;
- private static final int MAX_XT_SHAPES_SIZE = 0xff00;
+ public static final int MAX_XT_POINTS_SIZE = 0xff00;
+ public static final int MAX_XT_LINES_SIZE = 0xff00;
+ public static final int MAX_XT_SHAPES_SIZE = 0xff00;
private final Zoom zoom;
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev