Skip to content

Commit a6736ce

Browse files
committedJul 15, 2017
Add ability to select output fields from both layers to Intersection algorithm
1 parent 02bf88c commit a6736ce

File tree

2 files changed

+55
-9
lines changed

2 files changed

+55
-9
lines changed
 

‎python/plugins/processing/algs/qgis/Intersection.py

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,15 @@
3131

3232
from qgis.core import (QgsFeatureRequest,
3333
QgsFeature,
34+
QgsFields,
3435
QgsFeatureSink,
3536
QgsGeometry,
3637
QgsWkbTypes,
3738
QgsProcessingException,
3839
QgsProcessingParameterFeatureSource,
3940
QgsProcessingParameterFeatureSink,
4041
QgsSpatialIndex,
41-
QgsProcessingUtils)
42+
QgsProcessingParameterField)
4243

4344
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
4445
from processing.tools import vector
@@ -60,6 +61,8 @@ class Intersection(QgisAlgorithm):
6061
INPUT = 'INPUT'
6162
OVERLAY = 'OVERLAY'
6263
OUTPUT = 'OUTPUT'
64+
INPUT_FIELDS = 'INPUT_FIELDS'
65+
OVERLAY_FIELDS = 'OVERLAY_FIELDS'
6366

6467
def icon(self):
6568
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'intersect.png'))
@@ -76,6 +79,17 @@ def initAlgorithm(self, config=None):
7679
self.addParameter(QgsProcessingParameterFeatureSource(self.OVERLAY,
7780
self.tr('Intersection layer')))
7881

82+
self.addParameter(QgsProcessingParameterField(
83+
self.INPUT_FIELDS,
84+
self.tr('Input fields to keep (leave empty to keep all fields)'),
85+
parentLayerParameterName=self.INPUT,
86+
optional=True, allowMultiple=True))
87+
self.addParameter(QgsProcessingParameterField(
88+
self.OVERLAY_FIELDS,
89+
self.tr('Intersect fields to keep (leave empty to keep all fields)'),
90+
parentLayerParameterName=self.OVERLAY,
91+
optional=True, allowMultiple=True))
92+
7993
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Intersection')))
8094

8195
def name(self):
@@ -89,27 +103,61 @@ def processAlgorithm(self, parameters, context, feedback):
89103
sourceB = self.parameterAsSource(parameters, self.OVERLAY, context)
90104

91105
geomType = QgsWkbTypes.multiType(sourceA.wkbType())
92-
fields = vector.combineFields(sourceA.fields(), sourceB.fields())
106+
107+
fieldsA = self.parameterAsFields(parameters, self.INPUT_FIELDS, context)
108+
fieldsB = self.parameterAsFields(parameters, self.OVERLAY_FIELDS, context)
109+
110+
fieldListA = QgsFields()
111+
field_indices_a = []
112+
if len(fieldsA) > 0:
113+
for f in fieldsA:
114+
idxA = sourceA.fields().lookupField(f)
115+
if idxA >= 0:
116+
field_indices_a.append(idxA)
117+
fieldListA.append(sourceA.fields()[idxA])
118+
else:
119+
fieldListA = sourceA.fields()
120+
field_indices_a = [i for i in range(0, fieldListA.count())]
121+
122+
fieldListB = QgsFields()
123+
field_indices_b = []
124+
if len(fieldsB) > 0:
125+
for f in fieldsB:
126+
idxB = sourceB.fields().lookupField(f)
127+
if idxB >= 0:
128+
field_indices_b.append(idxB)
129+
fieldListB.append(sourceB.fields()[idxB])
130+
else:
131+
fieldListB = sourceB.fields()
132+
field_indices_b = [i for i in range(0, fieldListB.count())]
133+
134+
fieldListB = vector.testForUniqueness(fieldListA, fieldListB)
135+
for b in fieldListB:
136+
fieldListA.append(b)
93137

94138
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
95-
fields, geomType, sourceA.sourceCrs())
139+
fieldListA, geomType, sourceA.sourceCrs())
96140

97141
outFeat = QgsFeature()
98142
indexB = QgsSpatialIndex(sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(sourceA.sourceCrs())), feedback)
99143

100144
total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1
101145
count = 0
102146

103-
for featA in sourceA.getFeatures():
147+
for featA in sourceA.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(field_indices_a)):
104148
if feedback.isCanceled():
105149
break
106150

151+
if not featA.hasGeometry():
152+
continue
153+
107154
geom = featA.geometry()
108155
atMapA = featA.attributes()
109156
intersects = indexB.intersects(geom.boundingBox())
110157

111158
request = QgsFeatureRequest().setFilterFids(intersects)
112159
request.setDestinationCrs(sourceA.sourceCrs())
160+
request.setSubsetOfAttributes(field_indices_b)
113161

114162
engine = None
115163
if len(intersects) > 0:
@@ -123,7 +171,8 @@ def processAlgorithm(self, parameters, context, feedback):
123171

124172
tmpGeom = featB.geometry()
125173
if engine.intersects(tmpGeom.geometry()):
126-
atMapB = featB.attributes()
174+
out_attributes = [featA.attributes()[i] for i in field_indices_a]
175+
out_attributes.extend([featB.attributes()[i] for i in field_indices_b])
127176
int_geom = QgsGeometry(geom.intersection(tmpGeom))
128177
if int_geom.wkbType() == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(int_geom.geometry().wkbType()) == QgsWkbTypes.GeometryCollection:
129178
int_com = geom.combine(tmpGeom)
@@ -139,10 +188,7 @@ def processAlgorithm(self, parameters, context, feedback):
139188
try:
140189
if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
141190
outFeat.setGeometry(int_geom)
142-
attrs = []
143-
attrs.extend(atMapA)
144-
attrs.extend(atMapB)
145-
outFeat.setAttributes(attrs)
191+
outFeat.setAttributes(out_attributes)
146192
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
147193
except:
148194
raise QgsProcessingException(

0 commit comments

Comments
 (0)
Please sign in to comment.