注意#1:我无法重现所建议的问题,因为差异工具在我执行的多个测试中对我来说效果很好(可能是由于问题的简单几何形状,或者因为问题被解决以来对此工具进行了改进1年前问)。
但是,我提出了一种在PyQGIS中的解决方法,以避免使用“ 差异”工具。一切都基于两个输入层之间的局部相交(请参见下图):
- 表示Voronoi多边形的多边形矢量层;
- 表示需要从分析中排除的孔/约束的多边形矢量层。
注意#2:由于我不想使用“ 差异”工具,因此无法避免创建“条子”(请参见后文),因此我需要运行该v.clean
工具以消除它们。此外,正如@Chris W所说,
[...]但是第二个产生细条并不是完全意外的-毕竟,即使存在孔,该区域仍将分配给同一点。您可以使用该方法,然后使用清理方法将这些条合并到它们的邻居中。
在这些必要前提之后,我发布了代码:
##Voronoi_Polygons=vector polygon
##Constraints=vector polygon
##Voronoi_Cleaned=output vector
from qgis.core import *
voronoi = processing.getObject(Voronoi_Polygons)
crs = voronoi.crs().toWkt()
ex = voronoi.extent()
extent = '%f,%f,%f,%f' % (ex.xMinimum(), ex.xMaximum(), ex.yMinimum(), ex.yMaximum())
constraints = processing.getObject(Constraints)
# Create the output layer
voronoi_mod = QgsVectorLayer('Polygon?crs='+ crs, 'voronoi' , 'memory')
prov = voronoi_mod.dataProvider()
fields = voronoi.pendingFields() # Fields from the input layer
prov.addAttributes(fields) # Add input layer fields to the outLayer
voronoi_mod.updateFields()
# Spatial index containing all the 'constraints'
index_builds = QgsSpatialIndex()
for feat in constraints.getFeatures():
index_builds.insertFeature(feat)
final_geoms = {}
final_attrs = {}
for feat in voronoi.getFeatures():
input_geom = feat.geometry()
input_attrs = feat.attributes()
final_geom = []
multi_geom = input_geom.asPolygon()
input_geoms = [] # edges of the input geometry
for k in multi_geom:
input_geoms.extend(k)
final_geom.append(input_geoms)
idsList = index_builds.intersects(input_geom.boundingBox())
mid_geom = [] # edges of the holes/constraints
if len(idsList) > 0:
req = QgsFeatureRequest().setFilterFids(idsList)
for ft in constraints.getFeatures(req):
geom = ft.geometry()
hole = []
res = geom.intersection(input_geom)
res_geom = res.asPolygon()
for i in res_geom:
hole.extend(i)
mid_geom.append(hole)
final_geom.extend(mid_geom)
final_geoms[feat.id()] = final_geom
final_attrs[feat.id()] = input_attrs
# Add the features to the output layer
outGeom = QgsFeature()
for key, value in final_geoms.iteritems():
outGeom.setGeometry(QgsGeometry.fromPolygon(value))
outGeom.setAttributes(final_attrs[key])
prov.addFeatures([outGeom])
# Add 'voronoi_mod' to the Layers panel
QgsMapLayerRegistry.instance().addMapLayer(voronoi_mod)
# Run 'v.clean'
processing.runalg("grass7:v.clean",voronoi_mod, 2, 0.1, extent, -1, 0.0001, Voronoi_Cleaned, None)
# Remove 'voronoi_mod' to the Layers panel
QgsMapLayerRegistry.instance().removeMapLayer(voronoi_mod)
结果如下:
只是为了清楚起见,这是不使用该v.clean
工具的结果:
@LeaningCactus结果的不同之处在于,到现在为止,几何图形还没有损坏,可以无错误地“清理”它们。