Is there a way to obtain the bounding boxes of each TextSymbolizer present on the map? For now, I'm using mapnik 3 and I create a map using a custom XML containing TextSymbolizer. I want to have something like xmin, ymin and xmax, ymax of every labels.

Here is a sample of my XML file:

     <Filter>([symbo] = &quot;100&quot;) and ([placement_ok] = &quot;true&quot;)</Filter>
         face-name="DejaVu Sans Book" size="14.29"
         label-position-tolerance="0" fill="black"
         placement="point" allow-overlap="false"
         halo-fill="white" halo-radius="1.5">

1 Answer 1


I didn't find any built-in functions or any other straighforward way to do this.

I managed to find a solution using psycopg to fetch the data inside the database and Pillow to calculate the extents of labels.

Considering a map at a scale of 1/25 000, with a pixel size of 0.00028 m. This script works if you center your label placement in mapnik. You can modify the calculation of coordinates by applying the same translation as specified in mapnik.

def calculate_text_extent(fontname, fontsize, content):
    font = ImageFont.truetype(fontname, fontsize)
    size = font.getsize(content)
    return size

text = 'Hello World'
font = 'DejaVuSans.ttf'
size = 14
padding = 5
scale_denominator = 25000
pixel_size = calculate_text_extent(font, size, text)
width = (((pixel_size[0] + padding)/2)*0.00028*scale_denominator)
height = (((pixel_size[1] + padding)/2)*0.00028*scale_denominator)
xmin = x - width
xmax = x + width
ymin = y - height
ymax = y + height

The drawback is that it sometimes is a little displaced vertically, especially with crazy fonts and letters that expands downwards (such as p, j, g, q). I believe it is caused by mapnik, who considers the baseline of the text to place labels and not the lowest line of the text.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.