Page 1 of 1 (7 posts)

  • talks about »
  • labeling


Last update:
Wed Apr 16 22:45:10 2014

A Django site.

QGIS Planet

Fun with data-defined labels

Yesterday, I received an interesting QGIS question:

is there a way to make road label font size depending on road lenght (with osm layer)?
Indeed, it could be interresting to see all roads, even the smallest, on a city map rendering.

Thanks to the data-defined labeling capabilities of the new QGIS version, we can!

Just click the slightly weird symbol right of the label text size and select Edit …

Since OSM data is in WGS84 by default, street length will be measured in degrees and therefore the values will be small. To get to a reasonable font size, I selected $length * 1000.

The second part of the question can be addressed using a setting in the Rendering section which is – very descriptively – called “Show all labels for this layer (including colliding labels)”.


While I doubt that this simple method alone will create a great road map, I think it’s still an interesting exercise with sometimes surprising results.

Easier Conditional Labels in QGIS

With Martin’s latest addition of conditional statements it’s now even easier to get conditional labels in QGIS. Following up on the example used in my previous post, we can simplify

substr(osm_name, 0, (clazz = 11 or clazz = 13 or clazz = 15 or clazz = 21)*-1)


CASE WHEN (clazz = 11 or clazz = 13 or clazz = 15 or clazz = 21) THEN osm_name END

which is much easier to read and remember.

To avoid roads from being labeled with only their road numbers, I added an additional check that the “osm_name” is longer than six characters. Thanks to Nathan’s syntax highlighting this new and powerful expression based labeling is also comfortable to use.

Conditional labels for an osm2po layer

Conditional Labels in QGIS

The latest QGIS development build (1.9.90) has a new feature “expression based labeling” which can be used to create conditional labels. One typical use case would be if you want to label only certain (high-level) road classes in your road layer. By default, QGIS labels the features rather randomly:

default labeling

How can we label only the more important roads? Here is an example using OSM data imported into PostGIS using osm2po:

If you have loaded OSM using osm2po, your OSM table will contain a “clazz” attribute. (Check osm2po.config for the exact mapping.) To label only motorways, trunks, primary and secondary roads and nothing else, I wrote this labeling expression:

substr(osm_name, 0, (clazz = 11 or clazz = 13 or clazz = 15 or clazz = 21)*-1)

If clazz equals 11, 13, 15 or 21, the expression returns the value of osm_name. Otherwise it returns an empty string. (All checks will return false or 0 which causes the function to evaluate to substr(osm_name,0,0).) Kudos to Giuseppe Sucameli who explained this on the mailing list.

expression based "conditional" labels

Expression-based Labeling for QGIS

The latest development build version of QGIS contain a great new feature: Expression-based labeling, brought to you by Nathan.

QGIS new labeling dialog is extended by a new expression builder that facilitates building your own expressions using layer attributes together with various functions for data manipulation:

expression builder with function help

Thanks to it’s preview ability, it is easy to see how changes affect the final label output:

combine fields and follow changes in preview

For an in depth introduction into this new feature, check Nathan’s blog and enjoy!

Guide to Advanced Labeling for OSM Roads

Advanced labeling in QGIS new labeling engine is mostly about data-defined settings. Almost any property of the label can be controlled.

For this example, we will try to mimic the look of the classic Google map with it’s line and label styles. The data for this post is from the OpenStreetMap project provided as Shapefiles by Cloudmade.

After importing the roads into PostGIS using PostGIS Manager Plugin, we can create a view that will contain the necessary label style information. The trick here is to use CASE statements to distinguish between different label “classes”. Motorway labels will be bigger than the rest and the buffer color will be the same color as used for the corresponding lines.

drop view if exists v_osm_roads_styled ;

CREATE VIEW v_osm_roads_styled AS
CASE WHEN type = 'motorway' THEN 9
     ELSE 8 END
     as font_size,
