I have the following layers inside a layer group 'Parcels' layergroup

I have created a Plugin that will determine a coordinate (Coordx,Coordy) based on a user input and then pan/zoom the map to the coordinate (Note: Coordx and Coordy are Qstrings). What I want it to do is select a feature that contains the coordinate and zoom/pan to the extent of that feature. The feature could be in any of the 12 vector layers shown in the picture. If there is no feature that contains the coordinate in any of the layers, then the plugin will zoom/pan to the coordinate instead at some predetermined extent based on the variable 'scale'. I have included the code for the pan/zoom function for reference

            # Create new extent rectangle
        rect = QgsRectangle(
          float(Coordx) - scale,
          float(Coordy) - scale, 
          float(Coordx) + scale,
          float(Coordy) + scale)
        # Set the extent to our new rectangle
        # Refresh the map
  • I would recommend using a QgsFeatureRequest() in layer.getFeatures(). I'll post an answer later if you still need help. – Jesse McMillan Jan 15 '17 at 2:55
  • I would like a detailed answer since I have minimal coding experience and would like to implement the solution. Also note that the layers are not really Parcels1, Parcels2, etc, but have different names corresponding to the county they are in e.g. Fred, Alamaney, Duncan. I assume they need to be evaluated on an individual basis – Subgenius Jan 15 '17 at 3:21

I would iterate over a list of layers using a filter. This assumes everything is in the same CRS.

# create a rectangle to sort features by. Qgis will find overlapping features
# it's ok that xmin & xmax are the same and ymin & ymax are the same.
# typecast to float may be unnecessary 
filterRect = QgsRectangle(float(Coordx),float(Coordy),float(Coordx),float(Coordy))

projectRoot = QgsProject.instance().layerTreeRoot()
parcelGroup = projectRoot.findGroup("Parcels") # replace with actual group name

featFound = False

for lyr in parcelGroup.findLayers():
        # get feature iterator and select first one that overlaps
        featFound = lyr.layer().getFeatures(QgsFeatureRequest(filterRect)).next()

    except StopIteration:
        # if none do just move on

if featFound: # will still be false if no feature was found
    mapExtentRect = featFound.geometry().boundingBox()
    mapExtentRect = QgsRectangle(
        float(Coordx) - scale,
        float(Coordy) - scale, 
        float(Coordx) + scale,
        float(Coordy) + scale)

# Set the extent to our new rectangle
# Refresh the map

if for any reason you want to manually define a list of layers to search instead of using a group you can create a list of the layers by name:

searchLayers = ['layer1','layer2','layer3'...]
for layerName in searchLayers:
    layer = QgsMapLayerRegistry.instance().mapLayersByName( layerName )[0]
    # will return a list of layers matching name so select the first ([0])
  • new error featFound = lyr.getFeatures(QgsFeatureRequest(filterRect)).next() AttributeError: 'QgsLayerTreeLayer' object has no attribute 'getFeatures' – Subgenius Jan 15 '17 at 4:46
  • Oops typo. Mean lyr not layer. Fixed above – Jesse McMillan Jan 15 '17 at 4:47
  • Perhaps I should have mentioned that Coordx and Coordy are Qstrings: Had to change filterRect to filterRect = QgsRectangle( float(Coordx), float(Coordy), float(Coordx), float(Coordy)) edited my above comment with a new error --almost got this! – Subgenius Jan 15 '17 at 5:06
  • added fix. needed to use lyr.layer().getFeatures... to reference actual layer. my apologies. – Jesse McMillan Jan 15 '17 at 5:11
  • No worries, I appreciate the help. Got a new error now mapExtentRect = featFound.boundingBox() AttributeError: 'QgsFeature' object has no attribute 'boundingBox' – Subgenius Jan 15 '17 at 5:19

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.