简体   繁体   English

Function “消除选定的多边形”不适用于 PyQGIS

[英]Function “eliminate selected polygons” doesn't work with PyQGIS

I have a vector layer (correction) based on a raster layer.我有一个基于光栅层的矢量图层(校正)。 It contains some little features and I want to merge those features to bigger ones.它包含一些小功能,我想将这些功能合并到更大的功能。 The function "eliminate selected polygons" seems to do the trick when used in QGIS but when I used it in pyQGIS the selected features aren't taken into account. function “消除选定的多边形”在 QGIS 中使用时似乎可以解决问题,但是当我在 pyQGIS 中使用它时,没有考虑到选定的功能。

This is my layer with the selection这是我的选择层

This is the expected output, the one from QGIS这是预期的 output,来自 QGIS

This is my actual output, the one from pyQGIS这是我的实际 output,来自 pyQGIS

When I run my code the function doesn't trigger the CRITICAL error.当我运行我的代码时,function 不会触发 CRITICAL 错误。 The first log is my code and the second is the process without any polygon selection.第一个日志是我的代码,第二个是没有任何多边形选择的过程。

Does anyone already have this issue?有人已经有这个问题了吗? Is it possible to use another similar function?是否可以使用另一个类似的 function? Thanks in advance提前致谢

QGIS Version: 3.14 (pi) QGIS 版本:3.14 (pi)

OS: Linux Mint 20 Ulyana (Ubuntu focal 20.04)操作系统:Linux Mint 20 Ulyana(Ubuntu 焦点 20.04)

This is my code:这是我的代码:

chemin_sortie = "/projet_qgis/pente/donnees_traitement/"
#Input   
correction = chemin_sortie + 'correction' + '.shp'
correction_layer = iface.addVectorLayer(correction, '', 'ogr')
#Output 
pente_vecteur_grand = chemin_sortie + 'pente_vecteur_grand' + '.shp'

#Selection and process
correction_layer.selectByExpression('$area < 500')  
processing.run("qgis:eliminateselectedpolygons", {'INPUT':correction_layer,'MODE':2,'OUTPUT':pente_vecteur_grand})
pente_vecteur_grand_layer = iface.addVectorLayer(pente_vecteur_grand, '', 'ogr')

I made a function to realize the same operation as qgis:eliminateselectedpolygons.我做了一个 function 来实现和 qgis:eliminateselectedpolygons 一样的操作。 There is still some differences, I think it's related to the order of the polygons to merge.仍然存在一些差异,我认为这与要合并的多边形的顺序有关。 This function is optimizable but works for me.这个 function 是可优化的,但对我有用。

This is my layer with the selection这是我的选择层

This is the output with the qgis function with min area这是带有最小面积的 qgis function 的 output

This is the output of the pyqgis function with min area这是 pyqgis function 的 output 最小面积

This is the output with the qgis function with max area这是带有最大面积的 qgis function 的 output

This is the output of the pyqgis function with max area这是 pyqgis function 的 output,最大面积

This is the code:这是代码:

import types
    
chemin_sortie = "/projet_qgis/pente/donnees_traitement/"
    
# Input   
    correction = chemin_sortie + 'correction' + '.shp'
    correction_layer = iface.addVectorLayer(correction, '', 'ogr')
    
# Selection
    correction_layer.selectByExpression('$area < 500')

# Functions
def get_key(dict, val):
    for key, value in dict.items():
         if val == value:
             return key
def eliminateselectedpolygon(layer, param):
    if isinstance(param, types.BuiltinFunctionType):
        features = layer.getFeatures()
        n=0
        index = QgsSpatialIndex()
        allfeatures = {}
        selectedfeatures = {}

        for f in features:
            value=[]
            n = n+1
            geom = f.geometry()
            aire = geom.area()
            aire = '%.5f' % aire
            aire = float(aire)
            value.append(f)
            value.append(aire)
            allfeatures[f.id()]=value
            index.addFeature(f)
        for f in layer.selectedFeatures():
            selectedfeatures[f.id()]=f.id()
        suppression = []

        while len(selectedfeatures) != 0:
            f_id = min(selectedfeatures.values())
            f = allfeatures[f_id]
            f_geom = f[0]
            ids = index.intersects(f_geom.geometry().boundingBox())
            dict_aire = {}
            for a_id in ids:
                if a_id != f_id and allfeatures[a_id][0].geometry().touches(f_geom.geometry()) and QgsWkbTypes.displayString(int(allfeatures[a_id][0].geometry().intersection(f_geom.geometry()).wkbType())) != "Point" :
                    dict_aire[a_id]=allfeatures[a_id][1]
            a_id = get_key(dict_aire, param(dict_aire.values()))
            a = allfeatures[a_id]
            a_geom = a[0]
            attrs = layer.getFeature(a_id).attributes()
            suppression.append(f_id)
            suppression.append(a_id)
            if a_id in selectedfeatures:
                del selectedfeatures[a_id]
            del allfeatures[a_id]
            index.deleteFeature(a_geom)
            layer.startEditing()
            geom = None
            geom = QgsGeometry.fromWkt('GEOMETRYCOLLECTION()')
            geom = geom.combine(f_geom.geometry())
            geom = geom.combine(a_geom.geometry())
            feat = QgsFeature(layer.fields())
            feat.setGeometry(geom)
            feat.setAttributes(attrs)
            layer.addFeature(feat)
            feat.setId(abs(n))
            layer.commitChanges()
            layer.triggerRepaint()
            value_feat = []
            geom = feat.geometry()
            aire = geom.area()
            aire = '%.5f' % aire
            aire = float(aire)
            value_feat.append(feat)
            value_feat.append(aire)
            allfeatures[feat.id()]=value_feat
            index.addFeature(feat)
            del selectedfeatures[f_id]
            del allfeatures[f_id]
            index.deleteFeature(f_geom)
            n = n + 1
        layer.startEditing()
        for feature in suppression:
            res = layer.deleteFeature(feature)
        layer.commitChanges()
        layer.triggerRepaint()
        return layer
    print("Param should be min or max")
    return None

eliminateselectedpolygon(correction_layer, max)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM