The currently missing processing for the coastlines is probably the most annoying issue in mapsforge at the moment as it makes all map areas with coastlines look bad.
However, there is a work-around that requires no real changes to the map-writer nor the map-reader as it just utilises the render-theme mechanism.
This is how I do it:
First of all we need a good set of either land or sea areas. OSM data does not natively have this as coastlines, as opposed to all other data for areas, are just lines. The main OSM renderers all employ some sort of intermediate processing to get the sea and land areas right. I am using the dataset that Jochen Topf has provided on his
openstreetmapdata.com site. I am using just this set:
http://data.openstreetmapdata.com/land-polygons-split-4326.zip (I think the non-tiled version would also work).
First of all I cut the data down a bit, using ogr2ogr with the bounds for the desired map:
ogr2ogr -clipsrc $LEFT $BOTTOM $RIGHT $TOP output /data/coastline/land-polygons-split-4326/land_polygons.shp
This produces a, depending on your bounds, a much smaller coastline shapefile. I usually extend the boundaries of this file a bit over the actual area for the map to make sure I do not get any funny cut-offs.
Then I convert the resulting shapefile with shp2osm.py with slight modifications (as are always required with shp2osm). I set
fixed_tags = {
'natural': 'nosea',
}
which will attach this tag to all polygons. I also changed the starting id for the OSM ids, as otherwise there is chance of collision with real OSM ids, which will create strange artifacts, likes lines running through the map. I also changed the setting for the maximum length of ways, which does not seem to cause a problem.
I now have an OSM XML file with land represented as polygons with the tag "natural" -> "nosea". I agree, it is a stupid name and I first used the tag "natural" -> "land" but this is generally used to denote islands in lakes and such and will not play well with some rendering rules later.
The following steps could be taken in one, but I separated them out (a testing legacy):
I now merge the resulting osm file with the land polygons with my real osm data file:
$OSMOSIS_HOME/bin/osmosis --rb file=data.pbf --rx file=land.osm --sort --merge --wb file=out.pbf omitmetadata=true
out.pbf can now be fed into the mapfile-writer:
$OSMOSIS_HOME/bin/osmosis --rb file=out.pbf --mapfile-writer file=out.map map-start-position=$LAT,$LON bbox=$BOTTOM,$LEFT,$TOP,$RIGHT
The bounding box parameters are now those for the desired map, this will cut off any excess land polygons.
For this to work correctly, only the tag-mapping.xml file needed to be modified by adding:
<osm-tag key="natural" value="nosea" zoom-appear="5" />
This ensures that the new land polygons areas are included in the resulting file.
This finishes the map creation process.
On the reader side, the only change required is to display the land areas correctly by changing the render theme:
<?xml version="1.0" encoding="UTF-8"?>
<rule e="way" k="natural" v="nosea">
<area fill="#f8f8f8" stroke="#f8f8f8" stroke-width="0.1" />
</rule>
...
The first change is to paint the map on a blue (=sea) background. The next rule, at the very top of the file, makes sure all the nosea areas get painted first, here in some sort of grey.
The one short-coming here is that areas outside the map area all appear blue=sea. I guess that could be fixed by also extracting the real sea areas from the openstreetmapdata data set and painting them as well while having a different background, but this remains as an exercise to the reader.
Attached a few screenshots that show complicated coastline areas are all rendered correctly. I have not found a single area where I thought something was missing.
I am happy to answer questions about this. Sorry, this is not a full script to do this as my scripts tie into a few more infrastructure things that are difficult to factor out.
Ludwig