Skip to content
Permalink
Browse files

Fix dropping/adding z dimensions to certain output data types

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 0f22a29b9dccd13010d300bf101ab46cda813dc0
Showing with 75 additions and 0 deletions.
  1. +13 −0 src/core/qgsvectorfilewriter.cpp
  2. +62 −0 tests/src/python/test_qgsvectorfilewriter.py
@@ -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
@@ -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.
You can’t perform that action at this time.