Skip to content

Commit 4e4743a

Browse files
committed
Fix saving vector layers with z dimension (fix #14006, #12373)
1 parent 1b22dcc commit 4e4743a

File tree

2 files changed

+92
-5
lines changed

2 files changed

+92
-5
lines changed

src/core/qgsvectorfilewriter.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ void QgsVectorFileWriter::init( QString vectorFileName, QString fileEncoding, co
281281

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

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

1857-
// turn single geoemetry to multi geometry if needed
1858-
if ( geom->geometry()->wkbType() != mWkbType &&
1857+
// turn single geometry to multi geometry if needed
1858+
if ( QgsWKBTypes::flatType( geom->geometry()->wkbType() ) != QgsWKBTypes::flatType( mWkbType ) &&
18591859
QgsWKBTypes::flatType( geom->geometry()->wkbType() ) == QgsWKBTypes::flatType( QgsWKBTypes::singleType( mWkbType ) ) )
18601860
{
18611861
geom->convertToMultiType();

tests/src/python/test_qgsvectorfilewriter.py

+89-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
QgsPoint,
2121
QgsCoordinateReferenceSystem,
2222
QgsVectorFileWriter,
23-
QgsFeatureRequest
23+
QgsFeatureRequest,
24+
QgsWKBTypes
2425
)
2526
from PyQt4.QtCore import QDate, QTime, QDateTime, QVariant, QDir
2627
import os
@@ -29,7 +30,10 @@
2930
unittest
3031
)
3132

32-
from utilities import writeShape
33+
from utilities import (
34+
writeShape,
35+
compareWkt
36+
)
3337

3438
start_app()
3539

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

174+
def testWriteShapefileWithZ(self):
175+
"""Check writing geometries with Z dimension to an ESRI shapefile."""
176+
ml = QgsVectorLayer(
177+
('Point?crs=epsg:4326&field=id:int'),
178+
'test',
179+
'memory')
180+
181+
assert ml is not None, 'Provider not initialized'
182+
assert ml.isValid(), 'Source layer not valid'
183+
provider = ml.dataProvider()
184+
assert provider is not None
185+
186+
ft = QgsFeature()
187+
ft.setGeometry(QgsGeometry.fromWkt('PointZ (1 2 3)'))
188+
ft.setAttributes([1])
189+
res, features = provider.addFeatures([ft])
190+
assert res
191+
assert len(features) > 0
192+
193+
# check with both a standard PointZ and 25d style Point25D type
194+
for t in [QgsWKBTypes.PointZ, QgsWKBTypes.Point25D]:
195+
dest_file_name = os.path.join(str(QDir.tempPath()), 'point_{}.shp'.format(QgsWKBTypes.displayString(t)))
196+
print(dest_file_name)
197+
crs = QgsCoordinateReferenceSystem()
198+
crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId)
199+
write_result = QgsVectorFileWriter.writeAsVectorFormat(
200+
ml,
201+
dest_file_name,
202+
'utf-8',
203+
crs,
204+
'ESRI Shapefile',
205+
overrideGeometryType=t)
206+
self.assertEqual(write_result, QgsVectorFileWriter.NoError)
207+
208+
# Open result and check
209+
created_layer = QgsVectorLayer(u'{}|layerid=0'.format(dest_file_name), u'test', u'ogr')
210+
f = created_layer.getFeatures(QgsFeatureRequest()).next()
211+
g = f.geometry()
212+
wkt = g.exportToWkt()
213+
expWkt = 'PointZ (1 2 3)'
214+
assert compareWkt(expWkt, wkt), "saving geometry with Z failed: mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt)
215+
216+
def testWriteShapefileWithMultiConversion(self):
217+
"""Check writing geometries to an ESRI shapefile with conversion to multi."""
218+
ml = QgsVectorLayer(
219+
('Point?crs=epsg:4326&field=id:int'),
220+
'test',
221+
'memory')
222+
223+
assert ml is not None, 'Provider not initialized'
224+
assert ml.isValid(), 'Source layer not valid'
225+
provider = ml.dataProvider()
226+
assert provider is not None
227+
228+
ft = QgsFeature()
229+
ft.setGeometry(QgsGeometry.fromWkt('Point (1 2)'))
230+
ft.setAttributes([1])
231+
res, features = provider.addFeatures([ft])
232+
assert res
233+
assert len(features) > 0
234+
235+
dest_file_name = os.path.join(str(QDir.tempPath()), 'to_multi.shp')
236+
print(dest_file_name)
237+
crs = QgsCoordinateReferenceSystem()
238+
crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId)
239+
write_result = QgsVectorFileWriter.writeAsVectorFormat(
240+
ml,
241+
dest_file_name,
242+
'utf-8',
243+
crs,
244+
'ESRI Shapefile',
245+
forceMulti=True)
246+
self.assertEqual(write_result, QgsVectorFileWriter.NoError)
247+
248+
# Open result and check
249+
created_layer = QgsVectorLayer(u'{}|layerid=0'.format(dest_file_name), u'test', u'ogr')
250+
f = created_layer.getFeatures(QgsFeatureRequest()).next()
251+
g = f.geometry()
252+
wkt = g.exportToWkt()
253+
expWkt = 'MultiPoint ((1 2))'
254+
assert compareWkt(expWkt, wkt), "saving geometry with multi conversion failed: mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt)
255+
256+
170257
if __name__ == '__main__':
171258
unittest.main()

0 commit comments

Comments
 (0)