Skip to content
Permalink
Browse files

[processing][FEATURE] Return multi geometries from split alg

accept multi geometries as input
  • Loading branch information
bstroebl authored and nyalldawson committed Dec 2, 2016
1 parent 3a789e5 commit b02c6a32069004b1a7703724a81777a7e2452c3b
@@ -504,6 +504,8 @@ qgis:snappointstogrid: >

qgis:splitwithlines: >
This algorithm splits the lines or polygons in one layer using the lines in another layer to define the breaking points. Intersection between geometries in both layers are considered as split points.

Output will contain multi geometries for split features.

qgis:splitvectorlayer: >
This algorithm takes a vector layer and an attribute and generates a set of vector layers in an output folder. Each of the layers created in that folder contains all features from the input layer with the same value for the specified attribute.
@@ -26,7 +26,7 @@

__revision__ = '$Format:%H$'

from qgis.core import QgsFeatureRequest, QgsFeature, QgsGeometry, QgsSpatialIndex, QgsWkbTypes, QgsMessageLog
from qgis.core import QgsFeatureRequest, QgsFeature, QgsGeometry, QgsSpatialIndex, QgsWkbTypes, QgsPoint
from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.parameters import ParameterVector
from processing.core.outputs import OutputVector
@@ -61,7 +61,7 @@ def processAlgorithm(self, progress):
fieldList = layerA.fields()

writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fieldList,
layerA.wkbType(), layerA.crs())
QgsWkbTypes.multiType(layerA.wkbType()), layerA.crs())

spatialIndex = QgsSpatialIndex()
splitGeoms = {}
@@ -81,107 +81,107 @@ def processAlgorithm(self, progress):
else:
total = 100.0 / float(len(features))

multiGeoms = 0 # how many multi geometries were encountered

for current, inFeatA in enumerate(features):
inGeom = inFeatA.geometry()
attrsA = inFeatA.attributes()
outFeat.setAttributes(attrsA)

if inGeom.isMultipart():
multiGeoms += 1
# MultiGeometries are not allowed because the result of a splitted part cannot be clearly defined:
# 1) add both new parts as new features
# 2) store one part as a new feature and the other one as part of the multi geometry
# 2a) which part should be which, seems arbitrary
inGeoms = []

for g in inGeom.asGeometryCollection():
inGeoms.append(g)
else:
attrsA = inFeatA.attributes()
outFeat.setAttributes(attrsA)
inGeoms = [inGeom]
lines = spatialIndex.intersects(inGeom.boundingBox())

if len(lines) > 0: # has intersection of bounding boxes
splittingLines = []
lines = spatialIndex.intersects(inGeom.boundingBox())

if len(lines) > 0: # has intersection of bounding boxes
splittingLines = []

engine = QgsGeometry.createGeometryEngine(inGeom.geometry())
engine.prepareGeometry()

engine = QgsGeometry.createGeometryEngine(inGeom.geometry())
engine.prepareGeometry()
for i in lines:
try:
splitGeom = splitGeoms[i]
except:
continue

for i in lines:
try:
splitGeom = splitGeoms[i]
except:
# check if trying to self-intersect
if sameLayer:
if inFeatA.id() == i:
continue

# check if trying to self-intersect
if sameLayer:
if inFeatA.id() == i:
if engine.intersects(splitGeom.geometry()):
splittingLines.append(splitGeom)

if len(splittingLines) > 0:
for splitGeom in splittingLines:
splitterPList = None
outGeoms = []

split_geom_engine = QgsGeometry.createGeometryEngine(splitGeom.geometry())
split_geom_engine.prepareGeometry()

while len(inGeoms) > 0:
inGeom = inGeoms.pop()

if inGeom.isEmpty(): # this has been encountered and created a run-time error
continue

if engine.intersects(splitGeom.geometry()):
splittingLines.append(splitGeom)

if len(splittingLines) > 0:
for splitGeom in splittingLines:
splitterPList = None
outGeoms = []

split_geom_engine = QgsGeometry.createGeometryEngine(splitGeom.geometry())
split_geom_engine.prepareGeometry()

while len(inGeoms) > 0:
inGeom = inGeoms.pop()

if split_geom_engine.intersects(inGeom.geometry()):
inPoints = vector.extractPoints(inGeom)
if splitterPList == None:
splitterPList = vector.extractPoints(splitGeom)

try:
result, newGeometries, topoTestPoints = inGeom.splitGeometry(splitterPList, False)
except:
ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
self.tr('Geometry exception while splitting'))
result = 1

# splitGeometry: If there are several intersections
# between geometry and splitLine, only the first one is considered.
if result == 0: # split occurred
if inPoints == vector.extractPoints(inGeom):
# bug in splitGeometry: sometimes it returns 0 but
# the geometry is unchanged
QgsMessageLog.logMessage("appending")
outGeoms.append(inGeom)
else:
inGeoms.append(inGeom)

for aNewGeom in newGeometries:
inGeoms.append(aNewGeom)
else:
QgsMessageLog.logMessage("appending else")
if split_geom_engine.intersects(inGeom.geometry()):
inPoints = vector.extractPoints(inGeom)
if splitterPList == None:
splitterPList = vector.extractPoints(splitGeom)

try:
result, newGeometries, topoTestPoints = inGeom.splitGeometry(splitterPList, False)
except:
ProcessingLog.addToLog(ProcessingLog.LOG_WARNING,
self.tr('Geometry exception while splitting'))
result = 1

