Skip to content

Commit 88047cc

Browse files
authored
Merge pull request #3441 from nyalldawson/simplify
Simplify features + fixes
2 parents 798817e + 56b77db commit 88047cc

20 files changed

+446
-127
lines changed

python/core/qgsmaptopixelgeometrysimplifier.sip

+3
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ class QgsMapToPixelSimplifier : QgsAbstractGeometrySimplifier
4343
//! Sets the local simplification algorithm of the vector layer managed
4444
void setSimplifyAlgorithm( SimplifyAlgorithm simplifyAlgorithm );
4545

46+
//! Returns a simplified version the specified geometry
47+
virtual QgsGeometry simplify( const QgsGeometry& geometry ) const;
48+
4649
//! Sets the tolerance of the vector layer managed
4750
void setTolerance( double value );
4851

python/plugins/processing/algs/help/qgis.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,8 @@ qgis:setstyleforvectorlayer: >
429429
qgis:simplifygeometries: >
430430
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.
431431

432+
The algorithm gives a choice of simplification methods, including distance based (the "Douglas-Peucker" algorithm), area based ("Visvalingam" algorithm) and snapping geometries to grid.
433+
432434
qgis:singlepartstomultipart:
433435

434436

python/plugins/processing/algs/qgis/SimplifyGeometries.py

+29-36
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@
2929

3030
from qgis.PyQt.QtGui import QIcon
3131

32-
from qgis.core import Qgis, QgsFeature, QgsGeometry, QgsWkbTypes
32+
from qgis.core import Qgis, QgsFeature, QgsGeometry, QgsWkbTypes, QgsMapToPixelSimplifier
3333

3434
from processing.core.GeoAlgorithm import GeoAlgorithm
3535
from processing.core.ProcessingLog import ProcessingLog
3636
from processing.core.parameters import ParameterVector
3737
from processing.core.parameters import ParameterNumber
38+
from processing.core.parameters import ParameterSelection
3839
from processing.core.outputs import OutputVector
3940
from processing.tools import dataobjects, vector
4041

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

5052
def getIcon(self):
5153
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'simplify.png'))
@@ -57,6 +59,13 @@ def defineCharacteristics(self):
5759
self.addParameter(ParameterVector(self.INPUT,
5860
self.tr('Input layer'),
5961
[ParameterVector.VECTOR_TYPE_POLYGON, ParameterVector.VECTOR_TYPE_LINE]))
62+
self.methods = [self.tr('Distance (Douglas-Peucker)'),
63+
'Snap to grid',
64+
'Area (Visvalingam)']
65+
self.addParameter(ParameterSelection(
66+
self.METHOD,
67+
self.tr('Simplification method'),
68+
self.methods, default=0))
6069
self.addParameter(ParameterNumber(self.TOLERANCE,
6170
self.tr('Tolerance'), 0.0, 10000000.0, 1.0))
6271

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

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

7585
features = vector.features(layer)
7686
total = 100.0 / len(features)
77-
for current, f in enumerate(features):
78-
featGeometry = f.geometry()
79-
attrs = f.attributes()
80-
pointsBefore += self.geomVertexCount(featGeometry)
81-
newGeometry = featGeometry.simplify(tolerance)
82-
pointsAfter += self.geomVertexCount(newGeometry)
83-
feature = QgsFeature()
84-
feature.setGeometry(newGeometry)
85-
feature.setAttributes(attrs)
86-
writer.addFeature(feature)
87+
88+
if method != 0:
89+
simplifier = QgsMapToPixelSimplifier(QgsMapToPixelSimplifier.SimplifyGeometry, tolerance, method)
90+
91+
for current, input_feature in enumerate(features):
92+
out_feature = input_feature
93+
if input_feature.geometry():
94+
input_geometry = input_feature.geometry()
95+
pointsBefore += input_geometry.geometry().nCoordinates()
96+
97+
if method == 0: # distance
98+
output_geometry = input_geometry.simplify(tolerance)
99+
else:
100+
output_geometry = simplifier.simplify(input_geometry)
101+
102+
pointsAfter += output_geometry.geometry().nCoordinates()
103+
out_feature.setGeometry(output_geometry)
104+
writer.addFeature(out_feature)
87105
progress.setPercentage(int(current * total))
88106

89107
del writer
90108

