Categories: ProgrammingTutorials

Symbolizers

7 min read

In this article by Erik Westra, author of the book, Python Geospatial Analysis Essentials, we will see that symbolizers do the actual work of drawing a feature onto the map. Multiple symbolizers are often used to draw a single feature.

There are many different types of symbolizers available within Mapnik, and many of the symbolizers have complex options associated with them. Rather than exhaustively listing all the symbolizers and their various options, we will instead just look at some of the more common types of symbolizers and how they can be used.

(For more resources related to this topic, see here.)

PointSymbolizer

The PointSymbolizer class is used to draw an image centered over a Point geometry. By default, each point is displayed as a 4 x 4 pixel black square:

To use a different image, you have to create a mapnik.PathExpression object to represent the path to the desired image file, and then pass that to the PointSymbolizer object when you instantiate it:

path = mapnik.PathExpression("/path/to/image.png")
point_symbol = PointSymbolizer(path)

Note that PointSymbolizer draws the image centered on the desired point. To use a drop-pin image as shown in the preceding example, you will need to add extra transparent whitespace so that the tip of the pin is in the middle of the image, like this:

You can control the opacity of the drawn image by setting the symbolizer’s opacity attribute. You can also control whether labels will be drawn on top of the image by setting the allow_overlap attribute to True. Finally, you can apply an SVG transformation to the image by setting the transform attribute to a string containing a standard SVG transformation expression, for example point_symbol.transform = “rotate(45)”.

Documentation for the PointSymbolizer can be found at https://github.com/mapnik/mapnik/wiki/PointSymbolizer.

LineSymbolizer

A mapnik.LineSymbolizer is used to draw LineString geometries and the outlines of Polygon geometries. When you create a new LineSymbolizer, you would typically configure it using two parameters: the color to use to draw the line as a mapnik.Color object, and the width of the line, measured in pixels. For example:

line_symbol = mapnik.LineSymbolizer(mapnik.Color("black"), 0.5)

Notice that you can use fractional line widths; because Mapnik uses anti-aliasing, a line narrower than 1 pixel will often look better than a line with an integer width if you are drawing many lines close together.

In addition to the color and the width, you can also make the line semi-transparent by setting the opacity attribute. This should be set to a number between 0.0 and 1.0, where 0.0 means the line will be completely transparent and 1.0 means the line will be completely opaque.

You can also use the stroke attribute to get access to (or replace) the stroke object used by the line symbolizer. The stroke object, an instance of mapnik.Stroke, can be used for more complicated visual effects. For example, you can create a dashed line effect by calling the stroke’s add_dash() method:

line_symbol.stroke.add_dash(5, 7)

Both numbers are measured in pixels; the first number is the length of the dash segment, while the second is the length of the gap between dashes.

Note that you can create alternating dash patterns by calling add_dash() more than once.

You can also set the stroke’s line_cap attribute to control how the ends of the line should be drawn, and the stroke’s line_join attribute to control how the joins between the individual line segments are drawn whenever the LineString changes direction. The line_cap attribute can be set to one of the following values:

mapnik.line_cap.BUTT_CAP
mapnik.line_cap.ROUND_CAP
mapnik.line_cap.SQUARE_CAP

The line_join attribute can be set to one of the following:

mapnik.line_join.MITER_JOIN
mapnik.line_join.ROUND_JOIN
mapnik.line_join.BEVEL_JOIN

Documentation for the LineSymbolizer class can be found at https://github.com/mapnik/mapnik/wiki/LineSymbolizer.

PolygonSymbolizer

The mapnik.PolygonSymbolizer class is used to fill the interior of a Polygon geometry with a given color. When you create a new PolygonSymbolizer, you would typically pass it a single parameter: the mapnik.Color object to use to fill the polygon. You can also change the opacity of the symbolizer by setting the fill_opacity attribute, for example:

fill_symbol.fill_opacity = 0.8

Once again, the opacity is measured from 0.0 (completely transparent) to 1.0 (completely opaque).

There is one other PolygonSymbolizer attribute which you might find useful: gamma. The gamma value can be set to a number between 0.0 and 1.0. The gamma value controls the amount of anti-aliasing used to draw the edge of the polygon; with the default gamma value of 1.0, the edges of the polygon will be fully anti-aliased. While this is usually a good thing, if you try to draw adjacent polygons with the same color, the antialiasing will cause the edges of the polygons to be visible rather than combining them into a single larger area. By turning down the gamma slightly (for example, fill_symbol.gamma = 0.6), the edges between adjacent polygons will disappear.

