Skip to content
Permalink
Browse files

Port split with lines to new API

Improvements:
- handle transparent reprojection if layer and lines are in different CRS
  • Loading branch information
nyalldawson committed Jul 27, 2017
1 parent 516249c commit e23617a83d3ba3e80345745a9c5a581252dced29
@@ -112,6 +112,7 @@
from .SnapGeometries import SnapGeometriesToLayer
from .SpatialiteExecuteSQL import SpatialiteExecuteSQL
from .SpatialIndex import SpatialIndex
from .SplitWithLines import SplitWithLines
from .SumLines import SumLines
from .SymmetricalDifference import SymmetricalDifference
from .TextToFloat import TextToFloat
@@ -154,7 +155,6 @@
# from .SetRasterStyle import SetRasterStyle
# from .SelectByAttributeSum import SelectByAttributeSum
# from .HypsometricCurves import HypsometricCurves
# from .SplitWithLines import SplitWithLines
# from .FieldsMapper import FieldsMapper
# from .Datasources2Vrt import Datasources2Vrt
# from .OrientedMinimumBoundingBox import OrientedMinimumBoundingBox
@@ -205,7 +205,7 @@ def getAlgs(self):
# PointsFromLines(), PointsToPaths(),
# SetVectorStyle(), SetRasterStyle(),
# HypsometricCurves(),
# SplitWithLines(), CreateConstantRaster(),
# CreateConstantRaster(),
# FieldsMapper(), SelectByAttributeSum(), Datasources2Vrt(),
# OrientedMinimumBoundingBox(),
# DefineProjection(),
@@ -291,6 +291,7 @@ def getAlgs(self):
SnapGeometriesToLayer(),
SpatialiteExecuteSQL(),
SpatialIndex(),
SplitWithLines(),
SumLines(),
SymmetricalDifference(),
TextToFloat(),
@@ -26,26 +26,23 @@

__revision__ = '$Format:%H$'

from qgis.core import (QgsApplication,
QgsFeatureRequest,
from qgis.core import (QgsFeatureRequest,
QgsFeature,
QgsFeatureSink,
QgsGeometry,
QgsSpatialIndex,
QgsWkbTypes,
QgsMessageLog,
QgsProcessingUtils)
QgsProcessingParameterFeatureSource,
QgsProcessing,
QgsProcessingParameterFeatureSink)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.parameters import ParameterVector
from processing.core.outputs import OutputVector
from processing.tools import dataobjects
from processing.tools import vector


class SplitWithLines(QgisAlgorithm):

INPUT_A = 'INPUT_A'
INPUT_B = 'INPUT_B'
INPUT = 'INPUT'
LINES = 'LINES'

OUTPUT = 'OUTPUT'

@@ -56,12 +53,13 @@ def __init__(self):
super().__init__()

def initAlgorithm(self, config=None):
self.addParameter(ParameterVector(self.INPUT_A,
self.tr('Input layer, single geometries only'), [dataobjects.TYPE_VECTOR_POLYGON,
dataobjects.TYPE_VECTOR_LINE]))
self.addParameter(ParameterVector(self.INPUT_B,
self.tr('Split layer'), [dataobjects.TYPE_VECTOR_LINE]))
self.addOutput(OutputVector(self.OUTPUT, self.tr('Split')))
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Input layer, single geometries only'), [QgsProcessing.TypeVectorLine,
QgsProcessing.TypeVectorPolygon]))
self.addParameter(QgsProcessingParameterFeatureSource(self.LINES,
self.tr('Split layer'), [QgsProcessing.TypeVectorLine]))

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

def name(self):
return 'splitwithlines'
@@ -70,34 +68,37 @@ def displayName(self):
return self.tr('Split with lines')

def processAlgorithm(self, parameters, context, feedback):
layerA = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_A), context)
splitLayer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_B), context)
source = self.parameterAsSource(parameters, self.INPUT, context)
line_source = self.parameterAsSource(parameters, self.LINES, context)

sameLayer = self.getParameterValue(self.INPUT_A) == self.getParameterValue(self.INPUT_B)
fieldList = layerA.fields()
sameLayer = parameters[self.INPUT] == parameters[self.LINES]

writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fieldList, QgsWkbTypes.multiType(layerA.wkbType()),
layerA.crs(), context)
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
source.fields(), QgsWkbTypes.multiType(source.wkbType()), source.sourceCrs())

spatialIndex = QgsSpatialIndex()
splitGeoms = {}
request = QgsFeatureRequest()
request.setSubsetOfAttributes([])
request.setDestinationCrs(source.sourceCrs())

