Skip to content
Permalink
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!)
  • Loading branch information
nyalldawson committed Nov 20, 2020
1 parent 8f4367d commit 6c30a4640d196090f8a0dda176e2d1ad6022b63e
Showing with 19 additions and 14 deletions.
  1. +12 −7 src/core/geometry/qgswkbtypes.h
  2. +7 −7 tests/src/python/test_qgsgeometry.py
@@ -1176,13 +1176,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 );
@@ -3905,13 +3905,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 6c30a46

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