Skip to content

Commit e4d745f

Browse files
committedMay 15, 2017
[processing] handle NULL values in the single to multi algorithm (fix #15822)
1 parent fd7b52d commit e4d745f

File tree

6 files changed

+192
-17
lines changed

6 files changed

+192
-17
lines changed
 

‎python/plugins/processing/algs/qgis/SinglePartsToMultiparts.py

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
from qgis.PyQt.QtGui import QIcon
3131

32-
from qgis.core import QGis, QgsFeature, QgsGeometry
32+
from qgis.core import QGis, QgsFeature, QgsGeometry, NULL
3333

3434
from processing.core.GeoAlgorithm import GeoAlgorithm
3535
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
@@ -80,14 +80,26 @@ def processAlgorithm(self, progress):
8080
current = 0
8181
features = vector.features(layer)
8282
total = 100.0 / (len(features) * len(unique))
83+
84+
nullFeatures = []
8385
if not len(unique) == layer.featureCount():
8486
for i in unique:
85-
multi_feature = []
8687
first = True
88+
multi_feature = []
8789
features = vector.features(layer)
8890
for inFeat in features:
8991
atMap = inFeat.attributes()
9092
idVar = atMap[index]
93+
if idVar in [None, NULL] and inFeat.id() not in nullFeatures:
94+
nullFeatures.append(inFeat.id())
95+
outGeom = QgsGeometry(inFeat.geometry())
96+
outFeat.setAttributes(atMap)
97+
outFeat.setGeometry(outGeom)
98+
writer.addFeature(outFeat)
99+
current += 1
100+
progress.setPercentage(int(current * total))
101+
continue
102+
91103
if unicode(idVar).strip() == unicode(i).strip():
92104
if first:
93105
attrs = atMap
@@ -100,11 +112,12 @@ def processAlgorithm(self, progress):
100112
current += 1
101113
progress.setPercentage(int(current * total))
102114

103-
outFeat.setAttributes(attrs)
104-
outGeom = QgsGeometry(self.convertGeometry(multi_feature,
105-
vType))
106-
outFeat.setGeometry(outGeom)
107-
writer.addFeature(outFeat)
115+
if len(multi_feature) > 0:
116+
outGeom = QgsGeometry(
117+
self.convertGeometry(multi_feature, vType))
118+
outFeat.setGeometry(outGeom)
119+
outFeat.setAttributes(attrs)
120+
writer.addFeature(outFeat)
108121

109122
del writer
110123
else:
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<GMLFeatureClassList>
2+
<GMLFeatureClass>
3+
<Name>single_part_poly</Name>
4+
<ElementPath>single_part_poly</ElementPath>
5+
<!--POLYGON-->
6+
<GeometryType>3</GeometryType>
7+
<SRSName>EPSG:4326</SRSName>
8+
<DatasetSpecificInfo>
9+
<FeatureCount>7</FeatureCount>
10+
<ExtentXMin>0.21020</ExtentXMin>
11+
<ExtentXMax>8.96288</ExtentXMax>
12+
<ExtentYMin>-5.48232</ExtentYMin>
13+
<ExtentYMax>7.16399</ExtentYMax>
14+
</DatasetSpecificInfo>
15+
<PropertyDefn>
16+
<Name>id</Name>
17+
<ElementPath>id</ElementPath>
18+
<Type>Integer</Type>
19+
</PropertyDefn>
20+
</GMLFeatureClass>
21+
</GMLFeatureClassList>
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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.2101967462686566</gml:X><gml:Y>-5.482323358208955</gml:Y></gml:coord>
10+
<gml:coord><gml:X>8.962880985074626</gml:X><gml:Y>7.163993643533122</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:single_part_poly fid="single_part_poly.0">
16+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0.80194134384858,7.16399364353312 0.672499728706625,4.76932376340694 5.20295625867508,4.2839177066246 5.26276665671642,6.74081294029851 0.80194134384858,7.16399364353312</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
17+
<ogr:id></ogr:id>
18+
</ogr:single_part_poly>
19+
</gml:featureMember>
20+
<gml:featureMember>
21+
<ogr:single_part_poly fid="single_part_poly.1">
22+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6.30900588059701,4.21452798507463 6.00278952238806,2.60689210447761 8.4525203880597,1.81583317910448 8.96288098507463,4.26556404477612 8.24837614925373,7.04702929850746 6.30900588059701,4.21452798507463</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
23+
<ogr:id>1</ogr:id>
24+
</ogr:single_part_poly>
25+
</gml:featureMember>
26+
<gml:featureMember>
27+
<ogr:single_part_poly fid="single_part_poly.2">
28+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3.96134713432836,1.68824302985075 3.93582910447761,-1.14425828358209 8.27389417910448,-1.50151070149254 8.120786,0.64200380597015 3.96134713432836,1.68824302985075</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
29+
<ogr:id>1</ogr:id>
30+
</ogr:single_part_poly>
31+
</gml:featureMember>
32+
<gml:featureMember>
33+
<ogr:single_part_poly fid="single_part_poly.3">
34+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>1.69024247761194,3.0406986119403 1.9454227761194,1.48409879104478 3.47650456716418,2.47930195522388 3.45098653731343,3.52554117910448 1.69024247761194,3.0406986119403</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
35+
<ogr:id>2</ogr:id>
36+
</ogr:single_part_poly>
37+
</gml:featureMember>
38+
<gml:featureMember>
39+
<ogr:single_part_poly fid="single_part_poly.4">
40+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>1.46058020895522,-2.93052037313433 2.40474731343284,-5.48232335820895 6.02830755223881,-4.35953004477612 6.411078,-2.57326795522388 1.46058020895522,-2.93052037313433</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
41+
<ogr:id>2</ogr:id>
42+
</ogr:single_part_poly>
43+
</gml:featureMember>
44+
<gml:featureMember>
45+
<ogr:single_part_poly fid="single_part_poly.5">
46+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0.592967194029851,-0.17457314925373 1.58817035820896,-2.06290735820895 2.37922928358209,-1.3739205522388 2.63440958208955,0.284751388059703 0.592967194029851,-0.17457314925373</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
47+
<ogr:id>3</ogr:id>
48+
</ogr:single_part_poly>
49+
</gml:featureMember>
50+
<gml:featureMember>
51+
<ogr:single_part_poly fid="single_part_poly.6">
52+
<ogr:geometryProperty><gml:Polygon srsName="EPSG:4326"><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0.210196746268657,2.19860362686567 0.439859014925373,1.05029228358209 1.15436385074627,1.02477425373134 0.720557343283582,4.0359017761194 0.210196746268657,2.19860362686567</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></ogr:geometryProperty>
53+
<ogr:id>4</ogr:id>
54+
</ogr:single_part_poly>
55+
</gml:featureMember>
56+
</ogr:FeatureCollection>
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<ogr:FeatureCollection
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://ogr.maptools.org/ single_to_multi.xsd"
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.210196746268657</gml:X><gml:Y>-5.48232335820895</gml:Y></gml:coord>
10+
<gml:coord><gml:X>8.96288098507463</gml:X><gml:Y>7.16399364353312</gml:Y></gml:coord>
11+
</gml:Box>
12+
</gml:boundedBy>
13+
14+
<gml:featureMember>
15+
<ogr:single_to_multi fid="single_part_poly.0">
16+
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0.80194134384858,7.16399364353312 0.672499728706625,4.76932376340694 5.20295625867508,4.2839177066246 5.26276665671642,6.74081294029851 0.80194134384858,7.16399364353312</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
17+
</ogr:single_to_multi>
18+
</gml:featureMember>
19+
<gml:featureMember>
20+
<ogr:single_to_multi fid="single_part_poly.1">
21+
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>6.30900588059701,4.21452798507463 6.00278952238806,2.60689210447761 8.4525203880597,1.81583317910448 8.96288098507463,4.26556404477612 8.24837614925373,7.04702929850746 6.30900588059701,4.21452798507463</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>3.96134713432836,1.68824302985075 3.93582910447761,-1.14425828358209 8.27389417910448,-1.50151070149254 8.120786,0.64200380597015 3.96134713432836,1.68824302985075</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
22+
<ogr:id>1</ogr:id>
23+
</ogr:single_to_multi>
24+
</gml:featureMember>
25+
<gml:featureMember>
26+
<ogr:single_to_multi fid="single_part_poly.3">
27+
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>1.69024247761194,3.0406986119403 1.9454227761194,1.48409879104478 3.47650456716418,2.47930195522388 3.45098653731343,3.52554117910448 1.69024247761194,3.0406986119403</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>1.46058020895522,-2.93052037313433 2.40474731343284,-5.48232335820895 6.02830755223881,-4.35953004477612 6.411078,-2.57326795522388 1.46058020895522,-2.93052037313433</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
28+
<ogr:id>2</ogr:id>
29+
</ogr:single_to_multi>
30+
</gml:featureMember>
31+
<gml:featureMember>
32+
<ogr:single_to_multi fid="single_part_poly.5">
33+
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0.592967194029851,-0.17457314925373 1.58817035820896,-2.06290735820895 2.37922928358209,-1.3739205522388 2.63440958208955,0.284751388059703 0.592967194029851,-0.17457314925373</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
34+
<ogr:id>3</ogr:id>
35+
</ogr:single_to_multi>
36+
</gml:featureMember>
37+
<gml:featureMember>
38+
<ogr:single_to_multi fid="single_part_poly.6">
39+
<ogr:geometryProperty><gml:MultiPolygon srsName="EPSG:4326"><gml:polygonMember><gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>0.210196746268657,2.19860362686567 0.439859014925373,1.05029228358209 1.15436385074627,1.02477425373134 0.720557343283582,4.0359017761194 0.210196746268657,2.19860362686567</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs></gml:Polygon></gml:polygonMember></gml:MultiPolygon></ogr:geometryProperty>
40+
<ogr:id>4</ogr:id>
41+
</ogr:single_to_multi>
42+
</gml:featureMember>
43+
</ogr:FeatureCollection>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<xs:schema targetNamespace="http://ogr.maptools.org/" xmlns:ogr="http://ogr.maptools.org/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:gml="http://www.opengis.net/gml" elementFormDefault="qualified" version="1.0">
3+
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
4+
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
5+
<xs:complexType name="FeatureCollectionType">
6+
<xs:complexContent>
7+
<xs:extension base="gml:AbstractFeatureCollectionType">
8+
<xs:attribute name="lockId" type="xs:string" use="optional"/>
9+
<xs:attribute name="scope" type="xs:string" use="optional"/>
10+
</xs:extension>
11+
</xs:complexContent>
12+
</xs:complexType>
13+
<xs:element name="single_to_multi" type="ogr:single_to_multi_Type" substitutionGroup="gml:_Feature"/>
14+
<xs:complexType name="single_to_multi_Type">
15+
<xs:complexContent>
16+
<xs:extension base="gml:AbstractFeatureType">
17+
<xs:sequence>
18+
<xs:element name="geometryProperty" type="gml:MultiPolygonPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
19+
<xs:element name="id" nillable="true" minOccurs="0" maxOccurs="1">
20+
<xs:simpleType>
21+
<xs:restriction base="xs:integer">
22+
<xs:totalDigits value="10"/>
23+
</xs:restriction>
24+
</xs:simpleType>
25+
</xs:element>
26+
</xs:sequence>
27+
</xs:extension>
28+
</xs:complexContent>
29+
</xs:complexType>
30+
</xs:schema>

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

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ tests:
2323
OUTPUT:
2424
name: expected/polys_deleteholes.gml
2525
type: vector
26-
26+
2727
- algorithm: qgis:clip
2828
name: Clip lines by polygons
2929
params:
@@ -37,8 +37,8 @@ tests:
3737
OUTPUT:
3838
name: expected/clip_lines_by_polygon.gml
3939
type: vector
40-
41-
40+
41+
4242
- algorithm: qgis:clip
4343
name: Clip lines by multipolygon
4444
params:
@@ -52,7 +52,7 @@ tests:
5252
OUTPUT:
5353
name: expected/clip_lines_by_multipolygon.gml
5454
type: vector
55-
55+
5656
- algorithm: qgis:clip
5757
name: Clip polygons by multipolygons
5858
params:
@@ -66,7 +66,7 @@ tests:
6666
OUTPUT:
6767
name: expected/clip_polys_by_multipolygon.gml
6868
type: vector
69-
69+
7070
- algorithm: qgis:clip
7171
name: Clip multipolygons by polygons
7272
params:
@@ -80,7 +80,7 @@ tests:
8080
OUTPUT:
8181
name: expected/clip_multipolygons_by_polygons.gml
8282
type: vector
83-
83+
8484
- algorithm: qgis:clip
8585
name: Clip points by polygons
8686
params:
@@ -94,7 +94,7 @@ tests:
9494
OUTPUT:
9595
name: expected/clip_points_by_polygons.gml
9696
type: vector
97-
97+
9898
- algorithm: qgis:clip
9999
name: Clip points by multipolygons
100100
params:
@@ -108,8 +108,8 @@ tests:
108108
OUTPUT:
109109
name: expected/clip_points_by_multipolygons.gml
110110
type: vector
111-
112-
111+
112+
113113
# These datasets should produce a geometry collection and not a polygon only
114114
# dataset. If the algorithm is fixed, a new test should be introduced to
115115
# check this behavior.
@@ -440,7 +440,7 @@ tests:
440440
OUTPUT:
441441
name: expected/multi_to_single.gml
442442
type: vector
443-
443+
444444
- algorithm: qgis:boundingboxes
445445
name: Bounding boxes for lines
446446
params:
@@ -602,3 +602,15 @@ tests:
602602
# (features could be written in different order and still being correct output)
603603
# - geometry equality comparison instead of WKT string comparison
604604
# (geometries could different order of coordinate but still being correct output)
605+
606+
- algorithm: qgis:singlepartstomultipart
607+
name: Singleparts to multiparts
608+
params:
609+
INPUT:
610+
name: custom/single_part_poly.gml
611+
type: vector
612+
FIELD: id
613+
results:
614+
OUTPUT:
615+
name: expected/single_to_multi.gml
616+
type: vector

0 commit comments

Comments
 (0)