mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-11-04 00:04:25 -05:00 
			
		
		
		
	[processing] restore intersection algorithm (#4849)
This commit is contained in:
		
							parent
							
								
									93a8025bb2
								
							
						
					
					
						commit
						d3ad9131f4
					
				@ -34,13 +34,13 @@ from qgis.core import (QgsFeatureRequest,
 | 
			
		||||
                       QgsFeatureSink,
 | 
			
		||||
                       QgsGeometry,
 | 
			
		||||
                       QgsWkbTypes,
 | 
			
		||||
                       QgsMessageLog,
 | 
			
		||||
                       QgsProcessingParameterFeatureSource,
 | 
			
		||||
                       QgsProcessingParameterFeatureSink,
 | 
			
		||||
                       QgsSpatialIndex,
 | 
			
		||||
                       QgsProcessingUtils)
 | 
			
		||||
 | 
			
		||||
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
 | 
			
		||||
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
 | 
			
		||||
from processing.core.parameters import ParameterVector
 | 
			
		||||
from processing.core.outputs import OutputVector
 | 
			
		||||
from processing.tools import vector
 | 
			
		||||
 | 
			
		||||
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
 | 
			
		||||
@ -58,7 +58,7 @@ for key, value in list(wkbTypeGroups.items()):
 | 
			
		||||
class Intersection(QgisAlgorithm):
 | 
			
		||||
 | 
			
		||||
    INPUT = 'INPUT'
 | 
			
		||||
    INPUT2 = 'INPUT2'
 | 
			
		||||
    OVERLAY = 'OVERLAY'
 | 
			
		||||
    OUTPUT = 'OUTPUT'
 | 
			
		||||
 | 
			
		||||
    def icon(self):
 | 
			
		||||
@ -71,11 +71,12 @@ class Intersection(QgisAlgorithm):
 | 
			
		||||
        super().__init__()
 | 
			
		||||
 | 
			
		||||
    def initAlgorithm(self, config=None):
 | 
			
		||||
        self.addParameter(ParameterVector(self.INPUT,
 | 
			
		||||
                                          self.tr('Input layer')))
 | 
			
		||||
        self.addParameter(ParameterVector(self.INPUT2,
 | 
			
		||||
                                          self.tr('Intersect layer')))
 | 
			
		||||
        self.addOutput(OutputVector(self.OUTPUT, self.tr('Intersection')))
 | 
			
		||||
        self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
 | 
			
		||||
                                                              self.tr('Input layer')))
 | 
			
		||||
        self.addParameter(QgsProcessingParameterFeatureSource(self.OVERLAY,
 | 
			
		||||
                                                              self.tr('Intersection layer')))
 | 
			
		||||
 | 
			
		||||
        self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Intersection')))
 | 
			
		||||
 | 
			
		||||
    def name(self):
 | 
			
		||||
        return 'intersection'
 | 
			
		||||
