Another post from my series on OpenStreetMap map design – this one is about rendering implicit embankments and cuttings.
Embankments in OpenStreetMap are artificial slopes created mostly to provide a level base for construction of a road or railway or to otherwise artificially shape the topography. Cuttings are a bit like the opposite – an artificial cut into the natural topography created for similar reasons.
What does implicit mean in this context? In OpenStreetMap embankments can be mapped explicitly with a way tagged man_made=embankment drawn along the top of the embankment. This has been rendered in the standard style similar to natural=cliff with a gray line with small ticks on one side indicating the direction. Implicit mapping of embankments means the embankment or cutting is mapped by adding an additional attribute to the road/railway etc. to indicate the presence of it. This is done with the tags embankment=yes and cutting=yes. Implicit mapping using embankment=yes is used more than twice as popular as a tag as man_made=embankment – together embankment=yes and cutting=yes are used three times as frequently.
But none the less embankment=yes and cutting=yes are not rendered by OSM-Carto – because it is somewhat difficult to do so in a reasonably looking way.
What you can do without much problem is rendering embankment=yes as a special casing color similar to the rendering of bridges (or my rendering of fords in the alternative-colors style). But this is rather non-intuitive and cryptic. The more intuitive way to render embankment=yes tagged on a road is to render a line with ticks like it is used for man_made=embankment around the road line. Here is how this looks like in an abstract test:
As you can see this works nicely in very simple cases but fails very badly in some of the more complex situations. In particular if you have roads with seperate lines for both directions mapped separately like motorways this is a serious problem.
To avoid these problems you need to take the context of every road with an embankment into account, in particular other roads with and without an embankment around it. This get complicated and expensive in terms of query performance very quickly. Here is what i came up kind of as a compromise between quality and performance:
The query for this is about 4-5 times slower than the trivial version in my tests – which sounds like a lot slower but is actually not too bad. Because of the way queries are performed in the rendering framework used this is much less efficient though than it could be in theory. For rendering the roads themselves you need to query all the roads within the tile anyway and you could re-use the results of this query to much more efficiently do the necessary processing for the embankments. But unfortunately there is no way to re-use query results across different layers with mapnik.
Another technical problem that i already experienced with the rendering of springs and water barriers is that for more sophisticated geometry processing you need access to the line widths in the style depending on zoom level from within SQL. To do that without adding a long CASE statement with line width literals everywhere in the queries where the line widths are needed which all need to be modified whenever you want to change a line width i created a script (derived from the existing road colors script) that generates both SQL functions and MSS code for defining and selecting the line widths based on a yaml file.
Implicit embankments and cuttings are rendered for all the usual road types as well as railways and waterways.
As you can see i decreased the tick distance on the line compared to the OSM-Carto embankment line signature – this works better with high curvature rendering around roads.
I start rendering the implicit embankments from z16. Starting them at an earlier zoom level would mean taking up quite a large amount of space on the map because normally at z15 and below most roads are already rendered in a line with larger than the actual road and the embankment would further increase that. This would lead to frequent overlap with various features and strange results in some cases, in particular in areas with dense mapping which is counterproductive as a mapping incentive.
Here a few examples at z16:
And here at z17:
The last sample shows both the rendering of implicit and explicit mapping of embankments. The implicit variant is here rendered approximately at its real scale. The implicit mapping has the advantage that with this kind of rendering it looks good both at this and at other scales while the explicit mapping only looks good when the road is rendered in approximately its natural width. If the road rendering is less wide at the higher zoom levels there would be a gap between the road line and the embankment line and if the road is drawn wider than its real width it will overlap an explicitly mapped embankment and will not or only partially be visible. Avoiding this and adding displacement of explicitly mapped embankments at the lower zoom levels would be much more difficult. So for high quality maps with relatively simple rendering implicit mapping of embankments allows better quality results.
If you want to try this change yourself you can as usual find it in the alternative-colors style.