Documentation for the PolygonSymbolizer class can be found at https://github.com/mapnik/mapnik/wiki/PolygonSymbolizer.

TextSymbolizer

The TextSymbolizer class is used to draw textual labels onto a map. This type of symbolizer can be used for point, LineString, and Polygon geometries. The following example shows how a TextSymbolizer can be used:

text_symbol = mapnik.TextSymbolizer(mapnik.Expresion("[label]"), "DejaVu Sans Book", 10, mapnik.Color("black"))

As you can see, four parameters are typically passed to the TextSymbolizer’s initializer:

  • A mapnik.Expression object defining the text to be displayed. In this case, the text to be displayed will come from the label attribute in the datasource.
  • The name of the font to use for drawing the text. To see what fonts are available, type the following into the Python command line:
    import mapnik
    for font in mapnik.FontEngine.face_names():
       print font
  • The font size, measured in pixels.
  • The color to use to draw the text.

By default, the text will be drawn in the center of the geometry; for example:

This positioning of the label is called point placement. The TextSymbolizer allows you to change this to use what is called line placement, where the label will be drawn along the lines:

text_symbol.label_placement = mapnik.label_placement.LINE_PLACEMENT

As you can see, this causes the label to be drawn along the length of a LineString geometry, or along the perimeter of a Polygon. The text won’t be drawn at all for a Point geometry, since there are no lines within a point.

The TextSymbolizer will normally just draw the label once, but you can tell the symbolizer to repeat the label if you wish by specifying a pixel gap to use between each label:

text_symbol.label_spacing = 30


By default, Mapnik is smart enough to stop labels from overlapping each other. If possible, it moves the label slightly to avoid an overlap, and then hides the label completely if it would still overlap. For example:

You can change this by setting the allow_overlap attribute:

text_symbol.allow_overlap = True

Finally, you can set a halo effect to draw a lighter-colored border around the text so that it is visible even against a dark background. For example,

text_symbol.halo_fill = mapnik.Color("white")
text_symbol.halo_radius = 1

There are many more labeling options, all of which are described at length in the documentation for the TextSymbolizer class. This can be found at https://github.com/mapnik/mapnik/wiki/TextSymbolizer.

RasterSymbolizer

The RasterSymbolizer class is used to draw raster-format data onto a map. This type of symbolizer is typically used in conjunction with a Raster or GDAL datasource. To create a new raster symbolizer, you instantiate a new mapnik.RasterSymbolizer object:

raster_symbol = mapnik.RasterSymbolizer()

The raster symbolizer will automatically draw any raster-format data provided by the map layer’s datasource. This is often used to draw a basemap onto which the vector data is to be displayed; for example:

While there are some advanced options to control the way the raster data is displayed, in most cases, the only option you might be interested in is the opacity attribute. As usual, this sets the opacity for the displayed image, allowing you to layer semi-transparent raster images one on top of the other.

Documentation for the RasterSymbolizer can be found at https://github.com/mapnik/mapnik/wiki/RasterSymbolizer.

Summary

In this article, we covered different types of symbolizers, which are available in the Mapnik library.

We also examined that symbolizers which can be used to display spatial features, how the visible extent is used to control the portion of the map to be displayed, and how to render a map as an image file.

Resources for Article:


Further resources on this subject:


Packt

Share
Published by
Packt

Recent Posts

Harnessing Tech for Good to Drive Environmental Impact

At Packt, we are always on the lookout for innovative startups that are not only…

2 months ago

Top life hacks for prepping for your IT certification exam

I remember deciding to pursue my first IT certification, the CompTIA A+. I had signed…

3 years ago

Learn Transformers for Natural Language Processing with Denis Rothman

Key takeaways The transformer architecture has proved to be revolutionary in outperforming the classical RNN…

3 years ago

Learning Essential Linux Commands for Navigating the Shell Effectively

Once we learn how to deploy an Ubuntu server, how to manage users, and how…

3 years ago

Clean Coding in Python with Mariano Anaya

Key-takeaways:   Clean code isn’t just a nice thing to have or a luxury in software projects; it's a necessity. If we…

3 years ago

Exploring Forms in Angular – types, benefits and differences   

While developing a web application, or setting dynamic pages and meta tags we need to deal with…

3 years ago