Skip to content

Commit

Permalink
Add method which promotes all non-point WKB types to multitype
Browse files Browse the repository at this point in the history
equivalent

Specifically, this method should be used to determine the
most-permissive possible resultant WKB type which can result
from subtracting parts of a geometry. A single-point geometry
type can never become a multi-point geometry type as
a result of a subtraction, but a single-line or single-polygon
geometry CAN become a multipart geometry as a result of subtracting
portions of the geometry.
  • Loading branch information
nyalldawson committed Dec 9, 2021
1 parent 28fac71 commit fa12325
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 0 deletions.
18 changes: 18 additions & 0 deletions python/core/auto_generated/geometry/qgswkbtypes.sip.in
Expand Up @@ -118,6 +118,8 @@ Returns the single type for a WKB type. For example, for MultiPolygon WKB types
%Docstring
Returns the multi type for a WKB type. For example, for Polygon WKB types the multi type would be MultiPolygon.

.. seealso:: :py:func:`promoteNonPointTypesToMulti`

.. seealso:: :py:func:`isMultiType`

.. seealso:: :py:func:`singleType`
Expand All @@ -128,6 +130,22 @@ Returns the multi type for a WKB type. For example, for Polygon WKB types the mu
%End


static Type promoteNonPointTypesToMulti( Type type ) /HoldGIL/;
%Docstring
Promotes a WKB geometry type to its multi-type equivalent, with the exception of point geometry types.

Specifically, this method should be used to determine the most-permissive possible resultant WKB type which can result
from subtracting parts of a geometry. A single-point geometry type can never become a multi-point geometry type as
a result of a subtraction, but a single-line or single-polygon geometry CAN become a multipart geometry as a result of subtracting
portions of the geometry.

.. seealso:: :py:func:`multiType`

.. seealso:: :py:func:`singleType`

.. versionadded:: 3.24
%End

static Type curveType( Type type ) /HoldGIL/;
%Docstring
Returns the curve type for a WKB type. For example, for Polygon WKB types the curve type would be CurvePolygon.
Expand Down
30 changes: 30 additions & 0 deletions src/core/geometry/qgswkbtypes.h
Expand Up @@ -294,6 +294,8 @@ class CORE_EXPORT QgsWkbTypes

/**
* Returns the multi type for a WKB type. For example, for Polygon WKB types the multi type would be MultiPolygon.
*
* \see promoteNonPointTypesToMulti()
* \see isMultiType()
* \see singleType()
* \see curveType()
Expand Down Expand Up @@ -434,6 +436,34 @@ class CORE_EXPORT QgsWkbTypes
}


/**
* Promotes a WKB geometry type to its multi-type equivalent, with the exception of point geometry types.
*
* Specifically, this method should be used to determine the most-permissive possible resultant WKB type which can result
* from subtracting parts of a geometry. A single-point geometry type can never become a multi-point geometry type as
* a result of a subtraction, but a single-line or single-polygon geometry CAN become a multipart geometry as a result of subtracting
* portions of the geometry.
*
* \see multiType()
* \see singleType()
* \since QGIS 3.24
*/
static Type promoteNonPointTypesToMulti( Type type ) SIP_HOLDGIL
{
switch ( geometryType( type ) )
{
case QgsWkbTypes::PointGeometry:
case QgsWkbTypes::UnknownGeometry:
case QgsWkbTypes::NullGeometry:
return type;

case QgsWkbTypes::LineGeometry:
case QgsWkbTypes::PolygonGeometry:
return multiType( type );
}
return Unknown;
}