91109
ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
92110
self.tr('Simplify: Input geometries have been simplified from %s to %s points' % (pointsBefore, pointsAfter)))
93-
94-
def geomVertexCount(self, geometry):
95-
geomType = geometry.type()
96-
97-
if geomType == QgsWkbTypes.LineGeometry:
98-
if geometry.isMultipart():
99-
pointsList = geometry.asMultiPolyline()
100-
points = sum(pointsList, [])
101-
else:
102-
points = geometry.asPolyline()
103-
return len(points)
104-
elif geomType == QgsWkbTypes.PolygonGeometry:
105-
if geometry.isMultipart():
106-
polylinesList = geometry.asMultiPolygon()
107-
polylines = sum(polylinesList, [])
108-
else:
109-
polylines = geometry.asPolygon()
110-
111-
points = []
112-
for l in polylines:
113-
points.extend(l)
114-
115-
return len(points)
116-
else:
117-
return None
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>simplify_grid_lines</Name>
4+
<ElementPath>simplify_grid_lines</ElementPath>
5+
<GeometryType>2</GeometryType>
6+
<SRSName>EPSG:4326</SRSName>
7+
<DatasetSpecificInfo>
8+
<FeatureCount>4</FeatureCount>
9+
<ExtentXMin>-0.08703</ExtentXMin>
10+
<ExtentXMax>10.63163</ExtentXMax>
11+
<ExtentYMin>-0.26248</ExtentYMin>
12+
<ExtentYMax>4.98546</ExtentYMax>
13+
</DatasetSpecificInfo>
14+
</GMLFeatureClass>
15+
</GMLFeatureClassList>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation=""
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-0.08703339882121899</gml:X><gml:Y>-0.262475442043224</gml:Y></gml:coord>
10+
<gml:coord><gml:X>10.63163064833006</gml:X><gml:Y>4.985461689587426</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:simplify_grid_lines fid="1">
16+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-0.062278978388999,4.985461689587426 5.606483300589391,4.985461689587426</gml:coordinates></gml:LineString></ogr:geometryProperty>
17+
</ogr:simplify_grid_lines>
18+
</gml:featureMember>
19+
<gml:featureMember>
20+
<ogr:simplify_grid_lines fid="3">
21+
<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>
22+
</ogr:simplify_grid_lines>
23+
</gml:featureMember>
24+
<gml:featureMember>
25+
<ogr:simplify_grid_lines fid="2">
26+
<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>
27+
</ogr:simplify_grid_lines>
28+
</gml:featureMember>
29+
<gml:featureMember>
30+
<ogr:simplify_grid_lines fid="4">
31+
</ogr:simplify_grid_lines>
32+
</gml:featureMember>
33+
</ogr:FeatureCollection>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>simplify_lines</Name>
4+
<ElementPath>simplify_lines</ElementPath>
5+
<GeometryType>2</GeometryType>
6+
<SRSName>EPSG:4326</SRSName>
7+
<DatasetSpecificInfo>
8+
<FeatureCount>7</FeatureCount>
9+
<ExtentXMin>-1.00000</ExtentXMin>
10+
<ExtentXMax>11.00000</ExtentXMax>
11+
<ExtentYMin>-3.00000</ExtentYMin>
12+
<ExtentYMax>5.00000</ExtentYMax>
13+
</DatasetSpecificInfo>
14+
</GMLFeatureClass>
15+
</GMLFeatureClassList>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation=""
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-1</gml:X><gml:Y>-3</gml:Y></gml:coord>
10+
<gml:coord><gml:X>11</gml:X><gml:Y>5</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:simplify_lines fid="lines.0">
16+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,2 9,2 11,5</gml:coordinates></gml:LineString></ogr:geometryProperty>
17+
</ogr:simplify_lines>
18+
</gml:featureMember>
19+
<gml:featureMember>
20+
<ogr:simplify_lines fid="lines.1">
21+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
22+
</ogr:simplify_lines>
23+
</gml:featureMember>
24+
<gml:featureMember>
25+
<ogr:simplify_lines fid="lines.2">
26+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>2,0 3,3</gml:coordinates></gml:LineString></ogr:geometryProperty>
27+
</ogr:simplify_lines>
28+
</gml:featureMember>
29+
<gml:featureMember>
30+
<ogr:simplify_lines fid="lines.3">
31+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,1 5,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
32+
</ogr:simplify_lines>
33+
</gml:featureMember>
34+
<gml:featureMember>
35+
<ogr:simplify_lines fid="lines.4">
36+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,-3 10,-3</gml:coordinates></gml:LineString></ogr:geometryProperty>
37+
</ogr:simplify_lines>
38+
</gml:featureMember>
39+
<gml:featureMember>
40+
<ogr:simplify_lines fid="lines.5">
41+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,-3 10,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
42+
</ogr:simplify_lines>
43+
</gml:featureMember>
44+
<gml:featureMember>
45+
<ogr:simplify_lines fid="lines.6">
46+
</ogr:simplify_lines>
47+
</gml:featureMember>
48+
</ogr:FeatureCollection>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>simplify_multilines</Name>
4+
<ElementPath>simplify_multilines</ElementPath>
5+
<GeometryType>5</GeometryType>
6+
<SRSName>EPSG:4326</SRSName>
7+
<DatasetSpecificInfo>
8+
<FeatureCount>4</FeatureCount>
9+
<ExtentXMin>-1.00000</ExtentXMin>
10+
<ExtentXMax>5.58042</ExtentXMax>
11+
<ExtentYMin>-1.00000</ExtentYMin>
12+
<ExtentYMax>4.11977</ExtentYMax>
13+
</DatasetSpecificInfo>
14+
</GMLFeatureClass>
15+
</GMLFeatureClassList>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation=""
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-1</gml:X><gml:Y>-1</gml:Y></gml:coord>
10+
<gml:coord><gml:X>5.58042226487524</gml:X><gml:Y>4.119769673704415</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:simplify_multilines fid="lines.1">
16+
<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>
17+
</ogr:simplify_multilines>
18+
</gml:featureMember>
19+
<gml:featureMember>
20+
<ogr:simplify_multilines fid="lines.2">
21+
<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>
22+
</ogr:simplify_multilines>
23+
</gml:featureMember>
24+
<gml:featureMember>
25+
<ogr:simplify_multilines fid="lines.3">
26+
</ogr:simplify_multilines>
27+
</gml:featureMember>
28+
<gml:featureMember>
29+
<ogr:simplify_multilines fid="lines.4">
30+
<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>
31+
</ogr:simplify_multilines>
32+
</gml:featureMember>
33+
</ogr:FeatureCollection>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>simplify_vis_lines</Name>
4+
<ElementPath>simplify_vis_lines</ElementPath>
5+
<GeometryType>2</GeometryType>
6+
<SRSName>EPSG:4326</SRSName>
7+
<DatasetSpecificInfo>
8+
<FeatureCount>4</FeatureCount>
9+
<ExtentXMin>-0.08703</ExtentXMin>
10+
<ExtentXMax>10.63163</ExtentXMax>
11+
<ExtentYMin>-0.26248</ExtentYMin>
12+
<ExtentYMax>4.98546</ExtentYMax>
13+
</DatasetSpecificInfo>
14+
</GMLFeatureClass>
15+
</GMLFeatureClassList>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation=""
5+
xmlns:ogr="http://ogr.maptools.org/"
6+
xmlns:gml="http://www.opengis.net/gml">
7+
<gml:boundedBy>
8+
<gml:Box>
9+
<gml:coord><gml:X>-0.08703339882121899</gml:X><gml:Y>-0.262475442043224</gml:Y></gml:coord>
10+
<gml:coord><gml:X>10.63163064833006</gml:X><gml:Y>4.985461689587426</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:simplify_vis_lines fid="1">
16+
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-0.062278978388999,4.985461689587426 5.606483300589391,4.985461689587426</gml:coordinates></gml:LineString></ogr:geometryProperty>
17+
</ogr:simplify_vis_lines>
18+
</gml:featureMember>
19+
<gml:featureMember>
20+
<ogr:simplify_vis_lines fid="3">
21+
<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>
22+
</ogr:simplify_vis_lines>
23+
</gml:featureMember>
24+
<gml:featureMember>
25+
<ogr:simplify_vis_lines fid="2">
26+
<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>
27+
</ogr:simplify_vis_lines>
28+
</gml:featureMember>
29+
<gml:featureMember>
30+
<ogr:simplify_vis_lines fid="4">
31+
</ogr:simplify_vis_lines>
32+
</gml:featureMember>
33+
</ogr:FeatureCollection>

