mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-11-04 00:04:25 -05:00 
			
		
		
		
	[processing] Optimise feature requests within qgis algs
- don't use setFilterFid() within loops to fetch features one at time (as it's extremely slow), instead use setFilterFids() outside the loop - don't fetch unused attributes/geometry when it can be avoided
This commit is contained in:
		
							parent
							
								
									55f207108d
								
							
						
					
					
						commit
						86368f39c3
					
				@ -85,9 +85,9 @@ class Difference(GeoAlgorithm):
 | 
			
		||||
            diff_geom = QgsGeometry(geom)
 | 
			
		||||
            attrs = inFeatA.attributes()
 | 
			
		||||
            intersections = index.intersects(geom.boundingBox())
 | 
			
		||||
            for i in intersections:
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFid(i)
 | 
			
		||||
                inFeatB = next(layerB.getFeatures(request))
 | 
			
		||||
 | 
			
		||||
            request = QgsFeatureRequest().setFilterFids(intersections).setSubsetOfAttributes([])
 | 
			
		||||
            for inFeatB in layerB.getFeatures(request):
 | 
			
		||||
                tmpGeom = inFeatB.geometry()
 | 
			
		||||
                if diff_geom.intersects(tmpGeom):
 | 
			
		||||
                    diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))
 | 
			
		||||
 | 
			
		||||
@ -246,7 +246,7 @@ class Eliminate(GeoAlgorithm):
 | 
			
		||||
                geom2Eliminate = feat.geometry()
 | 
			
		||||
                bbox = geom2Eliminate.boundingBox()
 | 
			
		||||
                fit = processLayer.getFeatures(
 | 
			
		||||
                    QgsFeatureRequest().setFilterRect(bbox))
 | 
			
		||||
                    QgsFeatureRequest().setFilterRect(bbox).setSubsetOfAttributes([]))
 | 
			
		||||
                mergeWithFid = None
 | 
			
		||||
                mergeWithGeom = None
 | 
			
		||||
                max = 0
 | 
			
		||||
 | 
			
		||||
@ -84,9 +84,8 @@ class ExtractByLocation(GeoAlgorithm):
 | 
			
		||||
            geom = vector.snapToPrecision(f.geometry(), precision)
 | 
			
		||||
            bbox = vector.bufferedBoundingBox(geom.boundingBox(), 0.51 * precision)
 | 
			
		||||
            intersects = index.intersects(bbox)
 | 
			
		||||
            for i in intersects:
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFid(i)
 | 
			
		||||
                feat = next(layer.getFeatures(request))
 | 
			
		||||
            request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
 | 
			
		||||
            for feat in layer.getFeatures(request):
 | 
			
		||||
                tmpGeom = vector.snapToPrecision(feat.geometry(), precision)
 | 
			
		||||
                res = False
 | 
			
		||||
                for predicate in predicates:
 | 
			
		||||
 | 
			
		||||
@ -109,7 +109,7 @@ class HubDistanceLines(GeoAlgorithm):
 | 
			
		||||
            src = f.geometry().boundingBox().center()
 | 
			
		||||
 | 
			
		||||
            neighbors = index.nearestNeighbor(src, 1)
 | 
			
		||||
            ft = next(layerHubs.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0])))
 | 
			
		||||
            ft = next(layerHubs.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], layerHubs.fields())))
 | 
			
		||||
            closest = ft.geometry().boundingBox().center()
 | 
			
		||||
            hubDist = distance.measureLine(src, closest)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -109,7 +109,7 @@ class HubDistancePoints(GeoAlgorithm):
 | 
			
		||||
            src = f.geometry().boundingBox().center()
 | 
			
		||||
 | 
			
		||||
            neighbors = index.nearestNeighbor(src, 1)
 | 
			
		||||
            ft = next(layerHubs.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0])))
 | 
			
		||||
            ft = next(layerHubs.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], layerHubs.fields())))
 | 
			
		||||
            closest = ft.geometry().boundingBox().center()
 | 
			
		||||
            hubDist = distance.measureLine(src, closest)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -88,9 +88,8 @@ class Intersection(GeoAlgorithm):
 | 
			
		||||
            geom = inFeatA.geometry()
 | 
			
		||||
            atMapA = inFeatA.attributes()
 | 
			
		||||
            intersects = index.intersects(geom.boundingBox())
 | 
			
		||||
            for i in intersects:
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFid(i)
 | 
			
		||||
                inFeatB = next(vlayerB.getFeatures(request))
 | 
			
		||||
            request = QgsFeatureRequest().setFilterFids(intersects)
 | 
			
		||||
            for inFeatB in vlayerB.getFeatures(request):
 | 
			
		||||
                tmpGeom = inFeatB.geometry()
 | 
			
		||||
                if geom.intersects(tmpGeom):
 | 
			
		||||
                    atMapB = inFeatB.attributes()
 | 
			
		||||
 | 
			
		||||
