diff --git a/src/core/geometry/qgsrectangle.cpp b/src/core/geometry/qgsrectangle.cpp index 67cc65fa4ab9..136cee7629a7 100644 --- a/src/core/geometry/qgsrectangle.cpp +++ b/src/core/geometry/qgsrectangle.cpp @@ -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 ¢er, double width, double height ) diff --git a/tests/src/core/geometry/testqgsrectangle.cpp b/tests/src/core/geometry/testqgsrectangle.cpp index 0db9d048a212..571051c0c9be 100644 --- a/tests/src/core/geometry/testqgsrectangle.cpp +++ b/tests/src/core/geometry/testqgsrectangle.cpp @@ -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 ); @@ -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() );