python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml

+49
Original file line numberDiff line numberDiff line change
@@ -916,3 +916,52 @@ tests:
916916
name: expected/extract_nodes_lines.gml
917917
type: vector
918918

919+
- algorithm: qgis:simplifygeometries
920+
name: Simplify (lines)
921+
params:
922+
INPUT:
923+
name: lines.gml
924+
type: vector
925+
TOLERANCE: 1.0
926+
results:
927+
OUTPUT:
928+
name: expected/simplify_lines.gml
929+
type: vector
930+
931+
- algorithm: qgis:simplifygeometries
932+
name: Simplify (multilines)
933+
params:
934+
INPUT:
935+
name: multilines.gml
936+
type: vector
937+
TOLERANCE: 1.0
938+
results:
939+
OUTPUT:
940+
name: expected/simplify_multilines.gml
941+
type: vector
942+
943+
- algorithm: qgis:simplifygeometries
944+
name: Simplify (visval)
945+
params:
946+
INPUT:
947+
name: simplify_lines.gml
948+
type: vector
949+
METHOD: '2'
950+
TOLERANCE: 1.0
951+
results:
952+
OUTPUT:
953+
name: expected/simplify_vis_lines.gml
954+
type: vector
955+
956+
- algorithm: qgis:simplifygeometries
957+
name: Simplify (grid)
958+
params:
959+
INPUT:
960+
name: simplify_lines.gml
961+
type: vector
962+
METHOD: '1'
963+
TOLERANCE: 5.0
964+
results:
965+
OUTPUT:
966+
name: expected/simplify_grid_lines.gml
967+
type: vector

0 commit comments

Comments
 (0)