/**
* Returns the curve type for a WKB type. For example, for Polygon WKB types the curve type would be CurvePolygon.
*
Expand Down
63 changes: 63 additions & 0 deletions tests/src/python/test_qgsgeometry.py
Expand Up @@ -3154,6 +3154,69 @@ def testWkbTypes(self):
self.assertEqual(QgsWkbTypes.multiType(QgsWkbTypes.TriangleM), QgsWkbTypes.MultiPolygonM)
self.assertEqual(QgsWkbTypes.multiType(QgsWkbTypes.TriangleZM), QgsWkbTypes.MultiPolygonZM)

# test promoteNonPointTypesToMulti method
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.Unknown), QgsWkbTypes.Unknown)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.Point), QgsWkbTypes.Point)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.PointZ), QgsWkbTypes.PointZ)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.PointM), QgsWkbTypes.PointM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.PointZM), QgsWkbTypes.PointZM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiPoint), QgsWkbTypes.MultiPoint)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiPointZ), QgsWkbTypes.MultiPointZ)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiPointM), QgsWkbTypes.MultiPointM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiPointZM), QgsWkbTypes.MultiPointZM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.LineString), QgsWkbTypes.MultiLineString)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.LineStringZ), QgsWkbTypes.MultiLineStringZ)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.LineStringM), QgsWkbTypes.MultiLineStringM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.LineStringZM), QgsWkbTypes.MultiLineStringZM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiLineString), QgsWkbTypes.MultiLineString)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiLineStringZ), QgsWkbTypes.MultiLineStringZ)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiLineStringM), QgsWkbTypes.MultiLineStringM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiLineStringZM), QgsWkbTypes.MultiLineStringZM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.Polygon), QgsWkbTypes.MultiPolygon)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.PolygonZ), QgsWkbTypes.MultiPolygonZ)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.PolygonM), QgsWkbTypes.MultiPolygonM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.PolygonZM), QgsWkbTypes.MultiPolygonZM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiPolygon), QgsWkbTypes.MultiPolygon)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiPolygonZ), QgsWkbTypes.MultiPolygonZ)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiPolygonM), QgsWkbTypes.MultiPolygonM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiPolygonZM), QgsWkbTypes.MultiPolygonZM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.GeometryCollection), QgsWkbTypes.GeometryCollection)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.GeometryCollectionZ), QgsWkbTypes.GeometryCollectionZ)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.GeometryCollectionM), QgsWkbTypes.GeometryCollectionM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.GeometryCollectionZM), QgsWkbTypes.GeometryCollectionZM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.CircularString), QgsWkbTypes.MultiCurve)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.CircularStringZ), QgsWkbTypes.MultiCurveZ)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.CircularStringM), QgsWkbTypes.MultiCurveM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.CircularStringZM), QgsWkbTypes.MultiCurveZM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.CompoundCurve), QgsWkbTypes.MultiCurve)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.CompoundCurveZ), QgsWkbTypes.MultiCurveZ)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.CompoundCurveM), QgsWkbTypes.MultiCurveM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.CompoundCurveZM), QgsWkbTypes.MultiCurveZM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.CurvePolygon), QgsWkbTypes.MultiSurface)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.CurvePolygonZ), QgsWkbTypes.MultiSurfaceZ)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.CurvePolygonM), QgsWkbTypes.MultiSurfaceM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.CurvePolygonZM), QgsWkbTypes.MultiSurfaceZM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiCurve), QgsWkbTypes.MultiCurve)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiCurveZ), QgsWkbTypes.MultiCurveZ)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiCurveM), QgsWkbTypes.MultiCurveM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiCurveZM), QgsWkbTypes.MultiCurveZM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiSurface), QgsWkbTypes.MultiSurface)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiSurfaceZ), QgsWkbTypes.MultiSurfaceZ)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiSurfaceM), QgsWkbTypes.MultiSurfaceM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiSurfaceZM), QgsWkbTypes.MultiSurfaceZM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.NoGeometry), QgsWkbTypes.NoGeometry)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.Point25D), QgsWkbTypes.Point25D)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.LineString25D), QgsWkbTypes.MultiLineString25D)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.Polygon25D), QgsWkbTypes.MultiPolygon25D)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiPoint25D), QgsWkbTypes.MultiPoint25D)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiLineString25D), QgsWkbTypes.MultiLineString25D)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.MultiPolygon25D), QgsWkbTypes.MultiPolygon25D)
# until we have tin types, these should return multipolygons
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.Triangle), QgsWkbTypes.MultiPolygon)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.TriangleZ), QgsWkbTypes.MultiPolygonZ)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.TriangleM), QgsWkbTypes.MultiPolygonM)
self.assertEqual(QgsWkbTypes.promoteNonPointTypesToMulti(QgsWkbTypes.TriangleZM), QgsWkbTypes.MultiPolygonZM)

# test curveType method
self.assertEqual(QgsWkbTypes.curveType(QgsWkbTypes.Unknown), QgsWkbTypes.Unknown)
self.assertEqual(QgsWkbTypes.curveType(QgsWkbTypes.Point), QgsWkbTypes.Point)
Expand Down

0 comments on commit fa12325

Please sign in to comment.