With all the excitement due to mp recently, I had completely forgotten
about this little addition to the sea generation code I did a while
back. It adds a new generate-sea option called close-gaps which
takes a distance (in metres). Gaps in the coastline less than this
distance, will be closed with a straight line. Not yet proven so please
test.

Typical usage: --generate-sea=polygons,no-sea-sectors,close-gaps=1000

Mark
diff --git a/resources/help/en/options b/resources/help/en/options
index 1abef9f..db69e1e 100644
--- a/resources/help/en/options
+++ b/resources/help/en/options
@@ -314,6 +314,10 @@ Miscellaneous options:
 	land-tag=TAG=VAL
 		tag to use for land polygons (default natural=land).
 
+	close-gaps=NUM
+		close gaps in coastline that are less than this
+		distance (metres)
+
 --make-poi-index
 	Generate the POI index (not yet useful).
 
diff --git a/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java b/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
index 033fa63..33d6e77 100644
--- a/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
+++ b/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
@@ -118,6 +118,7 @@ class Osm5XmlHandler extends DefaultHandler {
 	private boolean generateSeaUsingMP = true;
 	private boolean allowSeaSectors = true;
 	private boolean extendSeaSectors = false;
+	private int maxCoastlineGap = 0;
 	private String[] landTag = { "natural", "land" };
 	private final Double minimumArcLength;
 	private final String frigRoundabouts;
@@ -144,6 +145,8 @@ class Osm5XmlHandler extends DefaultHandler {
 					generateSeaUsingMP = false;
 				else if("multipolygon".equals(o))
 					generateSeaUsingMP = true;
+				else if(o.startsWith("close-gaps="))
+					maxCoastlineGap = (int)Double.parseDouble(o.substring(11));
 				else if("no-sea-sectors".equals(o))
 					allowSeaSectors = false;
 				else if("extend-sea-sectors".equals(o)) {
@@ -161,6 +164,7 @@ class Osm5XmlHandler extends DefaultHandler {
 					System.err.println("  no-sea-sectors      disable use of \"sea sectors\"");
 					System.err.println("  extend-sea-sectors  extend coastline to reach border");
 					System.err.println("  land-tag=TAG=VAL    tag to use for land polygons (default natural=land)");
+					System.err.println("  close-gaps=NUM      close gaps in coastline that are less than this distance (metres)");
 				}
 			}
 		}
@@ -1154,7 +1158,7 @@ class Osm5XmlHandler extends DefaultHandler {
 				it.remove();
 			}
 		}
-		concatenateWays(shoreline);
+		concatenateWays(shoreline, seaBounds);
 		// there may be more islands now
 		it = shoreline.iterator();
 		while (it.hasNext()) {
@@ -1537,7 +1541,7 @@ class Osm5XmlHandler extends DefaultHandler {
 		return new EdgeHit(i, l);
 	} 
 	
-	private void concatenateWays(List<Way> ways) {
+	private void concatenateWays(List<Way> ways, Area bounds) {
 		Map<Coord, Way> beginMap = new HashMap<Coord, Way>();
 
 		for (Way w : ways) {
@@ -1581,5 +1585,62 @@ class Osm5XmlHandler extends DefaultHandler {
 				}
 			}
 		}
+
+		// join up coastline segments whose end points are less than
+		// maxCoastlineGap metres apart
+		if(maxCoastlineGap > 0) {
+			boolean changed = true;
+			while(changed) {
+				changed = false;
+				for(Way w1 : ways) {
+					if(w1.isClosed())
+						continue;
+					List<Coord> points1 = w1.getPoints();
+					Coord w1e = points1.get(points1.size() - 1);
+					if(bounds.onBoundary(w1e))
+						continue;
+					Way nearest = null;
+					double smallestGap = Double.MAX_VALUE;
+					for(Way w2 : ways) {
+						if(w1 == w2 || w2.isClosed())
+							continue;
+						List<Coord> points2 = w2.getPoints();
+						Coord w2s = points2.get(0);
+						if(bounds.onBoundary(w2s))
+							continue;
+						double gap = w1e.distance(w2s);
+						if(gap < smallestGap) {
+							nearest = w2;
+							smallestGap = gap;
+						}
+					}
+					if(nearest != null && smallestGap < maxCoastlineGap) {
+						Coord w2s = nearest.getPoints().get(0);
+						log.info("bridging " + (int)smallestGap + "m gap in coastline from " + w1e.toOSMURL() + " to " + w2s.toOSMURL());
+						Way wm;
+						if (w1.getId() < (1L << 62)) {
+							wm = new Way(FakeIdGenerator.makeFakeId());
+							ways.remove(w1);
+							ways.add(wm);
+							wm.getPoints().addAll(points1);
+							wm.copyTags(w1);
+						}
+						else {
+							wm = w1;
+						}
+						wm.getPoints().addAll(nearest.getPoints());
+						ways.remove(nearest);
+						// make a line that shows the filled gap
+						Way w = new Way(FakeIdGenerator.makeFakeId());
+						w.addTag("natural", "mkgmap:coastline-gap");
+						w.addPoint(w1e);
+						w.addPoint(w2s);
+						wayMap.put(w.getId(), w);
+						changed = true;
+						break;
+					}
+				}
+			}
+		}
 	}
 }
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to