Dear developers,

I'm new to mkgmap, just replacing cgpsmapper because it's slow, buggy and 
closed source. I have tried to compile from an .mp file. The resulting .img 
file had two huge problems:

1. Wrong character encoding.

I used an .mp source file in code page ISO-8859-2 (or Windows-1250). I was 
unable to fix encoding of Hungarian accented characters (áéíóúöőüű), tried all 
possible variations of --charset and --code-page options. I even tried to iconv 
.mp file to UTF-8 but it was also wrong way, img file had UTF-8 labels.

Finally, I have modified READING_CHARSET in mkgmap/reader/polish/PolishMapDataSource.java from 
"UTF-8" to "ISO-8859-2" and accented characters started to work. The used 
config was --charset=cp1252 --code-page=1252. The same worked when I specified ISO-8859-1, because 
the listed Hungarian characters are on the same place in two charsets. I think READING_CHARSET 
should be a new option or linked to --charset option.

2. Multipolygon errors.

Polygons with holes looked bizarre, long triangles appeared between endpoints 
of parts with alternating (negative/positive) rendering. Test showed detailed 
problems:

a. parts of multipart polygons were not closed at the last point
b. parts of multipart polygons were appended to each other, not stored as 
separated parts
c. multipolygon splitter treated "new" holes as areas, not holes

Investigating problem "b" showed that mkgmap stores polygons as a single 
List<Coord>. Garmin img also doesn't support holes or multipolygons.

For a working solution, I have created a workaround model for multipart polygons: first point of 
first part stands as a global starting point. Second part (hole or area, doesn't mind) is connected 
to this starting point with a zero-width capillary on the start and on the end as well. Every other 
parts are connected on the same way. Every parts should be closed (first node = last node), this 
was not checked before (problem "a"). Problem "b" became the spine of the 
solution, parts are appended. The connection between parts are only visible if polygon border is 
rendered.

Old cgpsmapper did the same way for holes, only difference is that cgpsmapper 
looked up the closest nodes for connection. I did not want to implement such a 
power-hungry algorithm, it's indifferent theoretically where holes are 
connected to areas. Another difference from cgpsmapper: multipolygons of 
disjoint areas were published to img as two independent polygons, resulting two 
labels on map.

I have implemented this model in two polygon processing class. Resulting .img 
file is now correct, even islands appear in holes. Modified files:

mkgmap/reader/polish/PolishMapDataSource.java
mkgmap/filters/PolygonSplitterBase.java

QUESTION: Where can I post my patch? Can I use SVN? Which branch? Attached 
patch against r1846.

Regards,
András Kolesár
diff -uNr mkgmap-r1846/src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java mkgmap-r1846-mod/src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java
--- mkgmap-r1846/src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java	2011-02-21 11:24:08.277801000 +0100
+++ mkgmap-r1846-mod/src/uk/me/parabola/mkgmap/filters/PolygonSplitterBase.java	2011-02-21 11:33:49.679676000 +0100
@@ -87,41 +87,85 @@
 	 */
 	private void areaToShapes(MapShape origShape, Area area, List<MapShape> outputs) {
 		float[] res = new float[6];
+		Coord firstCoord = null;
+		Coord firstCoordInPart = null;
+
 		PathIterator pit = area.getPathIterator(null);
 
-		List<Coord> coords = null;
+		// List<Coord> coords = null;
+		List<Coord> coords = new ArrayList<Coord>();
+
 		while (!pit.isDone()) {
 			int type = pit.currentSegment(res);
 
-			//System.out.println("T" + type + " " + res[0] + "," + res[1] + " " + res[2] + "," + res[3] + " " + res[4] + "," + res[5]);
+			// System.out.println("T" + type + " " + res[0] + "," + res[1] + " " + res[2] + "," + res[3] + " " + res[4] + "," + res[5]);
 			Coord co = new Coord(Math.round(res[1]), Math.round(res[0]));
 
 			if (type == PathIterator.SEG_MOVETO) {
 				// We get a moveto at the beginning and if this area is actually
 				// discontiguous we may get more than one, each one representing
 				// the start of another polygon in the output.
+
+/*
+				// following code commented out
+				// because we can't be sure if the next block is a new polygon
+				// can be a hole as well
+
 				if (coords != null) {
 					MapShape s2 = origShape.copy();
 					s2.setPoints(coords);
 					outputs.add(s2);
 				}
 				coords = new ArrayList<Coord>();
+*/
+
+				// we treat SEG_MOVETO as a new segment of the same polygon
 				coords.add(co);
+
+				// store starting coordinates of this part for closing
+				firstCoordInPart = co;
+
 			} else if (type == PathIterator.SEG_LINETO) {
+
 				// Continuing with the path.
 				assert coords != null;
 				coords.add(co);
+
 			} else if (type == PathIterator.SEG_CLOSE) {
 				// The end of a polygon
 				assert coords != null;
+				assert firstCoordInPart != null;
+
+				// SEG_CLOSE comes with the last SEG_LINETO coord
+				// no need to add twice
 				coords.add(co);
 
+				// if polygon was not closed, close first
+				if (!firstCoordInPart.equals(co)) {
+					coords.add(firstCoordInPart);
+				}
+
+				if (firstCoord == null) {
+					// store closing coordinates for next parts
+					firstCoord = firstCoordInPart;
+				} else {
+					// if this part was not first, then go back to first coord
+					coords.add(firstCoord);
+				}
+
+			/*
 				MapShape s2 = origShape.copy();
 				s2.setPoints(coords);
 				outputs.add(s2);
 				coords = null;
+			*/
 			}
 			pit.next();
 		}
+
+		// finally store the new shape
+		MapShape s2 = origShape.copy();
+		s2.setPoints(coords);
+		outputs.add(s2);
 	}
 }
diff -uNr mkgmap-r1846/src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java mkgmap-r1846-mod/src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java
--- mkgmap-r1846/src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java	2011-02-21 11:23:53.893473000 +0100
+++ mkgmap-r1846-mod/src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java	2011-02-21 11:45:30.740680000 +0100
@@ -63,7 +63,7 @@
 public class PolishMapDataSource extends MapperBasedMapDataSource implements LoadableMapDataSource {
 	private static final Logger log = Logger.getLogger(PolishMapDataSource.class);
 
-	private static final String READING_CHARSET = "UTF-8";
+	private static final String READING_CHARSET = "ISO-8859-1"; // "UTF-8";
 
 	private static final int S_IMG_ID = 1;
 	private static final int S_POINT = 2;
@@ -75,6 +75,7 @@
 	private MapShape shape;
 
 	private List<Coord> points;
+	private Coord firstCoord;
 
 	private final RoadHelper roadHelper = new RoadHelper();
 
@@ -262,6 +263,7 @@
 		section = 0;
 		endLevel = 0;
 		points = null;
+		firstCoord = null;
 	}
 
 	/**
@@ -431,6 +433,19 @@
 		} else if (name.startsWith("Data")) {
 			List<Coord> newPoints = coordsFromString(value);
 
+			// close polygon, gpsmapedit does not close
+			if (!newPoints.get(0).equals(newPoints.get(newPoints.size()-1)))
+				newPoints.add(newPoints.get(0));
+
+			// handle multipolygons
+			if (firstCoord != null) {
+				// this is not the first part, so move back to first point
+				newPoints.add(firstCoord);
+			} else {
+				// this is the first part, remember first point
+				firstCoord = newPoints.get(0);
+			}
+
 			if(points != null)
 				points.addAll(newPoints);
 			else
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to