mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-19 00:04:52 -04:00
Better clip for very separate features
This commit is contained in:
parent
71ebdb8f69
commit
d1aa03a09b
@ -60,40 +60,53 @@ class Clip(GeoAlgorithm):
|
|||||||
self.addOutput(OutputVector(Clip.OUTPUT, self.tr('Clipped')))
|
self.addOutput(OutputVector(Clip.OUTPUT, self.tr('Clipped')))
|
||||||
|
|
||||||
def processAlgorithm(self, progress):
|
def processAlgorithm(self, progress):
|
||||||
sourceLayer = dataobjects.getObjectFromUri(
|
source_layer = dataobjects.getObjectFromUri(
|
||||||
self.getParameterValue(Clip.INPUT))
|
self.getParameterValue(Clip.INPUT))
|
||||||
maskLayer = dataobjects.getObjectFromUri(
|
mask_layer = dataobjects.getObjectFromUri(
|
||||||
self.getParameterValue(Clip.OVERLAY))
|
self.getParameterValue(Clip.OVERLAY))
|
||||||
|
|
||||||
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
|
writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
|
||||||
sourceLayer.pendingFields(),
|
source_layer.fields(),
|
||||||
sourceLayer.dataProvider().geometryType(),
|
source_layer.dataProvider().geometryType(),
|
||||||
sourceLayer.dataProvider().crs())
|
source_layer.crs())
|
||||||
|
|
||||||
inFeatA = QgsFeature()
|
|
||||||
inFeatB = QgsFeature()
|
|
||||||
outFeat = QgsFeature()
|
|
||||||
|
|
||||||
# first build up a list of clip geometries
|
# first build up a list of clip geometries
|
||||||
clip_geoms = []
|
clip_geoms = []
|
||||||
for maskFeat in vector.features(maskLayer, QgsFeatureRequest().setSubsetOfAttributes([])):
|
for maskFeat in vector.features(mask_layer, QgsFeatureRequest().setSubsetOfAttributes([])):
|
||||||
clip_geoms.append(maskFeat.geometry())
|
clip_geoms.append(maskFeat.geometry())
|
||||||
|
|
||||||
|
# are we clipping against a single feature? if so, we can show finer progress reports
|
||||||
if len(clip_geoms) > 1:
|
if len(clip_geoms) > 1:
|
||||||
combined_clip_geom = QgsGeometry.unaryUnion(clip_geoms)
|
combined_clip_geom = QgsGeometry.unaryUnion(clip_geoms)
|
||||||
|
single_clip_feature = False
|
||||||
else:
|
else:
|
||||||
combined_clip_geom = clip_geoms[0]
|
combined_clip_geom = clip_geoms[0]
|
||||||
|
single_clip_feature = True
|
||||||
|
|
||||||
# use prepared geometries for faster insection tests
|
# use prepared geometries for faster intersection tests
|
||||||
engine = QgsGeometry.createGeometryEngine(combined_clip_geom.geometry())
|
engine = QgsGeometry.createGeometryEngine(combined_clip_geom.geometry())
|
||||||
engine.prepareGeometry()
|
engine.prepareGeometry()
|
||||||
|
|
||||||
input_features = [f for f in vector.features(sourceLayer, QgsFeatureRequest().setFilterRect(combined_clip_geom.boundingBox()))]
|
tested_feature_ids = set()
|
||||||
|
|
||||||
|
for i, clip_geom in enumerate(clip_geoms):
|
||||||
|
input_features = [f for f in vector.features(source_layer, QgsFeatureRequest().setFilterRect(clip_geom.boundingBox()))]
|
||||||
|
|
||||||
|
if single_clip_feature:
|
||||||
total = 100.0 / len(input_features)
|
total = 100.0 / len(input_features)
|
||||||
|
else:
|
||||||
|
total = 0
|
||||||
|
|
||||||
for current, in_feat in enumerate(input_features):
|
for current, in_feat in enumerate(input_features):
|
||||||
if not in_feat.geometry():
|
if not in_feat.geometry():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if in_feat.id() in tested_feature_ids:
|
||||||
|
# don't retest a feature we have already checked
|
||||||
|
continue
|
||||||
|
|
||||||
|
tested_feature_ids.add(in_feat.id())
|
||||||
|
|
||||||
if not engine.intersects(in_feat.geometry().geometry()):
|
if not engine.intersects(in_feat.geometry().geometry()):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -113,10 +126,10 @@ class Clip(GeoAlgorithm):
|
|||||||
new_geom = in_feat.geometry()
|
new_geom = in_feat.geometry()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
outFeat = QgsFeature()
|
out_feat = QgsFeature()
|
||||||
outFeat.setGeometry(new_geom)
|
out_feat.setGeometry(new_geom)
|
||||||
outFeat.setAttributes(in_feat.attributes())
|
out_feat.setAttributes(in_feat.attributes())
|
||||||
writer.addFeature(outFeat)
|
writer.addFeature(out_feat)
|
||||||
except:
|
except:
|
||||||
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
|
ProcessingLog.addToLog(ProcessingLog.LOG_ERROR,
|
||||||
self.tr('Feature geometry error: One or more '
|
self.tr('Feature geometry error: One or more '
|
||||||
@ -124,6 +137,11 @@ class Clip(GeoAlgorithm):
|
|||||||
'invalid geometry.'))
|
'invalid geometry.'))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if single_clip_feature:
|
||||||
progress.setPercentage(int(current * total))
|
progress.setPercentage(int(current * total))
|
||||||
|
|
||||||
|
if not single_clip_feature:
|
||||||
|
# coarse progress report for multiple clip geometries
|
||||||
|
progress.setPercentage(100.0 * i / len(clip_geoms))
|
||||||
|
|
||||||
del writer
|
del writer
|
||||||
|
Loading…
x
Reference in New Issue
Block a user