PyQGIS Zoom Extent – Applying Zoom Extent from Several QgsVector Layers with Labels in PyQGIS

pyqgiszoom

I have the following case:

  • Project consists of three layers:
    1. OpenLayers plugin with Google streets
    2. QGSVector layer with Point features and Label enabled
    3. QGSVector layer with Polyline features and Label enabled

I need to (1) zoom extent canvas for both #2 and #3 and (2) make sure Labels are visible for all the features placed on these two layers.

I'm using the following code:

        idList = []
        idList.append(vlPoint.id())
        idList.append(vlLine.id())
        render = QgsMapRenderer()
        render.setLayerSet(idList)
        canvas = qgis.utils.iface.mapCanvas()
        canvas.setExtent(render.fullExtent())
        canvas.refresh()

The result of this code execution is below:
enter image description here

As you see the very upper point feature is displayed partially and its label is missed at all. If I zoom out canvas manually just a little- everything is displayed OK.

Need to know how to correctly zoom to extent in my case – to make sure all the features and labels are displayed.

If I have only one vector layer – the following code solves such issue:

 vlPoint.selectAll()
 canvas.zoomToSelected()
 vlPoint.removeSelection()

But for two layers this approach doesn't work.

Best Answer

You can combine both layers' extents and increase a bit the resulting bounding box to make sure all geometries and labels are visible.

In the following code, I i) take first and second layers from the ToC, ii) combine their extents, and iii) scale the resulting bounding box by 10%:

extent = QgsRectangle()
extent.setMinimal()
layers = [ iface.mapCanvas().layers()[0], iface.mapCanvas().layers()[1] ]
for layer in layers:
    extent.combineExtentWith( layer.extent() )

extent.scale( 1.1 ) # Increase a bit the extent to make sure all geometries lie inside 
iface.mapCanvas().setExtent( extent )
iface.mapCanvas().refresh()
Related Question