2012-10-04 19:33:47 +02:00
# -*- coding: utf-8 -*-
"""
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Intersection . 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-09-11 19:32:38 +02: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 ,
QgsGeometry ,
QgsWkbTypes ,
QgsMessageLog ,
QgsProcessingUtils )
2016-01-29 11:03:38 +02:00
2013-10-01 20:52:22 +03:00
from processing . core . GeoAlgorithm import GeoAlgorithm
2014-07-14 14:19:09 +02:00
from processing . core . parameters import ParameterVector
from processing . core . outputs import OutputVector
2017-05-02 14:47:58 +10:00
from processing . tools import vector
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 ]
2014-01-14 21:14:49 +00:00
wkbTypeGroups = {
2016-08-04 09:10:08 +02:00
' Point ' : ( QgsWkbTypes . Point , QgsWkbTypes . MultiPoint , QgsWkbTypes . Point25D , QgsWkbTypes . MultiPoint25D , ) ,
' LineString ' : ( QgsWkbTypes . LineString , QgsWkbTypes . MultiLineString , QgsWkbTypes . LineString25D , QgsWkbTypes . MultiLineString25D , ) ,
' Polygon ' : ( QgsWkbTypes . Polygon , QgsWkbTypes . MultiPolygon , QgsWkbTypes . Polygon25D , QgsWkbTypes . MultiPolygon25D , ) ,
2014-01-14 21:14:49 +00:00
}
2016-09-21 18:24:26 +02:00
for key , value in list ( wkbTypeGroups . items ( ) ) :
2014-01-14 21:14:49 +00:00
for const in value :
wkbTypeGroups [ const ] = key
2012-09-15 18:25:25 +03:00
2015-08-22 14:29:41 +02:00
2012-09-15 18:25:25 +03:00
class Intersection ( GeoAlgorithm ) :
2013-10-01 20:52:22 +03:00
INPUT = ' INPUT '
INPUT2 = ' INPUT2 '
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 ' , ' intersect.png ' ) )
2017-03-29 12:04:09 +10:00
def group ( self ) :
return self . tr ( ' Vector overlay tools ' )
2017-03-29 12:51:59 +10:00
def name ( self ) :
2017-03-29 17:09:39 +10:00
return ' intersection '
2017-03-29 12:51:59 +10:00
def displayName ( self ) :
return self . tr ( ' Intersection ' )
2016-01-29 11:03:38 +02:00
def defineCharacteristics ( self ) :
self . addParameter ( ParameterVector ( self . INPUT ,
2016-08-23 19:33:42 +03:00
self . tr ( ' Input layer ' ) ) )
2016-01-29 11:03:38 +02:00
self . addParameter ( ParameterVector ( self . INPUT2 ,
2016-08-23 19:33:42 +03:00
self . tr ( ' Intersect layer ' ) ) )
2016-01-29 11:03:38 +02:00
self . addOutput ( OutputVector ( self . OUTPUT , self . tr ( ' Intersection ' ) ) )
2017-04-25 14:55:38 +10:00
def processAlgorithm ( self , context , feedback ) :
2017-05-02 13:40:49 +10:00
vlayerA = QgsProcessingUtils . mapLayerFromString ( self . getParameterValue ( self . INPUT ) , context )
vlayerB = QgsProcessingUtils . mapLayerFromString ( self . getParameterValue ( self . INPUT2 ) , context )
2013-02-07 01:09:39 +01:00
2016-10-19 19:58:23 +07:00
geomType = QgsWkbTypes . multiType ( vlayerA . wkbType ( ) )
2013-10-01 20:52:22 +03:00
fields = vector . combineVectorFields ( vlayerA , vlayerB )
2017-04-26 14:33:53 +10:00
writer = self . getOutputFromName ( self . OUTPUT ) . getVectorWriter ( fields , geomType , vlayerA . crs ( ) , context )
2012-09-15 18:25:25 +03:00
outFeat = QgsFeature ( )
2017-05-02 13:39:36 +10:00
index = QgsProcessingUtils . createSpatialIndex ( vlayerB , context )
2017-04-25 17:59:35 +10:00
selectionA = QgsProcessingUtils . getFeatures ( vlayerA , context )
2017-04-25 17:53:32 +10:00
total = 100.0 / QgsProcessingUtils . featureCount ( vlayerA , context )
2016-02-17 09:36:59 +02:00
for current , inFeatA in enumerate ( selectionA ) :
2017-01-06 20:04:00 +10:00
feedback . setProgress ( int ( current * total ) )
2016-08-01 16:25:46 +10:00
geom = inFeatA . geometry ( )
2013-02-04 00:14:39 +01:00
atMapA = inFeatA . attributes ( )
2013-10-01 20:52:22 +03:00
intersects = index . intersects ( geom . boundingBox ( ) )
2016-10-17 10:30:55 +10:00
request = QgsFeatureRequest ( ) . setFilterFids ( intersects )
2016-10-17 11:18:46 +10:00
engine = None
if len ( intersects ) > 0 :
# use prepared geometries for faster intersection tests
engine = QgsGeometry . createGeometryEngine ( geom . geometry ( ) )
engine . prepareGeometry ( )
2016-10-17 10:30:55 +10:00
for inFeatB in vlayerB . getFeatures ( request ) :
2016-08-01 16:25:46 +10:00
tmpGeom = inFeatB . geometry ( )
2016-10-17 11:18:46 +10:00
if engine . intersects ( tmpGeom . geometry ( ) ) :
2016-01-29 11:03:38 +02:00
atMapB = inFeatB . attributes ( )
int_geom = QgsGeometry ( geom . intersection ( tmpGeom ) )
2016-08-04 09:10:08 +02:00
if int_geom . wkbType ( ) == QgsWkbTypes . Unknown or QgsWkbTypes . flatType ( int_geom . geometry ( ) . wkbType ( ) ) == QgsWkbTypes . GeometryCollection :
2016-01-29 11:03:38 +02:00
int_com = geom . combine ( tmpGeom )
2016-09-16 17:50:46 +02:00
int_geom = QgsGeometry ( )
if int_com :
int_sym = geom . symDifference ( tmpGeom )
int_geom = QgsGeometry ( int_com . difference ( int_sym ) )
2017-01-30 22:22:09 +10:00
if int_geom . isEmpty ( ) or not int_geom . isGeosValid ( ) :
2017-04-26 12:52:23 +10:00
QgsMessageLog . logMessage ( self . tr ( ' GEOS geoprocessing error: One or '
' more input features have invalid '
' geometry. ' ) , self . tr ( ' Processing ' ) , QgsMessageLog . CRITICAL )
2016-01-29 11:03:38 +02:00
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 )
writer . addFeature ( outFeat )
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 . INFO )
2016-01-29 11:03:38 +02:00
continue
2014-03-27 19:56:46 +02:00
2012-09-15 18:25:25 +03:00
del writer