@ -105,9 +105,8 @@ class LinesIntersection(GeoAlgorithm):
 | 
			
		||||
                hasIntersections = True
 | 
			
		||||
 | 
			
		||||
            if hasIntersections:
 | 
			
		||||
                for i in lines:
 | 
			
		||||
                    request = QgsFeatureRequest().setFilterFid(i)
 | 
			
		||||
                    inFeatB = next(layerB.getFeatures(request))
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFids(lines)
 | 
			
		||||
                for inFeatB in layerB.getFeatures(request):
 | 
			
		||||
                    tmpGeom = inFeatB.geometry()
 | 
			
		||||
 | 
			
		||||
                    points = []
 | 
			
		||||
 | 
			
		||||
@ -95,7 +95,7 @@ class NearestNeighbourAnalysis(GeoAlgorithm):
 | 
			
		||||
        for current, feat in enumerate(features):
 | 
			
		||||
            neighbourID = spatialIndex.nearestNeighbor(
 | 
			
		||||
                feat.geometry().asPoint(), 2)[1]
 | 
			
		||||
            request = QgsFeatureRequest().setFilterFid(neighbourID)
 | 
			
		||||
            request = QgsFeatureRequest().setFilterFid(neighbourID).setSubsetOfAttributes([])
 | 
			
		||||
            neighbour = next(layer.getFeatures(request))
 | 
			
		||||
            sumDist += distance.measureLine(neighbour.geometry().asPoint(),
 | 
			
		||||
                                            feat.geometry().asPoint())
 | 
			
		||||
 | 
			
		||||
