v3 - generate land poly even if tile doesn't contain any sea (when
--generate-sea=no-mp is specified) so that GPS units that ignore the
colour of the background poly (0x4b) don't the wrong background colour.
---------
v2 - avoid generating sea poly when unclipped tile contains coastline
but the clipped tile contains no coastline.
---------
Firstly, I would like to thank everyone who responded to my
"Understanding the sea" post. From those posts and my own study, I
finally worked out what it does. And yes, it works pretty well inasmuch
that it generates some useful polygons. The "sea sector" heuristic
doesn't work for me so I have been disabling it.
The problem is, the end result is "butt ugly". Our MP implementation
really can't do a good job on zillions of little islands.
After frigging around for a couple of days trying to improve the
visual quality, I tried the obvious alternative technique of not using
a MP but, instead, just having a sea background and then put the land
on top using plain polygons. Guess what? It works very nicely as the
attached pics show. I now have a splendid map of the Baltic area (OK
it's weird at the edges but that's not a problem for now).
Here's the (future) commit comment for this patch:
Provide an alternative to using a multipolygon when generating the
sea.
The --generate-sea option can now take a comma separated list of
values:
no-mp - don't generate the sea using a multipolygon - instead,
generate a background sea polygon and then individual land polygons
with tag natural=land. This requires a suitable land polygon type
to be defined in the style file (suggested type is 0x010100) and
the polygon must be defined in the TYP file as having a higher
drawing level than the sea polygon type.
no-sea-sectors - disable the generation of "sea sectors" when the
coastline fails to reach the tile's boundary.
With no values specified, the --generate-sea option should work as
before.
Oh yes, this patch doesn't include it, but I am also disabling the DP
code for polygons as it makes them weird.
Cheers and thanks again for the helpful postings.
Mark
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 acc5cf9..299733a 100644
--- a/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
+++ b/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
@@ -111,6 +111,8 @@ class Osm5XmlHandler extends DefaultHandler {
private final boolean linkPOIsToWays;
private final boolean routing;
private final boolean generateSea;
+ private boolean generateSeaUsingMP = true;
+ private boolean allowSeaSectors = true;
private final Double minimumArcLength;
private final String frigRoundabouts;
@@ -126,7 +128,16 @@ class Osm5XmlHandler extends DefaultHandler {
}
linkPOIsToWays = props.getProperty("link-pois-to-ways", false);
ignoreBounds = props.getProperty("ignore-osm-bounds", false);
- generateSea = props.getProperty("generate-sea", false);
+ String gs = props.getProperty("generate-sea", null);
+ generateSea = gs != null;
+ if(generateSea) {
+ for(String o : gs.split(",")) {
+ if("no-mp".equals(o))
+ generateSeaUsingMP = false;
+ else if("no-sea-sectors".equals(o))
+ allowSeaSectors = false;
+ }
+ }
routing = props.containsKey("route");
String rsa = props.getProperty("remove-short-arcs", null);
if(rsa != null)
@@ -465,8 +476,10 @@ class Osm5XmlHandler extends DefaultHandler {
if("motorway".equals(highway) ||
"trunk".equals(highway))
motorways.add(currentWay);
- if(generateSea && "coastline".equals(currentWay.getTag("natural")))
- shoreline.add(currentWay);
+ if(generateSea && "coastline".equals(currentWay.getTag("natural"))) {
+ currentWay.deleteTag("natural");
+ shoreline.add(currentWay);
+ }
currentNodeInWay = null;
currentWayStartsWithFIXME = false;
currentWay = null;
@@ -995,6 +1008,10 @@ class Osm5XmlHandler extends DefaultHandler {
super.fatalError(e);
}
+ public long makeFakeId() {
+ return (1L << 62) + nextFakeId++;
+ }
+
private long idVal(String id) {
try {
// attempt to parse id as a number
@@ -1004,7 +1021,7 @@ class Osm5XmlHandler extends DefaultHandler {
// if that fails, fake a (hopefully) unique value
Long fakeIdVal = fakeIdMap.get(id);
if(fakeIdVal == null) {
- fakeIdVal = (1L << 62) + nextFakeId++;
+ fakeIdVal = makeFakeId();
fakeIdMap.put(id, fakeIdVal);
}
//System.out.printf("%s = 0x%016x\n", id, fakeIdVal);
@@ -1013,10 +1030,6 @@ class Osm5XmlHandler extends DefaultHandler {
}
private void generateSeaPolygon(List<Way> shoreline) {
- // don't do anything if there is no shoreline
- if (shoreline.isEmpty())
- return;
-
Area seaBounds;
if (bbox != null)
seaBounds = bbox;
@@ -1033,7 +1046,7 @@ class Osm5XmlHandler extends DefaultHandler {
log.info("clipping " + segment);
toBeRemoved.add(segment);
for (List<Coord> pts : clipped) {
- long id = (1L << 62) + nextFakeId++;
+ long id = makeFakeId();
Way shore = new Way(id, pts);
toBeAdded.add(shore);
}
@@ -1053,9 +1066,33 @@ class Osm5XmlHandler extends DefaultHandler {
Coord sw = new Coord(maxLat, minLong);
Coord se = new Coord(maxLat, maxLong);
- long multiId = (1L << 62) + nextFakeId++;
- Relation seaRelation = new GeneralRelation(multiId);
- seaRelation.addTag("type", "multipolygon");
+ if(shoreline.isEmpty()) {
+ // no sea required
+ if(!generateSeaUsingMP) {
+ // even though there is no sea, generate a land
+ // polygon so that the tile's background colour will
+ // match the land colour on the tiles that do contain
+ // some sea
+ long landId = makeFakeId();
+ Way land = new Way(landId);
+ land.addPoint(nw);
+ land.addPoint(sw);
+ land.addPoint(se);
+ land.addPoint(ne);
+ land.addPoint(nw);
+ land.addTag("natural", "land");
+ wayMap.put(landId, land);
+ }
+ // nothing more to do
+ return;
+ }
+
+ long multiId = makeFakeId();
+ Relation seaRelation = null;
+ if(generateSeaUsingMP) {
+ seaRelation = new GeneralRelation(multiId);
+ seaRelation.addTag("type", "multipolygon");
+ }
List<Way> islands = new ArrayList<Way>();
@@ -1083,7 +1120,12 @@ class Osm5XmlHandler extends DefaultHandler {
// create a "inner" way for each island
for (Way w : islands) {
log.info("adding island " + w);
- seaRelation.addElement("inner", w);
+ if(generateSeaUsingMP)
+ seaRelation.addElement("inner", w);
+ else {
+ w.addTag("natural", "land");
+ wayMap.put(w.getId(), w);
+ }
}
boolean generateSeaBackground = true;
@@ -1129,10 +1171,15 @@ class Osm5XmlHandler extends DefaultHandler {
if (nearlyClosed) {
// close the way
points.add(pStart);
- seaRelation.addElement("inner", w);
+ if(generateSeaUsingMP)
+ seaRelation.addElement("inner", w);
+ else {
+ w.addTag("natural", "land");
+ wayMap.put(w.getId(), w);
+ }
}
- else {
- seaId = (1L << 62) + nextFakeId++;
+ else if(allowSeaSectors) {
+ seaId = makeFakeId();
sea = new Way(seaId);
sea.getPoints().addAll(points);
sea.addPoint(new Coord(pEnd.getLatitude(), pStart.getLongitude()));
@@ -1140,7 +1187,8 @@ class Osm5XmlHandler extends DefaultHandler {
sea.addTag("natural", "sea");
log.info("sea: ", sea);
wayMap.put(seaId, sea);
- seaRelation.addElement("outer", sea);
+ if(generateSeaUsingMP)
+ seaRelation.addElement("outer", sea);
generateSeaBackground = false;
}
}
@@ -1151,7 +1199,7 @@ class Osm5XmlHandler extends DefaultHandler {
}
}
if (generateSeaBackground) {
- seaId = (1L << 62) + nextFakeId++;
+ seaId = makeFakeId();
sea = new Way(seaId);
sea.addPoint(nw);
sea.addPoint(sw);
@@ -1161,13 +1209,14 @@ class Osm5XmlHandler extends DefaultHandler {
sea.addTag("natural", "sea");
log.info("sea: ", sea);
wayMap.put(seaId, sea);
- seaRelation.addElement("outer", sea);
+ if(generateSeaUsingMP)
+ seaRelation.addElement("outer", sea);
}
// now construct inner ways from these segments
NavigableSet<EdgeHit> hits = (NavigableSet<EdgeHit>) hitMap.keySet();
while (!hits.isEmpty()) {
- long id = (1L << 62) + nextFakeId++;
+ long id = makeFakeId();
Way w = new Way(id);
wayMap.put(id, w);
@@ -1224,12 +1273,19 @@ class Osm5XmlHandler extends DefaultHandler {
w.getPoints().add(w.getPoints().get(0));
log.info("adding non-island landmass, hits.size()=" + hits.size());
//w.addTag("highway", "motorway");
- seaRelation.addElement("inner", w);
+ if(generateSeaUsingMP)
+ seaRelation.addElement("inner", w);
+ else {
+ w.addTag("natural", "land");
+ wayMap.put(w.getId(), w);
+ }
}
- seaRelation = new MultiPolygonRelation(seaRelation, wayMap);
- relationMap.put(multiId, seaRelation);
- seaRelation.processElements();
+ if(generateSeaUsingMP) {
+ seaRelation = new MultiPolygonRelation(seaRelation, wayMap);
+ relationMap.put(multiId, seaRelation);
+ seaRelation.processElements();
+ }
}
/**
@@ -1346,11 +1402,12 @@ class Osm5XmlHandler extends DefaultHandler {
List<Coord> points2 = w2.getPoints();
Way wm;
if (w1.getId() < (1L << 62)) {
- wm = new Way((1L << 62) + nextFakeId++);
+ wm = new Way(makeFakeId());
ways.remove(w1);
ways.add(wm);
wm.getPoints().addAll(points1);
beginMap.put(points1.get(0), wm);
+ wm.copyTags(w1);
}
else {
wm = w1;
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev