Skip to content

Commit

Permalink
[Geometry] Fix various issues related to Wkb/Wkt import
Browse files Browse the repository at this point in the history
- Make QgsCurvePolygonV2::fromWkb() accept CompoundCurveM sub-geometries
- Make QgsGeometryCollectionV2::fromWkb() validate the sub-geometry type,
  so that QgsGeometryCollectionV2 subclasses do not import incompatible
  sub-geometries
- Make QgsGeometryCollectionV2::fromWkt() accept curve sub-geometries
- Make QgsMultiPolygonV2::addGeometry() accept only Polygon and not
  CurvePolygon
- Add tests
  • Loading branch information
rouault committed Jun 20, 2016
1 parent dabc3b1 commit 6ea03ea
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 14 deletions.
9 changes: 4 additions & 5 deletions src/core/geometry/qgscurvepolygonv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,16 @@ bool QgsCurvePolygonV2::fromWkb( QgsConstWkbPtr wkbPtr )
{
QgsWKBTypes::Type curveType = wkbPtr.readHeader();
wkbPtr -= 1 + sizeof( int );
if ( curveType == QgsWKBTypes::LineString || curveType == QgsWKBTypes::LineStringZ || curveType == QgsWKBTypes::LineStringM ||
curveType == QgsWKBTypes::LineStringZM || curveType == QgsWKBTypes::LineString25D )
QgsWKBTypes::Type flatCurveType = QgsWKBTypes::flatType( curveType );
if ( flatCurveType == QgsWKBTypes::LineString )
{
currentCurve = new QgsLineStringV2();
}
else if ( curveType == QgsWKBTypes::CircularString || curveType == QgsWKBTypes::CircularStringZ || curveType == QgsWKBTypes::CircularStringZM ||
curveType == QgsWKBTypes::CircularStringM )
else if ( flatCurveType == QgsWKBTypes::CircularString )
{
currentCurve = new QgsCircularStringV2();
}
else if ( curveType == QgsWKBTypes::CompoundCurve || curveType == QgsWKBTypes::CompoundCurveZ || curveType == QgsWKBTypes::CompoundCurveZM )
else if ( flatCurveType == QgsWKBTypes::CompoundCurve )
{
currentCurve = new QgsCompoundCurveV2();
}
Expand Down
20 changes: 12 additions & 8 deletions src/core/geometry/qgsgeometrycollectionv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,22 +192,24 @@ bool QgsGeometryCollectionV2::fromWkb( QgsConstWkbPtr wkbPtr )
int nGeometries = 0;
wkbPtr >> nGeometries;

QList<QgsAbstractGeometryV2*> geometryList;
QVector<QgsAbstractGeometryV2*> geometryListBackup = mGeometries;
mGeometries.clear();
for ( int i = 0; i < nGeometries; ++i )
{
QgsAbstractGeometryV2* geom = QgsGeometryFactory::geomFromWkb( wkbPtr );
if ( geom )
{
geometryList.append( geom );
if ( !addGeometry( geom ) )
{
qDeleteAll( mGeometries );
mGeometries = geometryListBackup;
return false;
}
wkbPtr += geom->wkbSize();
}
}
qDeleteAll( geometryListBackup );

mGeometries.resize( geometryList.size() );
for ( int i = 0; i < geometryList.size(); ++i )
{
mGeometries[i] = geometryList.at( i );
}
clearCache(); //set bounding box invalid

return true;
Expand All @@ -217,8 +219,10 @@ bool QgsGeometryCollectionV2::fromWkt( const QString& wkt )
{
return fromCollectionWkt( wkt, QList<QgsAbstractGeometryV2*>() << new QgsPointV2 << new QgsLineStringV2 << new QgsPolygonV2
<< new QgsCircularStringV2 << new QgsCompoundCurveV2
<< new QgsCurvePolygonV2
<< new QgsMultiPointV2 << new QgsMultiLineStringV2
<< new QgsMultiPolygonV2 << new QgsGeometryCollectionV2, "GeometryCollection" );
<< new QgsMultiPolygonV2 << new QgsGeometryCollectionV2
<< new QgsMultiCurveV2 << new QgsMultiSurfaceV2, "GeometryCollection" );
}

