3

I'm trying to find features (polygons) that intersect a QgsRectangle but are not equal to themselves. In the image below, I have a bounding box around a feature. I'd like to see what other polygons intersect that bounding box. This is the part I'm stuck on. If features are found (usually two but maybe more or less), I'd like to create a convex hull of all those features.

My code of what I have thus far is below.

enter image description here

layer = iface.activeLayer()
features = layer.getFeatures()

feat = QgsFeature()
ok = features.nextFeature(feat)

p1 = None
p2 = None

while ok:
    p1 = feat.geometry()
    print('p1 is --')
    print(p1)
    rect = p1.boundingBox()
    search_area = QgsRectangle(
        rect.xMinimum() - 1,
        rect.yMinimum() - 1,
        rect.xMaximum() + 1,
        rect.yMaximum() + 1)
    print(p1.intersects(search_area))
    ok = features.nextFeature(feat)

Update: So Im trying to achieve the following - only create a convex hull of what the rectangle intersects with.

enter image description here

From @BERA excellent piece of work, I get the following back which is close but not exactly what I want:

enter image description here

2 Answers 2

5

List all intersecting polygons, union them and convex hull:

layer = iface.activeLayer()
all_features = [f for f in layer.getFeatures()] #Create a list of all features

for f in all_features:
    current_id = f.id()
    print(f"Processing polygon: {current_id}")
    rect = f.geometry().boundingBox()
    search_area = QgsRectangle(
        rect.xMinimum() - 10000,
        rect.yMinimum() - 10000,
        rect.xMaximum() + 10000,
        rect.yMaximum() + 10000)
    
    other_features = [x.geometry() for x in all_features if current_id!=x.id() and x.geometry().intersects(search_area)] #If they dont have the same id, but intersect, list them
    hull = QgsGeometry.unaryUnion(other_features).convexHull()

enter image description here

4
  • Kind of correct - It should only create a convex hull of what it intersects with. See extra added image above in original question Commented Nov 3, 2022 at 11:36
  • That is what it is doing. It has convex hulled 67, 259,252,253,254,70,66 which are intersecting 0:s bounding box+10000 m
    – Bera
    Commented Nov 3, 2022 at 11:37
  • Yep, I did that. I've updated it to this and it seems to work. see answer. Thanks a million for all your help - huge help Commented Nov 3, 2022 at 12:14
  • Last problem - how do I get it to only check polygons once? If a intersects b, then there is no need to check if b intersects a.Thanks Commented Nov 3, 2022 at 13:24
1

This seems to work perfectly.

layer = iface.activeLayer()
features = layer.getFeatures()

feat = QgsFeature()
ok = features.nextFeature(feat)
all_features = [f for f in layer.getFeatures()]

vl = QgsVectorLayer("Polygon?crs={}&index=yes".format(layer.crs().authid()), "HULL", "memory")
provider = vl.dataProvider()
f = QgsFeature()

while ok:
    polygon = feat.geometry()
    current_id = feat.id()
    rect = polygon.boundingBox()
    search_area = QgsRectangle(
        rect.xMinimum() - 1,
        rect.yMinimum() - 1,
        rect.xMaximum() + 1,
        rect.yMaximum() + 1)
    other_features = [x for x in all_features if current_id!=x.id() and x.geometry().intersects(search_area)] #If they dont have the same id, but intersect
    geoms = [polygon] + [x.geometry() for x in other_features]
    hull = QgsGeometry.unaryUnion(geoms).convexHull()
    f.setGeometry(hull)
    provider.addFeature(f)
    ok = features.nextFeature(feat)
  
QgsProject.instance().addMapLayer(vl)
 

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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