diff --git a/python/core/qgsgeometry.sip b/python/core/qgsgeometry.sip index c6c962c345c0..ac9e2729e256 100644 --- a/python/core/qgsgeometry.sip +++ b/python/core/qgsgeometry.sip @@ -41,6 +41,18 @@ class QgsGeometry /** static method that creates geometry from Wkt */ static QgsGeometry* fromWkt( QString wkt ) /Factory/; + /** static method that creates geometry from GML2 + @param XML representation of the geometry. GML elements are expected to be + in default namespace (...) or in "gml" namespace (...) + @note added in 1.9 + */ + static QgsGeometry* fromGML2( const QString& xmlString ) /Factory/; + + /** static method that creates geometry from GML2 + @note added in 1.9 + */ + static QgsGeometry* fromGML2( const QDomNode& geometryNode ) /Factory/; + /** construct geometry from a point */ static QgsGeometry* fromPoint( const QgsPoint& point ) /Factory/; /** construct geometry from a multipoint */ diff --git a/src/core/qgsexpression.cpp b/src/core/qgsexpression.cpp index 8d7599ac528c..eebb757b0eff 100644 --- a/src/core/qgsexpression.cpp +++ b/src/core/qgsexpression.cpp @@ -795,21 +795,8 @@ static QVariant fcnGeomFromWKT( const QVariantList& values, QgsFeature*, QgsExpr } static QVariant fcnGeomFromGML2( const QVariantList& values, QgsFeature*, QgsExpression* parent ) { - QDomDocument doc; - QString errorMsg; QString gml = getStringValue( values.at( 0 ), parent ); - if ( !doc.setContent( gml, true, &errorMsg ) ) - return QVariant(); - - QgsGeometry* geom = 0; - QDomElement elem = doc.documentElement(); - if ( elem.tagName() == "Box" ) - { - QgsRectangle* rect = new QgsRectangle( elem ); - geom = QgsGeometry::fromRect( *rect ); - } - else - geom = QgsGeometry::fromGML2( doc.documentElement() ); + QgsGeometry* geom = QgsGeometry::fromGML2( gml ); if ( geom ) return QVariant::fromValue( *geom ); diff --git a/src/core/qgsgeometry.cpp b/src/core/qgsgeometry.cpp index ca3a437f86ff..f027d97178c2 100644 --- a/src/core/qgsgeometry.cpp +++ b/src/core/qgsgeometry.cpp @@ -540,7 +540,7 @@ QgsGeometry* QgsGeometry::fromGML2( const QDomNode& geometryNode ) QDomElement geometryTypeElement = geometryNode.toElement(); QString geomType = geometryTypeElement.tagName(); - if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" || geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon" ) ) + if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" || geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon" || geomType == "Box" ) ) { QDomNode geometryChild = geometryNode.firstChild(); if ( geometryChild.isNull() ) @@ -551,7 +551,7 @@ QgsGeometry* QgsGeometry::fromGML2( const QDomNode& geometryNode ) geomType = geometryTypeElement.tagName(); } - if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" || geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon" ) ) + if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" || geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon" || geomType == "Box" ) ) return 0; if ( geomType == "Point" && g->setFromGML2Point( geometryTypeElement ) ) @@ -578,12 +578,28 @@ QgsGeometry* QgsGeometry::fromGML2( const QDomNode& geometryNode ) { return g; } + else if ( geomType == "Box" ) + { + return QgsGeometry::fromRect( QgsRectangle( geometryTypeElement ) ); + } else //unknown type { return 0; } } +QgsGeometry* QgsGeometry::fromGML2( const QString& xmlString ) +{ + // wrap the string into a root tag to have "gml" namespace (and also as a default namespace) + QString xml = QString( "%2").arg( GML_NAMESPACE ).arg( xmlString ); + QDomDocument doc; + if ( !doc.setContent( xml, true ) ) + return 0; + + return fromGML2( doc.documentElement().firstChildElement() ); +} + + bool QgsGeometry::setFromGML2Point( const QDomElement& geometryElement ) { QDomNodeList coordList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "coordinates" ); diff --git a/src/core/qgsgeometry.h b/src/core/qgsgeometry.h index e3806dec6ce0..f684cbbb9ecb 100644 --- a/src/core/qgsgeometry.h +++ b/src/core/qgsgeometry.h @@ -89,6 +89,13 @@ class CORE_EXPORT QgsGeometry /** static method that creates geometry from Wkt */ static QgsGeometry* fromWkt( QString wkt ); + /** static method that creates geometry from GML2 + @param XML representation of the geometry. GML elements are expected to be + in default namespace (...) or in "gml" namespace (...) + @note added in 1.9 + */ + static QgsGeometry* fromGML2( const QString& xmlString ); + /** static method that creates geometry from GML2 @note added in 1.9 */ diff --git a/tests/src/core/testqgsexpression.cpp b/tests/src/core/testqgsexpression.cpp index 8741b9222e58..ba6bcd193ad0 100644 --- a/tests/src/core/testqgsexpression.cpp +++ b/tests/src/core/testqgsexpression.cpp @@ -569,6 +569,20 @@ class TestQgsExpression: public QObject QTest::newRow( "geomFromWKT Line" ) << "geomFromWKT('" + QgsGeometry::fromPolyline( line )->exportToWkt() + "')" << ( void* ) QgsGeometry::fromPolyline( line ) << false; QTest::newRow( "geomFromWKT Polyline" ) << "geomFromWKT('" + QgsGeometry::fromPolyline( polyline )->exportToWkt() + "')" << ( void* ) QgsGeometry::fromPolyline( polyline ) << false; QTest::newRow( "geomFromWKT Polygon" ) << "geomFromWKT('" + QgsGeometry::fromPolygon( polygon )->exportToWkt() + "')" << ( void* ) QgsGeometry::fromPolygon( polygon ) << false; + + // GML Point + QTest::newRow( "GML Point (coordinates)" ) << "geomFromGML2('123,456')" << ( void * ) QgsGeometry::fromPoint( point ) << false; + // gml:pos if from GML3 + //QTest::newRow( "GML Point (pos)" ) << "geomFromGML2('123 456')" << ( void * ) QgsGeometry::fromPoint( point ) << false; + + // GML Box + QgsRectangle rect( 135.2239, 34.4879, 135.8578, 34.8471 ); + QTest::newRow( "GML Box" ) << "geomFromGML2('135.2239,34.4879 135.8578,34.8471')" << ( void * ) QgsGeometry::fromRect( rect ) << false; + // Envelope is from GML3 ? + //QTest::newRow( "GML Envelope" ) << "geomFromGML2('" + // "135.2239 34.4879" + // "135.8578 34.8471" + // "')" << ( void * ) QgsGeometry::fromRect( rect ) << false; } void eval_geometry_constructor() @@ -744,6 +758,113 @@ class TestQgsExpression: public QObject QgsExpression::unsetSpecialColumn( "$var1" ); } + + void test_from_ogc_filter_data() + { + QTest::addColumn( "xmlText" ); + QTest::addColumn( "dumpText" ); + + QTest::newRow( "=" ) << QString( + "" + "NAME" + "New York" + "" ) + << QString( "NAME = 'New York'" ); + + QTest::newRow( ">" ) << QString( + "" + "COUNT" + "3" + "" ) + << QString( "COUNT > 3" ); + + QTest::newRow( "AND" ) << QString( + "" + "" + "" + "pop" + "50000" + "" + "" + "pop" + "100000" + "" + "" + "" ) + << QString( "pop >= 50000 AND pop < 100000" ); + + // TODO: should work also without tags in Lower/Upper-Boundary tags? + QTest::newRow( "between" ) << QString( + "" + "POPULATION" + "100" + "200" + "" ) + << QString( "POPULATION >= 100 AND POPULATION <= 200" ); + + // TODO: needs to handle different wildcards, single chars, escape chars + QTest::newRow( "like" ) << QString( + "" + "" + "NAME*QGIS*" + "" ) + << QString( "NAME LIKE '*QGIS*'" ); + + QTest::newRow( "is null" ) << QString( + "" + "" + "FIRST_NAME" + "" + "" ) + << QString( "FIRST_NAME IS NULL" ); + + QTest::newRow( "bbox" ) << QString( + "" + "Name>NAME" + "135.2239,34.4879 135.8578,34.8471" + "" ) + << QString( "bbox($geometry, geomFromGML2('135.2239,34.4879 135.8578,34.8471'))" ); + + QTest::newRow( "Intersects" ) << QString( + "" + "" + "GEOMETRY" + "" + "123,456" + "" + "" + "" ) + << QString( "intersects($geometry, geomFromGML2('123,456'))" ); + } + + void test_from_ogc_filter() + { + QFETCH( QString, xmlText ); + QFETCH( QString, dumpText ); + + QDomDocument doc; + QVERIFY(doc.setContent(xmlText, true)); + QDomElement rootElem = doc.documentElement(); + + QgsExpression* expr = QgsExpression::createFromOgcFilter( rootElem ); + QVERIFY( expr ); + + qDebug("OGC XML : %s", xmlText.toAscii().data() ); + qDebug("EXPR-DUMP: %s", expr->dump().toAscii().data() ); + + if ( expr->hasParserError() ) + qDebug( "ERROR: %s ", expr->parserErrorString().toAscii().data() ); + QVERIFY( !expr->hasParserError() ); + + QCOMPARE( dumpText, expr->dump() ); + + delete expr; + } + + void test_to_ogc_filter() + { + // TODO + } }; QTEST_MAIN( TestQgsExpression ) diff --git a/tests/src/core/testqgsgeometry.cpp b/tests/src/core/testqgsgeometry.cpp index 7ddd39bdf9a1..d64221426bab 100644 --- a/tests/src/core/testqgsgeometry.cpp +++ b/tests/src/core/testqgsgeometry.cpp @@ -55,6 +55,9 @@ class TestQgsGeometry: public QObject void differenceCheck1(); void differenceCheck2(); void bufferCheck(); + + void gmlTest(); + private: /** A helper method to do a render check to see if the geometry op is as expected */ bool renderCheck( QString theTestName, QString theComment = "" ); @@ -369,6 +372,19 @@ void TestQgsGeometry::dumpPolyline( QgsPolyline &thePolyline ) mpPainter->drawPolyline( myPoints ); } +void TestQgsGeometry::gmlTest() +{ + QgsGeometry* geom = QgsGeometry::fromGML2( "123,456" ); + QVERIFY( geom ); + QVERIFY( geom->wkbType() == QGis::WKBPoint ); + QVERIFY( geom->asPoint() == QgsPoint( 123, 456 ) ); + + QgsGeometry* geomBox = QgsGeometry::fromGML2( "135.2239,34.4879 135.8578,34.8471" ); + QVERIFY( geomBox ); + QVERIFY( geomBox->wkbType() == QGis::WKBPolygon ); +} + + QTEST_MAIN( TestQgsGeometry ) #include "moc_testqgsgeometry.cxx"