This is part three of a four part series of blog posts on the depiction of trees in maps – see part one for a discussion of tree rendering in traditional maps and plans and part two for mapping of trees in OpenStreetMap and rendering in OSM based maps.
Based on what i discussed in the first two parts of this series of blog posts, i have contemplated and experimented with new ideas for rendering trees in digital maps for quite some time. In the alternative-colors style i had already reverted the removal of tree depiction from z16 and z17 earlier. Since trees are important for many map users and mappers evidently invest a lot of time and energy in mapping them, degrading them to a POI of local importance is not a good idea in my opinion.
But the problems with the existing rendering in OSM-Carto otherwise remain:
- The transparency in rendering is not working well on the higher zoom levels (z18 and z19) where it applies to a larger area.
- The symbols use a lot of space and affect readability of the map, in particular in areas with dense presence of trees and this could even discourage mappers from mapping all trees in some cases. At the same time it is wasteful because it transports no information beyond the simple here is a tree while – as discussed in the previous post – mappers use all kinds of secondary tags to further characterize trees which could well be used for more differentiated rendering, in particular at the higher zoom levels.
- These problems will further aggravate if you’d want to extend the style to higher zoom levels.
I contemplated the idea of using profile symbols, because – as discussed – this is very common in traditional maps and it allows transporting differentiated additional information on the type of tree. However, this approach would not work too well at larger scales/higher zoom levels. And it does not provide very precise information on the position of the tree. As i showed, large scale plans typically use from-the-top view depictions and have developed a lot of useful design concepts in that domain. If you want to have a useful depiction of the tree size at these scales there is really no alternative to a from-the-top view.
The basic design concept
The basic design idea i have now implemented is using from-the-top view symbols in a line drawing design. If the symbol design is not too dense it allows features below the tree symbol to be visible through the line drawing – while being less distorted in coloring than with the semitransparent fill color of the OSM-Carto design.
The difficulty is how to deal with symbol overlaps. I definitely wanted to retain the feature of tree symbols being non-blocking because trees frequently exist in dense groups and just rendering one of them in such cases is highly non-ideal. And in areas where there are a lot of POIs (like in dense urban environments) most trees would not be rendered if they were blocked by other symbols.
If you’d naively show line drawing symbols with overlaps you would often end up with a dense, non-discernible mess in areas with dense presence of trees. The technique of applying layer based opacity in OSM-Carto successfully avoids that – but only for a uniform fill color. I considered applying a structure pattern to a polygon aggregated from the buffers of the individual trees (a bit similar to the rendering of unpaved roads). But that would look rather crude for trees and would evidently be a solution just chosen because it is technically simple and not because it is good design.
The samples from architectural drawings and site plans i showed in the first part demonstrate a number of techniques how overlapping top view tree depictions can be handled graphically. None of the automated map rendering tools i know of has any kind of built-in support for anything like that though. What i ultimately ended up with is implementing the whole symbol drawing in PostGIS. This is certainly not very efficient (doing this at the compositioning level of the renderer rather than at the geometry processing stage would be much faster probably) but it is doable.
To make that possible, all the symbols were entered into a distinct database table as PostGIS polygon geometries and are then processed to generate the desired shapes to be then rendered just as if they were mapped geometries from the rendering database. This probably sounds more complex than it is in principle – though the geometry processing is certainly non-trivial. The route to get SVG symbols into a PostGIS database is via conversion to PDF using inkscape and then using OGR basic PDF support (with OGR_PDF_READ_NON_STRUCTURED). As an alternative route of symbol generation for simple abstract shapes i also implemented support for generating them using PostGIS code. Both routes can also be combined to supplement/edit a file based symbol with a PostGIS query. This is in particular useful for dynamically scaled symbols – as i will discuss in more detail below.
Tree type depiction
As you could already see in the examples so far i designed different symbols for different types of trees. This is less easy to do in an intuitive fashion than for profile symbols but it is still manageable at least for the basic
At z16 and z17 trees are – like in OSM-Carto before 2017 – rendered with a plain green dot. At z18 trees start being differentiated by
leaf_type and from z19 on also by
leaf_cycle. The illustration of deciduous
leaf_cycle takes the form of a display of the major branches and trunk of the tree (as visible from above in the absence of foliage) or a cleared center area in case of the needleleaved symbol. The lack of a specified
leaf_cycle is illustrated with a small circle in the center of the symbol. Palms (
taxon=Arecaceae) are shown with a distinct symbol (independent of the
The other main feature for individual tree rendering i implemented in addition to the
leaf_cycle depiction and the customized handling of symbol overlaps is dynamic scaling of symbols according to recorded information about the tree size.
Trees vary greatly in sizes – what is commonly mapped in OpenStreetMap as
natural=tree might have a height of just 2-3m for a small ornamental tree up to more than 50m. Canopy diameters (
diameter_crown) can range from a meter or less up to around 50m as well. Such information is not recorded for a large percentage of trees mapped in OpenStreetMap but in absolute numbers it is still quite a few that come with such data. And visualizing tree size information in the map at the higher zoom levels would increase the usefulness of tree rendering quite significantly.
With the top view visualization i have chosen here a natural way to visualize the tree size is by varying the symbol size based on the canopy diameter. This is also the way large scale site plans often differentiate trees – as i have shown in the first part of this blog post series. Just scaling the whole symbol however does not work very well for that. For a line drawing symbol, scaling the line work while maintaining the drawing width would be a possibility – that is what most of the mentioned site plans do. However this still can lead to the problem that smaller symbols would have a too detailed geometry while larger symbols are not detailed enough. I tried and implemented both the approach to design distinct symbols for different rendering sizes and to have parametrized symbol geometries that scale according to non-trivial rules. Here is how this looks like:
To inspect the symbols in the symbols table i also created a separate map style file (treeinspector.mml) that visualizes the content of the symbols table as is. Here is how this looks like:
The symbols for palms exist only for the sizes they have been designed for. The renderer then picks the closest match in size and scales it to the tagged tree size, rounded to the next integer pixel size to ensure pixel alignment as far as possible. For the parametrized symbols (most of the larger ones) a separate symbol is pre-generated by the generate_symbols.py script for every integer symbol size. This is either fully generated by PostGIS SQL code (for the unknown
leaf_type symbols on the right) or composed of a scaled SVG based design and additional parametrized modification via PostGIS (for the known
leaf_type symbols). As you can see the overall size of the symbols are scaled while the line with of the abstract circles and the geometry of the center symbol is not in the same way (for larger symbols this also gets increased moderately). For the larger symbols with know
leaf_cycle the center portion (indicating the
leaf_cycle) is rendered at a constant size while the outer rim (which does not change with
leaf_cycle) is scaled according to the symbol size. The definition of all these symbol generation rules can be found in symbols.yml.
In the above symbol table only odd sizes (in pixels) are shown above 17 pixels. Only those are used for the individual tree rendering to ensure a uniform pixel aligned rendering at different sizes. For the tree rows (see below), where the symbols are not pixel aligned, also the even sizes are used.
diameter_crown is not mapped for the tree an estimate is made from either the
height (0.3 times the height) or the trunk diameter (5 times the diameter). This is implemented in the function carto_tree_diameter_mapped(). As with other cases of ground unit rendering i implemented in the alternative-colors style, the symbol size is chosen as the maximum of the default symbol size for that zoom level and the size as tagged or estimated based on tagged height or trunk diameter.
With the shown technique to cut out overlapping tree symbols there is also a possibility to indicate different tree heights separately to some extent by having the height define the drawing order. If the height is not tagged, the drawing diameter of the tree symbol (determined as described above) is used to define the drawing order instead. That of course means that small trees completely under large ones are hidden.
One part of this tree rendering project i struggled quite a lot with are the tree rows. This is to a large extent because
natural=tree_row is a fairly ill defined concept in OpenStreetMap. As mentioned in part 2 there is no established tagging to indicate the spacing of trees in a tree row and neither is there a clear agreement what qualifies a set of trees to form a tree row. A tree row might be
- four trees spaced 50 meters apart but planted evidently in a collinear fashion so forming an abstract row while not in any way forming a continuous object.
- trees along the edge of a road or stream which might have originally been planted in a systematic fashion but with – at present – irregular intervals between them.
- a dense arrangement of trees along the side of a agricultural plantation serving as wind protection.
- a regularly spaced line of trees in a tree plantation for agricultural purposes.
All of that might indiscriminately be modeled with
natural=tree_row in OpenStreetMap. Visualizing that in a way that properly represents all of these cases in a decent fashion is next to impossible.
The traditional rendering in OSM-Carto is taking the simplistic approach to simply align the design directly to the data model. By rendering individual trees as a buffered point and rendering tree rows as a buffered line. While that is a reasonable choice to give the mapper very direct feedback to what they have mapped, it does not provide much support or guidance regarding the semantics of that mapping.
The approach i ultimately chose for tree rows is to render them like a line of individual trees with a relatively dense arrangement of individual tree symbols. But the cutting out of the individual tree symbols against each other is done in a different fashion, not prioritizing one symbol over the other but cutting them at the bisector between them. I am not sure if this is the best solution. But it is one that harmonizes quite well with the individual tree depiction and at the same time makes the results easy to distinguish from a line of trees mapped individually.
For efficiency in rendering – since all of this has to be done in SQL code on the fly – the individual tree symbols of the tree row are only cut against the previous and next point on the line which leads to some overlap artifacts in case of sharp corners on the line.
Some might wonder why i have not used a line pattern to generate this kind of visualization. There are multiple reasons for that. First: line patterns in Mapnik don’t have support for line caps – which would not work very well for this use case. Second: Line patterns are drawn continuously along the length of the line and no special attention is given to corners in the line geometry. What you’d want, however, for tree rows (and especially also hedges – see further below) is that there is a tree symbol positioned at every node of the line to give proper visual feedback on the exact geometry. The additional tree symbols would be distributed between the line nodes until the desired point density is achieved (which can be done with
ST_Segmentize() in PostGIS). This has the disadvantage that the symbol density along the line varies and the design needs to be robust enough to deal with that – which however is the case here. The third reason is that line patterns are always oriented along the line so there is no good way to implement a shading effect like i use in the tree symbols here.
Shrubs/bushes and hedges
For rendering shrubs i chose the same design as for trees – but they only get rendered starting at z19 so there is not much risk of confusion. The symbols at z19 are already differentiated by
leaf_type – but that difference is very subtle.
Hedges are rendered like in OSM-Carto until z19 and get the tree row like differentiated design at z20.
For hedges i added rendering for the regional specialty in northern Germany called Knick (see the second part of this blog post series) – for which there is a tag in OpenStreetMap:
hedge=hedge_bank. This is indicated in a similar fashion as i render implicit embankments on roads:
And here trees, shrubs, tree rows and hedges of various types at z20 for comparison.
Real world examples
And for the end of this part after all the abstract examples illustrating the design in principle, here a few examples based on actual OpenStreetMap data. More samples can be found on the Alternative-colors style sample gallery and on my style comparison page.
The fourth and last part of this series of blog post is going to provide some discussion and conclusions on the subject of individual tree rendering in digital maps.