Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add ability to select output fields from both layers to Intersection …
…algorithm
  • Loading branch information
nyalldawson committed Jul 15, 2017
1 parent 02bf88c commit a6736ce
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 9 deletions.
64 changes: 55 additions & 9 deletions python/plugins/processing/algs/qgis/Intersection.py
Expand Up @@ -31,14 +31,15 @@

from qgis.core import (QgsFeatureRequest,
QgsFeature,
QgsFields,
QgsFeatureSink,
QgsGeometry,
QgsWkbTypes,
QgsProcessingException,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink,
QgsSpatialIndex,
QgsProcessingUtils)
QgsProcessingParameterField)

from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.tools import vector
Expand All @@ -60,6 +61,8 @@ class Intersection(QgisAlgorithm):
INPUT = 'INPUT'
OVERLAY = 'OVERLAY'
OUTPUT = 'OUTPUT'
INPUT_FIELDS = 'INPUT_FIELDS'
OVERLAY_FIELDS = 'OVERLAY_FIELDS'

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

self.addParameter(QgsProcessingParameterField(
self.INPUT_FIELDS,
self.tr('Input fields to keep (leave empty to keep all fields)'),
parentLayerParameterName=self.INPUT,
optional=True, allowMultiple=True))
self.addParameter(QgsProcessingParameterField(
self.OVERLAY_FIELDS,
self.tr('Intersect fields to keep (leave empty to keep all fields)'),
parentLayerParameterName=self.OVERLAY,
optional=True, allowMultiple=True))

self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Intersection')))

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

geomType = QgsWkbTypes.multiType(sourceA.wkbType())
fields = vector.combineFields(sourceA.fields(), sourceB.fields())

fieldsA = self.parameterAsFields(parameters, self.INPUT_FIELDS, context)
fieldsB = self.parameterAsFields(parameters, self.OVERLAY_FIELDS, context)

fieldListA = QgsFields()
field_indices_a = []
if len(fieldsA) > 0:
for f in fieldsA:
idxA = sourceA.fields().lookupField(f)
if idxA >= 0:
field_indices_a.append(idxA)
fieldListA.append(sourceA.fields()[idxA])
else:
fieldListA = sourceA.fields()
field_indices_a = [i for i in range(0, fieldListA.count())]

fieldListB = QgsFields()
field_indices_b = []
if len(fieldsB) > 0:
for f in fieldsB:
idxB = sourceB.fields().lookupField(f)
if idxB >= 0:
field_indices_b.append(idxB)
fieldListB.append(sourceB.fields()[idxB])
else:
fieldListB = sourceB.fields()
field_indices_b = [i for i in range(0, fieldListB.count())]

fieldListB = vector.testForUniqueness(fieldListA, fieldListB)
for b in fieldListB:
fieldListA.append(b)

(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
fields, geomType, sourceA.sourceCrs())
fieldListA, geomType, sourceA.sourceCrs())

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

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

for featA in sourceA.getFeatures():
for featA in sourceA.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(field_indices_a)):
if feedback.isCanceled():
break

if not featA.hasGeometry():
continue

geom = featA.geometry()
atMapA = featA.attributes()
intersects = indexB.intersects(geom.boundingBox())

request = QgsFeatureRequest().setFilterFids(intersects)
request.setDestinationCrs(sourceA.sourceCrs())
request.setSubsetOfAttributes(field_indices_b)

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

tmpGeom = featB.geometry()
if engine.intersects(tmpGeom.geometry()):
atMapB = featB.attributes()
out_attributes = [featA.attributes()[i] for i in field_indices_a]
out_attributes.extend([featB.attributes()[i] for i in field_indices_b])
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)
Expand All @@ -139,10 +188,7 @@ def processAlgorithm(self, parameters, context, feedback):
try:
if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]:
outFeat.setGeometry(int_geom)
attrs = []
attrs.extend(atMapA)
attrs.extend(atMapB)
outFeat.setAttributes(attrs)
outFeat.setAttributes(out_attributes)
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
except:
raise QgsProcessingException(
Expand Down
Binary file not shown.

0 comments on commit a6736ce

Please sign in to comment.