Skip to content

Commit

Permalink
Fix dropping/adding z dimensions to certain output data types
Browse files Browse the repository at this point in the history
where the layer geometry type is defined by features, not preset
in advance

Fixes #20220, #17669
  • Loading branch information
nyalldawson committed Oct 26, 2018
1 parent 4bc561c commit 0f22a29
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/core/qgsvectorfilewriter.cpp
Expand Up @@ -2236,6 +2236,19 @@ gdal::ogr_feature_unique_ptr QgsVectorFileWriter::createFeature( const QgsFeatur
}
}

// drop m/z value if not present in output wkb type
if ( !QgsWkbTypes::hasZ( mWkbType ) && QgsWkbTypes::hasZ( geom.wkbType() ) )
geom.get()->dropZValue();
if ( !QgsWkbTypes::hasM( mWkbType ) && QgsWkbTypes::hasM( geom.wkbType() ) )
geom.get()->dropMValue();

// add m/z values if not present in the input wkb type -- this is needed for formats which determine
// geometry type based on features, e.g. geojson
if ( QgsWkbTypes::hasZ( mWkbType ) && !QgsWkbTypes::hasZ( geom.wkbType() ) )
geom.get()->addZValue( 0 );
if ( QgsWkbTypes::hasM( mWkbType ) && !QgsWkbTypes::hasM( geom.wkbType() ) )
geom.get()->addMValue( 0 );

if ( !mGeom2 )
{
// there's a problem when layer type is set as wkbtype Polygon
Expand Down
62 changes: 62 additions & 0 deletions tests/src/python/test_qgsvectorfilewriter.py
Expand Up @@ -982,6 +982,68 @@ def testCreateDGN(self):

os.unlink(filename)

def testAddZ(self):
"""Check adding z values to non z input."""
input = QgsVectorLayer(
'Point?crs=epsg:4326&field=name:string(20)',
'test',
'memory')

self.assertTrue(input.isValid(), 'Provider not initialized')

ft = QgsFeature()
ft.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10, 10)))
myResult, myFeatures = input.dataProvider().addFeatures([ft])
self.assertTrue(myResult)
self.assertTrue(myFeatures)

dest_file_name = os.path.join(str(QDir.tempPath()), 'add_z.geojson')
options = QgsVectorFileWriter.SaveVectorOptions()
options.overrideGeometryType = QgsWkbTypes.PointZ
options.driverName = 'GeoJSON'
write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
input,
dest_file_name,
options)
self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message)

# Open result and check
created_layer = QgsVectorLayer(dest_file_name, 'test', 'ogr')
self.assertTrue(created_layer.isValid())
f = next(created_layer.getFeatures(QgsFeatureRequest()))
self.assertEqual(f.geometry().asWkt(), 'PointZ (10 10 0)')

def testDropZ(self):
"""Check dropping z values input."""
input = QgsVectorLayer(
'PointZ?crs=epsg:4326&field=name:string(20)',
'test',
'memory')

self.assertTrue(input.isValid(), 'Provider not initialized')

ft = QgsFeature()
ft.setGeometry(QgsGeometry.fromWkt('PointM(10 10 2)'))
myResult, myFeatures = input.dataProvider().addFeatures([ft])
self.assertTrue(myResult)
self.assertTrue(myFeatures)

dest_file_name = os.path.join(str(QDir.tempPath()), 'drop_z.geojson')
options = QgsVectorFileWriter.SaveVectorOptions()
options.overrideGeometryType = QgsWkbTypes.PointM
options.driverName = 'GeoJSON'
write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
input,
dest_file_name,
options)
self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message)

# Open result and check
created_layer = QgsVectorLayer(dest_file_name, 'test', 'ogr')
self.assertTrue(created_layer.isValid())
f = next(created_layer.getFeatures(QgsFeatureRequest()))
self.assertEqual(f.geometry().asWkt(), 'Point (10 10)')


if __name__ == '__main__':
unittest.main()

0 comments on commit 0f22a29

Please sign in to comment.