2012-10-04 19:33:47 +02:00
# -*- coding: utf-8 -*-
"""
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Difference . py
- - - - - - - - - - - - - - - - - - - - -
Date : August 2012
Copyright : ( C ) 2012 by Victor Olaya
Email : volayaf at gmail dot com
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
"""
2013-10-01 20:52:22 +03:00
2012-10-04 19:33:47 +02:00
__author__ = ' Victor Olaya '
__date__ = ' August 2012 '
__copyright__ = ' (C) 2012, Victor Olaya '
2013-10-01 20:52:22 +03:00
2012-10-04 19:33:47 +02:00
# This will get replaced with a git SHA1 when you do a git archive
2013-10-01 20:52:22 +03:00
2012-10-04 19:33:47 +02:00
__revision__ = ' $Format: % H$ '
2016-01-25 15:42:11 +02:00
import os
2016-04-22 10:38:48 +02:00
from qgis . PyQt . QtGui import QIcon
2016-01-25 15:42:11 +02:00
2017-04-24 14:35:50 +10:00
from qgis . core import ( QgsFeatureRequest ,
QgsFeature ,
2017-06-23 14:34:38 +10:00
QgsFeatureSink ,
2017-04-24 14:35:50 +10:00
QgsGeometry ,
QgsWkbTypes ,
QgsMessageLog ,
QgsProcessingUtils )
2017-06-06 13:41:42 +10:00
from processing . algs . qgis . QgisAlgorithm import QgisAlgorithm
2017-03-04 19:41:23 +01:00
from processing . core . parameters import ParameterVector
2014-07-14 14:19:09 +02:00
from processing . core . outputs import OutputVector
2013-10-01 20:52:22 +03:00
2016-01-25 15:42:11 +02:00
pluginPath = os . path . split ( os . path . split ( os . path . dirname ( __file__ ) ) [ 0 ] ) [ 0 ]
2012-09-15 18:25:25 +03:00
2017-05-19 11:27:16 +10:00
class Difference ( QgisAlgorithm ) :
2012-09-15 18:25:25 +03:00
2013-10-01 20:52:22 +03:00
INPUT = ' INPUT '
OVERLAY = ' OVERLAY '
2016-07-04 00:43:36 +02:00
IGNORE_INVALID = ' IGNORE_INVALID '
2013-10-01 20:52:22 +03:00
OUTPUT = ' OUTPUT '
2012-09-15 18:25:25 +03:00
2017-03-29 10:42:42 +10:00
def icon ( self ) :
2016-01-25 15:42:11 +02:00
return QIcon ( os . path . join ( pluginPath , ' images ' , ' ftools ' , ' difference.png ' ) )
2012-09-15 18:25:25 +03:00
2017-03-29 12:04:09 +10:00
def group ( self ) :
return self . tr ( ' Vector overlay tools ' )
2017-05-15 13:40:38 +10:00
def __init__ ( self ) :
super ( ) . __init__ ( )
2015-01-15 20:41:15 +02:00
self . addParameter ( ParameterVector ( Difference . INPUT ,
2016-08-23 19:33:42 +03:00
self . tr ( ' Input layer ' ) ) )
2013-10-01 20:52:22 +03:00
self . addParameter ( ParameterVector ( Difference . OVERLAY ,
2016-08-23 19:33:42 +03:00
self . tr ( ' Difference layer ' ) ) )
2015-01-15 20:41:15 +02:00
self . addOutput ( OutputVector ( Difference . OUTPUT , self . tr ( ' Difference ' ) ) )
2013-02-28 14:03:01 +04:00
2017-05-15 13:40:38 +10:00
def name ( self ) :
return ' difference '
def displayName ( self ) :
return self . tr ( ' Difference ' )
2017-05-15 16:19:46 +10:00
def processAlgorithm ( self , parameters , context , feedback ) :
2017-05-02 13:40:49 +10:00
layerA = QgsProcessingUtils . mapLayerFromString ( self . getParameterValue ( Difference . INPUT ) , context )
layerB = QgsProcessingUtils . mapLayerFromString ( self . getParameterValue ( Difference . OVERLAY ) , context )
2013-02-28 14:03:01 +04:00
2016-10-19 19:58:23 +07:00
geomType = QgsWkbTypes . multiType ( layerA . wkbType ( ) )
2013-10-01 20:52:22 +03:00
writer = self . getOutputFromName (
2017-04-26 14:33:53 +10:00
Difference . OUTPUT ) . getVectorWriter ( layerA . fields ( ) , geomType , layerA . crs ( ) , context )
2013-02-28 14:03:01 +04:00
2012-09-15 18:25:25 +03:00
outFeat = QgsFeature ( )
2017-05-02 13:39:36 +10:00
index = QgsProcessingUtils . createSpatialIndex ( layerB , context )
2017-04-25 17:59:35 +10:00
selectionA = QgsProcessingUtils . getFeatures ( layerA , context )
2017-06-23 13:49:32 +10:00
total = 100.0 / layerA . featureCount ( ) if layerA . featureCount ( ) else 0
2016-02-17 09:36:59 +02:00
for current , inFeatA in enumerate ( selectionA ) :
2016-08-01 16:25:46 +10:00
geom = inFeatA . geometry ( )
2013-02-28 14:03:01 +04:00
diff_geom = QgsGeometry ( geom )
attrs = inFeatA . attributes ( )
intersections = index . intersects ( geom . boundingBox ( ) )
2016-10-17 10:30:55 +10:00
request = QgsFeatureRequest ( ) . setFilterFids ( intersections ) . setSubsetOfAttributes ( [ ] )
for inFeatB in layerB . getFeatures ( request ) :
2016-08-01 16:25:46 +10:00
tmpGeom = inFeatB . geometry ( )
2016-01-29 11:03:38 +02:00
if diff_geom . intersects ( tmpGeom ) :
diff_geom = QgsGeometry ( diff_geom . difference ( tmpGeom ) )
2016-12-15 12:25:20 +01:00
try :
outFeat . setGeometry ( diff_geom )
outFeat . setAttributes ( attrs )
2017-06-23 14:34:38 +10:00
writer . addFeature ( outFeat , QgsFeatureSink . FastInsert )
2016-12-15 12:25:20 +01:00
except :
2017-04-26 12:52:23 +10:00
QgsMessageLog . logMessage ( self . tr ( ' Feature geometry error: One or more output features ignored due to invalid geometry. ' ) , self . tr ( ' Processing ' ) , QgsMessageLog . WARNING )
2016-12-15 12:25:20 +01:00
continue
2013-01-21 23:04:34 +01:00
2017-01-06 20:04:00 +10:00
feedback . setProgress ( int ( current * total ) )
2013-02-07 01:09:39 +01:00
2012-09-15 18:25:25 +03:00
del writer