34
34
QgsFeatureSink ,
35
35
QgsGeometry ,
36
36
QgsWkbTypes ,
37
- QgsMessageLog ,
37
+ QgsProcessingParameterFeatureSource ,
38
+ QgsProcessingParameterFeatureSink ,
39
+ QgsSpatialIndex ,
38
40
QgsProcessingUtils )
39
41
40
42
from processing .core .GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
41
43
from processing .algs .qgis .QgisAlgorithm import QgisAlgorithm
42
- from processing .core .parameters import ParameterVector
43
- from processing .core .outputs import OutputVector
44
44
from processing .tools import vector
45
45
46
46
pluginPath = os .path .split (os .path .split (os .path .dirname (__file__ ))[0 ])[0 ]
58
58
class Intersection (QgisAlgorithm ):
59
59
60
60
INPUT = 'INPUT'
61
- INPUT2 = 'INPUT2 '
61
+ OVERLAY = 'OVERLAY '
62
62
OUTPUT = 'OUTPUT'
63
63
64
64
def icon (self ):
@@ -71,11 +71,12 @@ def __init__(self):
71
71
super ().__init__ ()
72
72
73
73
def initAlgorithm (self , config = None ):
74
- self .addParameter (ParameterVector (self .INPUT ,
75
- self .tr ('Input layer' )))
76
- self .addParameter (ParameterVector (self .INPUT2 ,
77
- self .tr ('Intersect layer' )))
78
- self .addOutput (OutputVector (self .OUTPUT , self .tr ('Intersection' )))
74
+ self .addParameter (QgsProcessingParameterFeatureSource (self .INPUT ,
75
+ self .tr ('Input layer' )))
76
+ self .addParameter (QgsProcessingParameterFeatureSource (self .OVERLAY ,
77
+ self .tr ('Intersection layer' )))
78
+
79
+ self .addParameter (QgsProcessingParameterFeatureSink (self .OUTPUT , self .tr ('Intersection' )))
79
80
80
81
def name (self ):
81
82
return 'intersection'
@@ -84,33 +85,45 @@ def displayName(self):
84
85
return self .tr ('Intersection' )
85
86
86
87
def processAlgorithm (self , parameters , context , feedback ):
87
- vlayerA = QgsProcessingUtils .mapLayerFromString (self .getParameterValue (self .INPUT ), context )
88
- vlayerB = QgsProcessingUtils .mapLayerFromString (self .getParameterValue (self .INPUT2 ), context )
88
+ sourceA = self .parameterAsSource (parameters , self .INPUT , context )
89
+ sourceB = self .parameterAsSource (parameters , self .OVERLAY , context )
90
+
91
+ geomType = QgsWkbTypes .multiType (sourceA .wkbType ())
92
+ fields = vector .combineFields (sourceA .fields (), sourceB .fields ())
93
+
94
+ (sink , dest_id ) = self .parameterAsSink (parameters , self .OUTPUT , context ,
95
+ fields , geomType , sourceA .sourceCrs ())
89
96
90
- geomType = QgsWkbTypes .multiType (vlayerA .wkbType ())
91
- fields = vector .combineVectorFields (vlayerA , vlayerB )
92
- writer = self .getOutputFromName (self .OUTPUT ).getVectorWriter (fields , geomType , vlayerA .crs (), context )
93
97
outFeat = QgsFeature ()
94
- index = QgsProcessingUtils .createSpatialIndex (vlayerB , context )
95
- selectionA = QgsProcessingUtils .getFeatures (vlayerA , context )
96
- total = 100.0 / vlayerA .featureCount () if vlayerA .featureCount () else 0
97
- for current , inFeatA in enumerate (selectionA ):
98
- feedback .setProgress (int (current * total ))
99
- geom = inFeatA .geometry ()
100
- atMapA = inFeatA .attributes ()
101
- intersects = index .intersects (geom .boundingBox ())
98
+ indexB = QgsSpatialIndex (sourceB .getFeatures (QgsFeatureRequest ().setSubsetOfAttributes ([]).setDestinationCrs (sourceA .sourceCrs ())))
99
+
100
+ total = 100.0 / sourceA .featureCount () if sourceA .featureCount () else 1
101
+ count = 0
102
+
103
+ for featA in sourceA .getFeatures ():
104
+ if feedback .isCanceled ():
105
+ break
106
+
107
+ geom = featA .geometry ()
108
+ atMapA = featA .attributes ()
109
+ intersects = indexB .intersects (geom .boundingBox ())
110
+
102
111
request = QgsFeatureRequest ().setFilterFids (intersects )
112
+ request .setDestinationCrs (sourceA .sourceCrs ())
103
113
104
114
engine = None
105
115
if len (intersects ) > 0 :
106
116
# use prepared geometries for faster intersection tests
107
117
engine = QgsGeometry .createGeometryEngine (geom .geometry ())
108
118
engine .prepareGeometry ()
109
119
110
- for inFeatB in vlayerB .getFeatures (request ):
111
- tmpGeom = inFeatB .geometry ()
120
+ for featB in sourceB .getFeatures (request ):
121
+ if feedback .isCanceled ():
122
+ break
123
+
124
+ tmpGeom = featB .geometry ()
112
125
if engine .intersects (tmpGeom .geometry ()):
113
- atMapB = inFeatB .attributes ()
126
+ atMapB = featB .attributes ()
114
127
int_geom = QgsGeometry (geom .intersection (tmpGeom ))
115
128
if int_geom .wkbType () == QgsWkbTypes .Unknown or QgsWkbTypes .flatType (int_geom .geometry ().wkbType ()) == QgsWkbTypes .GeometryCollection :
116
129
int_com = geom .combine (tmpGeom )
@@ -130,11 +143,14 @@ def processAlgorithm(self, parameters, context, feedback):
130
143
attrs .extend (atMapA )
131
144
attrs .extend (atMapB )
132
145
outFeat .setAttributes (attrs )
133
- writer .addFeature (outFeat , QgsFeatureSink .FastInsert )
146
+ sink .addFeature (outFeat , QgsFeatureSink .FastInsert )
134
147
except :
135
148
raise GeoAlgorithmExecutionException (
136
149
self .tr ('Feature geometry error: One or more '
137
150
'output features ignored due to invalid '
138
151
'geometry.' ))
139
152
140
- del writer
153
+ count += 1
154
+ feedback .setProgress (int (count * total ))
155
+
156
+ return {self .OUTPUT : dest_id }
0 commit comments