@ -84,22 +85,31 @@ class Intersection(QgisAlgorithm):
 | 
			
		||||
        return self.tr('Intersection')
 | 
			
		||||
 | 
			
		||||
    def processAlgorithm(self, parameters, context, feedback):
 | 
			
		||||
        vlayerA = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
 | 
			
		||||
        vlayerB = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT2), context)
 | 
			
		||||
        sourceA = self.parameterAsSource(parameters, self.INPUT, context)
 | 
			
		||||
        sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)
 | 
			
		||||
 | 
			
		||||
        geomType = QgsWkbTypes.multiType(sourceA.wkbType())
 | 
			
		||||
        fields = vector.combineFields(sourceA.fields(), sourceB.fields())
 | 
			
		||||
 | 
			
		||||
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
 | 
			
		||||
                                               fields, geomType, sourceA.sourceCrs())
 | 
			
		||||
 | 
			
		||||
        geomType = QgsWkbTypes.multiType(vlayerA.wkbType())
 | 
			
		||||
        fields = vector.combineVectorFields(vlayerA, vlayerB)
 | 
			
		||||
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, geomType, vlayerA.crs(), context)
 | 
			
		||||
        outFeat = QgsFeature()
 | 
			
		||||
        index = QgsProcessingUtils.createSpatialIndex(vlayerB, context)
 | 
			
		||||
        selectionA = QgsProcessingUtils.getFeatures(vlayerA, context)
 | 
			
		||||
        total = 100.0 / vlayerA.featureCount() if vlayerA.featureCount() else 0
 | 
			
		||||
        for current, inFeatA in enumerate(selectionA):
 | 
			
		||||
            feedback.setProgress(int(current * total))
 | 
			
		||||
            geom = inFeatA.geometry()
 | 
			
		||||
            atMapA = inFeatA.attributes()
 | 
			
		||||
            intersects = index.intersects(geom.boundingBox())
 | 
			
		||||
        indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())))
 | 
			
		||||
 | 
			
		||||
        total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1
 | 
			
		||||
        count = 0
 | 
			
		||||
 | 
			
		||||
        for featA in sourceA.getFeatures():
 | 
			
		||||
            if feedback.isCanceled():
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
            geom = featA.geometry()
 | 
			
		||||
            atMapA = featA.attributes()
 | 
			
		||||
            intersects = indexB.intersects(geom.boundingBox())
 | 
			
		||||
 | 
			
		||||
            request = QgsFeatureRequest().setFilterFids(intersects)
 | 
			
		||||
            request.setDestinationCrs(sourceA.sourceCrs())
 | 
			
		||||
 | 
			
		||||
            engine = None
 | 
			
		||||
            if len(intersects) > 0:
 | 
			
		||||
@ -107,10 +117,13 @@ class Intersection(QgisAlgorithm):
 | 
			
		||||
                engine = QgsGeometry.createGeometryEngine(geom.geometry())
 | 
			
		||||
                engine.prepareGeometry()
 | 
			
		||||
 | 
			
		||||
            for inFeatB in vlayerB.getFeatures(request):
 | 
			
		||||
                tmpGeom = inFeatB.geometry()
 | 
			
		||||
            for featB in sourceB.getFeatures(request):
 | 
			
		||||
                if feedback.isCanceled():
 | 
			
		||||
                    break
 | 
			
		||||
 | 
			
		||||
                tmpGeom = featB.geometry()
 | 
			
		||||
                if engine.intersects(tmpGeom.geometry()):
 | 
			
		||||
                    atMapB = inFeatB.attributes()
 | 
			
		||||
                    atMapB = featB.attributes()
 | 
			
		||||
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
 | 
			
		||||
                    if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
 | 
			
		||||
                        int_com = geom.combine(tmpGeom)
 | 
			
		||||
@ -130,11 +143,14 @@ class Intersection(QgisAlgorithm):
 | 
			
		||||
                            attrs.extend(atMapA)
 | 
			
		||||
                            attrs.extend(atMapB)
 | 
			
		||||
                            outFeat.setAttributes(attrs)
 | 
			
		||||
                            writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
 | 
			
		||||
                            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
 | 
			
		||||
                    except:
 | 
			
		||||
                        raise GeoAlgorithmExecutionException(
 | 
			
		||||
                            self.tr('Feature geometry error: One or more '
 | 
			
		||||
                                    'output features ignored due to invalid '
 | 
			
		||||
                                    'geometry.'))
 | 
			
		||||
 | 
			
		||||
        del writer
 | 
			
		||||
            count += 1
 | 
			
		||||
            feedback.setProgress(int(count * total))
 | 
			
		||||
 | 
			
		||||
        return {self.OUTPUT: dest_id}
 | 
			
		||||
 | 
			
		||||
@ -61,6 +61,7 @@ from .FixGeometry import FixGeometry
 | 
			
		||||
from .GridPolygon import GridPolygon
 | 
			
		||||
from .ImportIntoPostGIS import ImportIntoPostGIS
 | 
			
		||||