'black'::TEXT as font_color,
false as font_bold,
false as font_italic,
false as font_underline,
false as font_strikeout,
false as font_family,
1 as buffer_size,
CASE WHEN type = 'motorway' THEN '#fb9139'::TEXT
     WHEN type IN ( 'primary','primary_link','secondary','secondary_link') THEN '#fffb8b'::TEXT
     ELSE 'white'::TEXT END
     as buffer_color
from osm_roads;

In QGIS, we can then load the view and start styling. First, let’s get the line style ready. Using rule-based renderer, it’s easy to create complex styles. In this case, I’ve left it rather simple and don’t distinguish between different zoom levels. That’s a topic for another post :)

Google-style rules for OSM road data

Now for the labels! In “Data defined settings”, we can assign the special attributes created in the database view to the settings.

Completed "Data defined settings"

To achieve an even better look, go to “Advanced” tab and enable “curved” and “on line” placement. “Merge connected lines to avoid duplicate labels” option is very helpful too.

Finally – after adding some water objects (Cloudmade natural.shp) – this is what our result looks like:

Google-style OSM map

This solution can be improved considerably by adding multiple zoom levels with corresponding styles. One obvious difference between the original Google map and this look-alike is the lack of road numbers. Tim’s post on “shield labels” can be a starting point for adding road numbers the way Google does.

Multi-line Labels in QGIS

Ever wondered how to create multi-line labels in QGIS? The new labeling engine has a “Multiline labels” option but it’s not so obvious how to create a usable labeling attribute. Here is how it works (credits to @nhopton on QGIS forum):

  1. Create a big enough text field (if the data doesn’t contain any yet).
  2. In Layer Properties – Fields, chose a “Text edit” edit widget for the label field.
  3. Enter the multi-line text into the label field. You can do this using Attribute Table or Feature Form.

    A feature form with "Text edit" widget

  4. Activate labeling. You’ll have to tick “Multiline labels” option in Layer Labeling Settings – Advanced – Options. That’s it:

    Simple multi-line label example

A common use case is the wish to show multiple attribute values in a feature’s label. Using Field Calculator, you can combine them into multi-line labels. All you need is to combine the fields with the || operator and add ‘\n’ (newline) wherever there should be a line break:

Field1 || '\n' || Field2

Populating a multi-line label field using Field Calculator

And finally, the result:

Multi-line labels displaying city name and population

How to Label Only Selected Features in QGIS

The aim of this post is to describe a method for labeling of a subset of features within a layer using new labeling functionality.

The problem

Often, we want to label only a few features in a layer. Of course we can export those features to a new layer and label them that way, but that requires creation of additional files and layers within your project. Things will start to get messy fast.

Another approach is to delete unwanted label texts from the attribute table. This either means that you have to duplicate a “name” attribute and then start deleting from the newly created attribute table column or that you actually delete values in the original column. Both approaches are problematic. Either you produce redundancy that gets difficult to maintain (two attributes have to be updated if the name of a feature changes) or you loose information from the attribute table.

The suggested solution

Let me present a different approach using new labeling tools. The idea is based on moving unwanted labels out of view. This approach avoids duplication of features and duplication/deletion of label texts. And this is the workflow:

  1. Select the features you want to label
  2. Open attribute table
  3. If you don’t have label attributes ready yet: Add two type “real” columns called e.g. “label_x” and “label_y”
  4. Invert the selection (3rd button in attribute table window)
  5. Open field calculator and fill “label_x” and “label_y” fields of the selected features with 0 values (or any coordinates outside your map extent)
  6. Close field calculator and attribute table
  7. Save your edits
  8. Open the labeling dialog and set “data defined settings” – “x coordinate” and “y coordinate”
  9. Enable “Label this layer” and specify the label field
  10. Done

If you change your mind about a feature and want to label it later on: Simply delete the values in “label_x” and “label_y” fields (so they read NULL).

This works quite well for me but I’m aware that it’s still not optimal. Another “data defined setting” like “show this label (true/false)” would be more intuitive.

Have you found better solutions to this problem? Please, post them!

  • Page 1 of 1 ( 7 posts )
  • labeling

Back to Top