for aSplitFeature in line_source.getFeatures(request):
if feedback.isCanceled():
break

for aSplitFeature in QgsProcessingUtils.getFeatures(splitLayer, context, request):
splitGeoms[aSplitFeature.id()] = aSplitFeature.geometry()
spatialIndex.insertFeature(aSplitFeature)
# honor the case that user has selection on split layer and has setting "use selection"

outFeat = QgsFeature()
features = QgsProcessingUtils.getFeatures(layerA, context)
features = source.getFeatures()

if QgsProcessingUtils.featureCount(layerA, context) == 0:
total = 100
else:
total = 100.0 / layerA.featureCount() if layerA.featureCount() else 0
total = 100.0 / source.featureCount() if source.featureCount() else 100

for current, inFeatA in enumerate(features):
if feedback.isCanceled():
break

inGeom = inFeatA.geometry()
attrsA = inFeatA.attributes()
outFeat.setAttributes(attrsA)
@@ -141,6 +142,9 @@ def processAlgorithm(self, parameters, context, feedback):
split_geom_engine.prepareGeometry()

while len(inGeoms) > 0:
if feedback.isCanceled():
break

inGeom = inGeoms.pop()

if inGeom.isNull(): # this has been encountered and created a run-time error
@@ -154,7 +158,7 @@ def processAlgorithm(self, parameters, context, feedback):
try:
result, newGeometries, topoTestPoints = inGeom.splitGeometry(splitterPList, False)
except:
QgsMessageLog.logMessage(self.tr('Geometry exception while splitting'), self.tr('Processing'), QgsMessageLog.WARNING)
feedback.reportError(self.tr('Geometry exception while splitting'))
result = 1

# splitGeometry: If there are several intersections
@@ -179,6 +183,9 @@ def processAlgorithm(self, parameters, context, feedback):
parts = []

for aGeom in inGeoms:
if feedback.isCanceled():
break

passed = True

if QgsWkbTypes.geometryType(aGeom.wkbType()) == QgsWkbTypes.LineGeometry:
@@ -196,7 +203,7 @@ def processAlgorithm(self, parameters, context, feedback):

if len(parts) > 0:
outFeat.setGeometry(QgsGeometry.collectGeometry(parts))
writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
sink.addFeature(outFeat, QgsFeatureSink.FastInsert)

feedback.setProgress(int(current * total))
del writer
return {self.OUTPUT: dest_id}
@@ -1716,56 +1716,56 @@ tests:
name: expected/create_points.gml
type: vector

# - algorithm: qgis:splitwithlines
# name: Split lines with lines (new alg)
# params:
# INPUT_A:
# name: lines.gml
# type: vector
# INPUT_B:
# name: custom/lines2.gml
# type: vector
# results:
# OUTPUT:
# name: expected/split_lines_with_lines.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
# - algorithm: qgis:splitwithlines
# name: Split poly with lines
# params:
# INPUT_A:
# name: polys.gml
# type: vector
# INPUT_B:
# name: lines.gml
# type: vector
# results:
# OUTPUT:
# name: expected/split_polys_with_lines.gml
# type: vector
# compare:
# geometry:
# precision: 7
#
# - algorithm: qgis:splitwithlines
# name: Split lines with same lines
# params:
# INPUT_A:
# name: lines.gml
# type: vector
# INPUT_B:
# name: lines.gml
# type: vector
# results:
# OUTPUT:
# name: expected/split_lines_with_lines_same.gml
# type: vector
# compare:
# geometry:
# precision: 7
- algorithm: qgis:splitwithlines
name: Split lines with lines (new alg)
params:
INPUT:
name: lines.gml
type: vector
LINES:
name: custom/lines2.gml
type: vector
results:
OUTPUT:
name: expected/split_lines_with_lines.gml
type: vector
compare:
geometry:
precision: 7

- algorithm: qgis:splitwithlines
name: Split poly with lines
params:
INPUT:
name: polys.gml
type: vector
LINES:
name: lines.gml
type: vector
results:
OUTPUT:
name: expected/split_polys_with_lines.gml
type: vector
compare:
geometry:
precision: 7

- algorithm: qgis:splitwithlines
name: Split lines with same lines
params:
INPUT:
name: lines.gml
type: vector
LINES:
name: lines.gml
type: vector
results:
OUTPUT:
name: expected/split_lines_with_lines_same.gml
type: vector
compare:
geometry:
precision: 7

- algorithm: qgis:dropgeometries
name: Drop geometries

0 comments on commit e23617a

Please sign in to comment.
You can’t perform that action at this time.