Skip to content
Permalink
Browse files

Fix QgsGeometry::asQPolygonF doesn't handle multipolygon inputs

gracefully
  • Loading branch information
nyalldawson committed Jul 2, 2020
1 parent 766e0b2 commit 33f31d826a984f3566f6f0f9614c656915d76de5
@@ -1823,9 +1823,14 @@ otherwise returns a null QPointF.

QPolygonF asQPolygonF() const;
%Docstring
Returns contents of the geometry as a QPolygonF. If geometry is a linestring,
then the result will be an open QPolygonF. If the geometry is a polygon,
then the result will be a closed QPolygonF of the geometry's exterior ring.
Returns contents of the geometry as a QPolygonF.

If geometry is a linestring, then the result will be an open QPolygonF.
If the geometry is a polygon, then the result will be a closed QPolygonF
of the geometry's exterior ring.

If the geometry is a multi-part geometry, then only the first part will
be considered when converting to a QPolygonF.

.. versionadded:: 2.7
%End
@@ -2558,36 +2558,22 @@ QPointF QgsGeometry::asQPointF() const

QPolygonF QgsGeometry::asQPolygonF() const
{
const QgsWkbTypes::Type type = wkbType();
const QgsLineString *line = nullptr;
if ( QgsWkbTypes::flatType( type ) == QgsWkbTypes::LineString )
{
line = qgsgeometry_cast< const QgsLineString * >( constGet() );
}
else if ( QgsWkbTypes::flatType( type ) == QgsWkbTypes::Polygon )
{
const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( constGet() );
if ( polygon )
line = qgsgeometry_cast< const QgsLineString * >( polygon->exteriorRing() );
}
const QgsAbstractGeometry *part = constGet();

if ( line )
{
const double *srcX = line->xData();
const double *srcY = line->yData();
const int count = line->numPoints();
QPolygonF res( count );
QPointF *dest = res.data();
for ( int i = 0; i < count; ++i )
{
*dest++ = QPointF( *srcX++, *srcY++ );
}
return res;
}
else
// if a geometry collection, get first part only
if ( const QgsGeometryCollection *collection = qgsgeometry_cast< const QgsGeometryCollection *>( part ) )
{
return QPolygonF();
if ( collection->numGeometries() > 0 )
part = collection->geometryN( 0 );
else
return QPolygonF();
}

if ( const QgsCurve *curve = qgsgeometry_cast< const QgsCurve * >( part ) )
return curve->asQPolygonF();
else if ( const QgsCurvePolygon *polygon = qgsgeometry_cast< const QgsCurvePolygon * >( part ) )
return polygon->exteriorRing() ? polygon->exteriorRing()->asQPolygonF() : QPolygonF();
return QPolygonF();
}

bool QgsGeometry::deleteRing( int ringNum, int partNum )
@@ -1917,9 +1917,15 @@ class CORE_EXPORT QgsGeometry
QPointF asQPointF() const;

/**
* Returns contents of the geometry as a QPolygonF. If geometry is a linestring,
* then the result will be an open QPolygonF. If the geometry is a polygon,
* then the result will be a closed QPolygonF of the geometry's exterior ring.
* Returns contents of the geometry as a QPolygonF.
*
* If geometry is a linestring, then the result will be an open QPolygonF.
* If the geometry is a polygon, then the result will be a closed QPolygonF
* of the geometry's exterior ring.
*
* If the geometry is a multi-part geometry, then only the first part will
* be considered when converting to a QPolygonF.
*
* \since QGIS 2.7
*/
QPolygonF asQPolygonF() const;
QgsGeometry badGeom( QgsGeometry::fromPointXY( mPoint1 ) );
QPolygonF fromBad = badGeom.asQPolygonF();
QVERIFY( fromBad.isEmpty() );

// test a multipolygon
QPolygonF res = QgsGeometry::fromWkt( QStringLiteral( "MultiPolygon (((0 0, 10 0, 10 10, 0 10, 0 0 )),((2 2, 4 2, 4 4, 2 4, 2 2)))" ) ).asQPolygonF();
QVERIFY( res.isClosed() );
QCOMPARE( res.size(), 5 );
QCOMPARE( res.at( 0 ).x(), 0.0 );
QCOMPARE( res.at( 0 ).y(), 0.0 );
QCOMPARE( res.at( 1 ).x(), 10.0 );
QCOMPARE( res.at( 1 ).y(), 0.0 );
QCOMPARE( res.at( 2 ).x(), 10.0 );
QCOMPARE( res.at( 2 ).y(), 10.0 );
QCOMPARE( res.at( 3 ).x(), 0.0 );
QCOMPARE( res.at( 3 ).y(), 10.0 );
QCOMPARE( res.at( 4 ).x(), 0.0 );
QCOMPARE( res.at( 4 ).y(), 0.0 );

// test a multilinestring
res = QgsGeometry::fromWkt( QStringLiteral( "MultiLineString((0 0, 10 0, 10 10, 0 10 ),(2 2, 4 2, 4 4, 2 4))" ) ).asQPolygonF();
QVERIFY( !res.isClosed() );
QCOMPARE( res.size(), 4 );
QCOMPARE( res.at( 0 ).x(), 0.0 );
QCOMPARE( res.at( 0 ).y(), 0.0 );
QCOMPARE( res.at( 1 ).x(), 10.0 );
QCOMPARE( res.at( 1 ).y(), 0.0 );
QCOMPARE( res.at( 2 ).x(), 10.0 );
QCOMPARE( res.at( 2 ).y(), 10.0 );
QCOMPARE( res.at( 3 ).x(), 0.0 );
QCOMPARE( res.at( 3 ).y(), 10.0 );
}

void TestQgsGeometry::comparePolylines()

0 comments on commit 33f31d8

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