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
This commit is contained in:
Nyall Dawson 2018-10-26 10:30:25 +10:00
parent 4bc561cc5c
commit 0f22a29b9d
2 changed files with 75 additions and 0 deletions

View File

@ -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

View File

@ -982,6 +982,68 @@ class TestQgsVectorFileWriter(unittest.TestCase):
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()