[GIS] How to define leaders to a label in QGIS 2

labelingqgis

In QGIS 1.8 and 1.9 I used a plugin called Easy Labels to develop leader lines that would be saved as a memory layer. I have not been able to replicate this with QGIS 2.0, I can't even find the Easy Label Plugin. Assuming it is no longer valid in QGIS 2.

Question:
How can I create a leader from a label moved outside a polygon to the centroid of the polygon?

Best Answer

As a quick morning exercise I hacked a QGIS Python script together, creating lines in a memorylayer from a polygon centroid to a custom moved data binded label.

You need an x and y column in your table to have label coordinates stored. Also setup the data defined label x and y coordinates in labels properties.

Labels

Drag the label where you want it, with the label move tool:

labelmove

Copy the Python code below to a file called Labellines.py to you Python folder. On windows that would be C:\Users\USERNAME\ .qgis2\python.

"""
Generates lines from a data binded label to centroid of a polygon
Created by jakob at lanstorp dot com. Run from QGIS Python Console:

from Labellines import LabelLineGenerator
generator = LabelLineGenerator(qgis.utils.iface)
generator.createLabellines()
"""

from qgis.core import *

def run_script(iface):
     ''' Script runner from QGIS uses this driver code '''
     from Labellines import LabelLineGenerator
     generator = LabelLineGenerator(iface)
     generator.createLabellines()

class LabelLineGenerator:
    def __init__(self, iface):
        """Initialize using the qgis.utils.iface 
        object passed from the console.
        """

        # Set the name of the layer
        self.labelTable = 'Kommuner2006'

        self.iface = iface
        self.log = lambda m: QgsMessageLog.logMessage(m,'Labellines')
        self.log('LabelLineGenerator started ....')

    def createLabellines(self, layerToLable):
         self.createLabellineMemoryLayer()

         # Polygon layer to label
         vlayer = QgsVectorLayer("D:\data\Kommuner2006\Kommuner2006.shp","Kommuner", "ogr")

         # Iterate base layer
         iter = vlayer.getFeatures()
         i = 0
         for feature in iter:
             # Get data binded label coordinates
             xLabel = feature["x"]
             yLabel = feature["y"]
             # Skip labelline creation if label has not been moved
             if xLabel == NULL or yLabel == NULL:
                 continue   
             # Create label point
             labelPoint = QgsPoint(xLabel,yLabel)
             geom = feature.geometry()
             # Create centroid point
             centroidPoint = geom.centroid().asPoint()
             # Append label line to a memorylayer
             ft = QgsFeature()
             ft.setAttributes([i])
             ft.setGeometry(QgsGeometry.fromPolyline([geom.centroid().asPoint(),labelPoint]))
             self.labellineLayer.dataProvider().addFeatures([ft])
             i=i+1

         self.labellineLayer.commitChanges()

    def createLabellineMemoryLayer(self):
         ''' Create a memory layer for handling lines between centroid and label text '''
         self.labellineLayer =  QgsVectorLayer(
         "LineString?" +
         "crs=epsg:25832&" + 
         "field=id:integer&" +
         "index=yes",
         "Labelline",
         "memory")

         QgsMapLayerRegistry.instance().addMapLayer(self.labellineLayer)  

Update line 35 and 65 with your own settings.

Run it from the QGIS Python Console:

from Labellines import LabelLineGenerator    
generator = LabelLineGenerator(qgis.utils.iface)    
generator.createLabellines()

This is nothing compaired to the Easy Labels plugin, but did give me this map of some Copenhagen municipalities.

copenhagen

Line 35 - The polygon layer you want to label:

vlayer = QgsVectorLayer("D:\data\Kommuner2006\Kommuner2006.shp","Kommuner", "ogr")

Line 64 - The epsg code of your polygon layer:

"crs=epsg:25832&" +

Related Question