int QgsGeometryCollectionV2::wkbSize() const
Expand Down
2 changes: 1 addition & 1 deletion src/core/geometry/qgsmultipolygonv2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ QString QgsMultiPolygonV2::asJSON( int precision ) const

bool QgsMultiPolygonV2::addGeometry( QgsAbstractGeometryV2* g )
{
if ( !dynamic_cast<QgsCurvePolygonV2*>( g ) )
if ( !dynamic_cast<QgsPolygonV2*>( g ) )
{
delete g;
return false;
Expand Down
56 changes: 56 additions & 0 deletions tests/src/python/test_qgsgeometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -3304,6 +3304,62 @@ def testDeleteVertexCurvePolygon(self):
expected_wkt = "CurvePolygon (CompoundCurve (CircularString (0 0, 1 1, 2 0),(2 0, 0 0)))"
self.assertEqual(geom.exportToWkt(), QgsGeometry.fromWkt(expected_wkt).exportToWkt())

def testMisc(self):

# Test that we cannot add a CurvePolygon in a MultiPolygon
multipolygon = QgsMultiPolygonV2()
cp = QgsCurvePolygonV2()
cp.fromWkt("CurvePolygon ((0 0,0 1,1 1,0 0))")
assert not multipolygon.addGeometry( cp )

This comment has been minimized.

Copy link
@3nids

3nids Jan 5, 2022

Member

@rouault can you explain why we cannot add a curve polygon to a multi polygon?

How would you do with add part map tool then?

This comment has been minimized.

Copy link
@rouault

rouault Jan 5, 2022

Author Contributor

can you explain why we cannot add a curve polygon to a multi polygon?

it's not allowed by the OGC geometry model. You need to use a MultiSurface object as the container of a CurvePolygon


# Test that importing an invalid WKB (a MultiPolygon with a CurvePolygon) fails
geom = QgsGeometry.fromWkt('MultiSurface(((0 0,0 1,1 1,0 0)), CurvePolygon ((0 0,0 1,1 1,0 0)))')
wkb = geom.asWkb()
wkb = bytearray(wkb)
if wkb[1] == QgsWKBTypes.MultiSurface:
wkb[1] = QgsWKBTypes.MultiPolygon
elif wkb[1+4] == QgsWKBTypes.MultiSurface:
wkb[1+4] = QgsWKBTypes.MultiPolygon
else:
self.assertTrue(False)
geom = QgsGeometry()
geom.fromWkb(wkb)
self.assertEqual(geom.exportToWkt(), QgsMultiPolygonV2().asWkt())

# Test that fromWkt() on a GeometryCollection works with all possible geometries
wkt = "GeometryCollection( "
wkt += "Point(0 1)"
wkt += ","
wkt += "LineString(0 0,0 1)"
wkt += ","
wkt += "Polygon ((0 0,1 1,1 0,0 0))"
wkt += ","
wkt += "CurvePolygon ((0 0,1 1,1 0,0 0))"
wkt += ","
wkt += "CircularString (0 0,1 1,2 0)"
wkt += ","
wkt += "CompoundCurve ((0 0,0 1))"
wkt += ","
wkt += "MultiPoint ((0 0))"
wkt += ","
wkt += "MultiLineString((0 0,0 1))"
wkt += ","
wkt += "MultiCurve((0 0,0 1))"
wkt += ","
wkt += "MultiPolygon (((0 0,1 1,1 0,0 0)))"
wkt += ","
wkt += "MultiSurface (((0 0,1 1,1 0,0 0)))"
wkt += ","
wkt += "GeometryCollection (Point(0 0))"
wkt += ")"
geom = QgsGeometry.fromWkt(wkt)
assert geom is not None
wkb1 = geom.asWkb()
geom = QgsGeometry()
geom.fromWkb(wkb1)
wkb2 = geom.asWkb()
self.assertEqual(wkb1, wkb2)


if __name__ == '__main__':
unittest.main()

0 comments on commit 6ea03ea

Please sign in to comment.