diff --git a/src/core/geometry/qgscircularstring.cpp b/src/core/geometry/qgscircularstring.cpp index 7a5d1b1fceaf..42d42fa8792b 100644 --- a/src/core/geometry/qgscircularstring.cpp +++ b/src/core/geometry/qgscircularstring.cpp @@ -314,10 +314,18 @@ bool QgsCircularString::fromWkt( const QString &wkt ) return false; mWkbType = parts.first; - if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) + parts.second = parts.second.remove( '(' ).remove( ')' ); + QString secondWithoutParentheses = parts.second; + secondWithoutParentheses = secondWithoutParentheses.simplified().remove( ' ' ); + if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) || + secondWithoutParentheses.isEmpty() ) return true; - setPoints( QgsGeometryUtils::pointsFromWKT( parts.second, is3D(), isMeasure() ) ); + QgsPointSequence points = QgsGeometryUtils::pointsFromWKT( parts.second, is3D(), isMeasure() ); + if ( points.isEmpty() ) + return false; + + setPoints( points ); return true; } diff --git a/src/core/geometry/qgscompoundcurve.cpp b/src/core/geometry/qgscompoundcurve.cpp index c1caf408ddb1..8f27f41cfd87 100644 --- a/src/core/geometry/qgscompoundcurve.cpp +++ b/src/core/geometry/qgscompoundcurve.cpp @@ -179,7 +179,10 @@ bool QgsCompoundCurve::fromWkt( const QString &wkt ) return false; mWkbType = parts.first; - if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) + QString secondWithoutParentheses = parts.second; + secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' ); + if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) || + secondWithoutParentheses.isEmpty() ) return true; QString defaultChildWkbType = QStringLiteral( "LineString%1%2" ).arg( is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() ); diff --git a/src/core/geometry/qgscurvepolygon.cpp b/src/core/geometry/qgscurvepolygon.cpp index 1ff044ec55f2..7b62fb3261d4 100644 --- a/src/core/geometry/qgscurvepolygon.cpp +++ b/src/core/geometry/qgscurvepolygon.cpp @@ -215,7 +215,10 @@ bool QgsCurvePolygon::fromWkt( const QString &wkt ) mWkbType = parts.first; - if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) + QString secondWithoutParentheses = parts.second; + secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' ); + if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) || + secondWithoutParentheses.isEmpty() ) return true; QString defaultChildWkbType = QStringLiteral( "LineString%1%2" ).arg( is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() ); diff --git a/src/core/geometry/qgsgeometrycollection.cpp b/src/core/geometry/qgsgeometrycollection.cpp index d6eb25debd3b..086497c8d787 100644 --- a/src/core/geometry/qgsgeometrycollection.cpp +++ b/src/core/geometry/qgsgeometrycollection.cpp @@ -698,7 +698,10 @@ bool QgsGeometryCollection::fromCollectionWkt( const QString &wkt, const QVector } mWkbType = parts.first; - if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) + QString secondWithoutParentheses = parts.second; + secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' ); + if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) || + secondWithoutParentheses.isEmpty() ) return true; QString defChildWkbType = QStringLiteral( "%1%2%3 " ).arg( defaultChildWkbType, is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() ); diff --git a/src/core/geometry/qgsgeometryutils.cpp b/src/core/geometry/qgsgeometryutils.cpp index ad7f3a28b1d3..d123d9bfd0ef 100644 --- a/src/core/geometry/qgsgeometryutils.cpp +++ b/src/core/geometry/qgsgeometryutils.cpp @@ -1100,15 +1100,22 @@ QgsPointSequence QgsGeometryUtils::pointsFromWKT( const QString &wktCoordinateLi { int dim = 2 + is3D + isMeasure; QgsPointSequence points; + const QStringList coordList = wktCoordinateList.split( ',', QString::SkipEmptyParts ); //first scan through for extra unexpected dimensions bool foundZ = false; bool foundM = false; QRegularExpression rx( QStringLiteral( "\\s" ) ); + QRegularExpression rxIsNumber( QStringLiteral( "^[+-]?(\\d\\.?\\d*[Ee][+\\-]?\\d+|(\\d+\\.\\d*|\\d*\\.\\d+)|\\d+)$" ) ); for ( const QString &pointCoordinates : coordList ) { QStringList coordinates = pointCoordinates.split( rx, QString::SkipEmptyParts ); + + // exit with an empty set if one list contains invalid value. + if ( coordinates.filter( rxIsNumber ).size() != coordinates.size() ) + return points; + if ( coordinates.size() == 3 && !foundZ && !foundM && !is3D && !isMeasure ) { // 3 dimensional coordinates, but not specifically marked as such. We allow this @@ -1313,6 +1320,14 @@ QPair QgsGeometryUtils::wktReadBlock( const QString } else { + const int openedParenthesisCount = wktParsed.count( '(' ); + const int closedParenthesisCount = wktParsed.count( ')' ); + // closes missing parentheses + for ( int i = 0 ; i < openedParenthesisCount - closedParenthesisCount; ++i ) + wktParsed.push_back( ')' ); + // removes extra parentheses + wktParsed.truncate( wktParsed.size() - ( closedParenthesisCount - openedParenthesisCount ) ); + QRegularExpression cooRegEx( QStringLiteral( "^[^\\(]*\\((.*)\\)[^\\)]*$" ) ); cooRegEx.setPatternOptions( QRegularExpression::DotMatchesEverythingOption ); QRegularExpressionMatch match = cooRegEx.match( wktParsed ); diff --git a/src/core/geometry/qgslinestring.cpp b/src/core/geometry/qgslinestring.cpp index 39bcfd4b5d0c..d6083ea286f1 100644 --- a/src/core/geometry/qgslinestring.cpp +++ b/src/core/geometry/qgslinestring.cpp @@ -434,10 +434,20 @@ bool QgsLineString::fromWkt( const QString &wkt ) return false; mWkbType = parts.first; - if ( parts.second == "EMPTY" ) + QString secondWithoutParentheses = parts.second; + secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' ); + parts.second = parts.second.remove( '(' ).remove( ')' ); + if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) || + secondWithoutParentheses.isEmpty() ) return true; - setPoints( QgsGeometryUtils::pointsFromWKT( parts.second, is3D(), isMeasure() ) ); + QgsPointSequence points = QgsGeometryUtils::pointsFromWKT( parts.second, is3D(), isMeasure() ); + // There is a non number in the coordinates sequence + // LineString ( A b, 1 2) + if ( points.isEmpty() ) + return false; + + setPoints( points ); return true; } diff --git a/src/core/geometry/qgspoint.cpp b/src/core/geometry/qgspoint.cpp index 48a7ceb8aa7b..f6d147a98b10 100644 --- a/src/core/geometry/qgspoint.cpp +++ b/src/core/geometry/qgspoint.cpp @@ -169,11 +169,31 @@ bool QgsPoint::fromWkt( const QString &wkt ) return false; mWkbType = parts.first; - if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) + QString secondWithoutParentheses = parts.second; + secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' ); + parts.second = parts.second.remove( '(' ).remove( ')' ); + if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) || + secondWithoutParentheses.isEmpty() ) return true; QRegularExpression rx( QStringLiteral( "\\s" ) ); QStringList coordinates = parts.second.split( rx, QString::SkipEmptyParts ); + + // So far the parser hasn't looked at the coordinates. We'll avoid having anything but numbers and return NULL instead of 0 as a coordinate. + // Without this check, "POINT (a, b)" or "POINT (( 4, 3 ))" returned "POINT (0 ,0)" + // And some strange conversion... + // .. python: + // p = QgsPoint() + // p.fromWkt("POINT (-3.12, -4.2") + // False + // p.fromWkt( "POINT (-5.1234, -1.4321)" ) + // True + // p.asWkt() + // 'Point (0 -1.43209999999999993)' + QRegularExpression rxIsNumber( QStringLiteral( "^[+-]?(\\d\\.?\\d*[Ee][+\\-]?\\d+|(\\d+\\.\\d*|\\d*\\.\\d+)|\\d+)$" ) ); + if ( coordinates.filter( rxIsNumber ).size() != coordinates.size() ) + return false; + if ( coordinates.size() < 2 ) { clear(); diff --git a/src/core/geometry/qgstriangle.cpp b/src/core/geometry/qgstriangle.cpp index 86b5aa813229..6ee1dc291782 100644 --- a/src/core/geometry/qgstriangle.cpp +++ b/src/core/geometry/qgstriangle.cpp @@ -159,7 +159,6 @@ bool QgsTriangle::fromWkb( QgsConstWkbPtr &wkbPtr ) bool QgsTriangle::fromWkt( const QString &wkt ) { - clear(); QPair parts = QgsGeometryUtils::wktReadBlock( wkt ); @@ -169,7 +168,10 @@ bool QgsTriangle::fromWkt( const QString &wkt ) mWkbType = parts.first; - if ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) + QString secondWithoutParentheses = parts.second; + secondWithoutParentheses = secondWithoutParentheses.simplified().remove( ' ' ); + if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) || + secondWithoutParentheses.isEmpty() ) return true; QString defaultChildWkbType = QStringLiteral( "LineString%1%2" ).arg( is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() ); @@ -200,6 +202,11 @@ bool QgsTriangle::fromWkt( const QString &wkt ) return false; } mExteriorRing.reset( mInteriorRings.takeFirst() ); + if ( ( mExteriorRing->numPoints() < 3 ) || ( mExteriorRing->numPoints() > 4 ) || ( mExteriorRing->numPoints() == 4 && mExteriorRing->startPoint() != mExteriorRing->endPoint() ) ) + { + clear(); + return false; + } //scan through rings and check if dimensionality of rings is different to CurvePolygon. //if so, update the type dimensionality of the CurvePolygon to match diff --git a/tests/src/app/testqgsmaptooladdfeatureline.cpp b/tests/src/app/testqgsmaptooladdfeatureline.cpp index c29f958bbd6a..b463fac1a796 100644 --- a/tests/src/app/testqgsmaptooladdfeatureline.cpp +++ b/tests/src/app/testqgsmaptooladdfeatureline.cpp @@ -212,7 +212,7 @@ void TestQgsMapToolAddFeatureLine::initTestCase() mLayerTopoZ->startEditing(); QgsFeature topoFeat; - topoFeat.setGeometry( QgsGeometry::fromWkt( "MultiLineStringZ ((7.25 6 0, 7.25 7 0, 7.5 7 0, 7.5 6 0, 7.25 6 0),(6 6 0, 6 7 10, 7 7 0, 7 6 0, 6 6 0),(6.25 6.25 0, 6.75 6.25 0, 6.75 6.75 0, 6.25 6.75 0, 6.25 6.25 0)));" ) ); + topoFeat.setGeometry( QgsGeometry::fromWkt( "MultiLineStringZ ((7.25 6 0, 7.25 7 0, 7.5 7 0, 7.5 6 0, 7.25 6 0),(6 6 0, 6 7 10, 7 7 0, 7 6 0, 6 6 0),(6.25 6.25 0, 6.75 6.25 0, 6.75 6.75 0, 6.25 6.75 0, 6.25 6.25 0))" ) ); mLayerTopoZ->addFeature( topoFeat ); QCOMPARE( mLayerTopoZ->featureCount(), ( long ) 1 ); diff --git a/tests/src/core/testqgsexpression.cpp b/tests/src/core/testqgsexpression.cpp index 826b7ae53b6d..9533b1f8af4d 100644 --- a/tests/src/core/testqgsexpression.cpp +++ b/tests/src/core/testqgsexpression.cpp @@ -1262,27 +1262,27 @@ class TestQgsExpression: public QObject QTest::newRow( "is_multipart null" ) << "is_multipart(NULL)" << false << QVariant(); QTest::newRow( "z_max no 3D" ) << "z_max(geom_from_wkt('POINT (0 0)'))" << false << QVariant(); QTest::newRow( "z_max NULL" ) << "z_max(geom_from_wkt(NULL))" << false << QVariant(); - QTest::newRow( "z_max point Z NaN" ) << "z_max(geom_from_wkt('PointZ (1 1 nan)'))" << false << QVariant( QVariant::Double ); - QTest::newRow( "z_max line Z NaN" ) << "z_max(make_line(geom_from_wkt('PointZ (0 0 nan)'),make_point(-1,-1,-2)))" << false << QVariant( -2.0 ); QTest::newRow( "z_max point" ) << "z_max(geom_from_wkt('POINT (0 0 1)'))" << false << QVariant( 1.0 ); + QTest::newRow( "z_max point Z NaN" ) << "z_max(geom_from_wkt('PointZ (1 1 nan)'))" << false << QVariant( ); + QTest::newRow( "z_max line Z NaN" ) << "z_max(make_line(geom_from_wkt('PointZ (0 0 nan)'),make_point(-1,-1,-2)))" << false << QVariant( ); QTest::newRow( "z_max line" ) << "z_max(make_line(make_point(0,0,0),make_point(-1,-1,-2)))" << false << QVariant( 0.0 ); QTest::newRow( "z_min no 3D" ) << "z_min(geom_from_wkt('POINT (0 0)'))" << false << QVariant(); QTest::newRow( "z_min NULL" ) << "z_min(geom_from_wkt(NULL))" << false << QVariant(); - QTest::newRow( "z_min point Z NaN" ) << "z_min(geom_from_wkt('PointZ (1 1 nan)'))" << false << QVariant( QVariant::Double ); - QTest::newRow( "z_min line Z NaN" ) << "z_min(make_line(geom_from_wkt('PointZ (0 0 nan)'),make_point(-1,-1,-2)))" << false << QVariant( -2.0 ); QTest::newRow( "z_min point" ) << "z_min(geom_from_wkt('POINT (0 0 1)'))" << false << QVariant( 1.0 ); + QTest::newRow( "z_min point Z NaN" ) << "z_min(geom_from_wkt('PointZ (1 1 nan)'))" << false << QVariant( ); + QTest::newRow( "z_min line Z NaN" ) << "z_min(make_line(geom_from_wkt('PointZ (0 0 nan)'),make_point(-1,-1,-2)))" << false << QVariant( ); QTest::newRow( "z_min line" ) << "z_min(make_line(make_point(0,0,0),make_point(-1,-1,-2)))" << false << QVariant( -2.0 ); QTest::newRow( "m_max no measure" ) << "m_max(geom_from_wkt('POINT (0 0)'))" << false << QVariant(); QTest::newRow( "m_max NULL" ) << "m_max(geom_from_wkt(NULL))" << false << QVariant(); - QTest::newRow( "m_max point M NaN" ) << "m_max(geom_from_wkt('PointZM (0 0 0 nan)'))" << false << QVariant( QVariant::Double ); - QTest::newRow( "m_max line M NaN" ) << "m_max(make_line(geom_from_wkt('PointZM (0 0 0 nan)'),geom_from_wkt('PointZM (1 1 1 2)')))" << false << QVariant( 2.0 ); QTest::newRow( "m_max point" ) << "m_max(make_point_m(0,0,1))" << false << QVariant( 1.0 ); + QTest::newRow( "m_max point M NaN" ) << "m_max(geom_from_wkt('PointZM (0 0 0 nan)'))" << false << QVariant( ); + QTest::newRow( "m_max line M NaN" ) << "m_max(make_line(geom_from_wkt('PointZM (0 0 0 nan)'),geom_from_wkt('PointZM (1 1 1 2)')))" << false << QVariant( ); QTest::newRow( "m_max line" ) << "m_max(make_line(make_point_m(0,0,1),make_point_m(-1,-1,2),make_point_m(-2,-2,0)))" << false << QVariant( 2.0 ); QTest::newRow( "m_min no measure" ) << "m_min(geom_from_wkt('POINT (0 0)'))" << false << QVariant(); QTest::newRow( "m_min NULL" ) << "m_min(geom_from_wkt(NULL))" << false << QVariant(); - QTest::newRow( "m_min point M NaN" ) << "m_min(geom_from_wkt('PointZM (0 0 0 nan)'))" << false << QVariant( QVariant::Double ); - QTest::newRow( "m_min line M NaN" ) << "m_min(make_line(geom_from_wkt('PointZM (0 0 0 nan)'),geom_from_wkt('PointZM (1 1 1 2)')))" << false << QVariant( 2.0 ); QTest::newRow( "m_min point" ) << "m_min(make_point_m(0,0,1))" << false << QVariant( 1.0 ); + QTest::newRow( "m_min point M NaN" ) << "m_min(geom_from_wkt('PointZM (0 0 0 nan)'))" << false << QVariant( ); + QTest::newRow( "m_min line M NaN" ) << "m_min(make_line(geom_from_wkt('PointZM (0 0 0 nan)'),geom_from_wkt('PointZM (1 1 1 2)')))" << false << QVariant( ); QTest::newRow( "m_min line" ) << "m_min(make_line(make_point_m(0,0,1),make_point_m(-1,-1,2),make_point_m(-2,-2,0)))" << false << QVariant( 0.0 ); QTest::newRow( "main angle polygon" ) << "round(main_angle( geom_from_wkt('POLYGON((0 0,2 9,9 2,0 0))')))" << false << QVariant( 77 ); QTest::newRow( "main angle multi polygon" ) << "round(main_angle( geom_from_wkt('MULTIPOLYGON(((0 0,3 10,1 10,1 6,0 0)))')))" << false << QVariant( 17 ); diff --git a/tests/src/core/testqgsgeometry.cpp b/tests/src/core/testqgsgeometry.cpp index 788c5fe98ea1..cfc7917fdf7d 100644 --- a/tests/src/core/testqgsgeometry.cpp +++ b/tests/src/core/testqgsgeometry.cpp @@ -164,6 +164,8 @@ class TestQgsGeometry : public QObject void testRandomPointsInPolygon(); + void wktParser(); + private: //! Must be called before each render test void initPainterTest(); @@ -17504,7 +17506,7 @@ void TestQgsGeometry::makeValid() QStringLiteral( "GEOMETRYCOLLECTION(POLYGON((0 0, 0 1, 1 1, 1 0, 0 0)), LINESTRING(0 0, -1 0))" ) ); // collection with invalid geometries geoms << qMakePair( QStringLiteral( "GEOMETRYCOLLECTION(LINESTRING(0 0, 0 0), POLYGON((0 0, 10 10, 10 0, 0 10, 0 0)), LINESTRING(10 0, 10 10))" ), - QStringLiteral( "GEOMETRYCOLLECTION(POINT(0 0), MULTIPOLYGON(((5 5, 0 0, 0 10, 5 5)),((5 5, 10 10, 10 0, 5 5))), LINESTRING(10 0, 10 10)))" ) ); + QStringLiteral( "GEOMETRYCOLLECTION(POINT(0 0), MULTIPOLYGON(((5 5, 0 0, 0 10, 5 5)),((5 5, 10 10, 10 0, 5 5))), LINESTRING(10 0, 10 10))" ) ); // null line (#18077) geoms << qMakePair( QStringLiteral( "MultiLineString ((356984.0625 6300089, 356984.0625 6300089))" ), QStringLiteral( "MultiPoint ((356984.0625 6300089))" ) ); @@ -18097,5 +18099,266 @@ void TestQgsGeometry::testRandomPointsInPolygon() QVERIFY( foundp2Point ); } +void TestQgsGeometry::wktParser() +{ + // POINT + // unbalanced parentheses + QVERIFY( QgsPoint().fromWkt( "POINT((0 1)" ) ); + QVERIFY( QgsPoint().fromWkt( "POINT(0 1) )" ) ); + QVERIFY( QgsPoint().fromWkt( "POINT ((0 1)" ) ); + QVERIFY( QgsPoint().fromWkt( "POINT (0 1) )" ) ); + // extra parentheses + QVERIFY( QgsPoint().fromWkt( "POINT ( (5 1) )" ) ); + // not a number + QVERIFY( ! QgsPoint().fromWkt( "POINT (a, b)" ) ); + QVERIFY( ! QgsPoint().fromWkt( "POINT (a b)" ) ); + QVERIFY( ! QgsPoint().fromWkt( "POINT((0, 1)" ) ); + QVERIFY( ! QgsPoint().fromWkt( "POINT(0, 1) )" ) ); + QVERIFY( ! QgsPoint().fromWkt( "POINT ((0, 1)" ) ); + QVERIFY( ! QgsPoint().fromWkt( "POINT (0, 1) )" ) ); + QVERIFY( ! QgsPoint().fromWkt( "POINT ( (5, 1) )" ) ); + + // valid + QgsPoint p; + QVERIFY( p.fromWkt( "POINT (5 1)" ) ); + QCOMPARE( p.asWkt(), QStringLiteral( "Point (5 1)" ) ); + // extra parentheses + QVERIFY( p.fromWkt( "POINT ( (5 1) )" ) ); + // unbalanced parentheses + QVERIFY( p.fromWkt( "POINT ( (5 1)" ) ); + QCOMPARE( p.asWkt(), QStringLiteral( "Point (5 1)" ) ); + QVERIFY( p.fromWkt( "POINT (5 1) )" ) ); + QCOMPARE( p.asWkt(), QStringLiteral( "Point (5 1)" ) ); + + QVERIFY( p.fromWkt( "POINT (5.1234 1.4321)" ) ); + QCOMPARE( p.asWkt( 4 ), QStringLiteral( "Point (5.1234 1.4321)" ) ); + QVERIFY( p.fromWkt( "POINT (-5.1234 -1.4321)" ) ); + QCOMPARE( p.asWkt( 4 ), QStringLiteral( "Point (-5.1234 -1.4321)" ) ); + QVERIFY( p.fromWkt( "POINT (-12e4 -1.4e-1)" ) ); + QCOMPARE( p.asWkt( 2 ), QStringLiteral( "Point (-120000 -0.14)" ) ); + + QVERIFY( p.fromWkt( "POINT ( )" ) ); + QCOMPARE( p.asWkt(), QStringLiteral( "Point EMPTY" ) ); + QVERIFY( ! p.fromWkt( "POINT (a, b)" ) ); + QCOMPARE( p.asWkt(), QStringLiteral( "Point EMPTY" ) ); + // LINESTRING + QVERIFY( QgsLineString().fromWkt( "LineString(0 1, 1 2) )" ) ); + QVERIFY( QgsLineString().fromWkt( "LineString (0 1, 1 2) )" ) ); + QVERIFY( QgsLineString().fromWkt( "LineString ( (0 1) )" ) ); + QVERIFY( QgsLineString().fromWkt( "LineString ( ( 0 1, 2 3 ) )" ) ); + QVERIFY( QgsMultiLineString().fromWkt( "MULTILINESTRING ((((1 2, 2 4, 4 5))" ) ); + QVERIFY( QgsMultiLineString().fromWkt( "MULTILINESTRING((((1 2, 2 4, 4 5))" ) ); + // not a number + QVERIFY( ! QgsLineString().fromWkt( "LineString(0, 1) )" ) ); + QVERIFY( ! QgsLineString().fromWkt( "LineString (0, 1) )" ) ); + QVERIFY( ! QgsLineString().fromWkt( "LineString (a b, 3 4)" ) ); + QVERIFY( ! QgsMultiLineString().fromWkt( "MULTILINESTRING ((1 2, 2 a, 4 b))" ) ); + // valid + QgsLineString l; + QVERIFY( l.fromWkt( "LINESTRING ( 1 2, 3 4 )" ) ); + QCOMPARE( l.asWkt(), QStringLiteral( "LineString (1 2, 3 4)" ) ); + // unbalanced parentheses + QVERIFY( l.fromWkt( "LINESTRING ( ( 1 2, 3 4 )" ) ); + QCOMPARE( l.asWkt(), QStringLiteral( "LineString (1 2, 3 4)" ) ); + QVERIFY( l.fromWkt( "LINESTRING ( 1 2, 3 4 ) )" ) ); + QCOMPARE( l.asWkt(), QStringLiteral( "LineString (1 2, 3 4)" ) ); + // extra parentheses + QVERIFY( l.fromWkt( "LINESTRING( ( 1 2, 3 4 ) )" ) ); + QCOMPARE( l.asWkt(), QStringLiteral( "LineString (1 2, 3 4)" ) ); + // empty + QVERIFY( l.fromWkt( "LINESTRING ( )" ) ); + QCOMPARE( l.asWkt(), QStringLiteral( "LineString EMPTY" ) ); + QVERIFY( ! l.fromWkt( "LINESTRING ( a b, 2 3 )" ) ); + QCOMPARE( l.asWkt(), QStringLiteral( "LineString EMPTY" ) ); + QVERIFY( l.fromWkt( "LINESTRING ( 1e4 -2, 3 +4.5 )" ) ); + QCOMPARE( l.asWkt( 1 ), QStringLiteral( "LineString (10000 -2, 3 4.5)" ) ); + QgsMultiLineString m; + m.fromWkt( "MULTILINESTRING ((1 2, 2 3, 4 5))" ) ; + QVERIFY( m.fromWkt( "MULTILINESTRING ((1 2, 2 3, 4 5))" ) ); + QCOMPARE( m.asWkt( 1 ), QStringLiteral( "MultiLineString ((1 2, 2 3, 4 5))" ) ); + + // TRIANGLE + // unbalanced parenthesis + QVERIFY( QgsTriangle().fromWkt( "Triangle( (0 1, 1 2, 3 3) )) " ) ); + QVERIFY( QgsTriangle().fromWkt( "Triangle ( (0 1, 1 2, 3 3) )) " ) ); + QVERIFY( ! QgsTriangle().fromWkt( "Triangle(0 1, 1 2, 3 3) )" ) ); + QVERIFY( ! QgsTriangle().fromWkt( "Triangle (0 1, 1 2, 3 3) )" ) ); + // not a number + QVERIFY( ! QgsTriangle().fromWkt( "Triangle ( (0 a, b 2, 3 3 )) " ) ); + QVERIFY( ! QgsTriangle().fromWkt( "Triangle ( (0 a, b 2, 3 3, 0 a )) " ) ); + // incorrect number of points + QVERIFY( ! QgsTriangle().fromWkt( "Triangle (( 0 0, 1 1))" ) ); + QVERIFY( ! QgsTriangle().fromWkt( "Triangle (( 0 0, 1 1, 1 0, 2 3, 4 5))" ) ); + QVERIFY( ! QgsTriangle().fromWkt( "Triangle (( 0 1, 2 3, 3 4, 1 0))" ) ); // four points but start and last points are differents + // valid + QgsTriangle t; + QVERIFY( t.fromWkt( "TRIANGLE(( 0 1, 2 3, 3 4))" ) ); + QCOMPARE( t.asWkt(), QStringLiteral( "Triangle ((0 1, 2 3, 3 4))" ) ); + QVERIFY( t.fromWkt( "TRIANGLE(( 0 1, 2 3, 3 4, 0 1))" ) ); + QCOMPARE( t.asWkt(), QStringLiteral( "Triangle ((0 1, 2 3, 3 4, 0 1))" ) ); + QVERIFY( t.fromWkt( "TRIANGLE(( 0 1, 2 3, 3 4, 0 1))" ) ); + QCOMPARE( t.asWkt(), QStringLiteral( "Triangle ((0 1, 2 3, 3 4, 0 1))" ) ); + QVERIFY( ! t.fromWkt( "TRIANGLE(( 0 1, 2 3, 3 4, 0 3))" ) ); + QCOMPARE( t.asWkt(), QStringLiteral( "Triangle EMPTY" ) ); + QVERIFY( ! t.fromWkt( "TRIANGLE(( 0 1, 2 3, 3 4, 0 3, 4 5))" ) ); + QCOMPARE( t.asWkt(), QStringLiteral( "Triangle EMPTY" ) ); + QVERIFY( ! t.fromWkt( "TRIANGLE(( 0 1, 2 3 ))" ) ); + QCOMPARE( t.asWkt(), QStringLiteral( "Triangle EMPTY" ) ); + QVERIFY( t.fromWkt( "TRIANGLE((0 1e3, -2 3, +3 4, 0 1e3))" ) ); + QCOMPARE( t.asWkt(), QStringLiteral( "Triangle ((0 1000, -2 3, 3 4, 0 1000))" ) ); + + // POLYGON + // unbalanced parenthesis + QVERIFY( QgsPolygon().fromWkt( "Polygon( (0 1, 1 2, 3 3) )) " ) ); + QVERIFY( QgsPolygon().fromWkt( "Polygon ( (0 1, 1 2, 3 3) )) " ) ); + QVERIFY( ! QgsPolygon().fromWkt( "Polygon(0 1, 1 2, 3 3) )" ) ); + QVERIFY( ! QgsPolygon().fromWkt( "Polygon (0 1, 1 2, 3 3) )" ) ); + // not a number + QVERIFY( ! QgsPolygon().fromWkt( "Polygon ( (0 a, b 2, 3 3 )) " ) ); + QVERIFY( ! QgsPolygon().fromWkt( "Polygon ( (0 a, b 2, 3 3, 0 a )) " ) ); + // valid + QgsPolygon poly; + QVERIFY( poly.fromWkt( "Polygon(( 0 1, 2 3, 3 4))" ) ); + QCOMPARE( poly.asWkt(), QStringLiteral( "Polygon ((0 1, 2 3, 3 4))" ) ); // TODO: A polygon must be closed + QVERIFY( poly.fromWkt( "Polygon(( 0 1, 2 3, 3 4, 0 1))" ) ); + QCOMPARE( poly.asWkt(), QStringLiteral( "Polygon ((0 1, 2 3, 3 4, 0 1))" ) ); + QVERIFY( poly.fromWkt( "Polygon((0 1e3, -2 3, +3 4, 0 1))" ) ); + QCOMPARE( poly.asWkt(), QStringLiteral( "Polygon ((0 1000, -2 3, 3 4, 0 1))" ) ); + + // Circular string + // unbalanced parenthesis + QVERIFY( QgsCircularString().fromWkt( "CircularString(0 1, 1 2, 3 3) )" ) ); + QVERIFY( QgsCircularString().fromWkt( "CircularString (0 1, 1 2, 3 3) )" ) ); + QVERIFY( QgsCircularString().fromWkt( "CircularString( (0 1, 1 2, 3 3) )) " ) ); + QVERIFY( QgsCircularString().fromWkt( "CircularString ( (0 1, 1 2, 3 3) )) " ) ); + // not a number + QVERIFY( ! QgsCircularString().fromWkt( "CircularString (0 a, b 2, 3 3) " ) ); + QVERIFY( ! QgsCircularString().fromWkt( "CircularString (0 a, b 2, 3 3, 0 a) " ) ); + // valid + QgsCircularString c; + QVERIFY( c.fromWkt( "CircularString( 0 1, 2 3, 3 4)" ) ); + QCOMPARE( c.asWkt(), QStringLiteral( "CircularString (0 1, 2 3, 3 4)" ) ); + QVERIFY( c.fromWkt( "CircularString(0 1e3, -2 3, +3 4)" ) ); + QCOMPARE( c.asWkt(), QStringLiteral( "CircularString (0 1000, -2 3, 3 4)" ) ); + + QVERIFY( c.fromWkt( "CircularString ((0 0,1 1,2 0))" ) ); // Added from an old test with an invalid wkt, but allowed in QGIS https://github.com/qgis/QGIS/pull/38439/files/59aab9dc9cc58bdc98e6d8091840bc129564ed2f#diff-fe3aa1328ee04f0eb00a1b1d59c0ea71L4247 + QCOMPARE( c.asWkt(), QStringLiteral( "CircularString (0 0, 1 1, 2 0)" ) ); + + // multipoint + QgsMultiPoint mp; + QVERIFY( ! mp.fromWkt( "MULTIPOINT (((10 40), (40 30), (20 20), (30 10))" ) ); + QVERIFY( ! mp.fromWkt( "MULTIPOINT (((10 40), (40 30), (xx20 20), (30 10))" ) ); + QVERIFY( ! mp.fromWkt( "MULTIPOINT ((10 40, 40 30, 20 20, 30 10)" ) ); + QVERIFY( mp.fromWkt( "MULTIPOINT ((10 40), (40 30), (20 20), (30 10))))" ) ); + QVERIFY( mp.fromWkt( "MULTIPOINT ( )" ) ); + QVERIFY( mp.fromWkt( "MULTIPOINT EMPTY" ) ); + QVERIFY( mp.fromWkt( "MULTIPOINT ((10 40), (40 30), (20 20), (30 10))" ) ); + QCOMPARE( mp.asWkt(), QStringLiteral( "MultiPoint ((10 40),(40 30),(20 20),(30 10))" ) ); + QVERIFY( mp.fromWkt( "MULTIPOINT (10 40, 40 30, 20 20, 30 10)" ) ); + QCOMPARE( mp.asWkt(), QStringLiteral( "MultiPoint ((10 40),(40 30),(20 20),(30 10))" ) ); + QVERIFY( mp.fromWkt( "MULTIPOINT ((10 40), (40 30), (20 20), (30 10))))" ) ); + QCOMPARE( mp.asWkt(), QStringLiteral( "MultiPoint ((10 40),(40 30),(20 20),(30 10))" ) ); + QVERIFY( mp.fromWkt( "MULTIPOINT ( )" ) ); + QCOMPARE( mp.asWkt(), QStringLiteral( "MultiPoint EMPTY" ) ); + QVERIFY( mp.fromWkt( "MULTIPOINT EMPTY" ) ); + QCOMPARE( mp.asWkt(), QStringLiteral( "MultiPoint EMPTY" ) ); + // Added from an old test with an invalid wkt, but allowed in QGIS https://github.com/qgis/QGIS/pull/38439/files/59aab9dc9cc58bdc98e6d8091840bc129564ed2f#diff-4444b5a772b35be43721b71a4b95d785R50 + QVERIFY( mp.fromWkt( "MULTIPOINT(0 20,20 20))" ) ); + QCOMPARE( mp.asWkt(), QStringLiteral( "MultiPoint ((0 20),(20 20))" ) ); + + // compoundcurve + QgsCompoundCurve cc; + QVERIFY( ! cc.fromWkt( "COMPOUNDCURVE((CIRCULARSTRING( 0 0, 1 1, 2 2))" ) ); + QVERIFY( cc.fromWkt( "COMPOUNDCURVE(CIRCULARSTRING( 0 0, 1 1, 2 2)))" ) ); + QCOMPARE( cc.asWkt(), QStringLiteral( "CompoundCurve (CircularString (0 0, 1 1, 2 2))" ) ); + QVERIFY( cc.fromWkt( "COMPOUNDCURVE(CIRCULARSTRING( 0 0, 1 1, 2 2))" ) ); + QCOMPARE( cc.asWkt(), QStringLiteral( "CompoundCurve (CircularString (0 0, 1 1, 2 2))" ) ); + QVERIFY( cc.fromWkt( "COMPOUNDCURVE(CIRCULARSTRING( 0 0, 1 1, 2 2), LINESTRING((2 2, 3 3)))" ) ); + QCOMPARE( cc.asWkt(), QStringLiteral( "CompoundCurve (CircularString (0 0, 1 1, 2 2),(2 2, 3 3))" ) ); + QVERIFY( cc.fromWkt( "COMPOUNDCURVE ( )" ) ); + QCOMPARE( cc.asWkt(), QStringLiteral( "CompoundCurve EMPTY" ) ); + QVERIFY( cc.fromWkt( "COMPOUNDCURVE EMPTY" ) ); + QCOMPARE( cc.asWkt(), QStringLiteral( "CompoundCurve EMPTY" ) ); + // geometrycollection + QgsGeometryCollection gc; + QVERIFY( gc.fromWkt( "GeometryCollection((CIRCULARSTRING( 0 0, 1 1, 2 2))" ) ); + QCOMPARE( gc.asWkt(), QStringLiteral( "GeometryCollection (GeometryCollection (CircularString (0 0, 1 1, 2 2)))" ) ); + QVERIFY( gc.fromWkt( "GeometryCollection(CIRCULARSTRING( 0 0, 1 1, 2 2)))" ) ); + QCOMPARE( gc.asWkt(), QStringLiteral( "GeometryCollection (CircularString (0 0, 1 1, 2 2))" ) ); + QVERIFY( gc.fromWkt( "GeometryCollection(CIRCULARSTRING( 0 0, 1 1, 2 2))" ) ); + QCOMPARE( gc.asWkt(), QStringLiteral( "GeometryCollection (CircularString (0 0, 1 1, 2 2))" ) ); + QVERIFY( gc.fromWkt( "GeometryCollection(CIRCULARSTRING( 0 0, 1 1, 2 2), LINESTRING((2 2, 3 3)))" ) ); + QCOMPARE( gc.asWkt(), QStringLiteral( "GeometryCollection (CircularString (0 0, 1 1, 2 2),LineString (2 2, 3 3))" ) ); + QVERIFY( gc.fromWkt( "GeometryCollection ( )" ) ); + QCOMPARE( gc.asWkt(), QStringLiteral( "GeometryCollection EMPTY" ) ); + QVERIFY( gc.fromWkt( "GeometryCollection EMPTY" ) ); + QCOMPARE( gc.asWkt(), QStringLiteral( "GeometryCollection EMPTY" ) ); + // curvepolygon + QgsCurvePolygon cp; + QVERIFY( ! cp.fromWkt( "CurvePolygon((CIRCULARSTRING( 0 0, 1 1, 2 2))" ) ); + QVERIFY( cp.fromWkt( "CurvePolygon(CIRCULARSTRING( 0 0, 1 1, 2 2)))" ) ); + QCOMPARE( cp.asWkt(), QStringLiteral( "CurvePolygon (CircularString (0 0, 1 1, 2 2))" ) ); + QVERIFY( cp.fromWkt( "CurvePolygon(CIRCULARSTRING( 0 0, 1 1, 2 2))" ) ); + QCOMPARE( cp.asWkt(), QStringLiteral( "CurvePolygon (CircularString (0 0, 1 1, 2 2))" ) ); + QVERIFY( cp.fromWkt( "CurvePolygon(CIRCULARSTRING( 0 0, 1 1, 2 2), LINESTRING((2 2, 3 3)))" ) ); + QCOMPARE( cp.asWkt(), QStringLiteral( "CurvePolygon (CircularString (0 0, 1 1, 2 2),(2 2, 3 3))" ) ); + QVERIFY( cp.fromWkt( "CurvePolygon ( )" ) ); + QCOMPARE( cp.asWkt(), QStringLiteral( "CurvePolygon EMPTY" ) ); + QVERIFY( cp.fromWkt( "CurvePolygon EMPTY" ) ); + QCOMPARE( cp.asWkt(), QStringLiteral( "CurvePolygon EMPTY" ) ); + // multicurve + QgsMultiCurve mc; + QVERIFY( ! mc.fromWkt( "MultiCurve((CIRCULARSTRING( 0 0, 1 1, 2 2))" ) ); + QVERIFY( mc.fromWkt( "MultiCurve(CIRCULARSTRING( 0 0, 1 1, 2 2)))" ) ); + QCOMPARE( mc.asWkt(), QStringLiteral( "MultiCurve (CircularString (0 0, 1 1, 2 2))" ) ); + QVERIFY( mc.fromWkt( "MultiCurve(CIRCULARSTRING( 0 0, 1 1, 2 2))" ) ); + QCOMPARE( mc.asWkt(), QStringLiteral( "MultiCurve (CircularString (0 0, 1 1, 2 2))" ) ); + QVERIFY( mc.fromWkt( "MultiCurve(CIRCULARSTRING( 0 0, 1 1, 2 2), LINESTRING((2 2, 3 3)))" ) ); + QCOMPARE( mc.asWkt(), QStringLiteral( "MultiCurve (CircularString (0 0, 1 1, 2 2),LineString (2 2, 3 3))" ) ); + QVERIFY( mc.fromWkt( "MultiCurve ( )" ) ); + QCOMPARE( mc.asWkt(), QStringLiteral( "MultiCurve EMPTY" ) ); + QVERIFY( mc.fromWkt( "MultiCurve EMPTY" ) ); + QCOMPARE( mc.asWkt(), QStringLiteral( "MultiCurve EMPTY" ) ); + // multisurface + QgsMultiSurface ms; + QVERIFY( ! ms.fromWkt( "MultiSurface((Polygon( 0 0, 1 1, 2 2))" ) ); + QVERIFY( ms.fromWkt( "MultiSurface(Polygon(( 0 0, 1 1, 2 2)))" ) ); + QCOMPARE( ms.asWkt(), QStringLiteral( "MultiSurface (Polygon ((0 0, 1 1, 2 2)))" ) ); + QVERIFY( ms.fromWkt( "MultiSurface(Polygon(( 0 0, 1 1, 2 2)))" ) ); + QCOMPARE( ms.asWkt(), QStringLiteral( "MultiSurface (Polygon ((0 0, 1 1, 2 2)))" ) ); + QVERIFY( ms.fromWkt( "MultiSurface(Polygon(( 0 0, 1 1, 2 2)), Polygon((2 2, 3 3, 3 2)))" ) ); + QCOMPARE( ms.asWkt(), QStringLiteral( "MultiSurface (Polygon ((0 0, 1 1, 2 2)),Polygon ((2 2, 3 3, 3 2)))" ) ); + QVERIFY( ms.fromWkt( "MultiSurface ( )" ) ); + QCOMPARE( ms.asWkt(), QStringLiteral( "MultiSurface EMPTY" ) ); + QVERIFY( ms.fromWkt( "MultiSurface EMPTY" ) ); + QCOMPARE( ms.asWkt(), QStringLiteral( "MultiSurface EMPTY" ) ); + // multipolygon + QgsMultiPolygon mpoly; + QVERIFY( ! mpoly.fromWkt( "MultiPolygon((Polygon( 0 0, 1 1, 2 2))" ) ); + QVERIFY( mpoly.fromWkt( "MultiPolygon(Polygon(( 0 0, 1 1, 2 2)))" ) ); + QCOMPARE( mpoly.asWkt(), QStringLiteral( "MultiPolygon (((0 0, 1 1, 2 2)))" ) ); + QVERIFY( mpoly.fromWkt( "MultiPolygon(Polygon(( 0 0, 1 1, 2 2)))" ) ); + QCOMPARE( mpoly.asWkt(), QStringLiteral( "MultiPolygon (((0 0, 1 1, 2 2)))" ) ); + QVERIFY( mpoly.fromWkt( "MultiPolygon(Polygon(( 0 0, 1 1, 2 2)), Polygon((2 2, 3 3, 3 2)))" ) ); + QCOMPARE( mpoly.asWkt(), QStringLiteral( "MultiPolygon (((0 0, 1 1, 2 2)),((2 2, 3 3, 3 2)))" ) ); + QVERIFY( mpoly.fromWkt( "MultiPolygon ( )" ) ); + QCOMPARE( mpoly.asWkt(), QStringLiteral( "MultiPolygon EMPTY" ) ); + QVERIFY( mpoly.fromWkt( "MultiPolygon EMPTY" ) ); + QCOMPARE( mpoly.asWkt(), QStringLiteral( "MultiPolygon EMPTY" ) ); + + // multilinestring + QgsMultiLineString mline; + QVERIFY( ! mline.fromWkt( "MultiLineString((LineString( 0 0, 1 1, 2 2))" ) ); + QVERIFY( mline.fromWkt( "MultiLineString(LineString(( 0 0, 1 1, 2 2)))" ) ); + QCOMPARE( mline.asWkt(), QStringLiteral( "MultiLineString ((0 0, 1 1, 2 2))" ) ); + QVERIFY( mline.fromWkt( "MultiLineString(LineString(( 0 0, 1 1, 2 2)))" ) ); + QCOMPARE( mline.asWkt(), QStringLiteral( "MultiLineString ((0 0, 1 1, 2 2))" ) ); + QVERIFY( mline.fromWkt( "MultiLineString(LineString(( 0 0, 1 1, 2 2)), LineString((2 2, 3 3, 3 2)))" ) ); + QCOMPARE( mline.asWkt(), QStringLiteral( "MultiLineString ((0 0, 1 1, 2 2),(2 2, 3 3, 3 2))" ) ); + QVERIFY( mline.fromWkt( "MultiLineString ( )" ) ); + QCOMPARE( mline.asWkt(), QStringLiteral( "MultiLineString EMPTY" ) ); + QVERIFY( mline.fromWkt( "MultiLineString EMPTY" ) ); + QCOMPARE( mline.asWkt(), QStringLiteral( "MultiLineString EMPTY" ) ); +} QGSTEST_MAIN( TestQgsGeometry ) #include "testqgsgeometry.moc" diff --git a/tests/src/python/test_provider_ogr_gpkg.py b/tests/src/python/test_provider_ogr_gpkg.py index a2de092e3031..22b4831f8a36 100644 --- a/tests/src/python/test_provider_ogr_gpkg.py +++ b/tests/src/python/test_provider_ogr_gpkg.py @@ -320,7 +320,7 @@ def testCurveGeometryType(self): vl.dataProvider().addFeatures([f]) got = [feat for feat in vl.getFeatures()][0] got_geom = got.geometry() - reference = QgsGeometry.fromWkt('CurvePolygon (((0 0, 0 1, 1 1, 0 0)))') + reference = QgsGeometry.fromWkt('CurvePolygon ((0 0, 0 1, 1 1, 0 0))') # The geometries must be binarily identical self.assertEqual(got_geom.asWkb(), reference.asWkb(), 'Expected {}, got {}'.format(reference.asWkt(), got_geom.asWkt())) diff --git a/tests/src/python/test_qgsdistancearea.py b/tests/src/python/test_qgsdistancearea.py index fadcc2df0a70..12c7e4a022a1 100644 --- a/tests/src/python/test_qgsdistancearea.py +++ b/tests/src/python/test_qgsdistancearea.py @@ -984,7 +984,7 @@ def testSplitGeometryAtAntimeridian(self): self.assertEqual(g.asWkt(), 'PointZ (1 2 3)') g = da.splitGeometryAtAntimeridian(QgsGeometry.fromWkt('PointM(1 2 3)')) self.assertEqual(g.asWkt(), 'PointM (1 2 3)') - g = da.splitGeometryAtAntimeridian(QgsGeometry.fromWkt('LineString()')) + g = da.splitGeometryAtAntimeridian(QgsGeometry.fromWkt('LineString EMPTY')) self.assertEqual(g.asWkt(), 'MultiLineString EMPTY') # lines diff --git a/tests/src/python/test_qgsgeometry.py b/tests/src/python/test_qgsgeometry.py index 5a2e8558a57b..0781377d2704 100644 --- a/tests/src/python/test_qgsgeometry.py +++ b/tests/src/python/test_qgsgeometry.py @@ -842,7 +842,7 @@ def testReferenceGeometry(self): "Perimeter {}: mismatch Expected:\n{}\nGot:\n{}\n".format(i + 1, exp, result)) def testCollection(self): - g = QgsGeometry.fromWkt('MultiLineString()') + g = QgsGeometry.fromWkt('MultiLineString EMPTY') self.assertEqual(len(g.get()), 0) self.assertTrue(g.get()) g = QgsGeometry.fromWkt('MultiLineString((0 0, 1 1),(13 2, 14 1))') @@ -4244,42 +4244,42 @@ def testGeometryDisplayString(self): def testDeleteVertexCircularString(self): - wkt = "CircularString ((0 0,1 1,2 0))" + wkt = "CircularString (0 0,1 1,2 0)" geom = QgsGeometry.fromWkt(wkt) assert geom.deleteVertex(0) self.assertEqual(geom.asWkt(), QgsCircularString().asWkt()) - wkt = "CircularString ((0 0,1 1,2 0,3 -1,4 0))" + wkt = "CircularString (0 0,1 1,2 0,3 -1,4 0)" geom = QgsGeometry.fromWkt(wkt) assert geom.deleteVertex(0) expected_wkt = "CircularString (2 0, 3 -1, 4 0)" self.assertEqual(geom.asWkt(), QgsGeometry.fromWkt(expected_wkt).asWkt()) - wkt = "CircularString ((0 0,1 1,2 0,3 -1,4 0))" + wkt = "CircularString (0 0,1 1,2 0,3 -1,4 0)" geom = QgsGeometry.fromWkt(wkt) assert geom.deleteVertex(1) expected_wkt = "CircularString (0 0, 3 -1, 4 0)" self.assertEqual(geom.asWkt(), QgsGeometry.fromWkt(expected_wkt).asWkt()) - wkt = "CircularString ((0 0,1 1,2 0,3 -1,4 0))" + wkt = "CircularString (0 0,1 1,2 0,3 -1,4 0)" geom = QgsGeometry.fromWkt(wkt) assert geom.deleteVertex(2) expected_wkt = "CircularString (0 0, 1 1, 4 0)" self.assertEqual(geom.asWkt(), QgsGeometry.fromWkt(expected_wkt).asWkt()) - wkt = "CircularString ((0 0,1 1,2 0,3 -1,4 0))" + wkt = "CircularString (0 0,1 1,2 0,3 -1,4 0)" geom = QgsGeometry.fromWkt(wkt) assert geom.deleteVertex(3) expected_wkt = "CircularString (0 0, 1 1, 4 0)" self.assertEqual(geom.asWkt(), QgsGeometry.fromWkt(expected_wkt).asWkt()) - wkt = "CircularString ((0 0,1 1,2 0,3 -1,4 0))" + wkt = "CircularString (0 0,1 1,2 0,3 -1,4 0)" geom = QgsGeometry.fromWkt(wkt) assert geom.deleteVertex(4) expected_wkt = "CircularString (0 0,1 1,2 0)" self.assertEqual(geom.asWkt(), QgsGeometry.fromWkt(expected_wkt).asWkt()) - wkt = "CircularString ((0 0,1 1,2 0,3 -1,4 0))" + wkt = "CircularString (0 0,1 1,2 0,3 -1,4 0)" geom = QgsGeometry.fromWkt(wkt) assert not geom.deleteVertex(-1) assert not geom.deleteVertex(5) @@ -4528,7 +4528,7 @@ def testCurveSinuosity(self): """ Test curve straightDistance2d() and sinuosity() """ - linestring = QgsGeometry.fromWkt('LineString()') + linestring = QgsGeometry.fromWkt('LineString EMPTY') self.assertTrue(math.isnan(linestring.constGet().straightDistance2d())) self.assertTrue(math.isnan(linestring.constGet().sinuosity())) linestring = QgsGeometry.fromWkt('LineString(0 0, 10 0)') @@ -4844,7 +4844,7 @@ def testPolygonize(self): empty = QgsGeometry() o = QgsGeometry.polygonize([empty]) self.assertFalse(o) - line = QgsGeometry.fromWkt('LineString()') + line = QgsGeometry.fromWkt('LineString EMPTY') o = QgsGeometry.polygonize([line]) self.assertFalse(o) @@ -4873,7 +4873,7 @@ def testDelaunayTriangulation(self): empty = QgsGeometry() o = empty.delaunayTriangulation() self.assertFalse(o) - line = QgsGeometry.fromWkt('LineString()') + line = QgsGeometry.fromWkt('LineString EMPTY') o = line.delaunayTriangulation() self.assertFalse(o) @@ -4952,7 +4952,7 @@ def testVoronoi(self): empty = QgsGeometry() o = empty.voronoiDiagram() self.assertFalse(o) - line = QgsGeometry.fromWkt('LineString()') + line = QgsGeometry.fromWkt('LineString EMPTY') o = line.voronoiDiagram() self.assertFalse(o) @@ -5195,7 +5195,7 @@ def testCentroid(self): ["LINESTRING (10 10, 10 10)", "POINT (10 10)"], # zero length line ["MULTILINESTRING ((10 10, 10 10), (20 20, 20 20))", "POINT (15 15)"], # zero length multiline ["LINESTRING (60 180, 120 100, 180 180)", "POINT (120 140)"], - ["LINESTRING (80 0, 80 120, 120 120, 120 0))", "POINT (100 68.57142857142857)"], + ["LINESTRING (80 0, 80 120, 120 120, 120 0)", "POINT (100 68.57142857142857)"], ["MULTILINESTRING ((0 0, 0 100), (100 0, 100 100))", "POINT (50 50)"], [" MULTILINESTRING ((0 0, 0 200, 200 200, 200 0, 0 0),(60 180, 20 180, 20 140, 60 140, 60 180))", "POINT (90 110)"], @@ -5786,24 +5786,24 @@ def coerce_to_wkt(wkt, type): coerce_to_wkt('MultiPolygon(((1 1, 2 2, 3 3, 1 1)), ((1 1, 2 2, 3 3, 1 1)))', QgsWkbTypes.MultiPolygon), ['MultiPolygon (((1 1, 2 2, 3 3, 1 1)),((1 1, 2 2, 3 3, 1 1)))']) - self.assertEqual(coerce_to_wkt('LineString((1 1, 2 2, 3 3, 1 1))', QgsWkbTypes.LineString), - ['LineString (0 1, 2 2, 3 3, 1 0)']) - self.assertEqual(coerce_to_wkt('LineString z ((1 1 1, 2 2 2, 3 3 3, 1 1 1))', QgsWkbTypes.LineString), - ['LineString (0 1, 2 2, 3 3, 1 1)']) - self.assertEqual(coerce_to_wkt('LineString z ((1 1 1, 2 2 2, 3 3 3, 1 1 1))', QgsWkbTypes.LineStringZ), - ['LineStringZ (0 1 1, 2 2 2, 3 3 3, 1 1 0)']) - self.assertEqual(coerce_to_wkt('LineString m ((1 1 1, 2 2 2, 3 3 3, 1 1 1))', QgsWkbTypes.LineString), - ['LineString (0 1, 2 2, 3 3, 1 1)']) - self.assertEqual(coerce_to_wkt('LineString m ((1 1 1, 2 2 2, 3 3 3, 1 1 1))', QgsWkbTypes.LineStringM), - ['LineStringM (0 1 1, 2 2 2, 3 3 3, 1 1 0)']) + self.assertEqual(coerce_to_wkt('LineString(1 1, 2 2, 3 3, 1 1)', QgsWkbTypes.LineString), + ['LineString (1 1, 2 2, 3 3, 1 1)']) + self.assertEqual(coerce_to_wkt('LineString z (1 1 1, 2 2 2, 3 3 3, 1 1 1)', QgsWkbTypes.LineString), + ['LineString (1 1, 2 2, 3 3, 1 1)']) + self.assertEqual(coerce_to_wkt('LineString z (1 1 1, 2 2 2, 3 3 3, 1 1 1)', QgsWkbTypes.LineStringZ), + ['LineStringZ (1 1 1, 2 2 2, 3 3 3, 1 1 1)']) + self.assertEqual(coerce_to_wkt('LineString m (1 1 1, 2 2 2, 3 3 3, 1 1 1)', QgsWkbTypes.LineString), + ['LineString (1 1, 2 2, 3 3, 1 1)']) + self.assertEqual(coerce_to_wkt('LineString m (1 1 1, 2 2 2, 3 3 3, 1 1 1)', QgsWkbTypes.LineStringM), + ['LineStringM (1 1 1, 2 2 2, 3 3 3, 1 1 1)']) # Adding Z back - self.assertEqual(coerce_to_wkt('LineString (1 1, 2 2, 3 3, 1 1))', QgsWkbTypes.LineStringZ), - ['LineStringZ (1 1 0, 2 2 0, 3 3 0, 1 0 0)']) + self.assertEqual(coerce_to_wkt('LineString (1 1, 2 2, 3 3, 1 1)', QgsWkbTypes.LineStringZ), + ['LineStringZ (1 1 0, 2 2 0, 3 3 0, 1 1 0)']) # Adding M back - self.assertEqual(coerce_to_wkt('LineString (1 1, 2 2, 3 3, 1 1))', QgsWkbTypes.LineStringM), - ['LineStringM (1 1 0, 2 2 0, 3 3 0, 1 0 0)']) + self.assertEqual(coerce_to_wkt('LineString (1 1, 2 2, 3 3, 1 1)', QgsWkbTypes.LineStringM), + ['LineStringM (1 1 0, 2 2 0, 3 3 0, 1 1 0)']) self.assertEqual(coerce_to_wkt('LineString(1 1, 2 2, 3 3, 1 1)', QgsWkbTypes.MultiLineString), ['MultiLineString ((1 1, 2 2, 3 3, 1 1))']) diff --git a/tests/src/python/test_qgsprocessinginplace.py b/tests/src/python/test_qgsprocessinginplace.py index cfcb7031ea75..fdb2002cf0cb 100644 --- a/tests/src/python/test_qgsprocessinginplace.py +++ b/tests/src/python/test_qgsprocessinginplace.py @@ -250,7 +250,7 @@ def test_QgsVectorLayerUtilsmakeFeaturesCompatible(self): self._make_compatible_tester('MultiPoint((1 3), (2 2))', 'MultiPoint') self._make_compatible_tester('Polygon((1 1, 2 2, 3 3, 1 1))', 'Polygon') - self._make_compatible_tester('Polygon((1 1, 2 2, 3 3, 1 1)', 'Polygon', [1, 'nope']) + self._make_compatible_tester('Polygon((1 1, 2 2, 3 3, 1 1))', 'Polygon', [1, 'nope']) self._make_compatible_tester('Polygon z ((1 1 1, 2 2 2, 3 3 3, 1 1 1))', 'Polygon') self._make_compatible_tester('Polygon z ((1 1 1, 2 2 2, 3 3 3, 1 1 1))', 'PolygonZ') @@ -273,22 +273,22 @@ def test_QgsVectorLayerUtilsmakeFeaturesCompatible(self): self._make_compatible_tester('Polygon((1 1, 2 2, 3 3, 1 1))', 'MultiPolygon') self._make_compatible_tester('MultiPolygon(((1 1, 2 2, 3 3, 1 1)), ((1 1, 2 2, 3 3, 1 1)))', 'MultiPolygon') - self._make_compatible_tester('LineString((1 1, 2 2, 3 3, 1 1))', 'LineString') - self._make_compatible_tester('LineString((1 1, 2 2, 3 3, 1 1)', 'LineString', [1, 'nope']) - self._make_compatible_tester('LineString z ((1 1 1, 2 2 2, 3 3 3, 1 1 1))', 'LineString') - self._make_compatible_tester('LineString z ((1 1 1, 2 2 2, 3 3 3, 1 1 1))', 'LineStringZ') - self._make_compatible_tester('LineString m ((1 1 1, 2 2 2, 3 3 3, 1 1 1))', 'LineString') - self._make_compatible_tester('LineString m ((1 1 1, 2 2 2, 3 3 3, 1 1 1))', 'LineStringM') + self._make_compatible_tester('LineString(1 1, 2 2, 3 3, 1 1)', 'LineString') + self._make_compatible_tester('LineString(1 1, 2 2, 3 3, 1 1)', 'LineString', [1, 'nope']) + self._make_compatible_tester('LineString z (1 1 1, 2 2 2, 3 3 3, 1 1 1)', 'LineString') + self._make_compatible_tester('LineString z (1 1 1, 2 2 2, 3 3 3, 1 1 1)', 'LineStringZ') + self._make_compatible_tester('LineString m (1 1 1, 2 2 2, 3 3 3, 1 1 1)', 'LineString') + self._make_compatible_tester('LineString m (1 1 1, 2 2 2, 3 3 3, 1 1 1)', 'LineStringM') # Adding Z back - l, f = self._make_compatible_tester('LineString (1 1, 2 2, 3 3, 1 1))', 'LineStringZ') + l, f = self._make_compatible_tester('LineString (1 1, 2 2, 3 3, 1 1)', 'LineStringZ') g = f[0].geometry() g2 = g.constGet() for v in g2.vertices(): self.assertEqual(v.z(), 0) # Adding M back - l, f = self._make_compatible_tester('LineString (1 1, 2 2, 3 3, 1 1))', 'LineStringM') + l, f = self._make_compatible_tester('LineString (1 1, 2 2, 3 3, 1 1)', 'LineStringM') g = f[0].geometry() g2 = g.constGet() for v in g2.vertices(): diff --git a/tests/testdata/relates_data.csv b/tests/testdata/relates_data.csv index 9b9ef08d1ee3..70bbb05276a9 100644 --- a/tests/testdata/relates_data.csv +++ b/tests/testdata/relates_data.csv @@ -47,7 +47,7 @@ LINESTRING(20 20,100 20,20 20)|LINESTRING(60 20,200 20)|101FFF102 LINESTRING(40 60,180 60,180 140,100 140,100 60,220 60,220 180,80 180,80 60,280 60)|LINESTRING(140 60,180 60,220 60,260 60)|101FF0FF2 POINT(20 20)|POLYGON((60 120,60 40,160 40,160 120,60 120))|FF0FFF212 MULTIPOINT(0 20,40 20)|POLYGON((20 40,20 0,60 0,60 40,20 40))|0F0FFF212 -MULTIPOINT(0 20,20 20))|POLYGON((20 40,20 0,60 0,60 40,20 40))|F00FFF212 +MULTIPOINT(0 20,20 20)|POLYGON((20 40,20 0,60 0,60 40,20 40))|F00FFF212 MULTIPOINT(20 20,40 20)|POLYGON((20 40,20 0,60 0,60 40,20 40))|00FFFF212 MULTIPOINT(80 260,140 260,180 260)|POLYGON((40 320,140 320,140 200,40 200,40 320))|000FFF212 POINT(40 40)|MULTIPOLYGON(((0 40,0 0,40 0,40 40,0 40)),((40 80,40 40,80 40,80 80,40 80)))|F0FFFF212