Skip to content
Permalink
Browse files

Fix saving vector layers with z dimension (fix #14006, #12373)

  • Loading branch information
nyalldawson committed Feb 26, 2016
1 parent 1b22dcc commit 4e4743a2cd4d09e218a1335d8fde6b837e63c8b3
Showing with 92 additions and 5 deletions.
  1. +3 −3 src/core/qgsvectorfilewriter.cpp
  2. +89 −2 tests/src/python/test_qgsvectorfilewriter.py
@@ -281,7 +281,7 @@ void QgsVectorFileWriter::init( QString vectorFileName, QString fileEncoding, co

// datasource created, now create the output layer
QString layerName = QFileInfo( vectorFileName ).baseName();
OGRwkbGeometryType wkbType = static_cast<OGRwkbGeometryType>( geometryType );
OGRwkbGeometryType wkbType = ogrTypeFromWkbType( geometryType );

if ( !layerOptions.isEmpty() )
{
@@ -1854,8 +1854,8 @@ OGRFeatureH QgsVectorFileWriter::createFeature( QgsFeature& feature )
// build geometry from WKB
QgsGeometry* geom = feature.geometry();

// turn single geoemetry to multi geometry if needed
if ( geom->geometry()->wkbType() != mWkbType &&
// turn single geometry to multi geometry if needed
if ( QgsWKBTypes::flatType( geom->geometry()->wkbType() ) != QgsWKBTypes::flatType( mWkbType ) &&
QgsWKBTypes::flatType( geom->geometry()->wkbType() ) == QgsWKBTypes::flatType( QgsWKBTypes::singleType( mWkbType ) ) )
{
geom->convertToMultiType();
@@ -20,7 +20,8 @@
QgsPoint,
QgsCoordinateReferenceSystem,
QgsVectorFileWriter,
QgsFeatureRequest
QgsFeatureRequest,
QgsWKBTypes
)
from PyQt4.QtCore import QDate, QTime, QDateTime, QVariant, QDir
import os
@@ -29,7 +30,10 @@
unittest
)

from utilities import writeShape
from utilities import (
writeShape,
compareWkt
)

start_app()

@@ -167,5 +171,88 @@ def testDateTimeWriteTabfile(self):
assert isinstance(f.attributes()[datetime_idx], QDateTime)
self.assertEqual(f.attributes()[datetime_idx], QDateTime(QDate(2014, 3, 5), QTime(13, 45, 22)))

def testWriteShapefileWithZ(self):
"""Check writing geometries with Z dimension to an ESRI shapefile."""
ml = QgsVectorLayer(
('Point?crs=epsg:4326&field=id:int'),
'test',
'memory')

assert ml is not None, 'Provider not initialized'
assert ml.isValid(), 'Source layer not valid'
provider = ml.dataProvider()
assert provider is not None

ft = QgsFeature()
ft.setGeometry(QgsGeometry.fromWkt('PointZ (1 2 3)'))
ft.setAttributes([1])
res, features = provider.addFeatures([ft])
assert res
assert len(features) > 0

# check with both a standard PointZ and 25d style Point25D type
for t in [QgsWKBTypes.PointZ, QgsWKBTypes.Point25D]:
dest_file_name = os.path.join(str(QDir.tempPath()), 'point_{}.shp'.format(QgsWKBTypes.displayString(t)))
print(dest_file_name)
crs = QgsCoordinateReferenceSystem()
crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId)
write_result = QgsVectorFileWriter.writeAsVectorFormat(
ml,
dest_file_name,
'utf-8',
crs,
'ESRI Shapefile',
overrideGeometryType=t)
self.assertEqual(write_result, QgsVectorFileWriter.NoError)

# Open result and check
created_layer = QgsVectorLayer(u'{}|layerid=0'.format(dest_file_name), u'test', u'ogr')
f = created_layer.getFeatures(QgsFeatureRequest()).next()
g = f.geometry()
wkt = g.exportToWkt()
expWkt = 'PointZ (1 2 3)'
assert compareWkt(expWkt, wkt), "saving geometry with Z failed: mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt)

def testWriteShapefileWithMultiConversion(self):
"""Check writing geometries to an ESRI shapefile with conversion to multi."""
ml = QgsVectorLayer(
('Point?crs=epsg:4326&field=id:int'),
'test',
'memory')

assert ml is not None, 'Provider not initialized'
assert ml.isValid(), 'Source layer not valid'
provider = ml.dataProvider()
assert provider is not None

ft = QgsFeature()
ft.setGeometry(QgsGeometry.fromWkt('Point (1 2)'))
ft.setAttributes([1])
res, features = provider.addFeatures([ft])
assert res
assert len(features) > 0

dest_file_name = os.path.join(str(QDir.tempPath()), 'to_multi.shp')
print(dest_file_name)
crs = QgsCoordinateReferenceSystem()
crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId)
write_result = QgsVectorFileWriter.writeAsVectorFormat(
ml,
dest_file_name,
'utf-8',
crs,
'ESRI Shapefile',
forceMulti=True)
self.assertEqual(write_result, QgsVectorFileWriter.NoError)

# Open result and check
created_layer = QgsVectorLayer(u'{}|layerid=0'.format(dest_file_name), u'test', u'ogr')
f = created_layer.getFeatures(QgsFeatureRequest()).next()
g = f.geometry()
wkt = g.exportToWkt()
expWkt = 'MultiPoint ((1 2))'
assert compareWkt(expWkt, wkt), "saving geometry with multi conversion failed: mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt)


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

0 comments on commit 4e4743a

Please sign in to comment.
You can’t perform that action at this time.