# splitGeometry: If there are several intersections
# between geometry and splitLine, only the first one is considered.
if result == 0: # split occurred
if inPoints == vector.extractPoints(inGeom):
# bug in splitGeometry: sometimes it returns 0 but
# the geometry is unchanged
outGeoms.append(inGeom)
else:
inGeoms.append(inGeom)

for aNewGeom in newGeometries:
inGeoms.append(aNewGeom)
else:
outGeoms.append(inGeom)
else:
outGeoms.append(inGeom)

inGeoms = outGeoms
inGeoms = outGeoms

for aGeom in inGeoms:
passed = True
parts = []

if QgsWkbTypes.geometryType( aGeom.wkbType() ) == QgsWkbTypes.LineGeometry \
and not QgsWkbTypes.isMultiType(aGeom.wkbType()):
passed = len(aGeom.asPolyline()) > 2
for aGeom in inGeoms:
passed = True

if not passed:
passed = (len(aGeom.asPolyline()) == 2 and
aGeom.asPolyline()[0] != aGeom.asPolyline()[1])
# sometimes splitting results in lines of zero length
if QgsWkbTypes.geometryType( aGeom.wkbType() ) == QgsWkbTypes.LineGeometry:
numPoints = aGeom.geometry().numPoints()

if passed:
outFeat.setGeometry(aGeom)
writer.addFeature(outFeat)
if numPoints <= 2:
if numPoints == 2:
passed = not aGeom.geometry().isClosed() # tests if vertex 0 = vertex 1
else:
passed = False
# sometimes splitting results in lines of zero length

progress.setPercentage(int(current * total))
if passed:
parts.append(aGeom)

if multiGeoms > 0:
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
self.tr('Feature geometry error: %s input features ignored due to multi-geometry.') % str(multiGeoms))
if len(parts) > 0:
outFeat.setGeometry(QgsGeometry.collectGeometry(parts))
writer.addFeature(outFeat)

progress.setPercentage(int(current * total))
del writer
@@ -2,11 +2,11 @@
<GMLFeatureClass>
<Name>split_lines_with_lines</Name>
<ElementPath>split_lines_with_lines</ElementPath>
<!--LINESTRING-->
<GeometryType>2</GeometryType>
<!--MULTILINESTRING-->
<GeometryType>5</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>11</FeatureCount>
<FeatureCount>7</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>11.00000</ExtentXMax>
<ExtentYMin>-3.00000</ExtentYMin>
@@ -13,52 +13,32 @@

<gml:featureMember>
<ogr:split_lines_with_lines fid="lines.0">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,2 9,2 9,3 11,5</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>6,2 9,2 9,3 11,5</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:split_lines_with_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines fid="lines.1">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:split_lines_with_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines fid="lines.2">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2.0,1.86331771490359 2,2 3,2 3,3</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:split_lines_with_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines fid="lines.2">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,0 2.0,1.86331771490359</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:split_lines_with_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines fid="lines.3">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>4.21601489757914,1.0 5,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2.0,1.86331771490359 2,2 3,2 3,3</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>2,0 2.0,1.86331771490359</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:split_lines_with_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines fid="lines.3">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,1 4.21601489757914,1.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>4.21601489757914,1.0 5,1</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>3,1 4.21601489757914,1.0</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:split_lines_with_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines fid="lines.4">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>8.5655671605538,-3.0 10,-3</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:split_lines_with_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines fid="lines.4">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,-3 8.5655671605538,-3.0</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:split_lines_with_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines fid="lines.5">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6.91202704418487,-2.08797295581513 10,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>8.5655671605538,-3.0 10,-3</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>7,-3 8.5655671605538,-3.0</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:split_lines_with_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines fid="lines.5">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,-3 6.91202704418487,-2.08797295581513</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>6.91202704418487,-2.08797295581513 10,1</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>6,-3 6.91202704418487,-2.08797295581513</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:split_lines_with_lines>
</gml:featureMember>
<gml:featureMember>
@@ -2,8 +2,8 @@
<GMLFeatureClass>
<Name>split_lines_with_lines_same</Name>
<ElementPath>split_lines_with_lines_same</ElementPath>
<!--LINESTRING-->
<GeometryType>2</GeometryType>
<!--MULTILINESTRING-->
<GeometryType>5</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>7</FeatureCount>
@@ -13,32 +13,32 @@

<gml:featureMember>
<ogr:split_lines_with_lines_same fid="lines.0">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,2 9,2 9,3 11,5</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>6,2 9,2 9,3 11,5</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:split_lines_with_lines_same>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines_same fid="lines.1">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:split_lines_with_lines_same>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines_same fid="lines.2">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,0 2,2 3,2 3,3</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2,0 2,2 3,2 3,3</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:split_lines_with_lines_same>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines_same fid="lines.3">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,1 5,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>3,1 5,1</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:split_lines_with_lines_same>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines_same fid="lines.4">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,-3 10,-3</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>7,-3 10,-3</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:split_lines_with_lines_same>
</gml:featureMember>
<gml:featureMember>
<ogr:split_lines_with_lines_same fid="lines.5">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,-3 10,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>6,-3 10,1</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:split_lines_with_lines_same>
</gml:featureMember>
<gml:featureMember>

0 comments on commit b02c6a3

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