Skip to content

Commit

Permalink
[processing] Fix error when running delete duplicate geometries and
Browse files Browse the repository at this point in the history
some input features have null geometries

Fixes #20788

(cherry picked from commit 82c13bd)
  • Loading branch information
nyalldawson committed Dec 15, 2018
1 parent 489f32d commit 06c5bee
Show file tree
Hide file tree
Showing 4 changed files with 94 additions and 4 deletions.
16 changes: 12 additions & 4 deletions python/plugins/processing/algs/qgis/DeleteDuplicateGeometries.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,16 @@ def processAlgorithm(self, parameters, context, feedback):

total = 100.0 / source.featureCount() if source.featureCount() else 0
geoms = dict()
null_geom_features = set()
index = QgsSpatialIndex()
for current, f in enumerate(features):
if feedback.isCanceled():
break

if not f.hasGeometry():
null_geom_features.add(f.id())
continue

geoms[f.id()] = f.geometry()
index.addFeature(f)

Expand Down Expand Up @@ -112,17 +117,20 @@ def processAlgorithm(self, parameters, context, feedback):
current += 1
feedback.setProgress(int(0.80 * current * total) + 10) # takes about 80% of time

total = 100.0 / len(unique_features) if unique_features else 1

# now, fetch all the feature attributes for the unique features only
# be super-smart and don't re-fetch geometries
request = QgsFeatureRequest().setFilterFids(list(unique_features.keys())).setFlags(QgsFeatureRequest.NoGeometry)
distinct_geoms = set(unique_features.keys())
output_feature_ids = distinct_geoms.union(null_geom_features)
total = 100.0 / len(output_feature_ids) if output_feature_ids else 1

request = QgsFeatureRequest().setFilterFids(list(output_feature_ids)).setFlags(QgsFeatureRequest.NoGeometry)
for current, f in enumerate(source.getFeatures(request)):
if feedback.isCanceled():
break

# use already fetched geometry
f.setGeometry(unique_features[f.id()])
if f.id() not in null_geom_features:
f.setGeometry(unique_features[f.id()])
sink.addFeature(f, QgsFeatureSink.FastInsert)

feedback.setProgress(int(0.10 * current * total) + 90) # takes about 10% of time
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://ogr.maptools.org/ delete_duplicates_with_nulls.xsd"
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:delete_duplicates_with_nulls 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:delete_duplicates_with_nulls>
</gml:featureMember>
<gml:featureMember>
<ogr:delete_duplicates_with_nulls fid="lines.1">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>-1,-1 1,-1</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:delete_duplicates_with_nulls>
</gml:featureMember>
<gml:featureMember>
<ogr:delete_duplicates_with_nulls 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:delete_duplicates_with_nulls>
</gml:featureMember>
<gml:featureMember>
<ogr:delete_duplicates_with_nulls fid="lines.3">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>3,1 5,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:delete_duplicates_with_nulls>
</gml:featureMember>
<gml:featureMember>
<ogr:delete_duplicates_with_nulls fid="lines.4">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>7,-3 10,-3</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:delete_duplicates_with_nulls>
</gml:featureMember>
<gml:featureMember>
<ogr:delete_duplicates_with_nulls fid="lines.5">
<ogr:geometryProperty><gml:LineString srsName="EPSG:4326"><gml:coordinates>6,-3 10,1</gml:coordinates></gml:LineString></ogr:geometryProperty>
</ogr:delete_duplicates_with_nulls>
</gml:featureMember>
<gml:featureMember>
<ogr:delete_duplicates_with_nulls fid="lines.6">
</ogr:delete_duplicates_with_nulls>
</gml:featureMember>
</ogr:FeatureCollection>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<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">
<xs:import namespace="http://www.opengis.net/gml" schemaLocation="http://schemas.opengis.net/gml/2.1.2/feature.xsd"/>
<xs:element name="FeatureCollection" type="ogr:FeatureCollectionType" substitutionGroup="gml:_FeatureCollection"/>
<xs:complexType name="FeatureCollectionType">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureCollectionType">
<xs:attribute name="lockId" type="xs:string" use="optional"/>
<xs:attribute name="scope" type="xs:string" use="optional"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="delete_duplicates_with_nulls" type="ogr:delete_duplicates_with_nulls_Type" substitutionGroup="gml:_Feature"/>
<xs:complexType name="delete_duplicates_with_nulls_Type">
<xs:complexContent>
<xs:extension base="gml:AbstractFeatureType">
<xs:sequence>
<xs:element name="geometryProperty" type="gml:LineStringPropertyType" nillable="true" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:schema>
11 changes: 11 additions & 0 deletions python/plugins/processing/tests/testdata/qgis_algorithm_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6269,4 +6269,15 @@ tests:
fields:
path: skip

- algorithm: qgis:deleteduplicategeometries
name: Delete Duplicates with null geometries
params:
INPUT:
name: lines.gml|layername=lines
type: vector
results:
OUTPUT:
name: expected/delete_duplicates_with_nulls.gml
type: vector

# See ../README.md for a description of the file format

0 comments on commit 06c5bee

Please sign in to comment.