Going further from what i wrote about in the previous post regarding map design for coastal constructions and harbor features, i here want to look into rendering aquaculture installations.
Those have been mapped in OpenStreetMap for a long time with landuse=aquaculture
and that tag is meanwhile used nearly 90k times and we have had an open request in OSM-Carto to render those since 2015 when the tag was only used less than 10 percent of what it is used today.
Several ideas for rendering were discussed back then but nothing was developed to a state were it was really suitable for integration into the style. The main difficulties are:
- Aquacultures produce a wide range of things – like fish and mussels, but also seaweed. Designing a pictorial symbol for generic
landuse=aquaculture
that covers this full range and is still intuitively understandable is hard. - The design needs to reflect that it represents a physical, artificial structure and neither a natural feature (like a reef or tidalflat) nor an abstract area reserved for certain purposes (like a fishing ground)
- The design needs to ensure that the background is not fully obscured (it needs to be clear that it is water, possibly tidal, in the AC-Style also possibly different types of water), but at the same time overlaps between
landuse=aquaculture
andnatural=reef
orwetland=tidalflat
need to render in a readable way.
I have now developed a design that in my eyes mostly satisfies these requirements, that i want to show and discuss here now. The basic rendering concept looks fairly unspectacular:

Basic rendering concept for landuse=aquaculture
on different water color backgrounds – link goes to double resolution rendering
Now, it probably seems that the design is too noisy for the lower zoom levels (z9-z10). But keep in mind that aquacultures are typically rather limited in size. And the rendering is size dependent, as you can see in the following illustration.
This basic design is varied according to the produce cultivated in the aquaculture. Unfortunately, tagging practice here is not very consistent – both aquaculture=*
and produce=*
are used. The visualization of these variants is done with a single symbol pattern similar to what is used for sport pitches. And, like for pitches, the symbol size is increased if there is sufficient space. While, in case of sport pitches, this was implemented using standard Mapnik compositioning operations, i use GMIC here (because that is used anyway – see below).
So, overall, i use the following design elements:
- A dotted outline in dark blue to clearly mark the extent as mapped.
- A regular structure pattern to indicate an artificial structure.
- A single non-blocking symbol in a size adjusted to the polygon size and – if necessary – clipped by the polygon extent. This part is only done if the feature is sufficiently large in display.
This seems relatively plain and simple to implement at first. The difficulty, however, is in the details. If you look closely, you can see, that the structure pattern does not extend to either the outline or the center symbol, it leaves a small gap to those. This is important for readability of both the outline as a perimeter of the geometry and the symbol. If the structure pattern did cover the whole polygon, its dots would reduce the clarity of the rendering of those.
You could try to implement this with standard means in CartoCSS/Mapnik by painting over the pattern with a polygon outline and an outlined version of the symbol in water color. That would, however, defeat the very purpose of why we render this with a partial coverage overlay pattern and a dotted outline: The differentiated display of the water underneath – in particular that different types of waterbody and tidal features remain clearly visible.
What i did instead is using again GMIC for composing the different layers with the help of morphological processing of the alpha masks. Like with the quay rendering discussed in the previous post the GMIC scripts are wrapped in a conditional, so, if no aquacultures are rendered and the raw rendering buffer of that layer is therefore empty at the beginning of processing, the potentially expensive operations are skipped.
What is different here from the previously explained GMIC scripts is that the buffers that are not needed any more are individually discarded while otherwise i used -keep[name]
to keep only the buffer to be used and discard everything else. The reason is that at this stage in rendering there are other buffers on the stack that are still needed later (specifically the water masks used for the quay processing – see the previous blog post).
So far, so good. But you might remember the last difficulty described at the beginning of this post – if the aquaculture is mapped over a reef or a tidalflat, the result would essentially be unreadable because two strongly structured patterns would overlap. The solution here is to cut out the area covered by the aquaculture from the pattern rendering of the reefs and wetlands – again with a small buffer so the outline remains clearly visible. To do this i left the original polygon mask from the aquaculture layer on the GMIC stack (named aquaculture_mask
) after rendering the aquaculture layer. The reef and wetland patterns are rendered in the landcover-area-symbols
layer, which is rendered after the aquaculture layer. There, the mask is used in the following way:
zoom={round(log2(559082264.028/$_mapnik_scale_denominator))}
-if $zoom>=9
-if $_mapnik_render_trivial
-remove[aquaculture_mask]
-else
+channels[landcover_area_symbols_water] 3 -name. las_mask
-dilate_circ[aquaculture_mask] {5.0*$_mapnik_scale_factor}
-sub[las_mask] [aquaculture_mask]
-to_rgb[landcover_area_symbols_water]
-append[landcover_area_symbols_water] [las_mask],c
-remove[las_mask] -remove[aquaculture_mask]
-fi
-fi
-name. use
This is not very complex – apart from the wrapping conditional that limits the actual use of the GMIC script to z>=9. This is necessary since the landcover-area-symbols
layer is also rendered at z<9 and the GMIC script cannot - as explained in the previous blog post - be made conditional through a CartoCSS selector. The actual processing of interest at z>=9 in the non-trivial case happens after the -else
and does the following:
- duplicate the alpha channel of the landcover overlay pattern rendering as
las_mask
(image 1). - dilate (expand) the alpha channel of the plain color rendering of the aquaculture layer (the mask as retained from the aquaculture rendering: image 2, after expansion: image 3)
- subtract the expanded aquaculture polygon mask from the landcover overlay pattern mask (image 4).
- replace the alpha channel of the original landcover overlay pattern rendering (image 5) with the the modified alpha mask from the previous step (image 6).
- remove all the buffers not needed any more.
- use the modified rendering for composing this layer – the final rendering result is shown in image 7.

The different buffers at the different steps in the GMIC sequence with the numbers referenced above – rendered in double resolution and with bright gray indicating transparent background
Design wise this seems to work reasonably well in the different contexts. The dotted outline of the aquacultures is clearly visible – thanks to the buffered cut-outs of the patterns. And the different patterns do not interfere with each other while the edges between tidal and non-tidal areas and ocean, inland water and rivers remain visible.
Conclusions
What i have shown here are examples how more complex raster processing using morphological operations can be used to render different design elements in a map with cut-outs relative to each other. This facilitated solving a long standing problem in OSM based map design with well readable results.
It also shows that, as a map style grows more and more complex, both technically and design wise – with different elements being carefully adjusted in relation to each other, it becomes increasingly complex to add new features without creating a mess at least in some situations. A solid and capable technical framework and means of systematic testing are key to tackling these challenges.
As usual the changes shown here can be found in the AC-Style.
Pingback: weeklyOSM 776 – weekly – semanario – hebdo – 週刊 – týdeník – Wochennotiz – 주간 – tygodnik