Skip to content
Permalink
Browse files
Merge pull request #3441 from nyalldawson/simplify
Simplify features + fixes
  • Loading branch information
nyalldawson committed Sep 1, 2016
2 parents 798817e + 56b77db commit 88047cc
Show file tree
Hide file tree
Showing 20 changed files with 446 additions and 127 deletions.
@@ -43,6 +43,9 @@ class QgsMapToPixelSimplifier : QgsAbstractGeometrySimplifier
//! Sets the local simplification algorithm of the vector layer managed
void setSimplifyAlgorithm( SimplifyAlgorithm simplifyAlgorithm );

//! Returns a simplified version the specified geometry
virtual QgsGeometry simplify( const QgsGeometry& geometry ) const;

//! Sets the tolerance of the vector layer managed
void setTolerance( double value );

@@ -429,6 +429,8 @@ qgis:setstyleforvectorlayer: >
qgis:simplifygeometries: >
This algorithm simplifies the geometries in a line or polygon layer. It creates a new layer with the same features as the ones in the input layer, but with geometries containing a lower number of vertices.

The algorithm gives a choice of simplification methods, including distance based (the "Douglas-Peucker" algorithm), area based ("Visvalingam" algorithm) and snapping geometries to grid.

qgis:singlepartstomultipart:


@@ -29,12 +29,13 @@

from qgis.PyQt.QtGui import QIcon

from qgis.core import Qgis, QgsFeature, QgsGeometry, QgsWkbTypes
from qgis.core import Qgis, QgsFeature, QgsGeometry, QgsWkbTypes, QgsMapToPixelSimplifier

from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.ProcessingLog import ProcessingLog
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterNumber
from processing.core.parameters import ParameterSelection
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector

@@ -46,6 +47,7 @@ class SimplifyGeometries(GeoAlgorithm):
INPUT = 'INPUT'
TOLERANCE = 'TOLERANCE'
OUTPUT = 'OUTPUT'
METHOD = 'METHOD'

def getIcon(self):
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'simplify.png'))
@@ -57,6 +59,13 @@ def defineCharacteristics(self):
self.addParameter(ParameterVector(self.INPUT,
self.tr('Input layer'),
[ParameterVector.VECTOR_TYPE_POLYGON, ParameterVector.VECTOR_TYPE_LINE]))
self.methods = [self.tr('Distance (Douglas-Peucker)'),
'Snap to grid',
'Area (Visvalingam)']
self.addParameter(ParameterSelection(
self.METHOD,
self.tr('Simplification method'),
self.methods, default=0))
self.addParameter(ParameterNumber(self.TOLERANCE,
self.tr('Tolerance'), 0.0, 10000000.0, 1.0))

@@ -65,6 +74,7 @@ def defineCharacteristics(self):
def processAlgorithm(self, progress):
layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
tolerance = self.getParameterValue(self.TOLERANCE)
method = self.getParameterValue(self.METHOD)

pointsBefore = 0
pointsAfter = 0
@@ -74,44 +84,27 @@ def processAlgorithm(self, progress):

features = vector.features(layer)
total = 100.0 / len(features)
for current, f in enumerate(features):
featGeometry = f.geometry()
attrs = f.attributes()
pointsBefore += self.geomVertexCount(featGeometry)
newGeometry = featGeometry.simplify(tolerance)
pointsAfter += self.geomVertexCount(newGeometry)
feature = QgsFeature()
feature.setGeometry(newGeometry)
feature.setAttributes(attrs)
writer.addFeature(feature)

if method != 0:
simplifier = QgsMapToPixelSimplifier(QgsMapToPixelSimplifier.SimplifyGeometry, tolerance, method)

for current, input_feature in enumerate(features):
out_feature = input_feature
if input_feature.geometry():
input_geometry = input_feature.geometry()
pointsBefore += input_geometry.geometry().nCoordinates()

if method == 0: # distance
output_geometry = input_geometry.simplify(tolerance)
else:
output_geometry = simplifier.simplify(input_geometry)

pointsAfter += output_geometry.geometry().nCoordinates()
out_feature.setGeometry(output_geometry)
writer.addFeature(out_feature)
progress.setPercentage(int(current * total))

del writer

ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
self.tr('Simplify: Input geometries have been simplified from %s to %s points' % (pointsBefore, pointsAfter)))

def geomVertexCount(self, geometry):
geomType = geometry.type()

if geomType == QgsWkbTypes.LineGeometry:
if geometry.isMultipart():
pointsList = geometry.asMultiPolyline()
points = sum(pointsList, [])
else:
points = geometry.asPolyline()
return len(points)
elif geomType == QgsWkbTypes.PolygonGeometry:
if geometry.isMultipart():
polylinesList = geometry.asMultiPolygon()
polylines = sum(polylinesList, [])
else:
polylines = geometry.asPolygon()

points = []
for l in polylines:
points.extend(l)

