Skip to content

Commit

Permalink
Optimise QgsRectangle::fromWkt
Browse files Browse the repository at this point in the history
And be more tolerant, eg allowing a rectangular polygon as the
only object in a multipolygon
  • Loading branch information
nyalldawson committed Oct 6, 2023
1 parent 2858662 commit d9d531e
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 11 deletions.
25 changes: 15 additions & 10 deletions src/core/geometry/qgsrectangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,24 @@
QgsRectangle QgsRectangle::fromWkt( const QString &wkt )
{
const QgsGeometry geom = QgsGeometry::fromWkt( wkt );
if ( geom.isMultipart() )
if ( geom.isEmpty() )
return QgsRectangle();

const QgsPolygonXY poly = geom.asPolygon();

if ( poly.size() != 1 )
return QgsRectangle();
if ( const QgsPolygon *polygon = qgsgeometry_cast< const QgsPolygon * >( geom.constGet()->simplifiedTypeRef() ) )
{
if ( polygon->numInteriorRings() > 0 )
return QgsRectangle();

const QgsPolylineXY polyline = geom.asPolygon().at( 0 );
if ( polyline.size() == 5 && polyline.at( 0 ) == polyline.at( 4 ) && geom.isGeosValid() )
return QgsRectangle( polyline.at( 0 ).x(), polyline.at( 0 ).y(), polyline.at( 2 ).x(), polyline.at( 2 ).y() );
else
return QgsRectangle();
if ( const QgsLineString *exterior = qgsgeometry_cast< QgsLineString * >( polygon->exteriorRing() ) )
{
if ( exterior->numPoints() == 5
&& qgsDoubleNear( exterior->xAt( 0 ), exterior->xAt( 4 ) )
&& qgsDoubleNear( exterior->yAt( 0 ), exterior->yAt( 4 ) )
&& geom.isGeosValid() )
return QgsRectangle( exterior->xAt( 0 ), exterior->yAt( 0 ), exterior->xAt( 2 ), exterior->yAt( 2 ) );
}
}
return QgsRectangle();
}

QgsRectangle QgsRectangle::fromCenterAndSize( const QgsPointXY &center, double width, double height )
Expand Down
32 changes: 31 additions & 1 deletion tests/src/core/geometry/testqgsrectangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ void TestQgsRectangle::isNull()

void TestQgsRectangle::fromWkt()
{
const QgsRectangle rect = QgsRectangle::fromWkt( QStringLiteral( "POLYGON((0 0,1 0,1 1,0 1,0 0))" ) );
QgsRectangle rect = QgsRectangle::fromWkt( QStringLiteral( "POLYGON((0 0,1 0,1 1,0 1,0 0))" ) );
QVERIFY( ! rect.isEmpty() );
QCOMPARE( rect.xMinimum(), 0.0 );
QCOMPARE( rect.yMinimum(), 0.0 );
Expand All @@ -89,6 +89,36 @@ void TestQgsRectangle::fromWkt()

QVERIFY( rect == QgsRectangle::fromWkt( rect.asWktPolygon() ) );

rect = QgsRectangle::fromWkt( QStringLiteral( "POLYGONZ((0 0 2,1 0 2,1 1 2,0 1 2,0 0 2))" ) );
QVERIFY( ! rect.isEmpty() );
QCOMPARE( rect.xMinimum(), 0.0 );
QCOMPARE( rect.yMinimum(), 0.0 );
QCOMPARE( rect.xMaximum(), 1.0 );
QCOMPARE( rect.yMaximum(), 1.0 );

QVERIFY( rect == QgsRectangle::fromWkt( rect.asWktPolygon() ) );

// this is ok, a single rectangular polygon in a multipolygon object
rect = QgsRectangle::fromWkt( QStringLiteral( "MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0)))" ) );
QVERIFY( ! rect.isEmpty() );
QCOMPARE( rect.xMinimum(), 0.0 );
QCOMPARE( rect.yMinimum(), 0.0 );
QCOMPARE( rect.xMaximum(), 1.0 );
QCOMPARE( rect.yMaximum(), 1.0 );
QVERIFY( rect == QgsRectangle::fromWkt( rect.asWktPolygon() ) );

// this is ok, a single rectangular polygon in a collection
rect = QgsRectangle::fromWkt( QStringLiteral( "GEOMETRYCOLLECTION(MULTIPOLYGON(((0 0,1 0,1 1,0 1,0 0))))" ) );
QVERIFY( ! rect.isEmpty() );
QCOMPARE( rect.xMinimum(), 0.0 );
QCOMPARE( rect.yMinimum(), 0.0 );
QCOMPARE( rect.xMaximum(), 1.0 );
QCOMPARE( rect.yMaximum(), 1.0 );
QVERIFY( rect == QgsRectangle::fromWkt( rect.asWktPolygon() ) );

QVERIFY( QgsRectangle::fromWkt( QStringLiteral( "xxx" ) ).isEmpty() );
QVERIFY( QgsRectangle::fromWkt( QStringLiteral( "LINESTRING ()" ) ).isEmpty() );
QVERIFY( QgsRectangle::fromWkt( QStringLiteral( "MULTIPOLYGON()" ) ).isEmpty() );
QVERIFY( QgsRectangle::fromWkt( QStringLiteral( "LINESTRING (0 0,1 0,1 1,0 1,0 0)" ) ).isEmpty() );
QVERIFY( QgsRectangle::fromWkt( QStringLiteral( "MULTIPOLYGON(((0 0,3 0,3 3,0 3,0 0)),((1 1, 1 2, 2 2, 2 1)))" ) ).isEmpty() );
QVERIFY( QgsRectangle::fromWkt( QStringLiteral( "MULTIPOLYGON(((0 0,3 0,3 3,0 3,0 0), (10 10,13 10,13 13,10 13,10 10)))" ) ).isEmpty() );
Expand Down

0 comments on commit d9d531e

Please sign in to comment.