@ -136,9 +136,8 @@ class PointDistance(GeoAlgorithm):
 | 
			
		||||
            featList = index.nearestNeighbor(inGeom.asPoint(), nPoints)
 | 
			
		||||
            distList = []
 | 
			
		||||
            vari = 0.0
 | 
			
		||||
            for i in featList:
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFid(i)
 | 
			
		||||
                outFeat = next(targetLayer.getFeatures(request))
 | 
			
		||||
            request = QgsFeatureRequest().setFilterFids(featList).setSubsetOfAttributes([outIdx])
 | 
			
		||||
            for outFeat in targetLayer.getFeatures(request):
 | 
			
		||||
                outID = outFeat.attributes()[outIdx]
 | 
			
		||||
                outGeom = outFeat.geometry()
 | 
			
		||||
                dist = distArea.measureLine(inGeom.asPoint(),
 | 
			
		||||
 | 
			
		||||
@ -86,11 +86,10 @@ class PointsDisplacement(GeoAlgorithm):
 | 
			
		||||
 | 
			
		||||
        fullPerimeter = 2 * math.pi
 | 
			
		||||
 | 
			
		||||
        request = QgsFeatureRequest()
 | 
			
		||||
        for (geom, fids) in list(duplicates.items()):
 | 
			
		||||
            count = len(fids)
 | 
			
		||||
            if count == 1:
 | 
			
		||||
                f = next(layer.getFeatures(request.setFilterFid(fids[0])))
 | 
			
		||||
                f = next(layer.getFeatures(QgsFeatureRequest().setFilterFid(fids[0])))
 | 
			
		||||
                writer.addFeature(f)
 | 
			
		||||
            else:
 | 
			
		||||
                angleStep = fullPerimeter / count
 | 
			
		||||
@ -100,14 +99,14 @@ class PointsDisplacement(GeoAlgorithm):
 | 
			
		||||
                    currentAngle = 0
 | 
			
		||||
 | 
			
		||||
                old_point = QgsGeometry.fromWkt(geom).asPoint()
 | 
			
		||||
                for fid in fids:
 | 
			
		||||
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFids(fids).setFlags(QgsFeatureRequest.NoGeometry)
 | 
			
		||||
                for f in layer.getFeatures(request):
 | 
			
		||||
                    sinusCurrentAngle = math.sin(currentAngle)
 | 
			
		||||
                    cosinusCurrentAngle = math.cos(currentAngle)
 | 
			
		||||
                    dx = radius * sinusCurrentAngle
 | 
			
		||||
                    dy = radius * cosinusCurrentAngle
 | 
			
		||||
 | 
			
		||||
                    f = next(layer.getFeatures(request.setFilterFid(fid)))
 | 
			
		||||
 | 
			
		||||
                    new_point = QgsPoint(old_point.x() + dx, old_point.y()
 | 
			
		||||
                                         + dy)
 | 
			
		||||
                    out_feature = QgsFeature()
 | 
			
		||||
 | 
			
		||||
@ -96,7 +96,7 @@ class PointsInPolygon(GeoAlgorithm):
 | 
			
		||||
            count = 0
 | 
			
		||||
            points = spatialIndex.intersects(geom.boundingBox())
 | 
			
		||||
            if len(points) > 0:
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFids(points)
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFids(points).setSubsetOfAttributes([])
 | 
			
		||||
                fit = pointLayer.getFeatures(request)
 | 
			
		||||
                ftPoint = QgsFeature()
 | 
			
		||||
                while fit.nextFeature(ftPoint):
 | 
			
		||||
 | 
			
		||||
@ -90,7 +90,7 @@ class PointsInPolygonUnique(GeoAlgorithm):
 | 
			
		||||
            classes = set()
 | 
			
		||||
            points = spatialIndex.intersects(geom.boundingBox())
 | 
			
		||||
            if len(points) > 0:
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFids(points)
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFids(points).setSubsetOfAttributes([classFieldIndex])
 | 
			
		||||
                fit = pointLayer.getFeatures(request)
 | 
			
		||||
                ftPoint = QgsFeature()
 | 
			
		||||
                while fit.nextFeature(ftPoint):
 | 
			
		||||
 | 
			
		||||
@ -98,7 +98,7 @@ class PointsInPolygonWeighted(GeoAlgorithm):
 | 
			
		||||
            points = spatialIndex.intersects(geom.boundingBox())
 | 
			
		||||
            if len(points) > 0:
 | 
			
		||||
                progress.setText(str(len(points)))
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFids(points)
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFids(points).setSubsetOfAttributes([fieldIdx])
 | 
			
		||||
                fit = pointLayer.getFeatures(request)
 | 
			
		||||
                ftPoint = QgsFeature()
 | 
			
		||||
                while fit.nextFeature(ftPoint):
 | 
			
		||||
 | 
			
		||||
@ -88,7 +88,7 @@ class RandomPointsAlongLines(GeoAlgorithm):
 | 
			
		||||
        while nIterations < maxIterations and nPoints < pointCount:
 | 
			
		||||
            # pick random feature
 | 
			
		||||
            fid = random.randint(0, featureCount - 1)
 | 
			
		||||
            f = next(layer.getFeatures(request.setFilterFid(fid)))
 | 
			
		||||
            f = next(layer.getFeatures(request.setFilterFid(fid).setSubsetOfAttributes([])))
 | 
			
		||||
            fGeom = f.geometry()
 | 
			
		||||
 | 
			
		||||
            if fGeom.isMultipart():
 | 
			
		||||
 | 
			
		||||
@ -88,8 +88,6 @@ class RandomPointsLayer(GeoAlgorithm):
 | 
			
		||||
        index = QgsSpatialIndex()
 | 
			
		||||
        points = dict()
 | 
			
		||||
 | 
			
		||||
        request = QgsFeatureRequest()
 | 
			
		||||
 | 
			
		||||
        random.seed()
 | 
			
		||||
 | 
			
		||||
        while nIterations < maxIterations and nPoints < pointCount:
 | 
			
		||||
@ -101,8 +99,8 @@ class RandomPointsLayer(GeoAlgorithm):
 | 
			
		||||
            ids = idxLayer.intersects(geom.buffer(5, 5).boundingBox())
 | 
			
		||||
            if len(ids) > 0 and \
 | 
			
		||||
                    vector.checkMinDistance(pnt, index, minDistance, points):
 | 
			
		||||
                for i in ids:
 | 
			
		||||
                    f = next(layer.getFeatures(request.setFilterFid(i)))
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFids(ids).setSubsetOfAttributes([])
 | 
			
		||||
                for f in layer.getFeatures(request):
 | 
			
		||||
                    tmpGeom = f.geometry()
 | 
			
		||||
                    if geom.within(tmpGeom):
 | 
			
		||||
                        f = QgsFeature(nPoints)
 | 
			
		||||
 | 
			
		||||
@ -111,7 +111,7 @@ class SelectByAttribute(GeoAlgorithm):
 | 
			
		||||
 | 
			
		||||
        qExp = QgsExpression(expr)
 | 
			
		||||
        if not qExp.hasParserError():
 | 
			
		||||
            qReq = QgsFeatureRequest(qExp)
 | 
			
		||||
            qReq = QgsFeatureRequest(qExp).setSubsetOfAttributes([])
 | 
			
		||||
        else:
 | 
			
		||||
            raise GeoAlgorithmExecutionException(qExp.parserErrorString())
 | 
			
		||||
        selected = [f.id() for f in layer.getFeatures(qReq)]
 | 
			
		||||
 | 
			
		||||
@ -82,8 +82,8 @@ class SelectByAttributeSum(GeoAlgorithm):
 | 
			
		||||
                progress.setInfo(self.tr('No adjacent features found.'))
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
            for i in intersected:
 | 
			
		||||
                ft = next(layer.getFeatures(req.setFilterFid(i)))
 | 
			
		||||
            req = QgsFeatureRequest().setFilterFids(intersected).setSubsetOfAttributes([fieldName], layer.fields())
 | 
			
		||||
            for ft in layer.getFeatures(req):
 | 
			
		||||
                tmpGeom = ft.geometry()
 | 
			
		||||
                if tmpGeom.touches(geom):
 | 
			
		||||
                    geom = tmpGeom.combine(geom)
 | 
			
		||||
 | 
			
		||||
@ -105,9 +105,8 @@ class SelectByLocation(GeoAlgorithm):
 | 
			
		||||
            bbox = vector.bufferedBoundingBox(geom.boundingBox(), 0.51 * precision)
 | 
			
		||||
            intersects = index.intersects(bbox)
 | 
			
		||||
 | 
			
		||||
            for i in intersects:
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFid(i)
 | 
			
		||||
                feat = next(inputLayer.getFeatures(request))
 | 
			
		||||
            request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
 | 
			
		||||
            for feat in inputLayer.getFeatures(request):
 | 
			
		||||
                tmpGeom = vector.snapToPrecision(feat.geometry(), precision)
 | 
			
		||||
 | 
			
		||||
                res = False
 | 
			
		||||
 | 
			
		||||
@ -79,9 +79,8 @@ class SplitLinesWithLines(GeoAlgorithm):
 | 
			
		||||
            if len(lines) > 0:  # hasIntersections
 | 
			
		||||
                splittingLines = []
 | 
			
		||||
 | 
			
		||||
                for i in lines:
 | 
			
		||||
                    request = QgsFeatureRequest().setFilterFid(i)
 | 
			
		||||
                    inFeatB = next(layerB.getFeatures(request))
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFids(lines).setSubsetOfAttributes([])
 | 
			
		||||
                for inFeatB in layerB.getFeatures(request):
 | 
			
		||||
                    # check if trying to self-intersect
 | 
			
		||||
                    if sameLayer:
 | 
			
		||||
                        if inFeatA.id() == inFeatB.id():
 | 
			
		||||
 | 
			
		||||
@ -104,9 +104,8 @@ class SumLines(GeoAlgorithm):
 | 
			
		||||
                hasIntersections = True
 | 
			
		||||
 | 
			
		||||
            if hasIntersections:
 | 
			
		||||
                for i in lines:
 | 
			
		||||
                    request = QgsFeatureRequest().setFilterFid(i)
 | 
			
		||||
                    ftLine = next(lineLayer.getFeatures(request))
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFids(lines).setSubsetOfAttributes([])
 | 
			
		||||
                for ftLine in lineLayer.getFeatures(request):
 | 
			
		||||
                    tmpGeom = ftLine.geometry()
 | 
			
		||||
                    if inGeom.intersects(tmpGeom):
 | 
			
		||||
                        outGeom = inGeom.intersection(tmpGeom)
 | 
			
		||||
 | 
			
		||||
@ -88,8 +88,8 @@ class SymmetricalDifference(GeoAlgorithm):
 | 
			
		||||
            diffGeom = QgsGeometry(geom)
 | 
			
		||||
            attrs = featA.attributes()
 | 
			
		||||
            intersects = indexA.intersects(geom.boundingBox())
 | 
			
		||||
            for i in intersects:
 | 
			
		||||
                layerB.getFeatures(QgsFeatureRequest().setFilterFid(i)).nextFeature(featB)
 | 
			
		||||
            request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
 | 
			
		||||
            for featB in layerB.getFeatures(request):
 | 
			
		||||
                tmpGeom = featB.geometry()
 | 
			
		||||
                if diffGeom.intersects(tmpGeom):
 | 
			
		||||
                    diffGeom = QgsGeometry(diffGeom.difference(tmpGeom))
 | 
			
		||||
@ -123,8 +123,8 @@ class SymmetricalDifference(GeoAlgorithm):
 | 
			
		||||
            attrs = featA.attributes()
 | 
			
		||||
            attrs = [NULL] * length + attrs
 | 
			
		||||
            intersects = indexB.intersects(geom.boundingBox())
 | 
			
		||||
            for i in intersects:
 | 
			
		||||
                layerA.getFeatures(QgsFeatureRequest().setFilterFid(i)).nextFeature(featB)
 | 
			
		||||
            request = QgsFeatureRequest().setFilterFids(intersects).setSubsetOfAttributes([])
 | 
			
		||||
            for featB in layerA.getFeatures(request):
 | 
			
		||||
                tmpGeom = featB.geometry()
 | 
			
		||||
                if diffGeom.intersects(tmpGeom):
 | 
			
		||||
                    diffGeom = QgsGeometry(diffGeom.difference(tmpGeom))
 | 
			
		||||
 | 
			
		||||
@ -105,10 +105,10 @@ class Union(GeoAlgorithm):
 | 
			
		||||
                    ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
 | 
			
		||||
                                           self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
 | 
			
		||||
            else:
 | 
			
		||||
                for id in intersects:
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFids(intersects)
 | 
			
		||||
                for inFeatB in vlayerB.getFeatures(request):
 | 
			
		||||
                    count += 1
 | 
			
		||||
                    request = QgsFeatureRequest().setFilterFid(id)
 | 
			
		||||
                    inFeatB = next(vlayerB.getFeatures(request))
 | 
			
		||||
 | 
			
		||||
                    atMapB = inFeatB.attributes()
 | 
			
		||||
                    tmpGeom = inFeatB.geometry()
 | 
			
		||||
 | 
			
		||||
@ -197,9 +197,8 @@ class Union(GeoAlgorithm):
 | 
			
		||||
                    ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
 | 
			
		||||
                                           self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'))
 | 
			
		||||
            else:
 | 
			
		||||
                for id in intersects:
 | 
			
		||||
                    request = QgsFeatureRequest().setFilterFid(id)
 | 
			
		||||
                    inFeatB = next(vlayerA.getFeatures(request))
 | 
			
		||||
                request = QgsFeatureRequest().setFilterFids(intersects)
 | 
			
		||||
                for inFeatB in vlayerA.getFeatures(request):
 | 
			
		||||
                    atMapB = inFeatB.attributes()
 | 
			
		||||
                    tmpGeom = inFeatB.geometry()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user