return len(points)
else:
return None
@@ -0,0 +1,15 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>simplify_grid_lines</Name>
<ElementPath>simplify_grid_lines</ElementPath>
<GeometryType>2</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>4</FeatureCount>
<ExtentXMin>-0.08703</ExtentXMin>
<ExtentXMax>10.63163</ExtentXMax>
<ExtentYMin>-0.26248</ExtentYMin>
<ExtentYMax>4.98546</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>-0.08703339882121899</gml:X><gml:Y>-0.262475442043224</gml:Y></gml:coord>
<gml:coord><gml:X>10.63163064833006</gml:X><gml:Y>4.985461689587426</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:simplify_grid_lines fid="1">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-0.062278978388999,4.985461689587426 5.606483300589391,4.985461689587426</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:simplify_grid_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_grid_lines fid="3">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-0.087033398821219,2.782318271119842 2.314145383104125,2.757563850687622 7.388801571709235,4.713163064833005 9.789980353634579,2.757563850687622 10.631630648330059,2.757563850687622</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:simplify_grid_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_grid_lines fid="2">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>0.061493123772101,-0.237721021611003 1.967583497053045,-0.262475442043224 4.34400785854617,2.262475442043221 6.448133595284873,-0.262475442043224 10.606876227897841,-0.188212180746563</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:simplify_grid_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_grid_lines fid="4">
</ogr:simplify_grid_lines>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,15 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>simplify_lines</Name>
<ElementPath>simplify_lines</ElementPath>
<GeometryType>2</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>7</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>11.00000</ExtentXMax>
<ExtentYMin>-3.00000</ExtentYMin>
<ExtentYMax>5.00000</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
<gml:coord><gml:X>11</gml:X><gml:Y>5</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:simplify_lines fid="lines.0">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,2 9,2 11,5</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:simplify_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_lines fid="lines.1">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:simplify_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_lines fid="lines.2">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,0 3,3</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:simplify_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_lines fid="lines.3">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,1 5,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:simplify_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_lines fid="lines.4">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,-3 10,-3</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:simplify_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_lines fid="lines.5">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,-3 10,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:simplify_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_lines fid="lines.6">
</ogr:simplify_lines>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,15 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>simplify_multilines</Name>
<ElementPath>simplify_multilines</ElementPath>
<GeometryType>5</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>4</FeatureCount>
<ExtentXMin>-1.00000</ExtentXMin>
<ExtentXMax>5.58042</ExtentXMax>
<ExtentYMin>-1.00000</ExtentYMin>
<ExtentYMax>4.11977</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>-1</gml:X><gml:Y>-1</gml:Y></gml:coord>
<gml:coord><gml:X>5.58042226487524</gml:X><gml:Y>4.119769673704415</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:simplify_multilines fid="lines.1">
<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:simplify_multilines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_multilines fid="lines.2">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>3,1 5,1</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>5.024184261036468,2.414779270633399 5,1</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:simplify_multilines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_multilines fid="lines.3">
</ogr:simplify_multilines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_multilines fid="lines.4">
<ogr:geometryProperty><gml:MultiLineString srsName="EPSG:4326"><gml:lineStringMember><gml:LineString><gml:coordinates>2,0 3,3</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>2.944337811900192,4.04721689059501 5.459500959692898,4.119769673704415</gml:coordinates></gml:LineString></gml:lineStringMember><gml:lineStringMember><gml:LineString><gml:coordinates>3,3 5.58042226487524,2.946833013435702</gml:coordinates></gml:LineString></gml:lineStringMember></gml:MultiLineString></ogr:geometryProperty>
</ogr:simplify_multilines>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -0,0 +1,15 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>simplify_vis_lines</Name>
<ElementPath>simplify_vis_lines</ElementPath>
<GeometryType>2</GeometryType>
<SRSName>EPSG:4326</SRSName>
<DatasetSpecificInfo>
<FeatureCount>4</FeatureCount>
<ExtentXMin>-0.08703</ExtentXMin>
<ExtentXMax>10.63163</ExtentXMax>
<ExtentYMin>-0.26248</ExtentYMin>
<ExtentYMax>4.98546</ExtentYMax>
</DatasetSpecificInfo>
</GMLFeatureClass>
</GMLFeatureClassList>
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy>
<gml:Box>
<gml:coord><gml:X>-0.08703339882121899</gml:X><gml:Y>-0.262475442043224</gml:Y></gml:coord>
<gml:coord><gml:X>10.63163064833006</gml:X><gml:Y>4.985461689587426</gml:Y></gml:coord>
</gml:Box>
</gml:boundedBy>

<gml:featureMember>
<ogr:simplify_vis_lines fid="1">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-0.062278978388999,4.985461689587426 5.606483300589391,4.985461689587426</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:simplify_vis_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_vis_lines fid="3">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-0.087033398821219,2.782318271119842 5.284675834970531,2.782318271119842 7.388801571709235,4.713163064833005 10.631630648330059,2.757563850687622</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:simplify_vis_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_vis_lines fid="2">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>0.061493123772101,-0.237721021611003 1.967583497053045,-0.262475442043224 4.34400785854617,2.262475442043221 6.448133595284873,-0.262475442043224 10.606876227897841,-0.188212180746563</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:simplify_vis_lines>
</gml:featureMember>
<gml:featureMember>
<ogr:simplify_vis_lines fid="4">
</ogr:simplify_vis_lines>
</gml:featureMember>
</ogr:FeatureCollection>
@@ -916,3 +916,52 @@ tests:
name: expected/extract_nodes_lines.gml
type: vector

- algorithm: qgis:simplifygeometries
name: Simplify (lines)
params:
INPUT:
name: lines.gml
type: vector
TOLERANCE: 1.0
results:
OUTPUT:
name: expected/simplify_lines.gml
type: vector

- algorithm: qgis:simplifygeometries
name: Simplify (multilines)
params:
INPUT:
name: multilines.gml
type: vector
TOLERANCE: 1.0
results:
OUTPUT:
name: expected/simplify_multilines.gml
type: vector

- algorithm: qgis:simplifygeometries
name: Simplify (visval)
params:
INPUT:
name: simplify_lines.gml
type: vector
METHOD: '2'
TOLERANCE: 1.0
results:
OUTPUT:
name: expected/simplify_vis_lines.gml
type: vector

- algorithm: qgis:simplifygeometries
name: Simplify (grid)
params:
INPUT:
name: simplify_lines.gml
type: vector
METHOD: '1'
TOLERANCE: 5.0
results:
OUTPUT:
name: expected/simplify_grid_lines.gml
type: vector

0 comments on commit 88047cc

Please sign in to comment.