from .ImportIntoSpatialite import ImportIntoSpatialite
 | 
			
		||||
from .Intersection import Intersection
 | 
			
		||||
from .Merge import Merge
 | 
			
		||||
from .PointsLayerFromTable import PointsLayerFromTable
 | 
			
		||||
from .PostGISExecuteSQL import PostGISExecuteSQL
 | 
			
		||||
@ -98,7 +99,6 @@ from .ZonalStatistics import ZonalStatistics
 | 
			
		||||
# from .ConvexHull import ConvexHull
 | 
			
		||||
# from .FixedDistanceBuffer import FixedDistanceBuffer
 | 
			
		||||
# from .VariableDistanceBuffer import VariableDistanceBuffer
 | 
			
		||||
# from .Intersection import Intersection
 | 
			
		||||
# from .RandomSelection import RandomSelection
 | 
			
		||||
# from .RandomSelectionWithinSubsets import RandomSelectionWithinSubsets
 | 
			
		||||
# from .SelectByLocation import SelectByLocation
 | 
			
		||||
@ -194,7 +194,6 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
 | 
			
		||||
        #         PolygonsToLines(), LinesToPolygons(), ExtractNodes(),
 | 
			
		||||
        #         ConvexHull(), FixedDistanceBuffer(),
 | 
			
		||||
        #         VariableDistanceBuffer(),
 | 
			
		||||
        #         Intersection(),
 | 
			
		||||
        #         RandomSelection(), RandomSelectionWithinSubsets(),
 | 
			
		||||
        #         SelectByLocation(),
 | 
			
		||||
        #         ExtractByLocation(),
 | 
			
		||||
@ -260,6 +259,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
 | 
			
		||||
                GridPolygon(),
 | 
			
		||||
                ImportIntoPostGIS(),
 | 
			
		||||
                ImportIntoSpatialite(),
 | 
			
		||||
                Intersection(),
 | 
			
		||||
                Merge(),
 | 
			
		||||
                PointsLayerFromTable(),
 | 
			
		||||
                PostGISExecuteSQL(),
 | 
			
		||||
 | 
			
		||||
@ -115,20 +115,20 @@ tests:
 | 
			
		||||
#  # check this behavior.
 | 
			
		||||
#  # This test should stay in place because for shapefiles there should always
 | 
			
		||||
#  # be a polygon result created since it does not support geometry collections.
 | 
			
		||||
#  - name: Intersection (Collection Fallback)
 | 
			
		||||
#    algorithm: qgis:intersection
 | 
			
		||||
#    params:
 | 
			
		||||
#      INPUT:
 | 
			
		||||
#        name: multipolys.gml
 | 
			
		||||
#        type: vector
 | 
			
		||||
#      INPUT2:
 | 
			
		||||
#        name: polys.gml
 | 
			
		||||
#        type: vector
 | 
			
		||||
#    results:
 | 
			
		||||
#      OUTPUT:
 | 
			
		||||
#        name: expected/intersection_collection_fallback.shp
 | 
			
		||||
#        type: vector
 | 
			
		||||
#
 | 
			
		||||
  - algorithm: qgis:intersection
 | 
			
		||||
    name: Intersects multipolygons with polygons
 | 
			
		||||
    params:
 | 
			
		||||
      INPUT:
 | 
			
		||||
        name: multipolys.gml
 | 
			
		||||
        type: vector
 | 
			
		||||
      OVERLAY:
 | 
			
		||||
        name: polys.gml
 | 
			
		||||
        type: vector
 | 
			
		||||
    results:
 | 
			
		||||
      OUTPUT:
 | 
			
		||||
        name: expected/intersection_collection_fallback.shp
 | 
			
		||||
        type: vector
 | 
			
		||||
 | 
			
		||||
  - name: Densify geometries
 | 
			
		||||
    algorithm: qgis:densifygeometries
 | 
			
		||||
    params:
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user