Skip to content
Browse files

Fix errors and inconsistencies resulting from adding M values to

a dataset with a ****25D wkb type

Previously we did not handle adding M values to any "25d" WKB
type (as there's no such thing as Point25DM, etc). But being strict
like this turns out to be wrong, because it results in corrupted/
inconsistent geometries as a result of calls to QgsAbstractGeometry.addMValue()
whenever the original geometry is a 25D type.

In this situation, the M values were being added but the WKB type
wasn't being updated to reflect this and would remain at the original *25D
type. Ultimately, this causes GDAL to reject any wkb generated for the
geometries and failures to write features into an output dataset.

This is especially the case with GDB files, where the dataset can
sometimes be reported as a ZM type while individual features are
only 25D types (for whatever archiac reasons!)

(cherry picked from commit 6c30a46)
  • Loading branch information
nyalldawson committed Dec 20, 2020
1 parent 311f3bb commit b16285be71ecd0e461b0d04feca4813a42a2c6e5
Showing with 19 additions and 14 deletions.
  1. +12 −7 src/core/geometry/qgswkbtypes.h
  2. +7 −7 tests/src/python/
@@ -1159,13 +1159,18 @@ class CORE_EXPORT QgsWkbTypes
return Unknown;
else if ( type == NoGeometry )
return NoGeometry;
else if ( type == Point25D ||
type == LineString25D ||
type == Polygon25D ||
type == MultiPoint25D ||
type == MultiLineString25D ||
type == MultiPolygon25D )
return type; //can't add M dimension to these types
else if ( type == Point25D )
return PointZM;
else if ( type == LineString25D )
return LineStringZM;
else if ( type == Polygon25D )
return PolygonZM;
else if ( type == MultiPoint25D )
return MultiPointZM;
else if ( type == MultiLineString25D )
return MultiLineStringZM;
else if ( type == MultiPolygon25D )
return MultiPolygonZM;

//upgrade with m dimension
Type flat = flatType( type );
@@ -3650,13 +3650,13 @@ def testWkbTypes(self):
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.MultiSurfaceM), QgsWkbTypes.MultiSurfaceM)
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.MultiSurfaceZM), QgsWkbTypes.MultiSurfaceZM)
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.NoGeometry), QgsWkbTypes.NoGeometry)
# can't be added to these types
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.Point25D), QgsWkbTypes.Point25D)
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.LineString25D), QgsWkbTypes.LineString25D)
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.Polygon25D), QgsWkbTypes.Polygon25D)
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.MultiPoint25D), QgsWkbTypes.MultiPoint25D)
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.MultiLineString25D), QgsWkbTypes.MultiLineString25D)
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.MultiPolygon25D), QgsWkbTypes.MultiPolygon25D)
# we force upgrade 25D types to "Z" before adding the M value
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.Point25D), QgsWkbTypes.PointZM)
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.LineString25D), QgsWkbTypes.LineStringZM)
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.Polygon25D), QgsWkbTypes.PolygonZM)
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.MultiPoint25D), QgsWkbTypes.MultiPointZM)
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.MultiLineString25D), QgsWkbTypes.MultiLineStringZM)
self.assertEqual(QgsWkbTypes.addM(QgsWkbTypes.MultiPolygon25D), QgsWkbTypes.MultiPolygonZM)

# test dropping z dimension from types
self.assertEqual(QgsWkbTypes.dropZ(QgsWkbTypes.Unknown), QgsWkbTypes.Unknown)

0 comments on commit b16285b

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