Skip to content

Commit

Permalink
Fix errors and inconsistencies resulting from adding M values to
Browse files Browse the repository at this point in the history
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 6c30a46
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 14 deletions.
19 changes: 12 additions & 7 deletions src/core/geometry/qgswkbtypes.h
Expand Up @@ -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 );
Expand Down
14 changes: 7 additions & 7 deletions tests/src/python/test_qgsgeometry.py
Expand Up @@ -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)
Expand Down

0 comments on commit 6c30a46

Please sign in to comment.