I'm trying to create a map to print out and the size of my polygons varies greatly. As this will be a reference map I need to label every polygon, but some of the names will not fit in the polygon. In those cases I'd like to use the feature id instead and then have an attribute table link the id to the name.
What I would like to do is have some sort of expression that I can use to select which label to use on the map and which rows to include in the attribute table. Something like isLabelled
that would be able to take the map scale, label length, font size etc into account.
Best Answer
Here's a somewhat approximate (but hopefully effective) way to do it.
First some math. We need to figure out how many characters at a certain font-size a feature can contain. Here things / assumptions to know:
To find how long an item is on screen / print we can use it's longest dimension (length or hight, or just length if your labels are horizontal only) / scale * 100 (to go from M to CM)
Then we can see if our label would fit.
You could do it all in the expression engine, but a custom python expression would be more efficient. Here is a tutorial on how to create one.
My custom expression:
Then just use that expression in the label:
You'll need to plug in whatever attribute you're actually using of course, and change the font size from 8 to whatever you're using. Also, since fonts vary quite a bit you may need to tweak it a little bit till it looks right.
You could also use that expression to do things like change the color based on if the label fits or not.
To use this expression outside the map canvas (i.e. in a composer label or attribute table) we need a way to programmatically get the scale of a given map item. I've posted code to accomplish that in another answer here The method there gives us an expression getScale('composername','mapname') so to incorporate it into our expression: