diff --git a/python/core/core.sip b/python/core/core.sip
index 9cd10b13967..42b66b67730 100644
--- a/python/core/core.sip
+++ b/python/core/core.sip
@@ -47,6 +47,7 @@
%Include qgsmimedatautils.sip
%Include qgsnetworkaccessmanager.sip
%Include qgsofflineediting.sip
+%Include qgsogcutils.sip
%Include qgsoverlayobject.sip
%Include qgsowsconnection.sip
%Include qgspaintenginehack.sip
diff --git a/python/core/qgsgeometry.sip b/python/core/qgsgeometry.sip
index ac9e2729e25..c6c962c345c 100644
--- a/python/core/qgsgeometry.sip
+++ b/python/core/qgsgeometry.sip
@@ -41,18 +41,6 @@ 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/python/core/qgsogcutils.sip b/python/core/qgsogcutils.sip
new file mode 100644
index 00000000000..4306e1283b2
--- /dev/null
+++ b/python/core/qgsogcutils.sip
@@ -0,0 +1,32 @@
+
+
+class QgsOgcUtils
+{
+%TypeHeaderCode
+#include
+%End
+
+public:
+
+ /** 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* geometryFromGML2( const QString& xmlString ) /Factory/;
+
+ /** static method that creates geometry from GML2
+ @note added in 1.9
+ */
+ static QgsGeometry* geometryFromGML2( const QDomNode& geometryNode ) /Factory/;
+
+ /** Exports the geometry to mGML2
+ @return true in case of success and false else
+ */
+ static QDomElement geometryToGML2( QgsGeometry* geometry, QDomDocument& doc );
+
+ /** read rectangle from GML2 Box */
+ static QgsRectangle rectangleFromGMLBox( const QDomNode& boxNode );
+
+};
+
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 5aacc5c520f..4cd2bf45cea 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -86,6 +86,7 @@ SET(QGIS_CORE_SRCS
qgsnetworkreplyparser.cpp
qgscredentials.cpp
qgsofflineediting.cpp
+ qgsogcutils.cpp
qgsoverlayobject.cpp
qgsowsconnection.cpp
qgspalgeometry.cpp
@@ -404,6 +405,7 @@ SET(QGIS_CORE_HDRS
qgsnetworkreplyparser.h
qgscredentials.h
qgsofflineediting.h
+ qgsogcutils.h
qgsoverlayobjectpositionmanager.h
qgsowsconnection.h
qgspallabeling.h
diff --git a/src/core/qgsexpression.cpp b/src/core/qgsexpression.cpp
index eebb757b0ef..502de7acf87 100644
--- a/src/core/qgsexpression.cpp
+++ b/src/core/qgsexpression.cpp
@@ -28,6 +28,7 @@
#include "qgsfeature.h"
#include "qgsgeometry.h"
#include "qgslogger.h"
+#include "qgsogcutils.h"
// from parser
extern QgsExpression::Node* parseExpression( const QString& str, QString& parserErrorMsg );
@@ -796,7 +797,7 @@ static QVariant fcnGeomFromWKT( const QVariantList& values, QgsFeature*, QgsExpr
static QVariant fcnGeomFromGML2( const QVariantList& values, QgsFeature*, QgsExpression* parent )
{
QString gml = getStringValue( values.at( 0 ), parent );
- QgsGeometry* geom = QgsGeometry::fromGML2( gml );
+ QgsGeometry* geom = QgsOgcUtils::geometryFromGML2( gml );
if ( geom )
return QVariant::fromValue( *geom );
@@ -2268,11 +2269,10 @@ void QgsExpression::NodeFunction::toOgcFilter( QDomDocument &doc, QDomElement &e
{
if ( childElem.attribute( "name" ) == "geomFromWKT" )
{
- QgsGeometry* geom = 0;
- geom = QgsGeometry::fromWkt( childElem.firstChildElement().text() );
+ QgsGeometry* geom = QgsGeometry::fromWkt( childElem.firstChildElement().text() );
if ( geom )
- funcElem.appendChild( geom->exportToGML2( doc ) );
-
+ funcElem.appendChild( QgsOgcUtils::geometryToGML2( geom, doc ) );
+ delete geom;
}
else if ( childElem.attribute( "name" ) == "geomFromGML2" )
{
diff --git a/src/core/qgsgeometry.cpp b/src/core/qgsgeometry.cpp
index f027d97178c..edfe258ab24 100644
--- a/src/core/qgsgeometry.cpp
+++ b/src/core/qgsgeometry.cpp
@@ -533,625 +533,6 @@ QgsGeometry* QgsGeometry::fromRect( const QgsRectangle& rect )
return fromPolygon( polygon );
}
-static const QString GML_NAMESPACE = "http://www.opengis.net/gml";
-QgsGeometry* QgsGeometry::fromGML2( const QDomNode& geometryNode )
-{
- QgsGeometry* g = new QgsGeometry();
- QDomElement geometryTypeElement = geometryNode.toElement();
- QString geomType = geometryTypeElement.tagName();
-
- if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" || geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon" || geomType == "Box" ) )
- {
- QDomNode geometryChild = geometryNode.firstChild();
- if ( geometryChild.isNull() )
- {
- return 0;
- }
- geometryTypeElement = geometryChild.toElement();
- geomType = geometryTypeElement.tagName();
- }
-
- if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" || geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon" || geomType == "Box" ) )
- return 0;
-
- if ( geomType == "Point" && g->setFromGML2Point( geometryTypeElement ) )
- {
- return g;
- }
- else if ( geomType == "LineString" && g->setFromGML2LineString( geometryTypeElement ) )
- {
- return g;
- }
- else if ( geomType == "Polygon" && g->setFromGML2Polygon( geometryTypeElement ) )
- {
- return g;
- }
- else if ( geomType == "MultiPoint" && g->setFromGML2MultiPoint( geometryTypeElement ) )
- {
- return g;
- }
- else if ( geomType == "MultiLineString" && g->setFromGML2MultiLineString( geometryTypeElement ) )
- {
- return g;
- }
- else if ( geomType == "MultiPolygon" && g->setFromGML2MultiPolygon( geometryTypeElement ) )
- {
- 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" );
- if ( coordList.size() < 1 )
- {
- return false;
- }
- QDomElement coordElement = coordList.at( 0 ).toElement();
- std::list pointCoordinate;
- if ( readGML2Coordinates( pointCoordinate, coordElement ) != 0 )
- {
- return false;
- }
-
- if ( pointCoordinate.size() < 1 )
- {
- return false;
- }
-
- std::list::const_iterator point_it = pointCoordinate.begin();
- //char e = QgsApplication::endian();
- char e = ( htonl( 1 ) == 1 ) ? 0 : 1 ;
- double x = point_it->x();
- double y = point_it->y();
- int size = 1 + sizeof( int ) + 2 * sizeof( double );
-
- QGis::WkbType type = QGis::WKBPoint;
- unsigned char* wkb = new unsigned char[size];
-
- int wkbPosition = 0; //current offset from wkb beginning (in bytes)
- memcpy( &( wkb )[wkbPosition], &e, 1 );
- wkbPosition += 1;
- memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
- wkbPosition += sizeof( int );
- memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) );
- wkbPosition += sizeof( double );
- memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) );
-
- fromWkb( wkb, size );
- return true;
-}
-
-bool QgsGeometry::setFromGML2LineString( const QDomElement& geometryElement )
-{
- QDomNodeList coordinatesList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "coordinates" );
- if ( coordinatesList.size() < 1 )
- {
- return false;
- }
- QDomElement coordinatesElement = coordinatesList.at( 0 ).toElement();
- std::list lineCoordinates;
- if ( readGML2Coordinates( lineCoordinates, coordinatesElement ) != 0 )
- {
- return false;
- }
-
- //char e = QgsApplication::endian();
- char e = ( htonl( 1 ) == 1 ) ? 0 : 1 ;
- int size = 1 + 2 * sizeof( int ) + lineCoordinates.size() * 2 * sizeof( double );
-
- QGis::WkbType type = QGis::WKBLineString;
- unsigned char* wkb = new unsigned char[size];
-
- int wkbPosition = 0; //current offset from wkb beginning (in bytes)
- double x, y;
- int nPoints = lineCoordinates.size();
-
- //fill the contents into *wkb
- memcpy( &( wkb )[wkbPosition], &e, 1 );
- wkbPosition += 1;
- memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
- wkbPosition += sizeof( int );
- memcpy( &( wkb )[wkbPosition], &nPoints, sizeof( int ) );
- wkbPosition += sizeof( int );
-
- std::list::const_iterator iter;
- for ( iter = lineCoordinates.begin(); iter != lineCoordinates.end(); ++iter )
- {
- x = iter->x();
- y = iter->y();
- memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) );
- wkbPosition += sizeof( double );
- memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) );
- wkbPosition += sizeof( double );
- }
-
- fromWkb( wkb, size );
- return true;
-}
-
-bool QgsGeometry::setFromGML2Polygon( const QDomElement& geometryElement )
-{
- //read all the coordinates (as QgsPoint) into memory. Each linear ring has an entry in the vector
- std::vector > ringCoordinates;
-
- //read coordinates for outer boundary
- QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "outerBoundaryIs" );
- if ( outerBoundaryList.size() < 1 ) //outer ring is necessary
- {
- return false;
- }
- QDomElement coordinatesElement = outerBoundaryList.at( 0 ).firstChild().firstChild().toElement();
- if ( coordinatesElement.isNull() )
- {
- return false;
- }
- std::list exteriorPointList;
- if ( readGML2Coordinates( exteriorPointList, coordinatesElement ) != 0 )
- {
- return false;
- }
- ringCoordinates.push_back( exteriorPointList );
-
- //read coordinates for inner boundary
- QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "innerBoundaryIs" );
- for ( int i = 0; i < innerBoundaryList.size(); ++i )
- {
- std::list interiorPointList;
- QDomElement coordinatesElement = innerBoundaryList.at( i ).firstChild().firstChild().toElement();
- if ( coordinatesElement.isNull() )
- {
- return false;
- }
- if ( readGML2Coordinates( interiorPointList, coordinatesElement ) != 0 )
- {
- return false;
- }
- ringCoordinates.push_back( interiorPointList );
- }
-
- //calculate number of bytes to allocate
- int nrings = ringCoordinates.size();
- int npoints = 0;//total number of points
- for ( std::vector >::const_iterator it = ringCoordinates.begin(); it != ringCoordinates.end(); ++it )
- {
- npoints += it->size();
- }
- int size = 1 + 2 * sizeof( int ) + nrings * sizeof( int ) + 2 * npoints * sizeof( double );
-
- QGis::WkbType type = QGis::WKBPolygon;
- unsigned char* wkb = new unsigned char[size];
-
- //char e = QgsApplication::endian();
- char e = ( htonl( 1 ) == 1 ) ? 0 : 1 ;
- int wkbPosition = 0; //current offset from wkb beginning (in bytes)
- int nPointsInRing = 0;
- double x, y;
-
- //fill the contents into *wkb
- memcpy( &( wkb )[wkbPosition], &e, 1 );
- wkbPosition += 1;
- memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
- wkbPosition += sizeof( int );
- memcpy( &( wkb )[wkbPosition], &nrings, sizeof( int ) );
- wkbPosition += sizeof( int );
- for ( std::vector >::const_iterator it = ringCoordinates.begin(); it != ringCoordinates.end(); ++it )
- {
- nPointsInRing = it->size();
- memcpy( &( wkb )[wkbPosition], &nPointsInRing, sizeof( int ) );
- wkbPosition += sizeof( int );
- //iterate through the string list converting the strings to x-/y- doubles
- std::list::const_iterator iter;
- for ( iter = it->begin(); iter != it->end(); ++iter )
- {
- x = iter->x();
- y = iter->y();
- //qWarning("currentCoordinate: " + QString::number(x) + " // " + QString::number(y));
- memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) );
- wkbPosition += sizeof( double );
- memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) );
- wkbPosition += sizeof( double );
- }
- }
-
- fromWkb( wkb, size );
- return true;
-}
-
-bool QgsGeometry::setFromGML2MultiPoint( const QDomElement& geometryElement )
-{
- std::list pointList;
- std::list currentPoint;
- QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "pointMember" );
- if ( pointMemberList.size() < 1 )
- {
- return false;
- }
- QDomNodeList pointNodeList;
- QDomNodeList coordinatesList;
- for ( int i = 0; i < pointMemberList.size(); ++i )
- {
- // element
- pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS( GML_NAMESPACE, "Point" );
- if ( pointNodeList.size() < 1 )
- {
- continue;
- }
- // element
- coordinatesList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS( GML_NAMESPACE, "coordinates" );
- if ( coordinatesList.size() < 1 )
- {
- continue;
- }
- currentPoint.clear();
- if ( readGML2Coordinates( currentPoint, coordinatesList.at( 0 ).toElement() ) != 0 )
- {
- continue;
- }
- if ( currentPoint.size() < 1 )
- {
- continue;
- }
- pointList.push_back(( *currentPoint.begin() ) );
- }
-
- //calculate the required wkb size
- int size = 1 + 2 * sizeof( int ) + pointList.size() * ( 2 * sizeof( double ) + 1 + sizeof( int ) );
-
- QGis::WkbType type = QGis::WKBMultiPoint;
- unsigned char* wkb = new unsigned char[size];
-
- //fill the wkb content
- //char e = QgsApplication::endian();
- char e = ( htonl( 1 ) == 1 ) ? 0 : 1 ;
- int wkbPosition = 0; //current offset from wkb beginning (in bytes)
- int nPoints = pointList.size(); //number of points
- double x, y;
- memcpy( &( wkb )[wkbPosition], &e, 1 );
- wkbPosition += 1;
- memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
- wkbPosition += sizeof( int );
- memcpy( &( wkb )[wkbPosition], &nPoints, sizeof( int ) );
- wkbPosition += sizeof( int );
- for ( std::list::const_iterator it = pointList.begin(); it != pointList.end(); ++it )
- {
- memcpy( &( wkb )[wkbPosition], &e, 1 );
- wkbPosition += 1;
- memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
- wkbPosition += sizeof( int );
- x = it->x();
- memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) );
- wkbPosition += sizeof( double );
- y = it->y();
- memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) );
- wkbPosition += sizeof( double );
- }
-
- fromWkb( wkb, size );
- return true;
-}
-
-bool QgsGeometry::setFromGML2MultiLineString( const QDomElement& geometryElement )
-{
- //geoserver has
- //
- //
- //
-
- //mapserver has directly
- // > lineCoordinates; //first list: lines, second list: points of one line
- QDomElement currentLineStringElement;
- QDomNodeList currentCoordList;
-
- QDomNodeList lineStringMemberList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "lineStringMember" );
- if ( lineStringMemberList.size() > 0 ) //geoserver
- {
- for ( int i = 0; i < lineStringMemberList.size(); ++i )
- {
- QDomNodeList lineStringNodeList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "LineString" );
- if ( lineStringNodeList.size() < 1 )
- {
- return false;
- }
- currentLineStringElement = lineStringNodeList.at( 0 ).toElement();
- currentCoordList = currentLineStringElement.elementsByTagNameNS( GML_NAMESPACE, "coordinates" );
- if ( currentCoordList.size() < 1 )
- {
- return false;
- }
- std::list currentPointList;
- if ( readGML2Coordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
- {
- return false;
- }
- lineCoordinates.push_back( currentPointList );
- }
- }
- else
- {
- QDomNodeList lineStringList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "LineString" );
- if ( lineStringList.size() > 0 ) //mapserver
- {
- for ( int i = 0; i < lineStringList.size(); ++i )
- {
- currentLineStringElement = lineStringList.at( i ).toElement();
- currentCoordList = currentLineStringElement.elementsByTagNameNS( GML_NAMESPACE, "coordinates" );
- if ( currentCoordList.size() < 1 )
- {
- return false;
- }
- std::list currentPointList;
- if ( readGML2Coordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
- {
- return false;
- }
- lineCoordinates.push_back( currentPointList );
- }
- }
- else
- {
- return false;
- }
- }
-
-
- //calculate the required wkb size
- int size = ( lineCoordinates.size() + 1 ) * ( 1 + 2 * sizeof( int ) );
- for ( std::list >::const_iterator it = lineCoordinates.begin(); it != lineCoordinates.end(); ++it )
- {
- size += it->size() * 2 * sizeof( double );
- }
-
- QGis::WkbType type = QGis::WKBMultiLineString;
- unsigned char* wkb = new unsigned char[size];
-
- //fill the wkb content
- //char e = QgsApplication::endian();
- char e = ( htonl( 1 ) == 1 ) ? 0 : 1 ;
- int wkbPosition = 0; //current offset from wkb beginning (in bytes)
- int nLines = lineCoordinates.size();
- int nPoints; //number of points in a line
- double x, y;
- memcpy( &( wkb )[wkbPosition], &e, 1 );
- wkbPosition += 1;
- memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
- wkbPosition += sizeof( int );
- memcpy( &( wkb )[wkbPosition], &nLines, sizeof( int ) );
- wkbPosition += sizeof( int );
- for ( std::list >::const_iterator it = lineCoordinates.begin(); it != lineCoordinates.end(); ++it )
- {
- memcpy( &( wkb )[wkbPosition], &e, 1 );
- wkbPosition += 1;
- memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
- wkbPosition += sizeof( int );
- nPoints = it->size();
- memcpy( &( wkb )[wkbPosition], &nPoints, sizeof( int ) );
- wkbPosition += sizeof( int );
- for ( std::list::const_iterator iter = it->begin(); iter != it->end(); ++iter )
- {
- x = iter->x();
- //qWarning("x is: " + QString::number(x));
- y = iter->y();
- //qWarning("y is: " + QString::number(y));
- memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) );
- wkbPosition += sizeof( double );
- memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) );
- wkbPosition += sizeof( double );
- }
- }
-
- fromWkb( wkb, size );
- return true;
-}
-
-bool QgsGeometry::setFromGML2MultiPolygon( const QDomElement& geometryElement )
-{
- //first list: different polygons, second list: different rings, third list: different points
- std::list > > multiPolygonPoints;
- QDomElement currentPolygonMemberElement;
- QDomNodeList polygonList;
- QDomElement currentPolygonElement;
- QDomNodeList outerBoundaryList;
- QDomElement currentOuterBoundaryElement;
- QDomElement currentInnerBoundaryElement;
- QDomNodeList innerBoundaryList;
- QDomNodeList linearRingNodeList;
- QDomElement currentLinearRingElement;
- QDomNodeList currentCoordinateList;
-
- QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "polygonMember" );
- for ( int i = 0; i < polygonMemberList.size(); ++i )
- {
- std::list > currentPolygonList;
- currentPolygonMemberElement = polygonMemberList.at( i ).toElement();
- polygonList = currentPolygonMemberElement.elementsByTagNameNS( GML_NAMESPACE, "Polygon" );
- if ( polygonList.size() < 1 )
- {
- continue;
- }
- currentPolygonElement = polygonList.at( 0 ).toElement();
-
- //find exterior ring
- outerBoundaryList = currentPolygonElement.elementsByTagNameNS( GML_NAMESPACE, "outerBoundaryIs" );
- if ( outerBoundaryList.size() < 1 )
- {
- continue;
- }
-
- currentOuterBoundaryElement = outerBoundaryList.at( 0 ).toElement();
- std::list ringCoordinates;
-
- linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS( GML_NAMESPACE, "LinearRing" );
- if ( linearRingNodeList.size() < 1 )
- {
- continue;
- }
- currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
- currentCoordinateList = currentLinearRingElement.elementsByTagNameNS( GML_NAMESPACE, "coordinates" );
- if ( currentCoordinateList.size() < 1 )
- {
- continue;
- }
- if ( readGML2Coordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
- {
- continue;
- }
- currentPolygonList.push_back( ringCoordinates );
-
- //find interior rings
- QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS( GML_NAMESPACE, "innerBoundaryIs" );
- for ( int j = 0; j < innerBoundaryList.size(); ++j )
- {
- std::list ringCoordinates;
- currentInnerBoundaryElement = innerBoundaryList.at( j ).toElement();
- linearRingNodeList = currentInnerBoundaryElement.elementsByTagNameNS( GML_NAMESPACE, "LinearRing" );
- if ( linearRingNodeList.size() < 1 )
- {
- continue;
- }
- currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
- currentCoordinateList = currentLinearRingElement.elementsByTagNameNS( GML_NAMESPACE, "coordinates" );
- if ( currentCoordinateList.size() < 1 )
- {
- continue;
- }
- if ( readGML2Coordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
- {
- continue;
- }
- currentPolygonList.push_back( ringCoordinates );
- }
- multiPolygonPoints.push_back( currentPolygonList );
- }
-
- int size = 1 + 2 * sizeof( int );
- //calculate the wkb size
- for ( std::list > >::const_iterator it = multiPolygonPoints.begin(); it != multiPolygonPoints.end(); ++it )
- {
- size += 1 + 2 * sizeof( int );
- for ( std::list >::const_iterator iter = it->begin(); iter != it->end(); ++iter )
- {
- size += sizeof( int ) + 2 * iter->size() * sizeof( double );
- }
- }
-
- QGis::WkbType type = QGis::WKBMultiPolygon;
- unsigned char* wkb = new unsigned char[size];
-
- int polygonType = QGis::WKBPolygon;
- //char e = QgsApplication::endian();
- char e = ( htonl( 1 ) == 1 ) ? 0 : 1 ;
- int wkbPosition = 0; //current offset from wkb beginning (in bytes)
- double x, y;
- int nPolygons = multiPolygonPoints.size();
- int nRings;
- int nPointsInRing;
-
- //fill the contents into *wkb
- memcpy( &( wkb )[wkbPosition], &e, 1 );
- wkbPosition += 1;
- memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
- wkbPosition += sizeof( int );
- memcpy( &( wkb )[wkbPosition], &nPolygons, sizeof( int ) );
- wkbPosition += sizeof( int );
-
- for ( std::list > >::const_iterator it = multiPolygonPoints.begin(); it != multiPolygonPoints.end(); ++it )
- {
- memcpy( &( wkb )[wkbPosition], &e, 1 );
- wkbPosition += 1;
- memcpy( &( wkb )[wkbPosition], &polygonType, sizeof( int ) );
- wkbPosition += sizeof( int );
- nRings = it->size();
- memcpy( &( wkb )[wkbPosition], &nRings, sizeof( int ) );
- wkbPosition += sizeof( int );
- for ( std::list >::const_iterator iter = it->begin(); iter != it->end(); ++iter )
- {
- nPointsInRing = iter->size();
- memcpy( &( wkb )[wkbPosition], &nPointsInRing, sizeof( int ) );
- wkbPosition += sizeof( int );
- for ( std::list::const_iterator iterator = iter->begin(); iterator != iter->end(); ++iterator )
- {
- x = iterator->x();
- y = iterator->y();
- memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) );
- wkbPosition += sizeof( double );
- memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) );
- wkbPosition += sizeof( double );
- }
- }
- }
-
- fromWkb( wkb, size );
- return true;
-}
-
-bool QgsGeometry::readGML2Coordinates( std::list& coords, const QDomElement elem ) const
-{
- QString coordSeparator = ",";
- QString tupelSeparator = " ";
- //"decimal" has to be "."
-
- coords.clear();
-
- if ( elem.hasAttribute( "cs" ) )
- {
- coordSeparator = elem.attribute( "cs" );
- }
- if ( elem.hasAttribute( "ts" ) )
- {
- tupelSeparator = elem.attribute( "ts" );
- }
-
- QStringList tupels = elem.text().split( tupelSeparator, QString::SkipEmptyParts );
- QStringList tupel_coords;
- double x, y;
- bool conversionSuccess;
-
- QStringList::const_iterator it;
- for ( it = tupels.constBegin(); it != tupels.constEnd(); ++it )
- {
- tupel_coords = ( *it ).split( coordSeparator, QString::SkipEmptyParts );
- if ( tupel_coords.size() < 2 )
- {
- continue;
- }
- x = tupel_coords.at( 0 ).toDouble( &conversionSuccess );
- if ( !conversionSuccess )
- {
- return 1;
- }
- y = tupel_coords.at( 1 ).toDouble( &conversionSuccess );
- if ( !conversionSuccess )
- {
- return 1;
- }
- coords.push_back( QgsPoint( x, y ) );
- }
- return 0;
-}
QgsGeometry & QgsGeometry::operator=( QgsGeometry const & rhs )
{
@@ -5145,316 +4526,6 @@ QString QgsGeometry::exportToGeoJSON()
}
}
-QDomElement QgsGeometry::exportToGML2( QDomDocument& doc )
-{
- QgsDebugMsg( "entered." );
-
- // TODO: implement with GEOS
- if ( mDirtyWkb )
- {
- exportGeosToWkb();
- }
-
- if ( !mGeometry )
- {
- QgsDebugMsg( "WKB geometry not available!" );
- return QDomElement();
- }
-
- QGis::WkbType wkbType;
- bool hasZValue = false;
- double *x, *y;
-
- QString mWkt; // TODO: rename
-
- // Will this really work when mGeometry[0] == 0 ???? I (gavin) think not.
- //wkbType = (mGeometry[0] == 1) ? mGeometry[1] : mGeometry[4];
- memcpy( &wkbType, &( mGeometry[1] ), sizeof( int ) );
-
- switch ( wkbType )
- {
- case QGis::WKBPoint25D:
- case QGis::WKBPoint:
- {
- QDomElement pointElem = doc.createElement( "gml:Point" );
- QDomElement coordElem = doc.createElement( "gml:coordinates" );
- coordElem.setAttribute( "cs", "," );
- coordElem.setAttribute( "ts", " " );
- QString coordString;
- x = ( double * )( mGeometry + 5 );
- coordString += QString::number( *x, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
- coordString += ",";
- y = ( double * )( mGeometry + 5 + sizeof( double ) );
- coordString += QString::number( *y, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
- QDomText coordText = doc.createTextNode( coordString );
- coordElem.appendChild( coordText );
- pointElem.appendChild( coordElem );
- return pointElem;
- }
- case QGis::WKBMultiPoint25D:
- hasZValue = true;
- case QGis::WKBMultiPoint:
- {
- unsigned char *ptr;
- int idx;
- int *nPoints;
-
- QDomElement multiPointElem = doc.createElement( "gml:MultiPoint" );
- nPoints = ( int* )( mGeometry + 5 );
- ptr = mGeometry + 5 + sizeof( int );
- for ( idx = 0; idx < *nPoints; ++idx )
- {
- ptr += ( 1 + sizeof( int ) );
- QDomElement pointMemberElem = doc.createElement( "gml:pointMember" );
- QDomElement pointElem = doc.createElement( "gml:Point" );
- QDomElement coordElem = doc.createElement( "gml:coordinates" );
- coordElem.setAttribute( "cs", "," );
- coordElem.setAttribute( "ts", " " );
- QString coordString;
- x = ( double * )( ptr );
- coordString += QString::number( *x, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
- coordString += ",";
- ptr += sizeof( double );
- y = ( double * )( ptr );
- coordString += QString::number( *y, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
- QDomText coordText = doc.createTextNode( coordString );
- coordElem.appendChild( coordText );
- pointElem.appendChild( coordElem );
-
- ptr += sizeof( double );
- if ( hasZValue )
- {
- ptr += sizeof( double );
- }
- pointMemberElem.appendChild( pointElem );
- multiPointElem.appendChild( pointMemberElem );
- }
- return multiPointElem;
- }
- case QGis::WKBLineString25D:
- hasZValue = true;
- case QGis::WKBLineString:
- {
- QgsDebugMsg( "LINESTRING found" );
- unsigned char *ptr;
- int *nPoints;
- int idx;
-
- QDomElement lineStringElem = doc.createElement( "gml:LineString" );
- // get number of points in the line
- ptr = mGeometry + 5;
- nPoints = ( int * ) ptr;
- ptr = mGeometry + 1 + 2 * sizeof( int );
- QDomElement coordElem = doc.createElement( "gml:coordinates" );
- coordElem.setAttribute( "cs", "," );
- coordElem.setAttribute( "ts", " " );
- QString coordString;
- for ( idx = 0; idx < *nPoints; ++idx )
- {
- if ( idx != 0 )
- {
- coordString += " ";
- }
- x = ( double * ) ptr;
- coordString += QString::number( *x, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
- coordString += ",";
- ptr += sizeof( double );
- y = ( double * ) ptr;
- coordString += QString::number( *y, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
- ptr += sizeof( double );
- if ( hasZValue )
- {
- ptr += sizeof( double );
- }
- }
- QDomText coordText = doc.createTextNode( coordString );
- coordElem.appendChild( coordText );
- lineStringElem.appendChild( coordElem );
- return lineStringElem;
- }
- case QGis::WKBMultiLineString25D:
- hasZValue = true;
- case QGis::WKBMultiLineString:
- {
- QgsDebugMsg( "MULTILINESTRING found" );
- unsigned char *ptr;
- int idx, jdx, numLineStrings;
- int *nPoints;
-
- QDomElement multiLineStringElem = doc.createElement( "gml:MultiLineString" );
- numLineStrings = ( int )( mGeometry[5] );
- ptr = mGeometry + 9;
- for ( jdx = 0; jdx < numLineStrings; jdx++ )
- {
- QDomElement lineStringMemberElem = doc.createElement( "gml:lineStringMember" );
- QDomElement lineStringElem = doc.createElement( "gml:LineString" );
- ptr += 5; // skip type since we know its 2
- nPoints = ( int * ) ptr;
- ptr += sizeof( int );
- QDomElement coordElem = doc.createElement( "gml:coordinates" );
- coordElem.setAttribute( "cs", "," );
- coordElem.setAttribute( "ts", " " );
- QString coordString;
- for ( idx = 0; idx < *nPoints; idx++ )
- {
- if ( idx != 0 )
- {
- coordString += " ";
- }
- x = ( double * ) ptr;
- coordString += QString::number( *x, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
- ptr += sizeof( double );
- coordString += ",";
- y = ( double * ) ptr;
- coordString += QString::number( *y, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
- ptr += sizeof( double );
- if ( hasZValue )
- {
- ptr += sizeof( double );
- }
- }
- QDomText coordText = doc.createTextNode( coordString );
- coordElem.appendChild( coordText );
- lineStringElem.appendChild( coordElem );
- lineStringMemberElem.appendChild( lineStringElem );
- multiLineStringElem.appendChild( lineStringMemberElem );
- }
- return multiLineStringElem;
- }
- case QGis::WKBPolygon25D:
- hasZValue = true;
- case QGis::WKBPolygon:
- {
- QgsDebugMsg( "POLYGON found" );
- unsigned char *ptr;
- int idx, jdx;
- int *numRings, *nPoints;
-
- QDomElement polygonElem = doc.createElement( "gml:Polygon" );
- // get number of rings in the polygon
- numRings = ( int * )( mGeometry + 1 + sizeof( int ) );
- if ( !( *numRings ) ) // sanity check for zero rings in polygon
- {
- return QDomElement();
- }
- int *ringStart; // index of first point for each ring
- int *ringNumPoints; // number of points in each ring
- ringStart = new int[*numRings];
- ringNumPoints = new int[*numRings];
- ptr = mGeometry + 1 + 2 * sizeof( int ); // set pointer to the first ring
- for ( idx = 0; idx < *numRings; idx++ )
- {
- QString boundaryName = "gml:outerBoundaryIs";
- if ( idx != 0 )
- {
- boundaryName = "gml:innerBoundaryIs";
- }
- QDomElement boundaryElem = doc.createElement( boundaryName );
- QDomElement ringElem = doc.createElement( "gml:LinearRing" );
- // get number of points in the ring
- nPoints = ( int * ) ptr;
- ringNumPoints[idx] = *nPoints;
- ptr += 4;
- QDomElement coordElem = doc.createElement( "gml:coordinates" );
- coordElem.setAttribute( "cs", "," );
- coordElem.setAttribute( "ts", " " );
- QString coordString;
- for ( jdx = 0; jdx < *nPoints; jdx++ )
- {
- if ( jdx != 0 )
- {
- coordString += " ";
- }
- x = ( double * ) ptr;
- coordString += QString::number( *x, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
- coordString += ",";
- ptr += sizeof( double );
- y = ( double * ) ptr;
- coordString += QString::number( *y, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
- ptr += sizeof( double );
- if ( hasZValue )
- {
- ptr += sizeof( double );
- }
- }
- QDomText coordText = doc.createTextNode( coordString );
- coordElem.appendChild( coordText );
- ringElem.appendChild( coordElem );
- boundaryElem.appendChild( ringElem );
- polygonElem.appendChild( boundaryElem );
- }
- delete [] ringStart;
- delete [] ringNumPoints;
- return polygonElem;
- }
- case QGis::WKBMultiPolygon25D:
- hasZValue = true;
- case QGis::WKBMultiPolygon:
- {
- QgsDebugMsg( "MULTIPOLYGON found" );
- unsigned char *ptr;
- int idx, jdx, kdx;
- int *numPolygons, *numRings, *nPoints;
-
- QDomElement multiPolygonElem = doc.createElement( "gml:MultiPolygon" );
- ptr = mGeometry + 5;
- numPolygons = ( int * ) ptr;
- ptr = mGeometry + 9;
- for ( kdx = 0; kdx < *numPolygons; kdx++ )
- {
- QDomElement polygonMemberElem = doc.createElement( "gml:polygonMember" );
- QDomElement polygonElem = doc.createElement( "gml:Polygon" );
- ptr += 5;
- numRings = ( int * ) ptr;
- ptr += 4;
- for ( idx = 0; idx < *numRings; idx++ )
- {
- QString boundaryName = "gml:outerBoundaryIs";
- if ( idx != 0 )
- {
- boundaryName = "gml:innerBoundaryIs";
- }
- QDomElement boundaryElem = doc.createElement( boundaryName );
- QDomElement ringElem = doc.createElement( "gml:LinearRing" );
- nPoints = ( int * ) ptr;
- ptr += 4;
- QDomElement coordElem = doc.createElement( "gml:coordinates" );
- coordElem.setAttribute( "cs", "," );
- coordElem.setAttribute( "ts", " " );
- QString coordString;
- for ( jdx = 0; jdx < *nPoints; jdx++ )
- {
- if ( jdx != 0 )
- {
- coordString += " ";
- }
- x = ( double * ) ptr;
- coordString += QString::number( *x, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
- ptr += sizeof( double );
- coordString += ",";
- y = ( double * ) ptr;
- coordString += QString::number( *y, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
- ptr += sizeof( double );
- if ( hasZValue )
- {
- ptr += sizeof( double );
- }
- }
- QDomText coordText = doc.createTextNode( coordString );
- coordElem.appendChild( coordText );
- ringElem.appendChild( coordElem );
- boundaryElem.appendChild( ringElem );
- polygonElem.appendChild( boundaryElem );
- polygonMemberElem.appendChild( polygonElem );
- multiPolygonElem.appendChild( polygonMemberElem );
- }
- }
- return multiPolygonElem;
- }
- default:
- return QDomElement();
- }
-}
bool QgsGeometry::exportWkbToGeos()
{
diff --git a/src/core/qgsgeometry.h b/src/core/qgsgeometry.h
index f684cbbb9ec..21e60afb530 100644
--- a/src/core/qgsgeometry.h
+++ b/src/core/qgsgeometry.h
@@ -89,18 +89,6 @@ 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
- */
- static QgsGeometry* fromGML2( const QDomNode& geometryNode );
-
/** construct geometry from a point */
static QgsGeometry* fromPoint( const QgsPoint& point );
/** construct geometry from a multipoint */
@@ -395,12 +383,6 @@ class CORE_EXPORT QgsGeometry
*/
QString exportToGeoJSON();
- /** Exports the geometry to mGML2
- @return true in case of success and false else
- * @note added in 1.9
- */
- QDomElement exportToGML2( QDomDocument& doc );
-
/* Accessor functions for getting geometry data */
/** return contents of the geometry as a point
@@ -506,24 +488,6 @@ class CORE_EXPORT QgsGeometry
// Private functions
- /** static method that creates geometry from GML2 Point */
- bool setFromGML2Point( const QDomElement& geometryElement );
- /** static method that creates geometry from GML2 LineString */
- bool setFromGML2LineString( const QDomElement& geometryElement );
- /** static method that creates geometry from GML2 Polygon */
- bool setFromGML2Polygon( const QDomElement& geometryElement );
- /** static method that creates geometry from GML2 MultiPoint */
- bool setFromGML2MultiPoint( const QDomElement& geometryElement );
- /** static method that creates geometry from GML2 MultiLineString */
- bool setFromGML2MultiLineString( const QDomElement& geometryElement );
- /** static method that creates geometry from GML2 MultiPolygon */
- bool setFromGML2MultiPolygon( const QDomElement& geometryElement );
- /**Reads the element and extracts the coordinates as points
- @param coords list where the found coordinates are appended
- @param elem the element
- @return boolean for success*/
- bool readGML2Coordinates( std::list& coords, const QDomElement elem ) const;
-
/** Converts from the WKB geometry to the GEOS geometry.
@return true in case of success and false else
*/
diff --git a/src/core/qgsogcutils.cpp b/src/core/qgsogcutils.cpp
new file mode 100644
index 00000000000..c71053710a7
--- /dev/null
+++ b/src/core/qgsogcutils.cpp
@@ -0,0 +1,969 @@
+#include "qgsogcutils.h"
+
+#include "qgsgeometry.h"
+
+#include
+
+#ifndef Q_WS_WIN
+#include
+#else
+#include
+#endif
+
+
+static const QString GML_NAMESPACE = "http://www.opengis.net/gml";
+
+QgsGeometry* QgsOgcUtils::geometryFromGML2( const QDomNode& geometryNode )
+{
+ QDomElement geometryTypeElement = geometryNode.toElement();
+ QString geomType = geometryTypeElement.tagName();
+
+ if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" || geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon" || geomType == "Box" ) )
+ {
+ QDomNode geometryChild = geometryNode.firstChild();
+ if ( geometryChild.isNull() )
+ {
+ return 0;
+ }
+ geometryTypeElement = geometryChild.toElement();
+ geomType = geometryTypeElement.tagName();
+ }
+
+ if ( !( geomType == "Point" || geomType == "LineString" || geomType == "Polygon" || geomType == "MultiPoint" || geomType == "MultiLineString" || geomType == "MultiPolygon" || geomType == "Box" ) )
+ return 0;
+
+ if ( geomType == "Point" )
+ {
+ return geometryFromGML2Point( geometryTypeElement );
+ }
+ else if ( geomType == "LineString" )
+ {
+ return geometryFromGML2LineString( geometryTypeElement );
+ }
+ else if ( geomType == "Polygon" )
+ {
+ return geometryFromGML2Polygon( geometryTypeElement );
+ }
+ else if ( geomType == "MultiPoint" )
+ {
+ return geometryFromGML2MultiPoint( geometryTypeElement );
+ }
+ else if ( geomType == "MultiLineString" )
+ {
+ return geometryFromGML2MultiLineString( geometryTypeElement );
+ }
+ else if ( geomType == "MultiPolygon" )
+ {
+ return geometryFromGML2MultiPolygon( geometryTypeElement );
+ }
+ else if ( geomType == "Box" )
+ {
+ return QgsGeometry::fromRect( rectangleFromGMLBox( geometryTypeElement ) );
+ }
+ else //unknown type
+ {
+ return 0;
+ }
+}
+
+QgsGeometry* QgsOgcUtils::geometryFromGML2( 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 geometryFromGML2( doc.documentElement().firstChildElement() );
+}
+
+
+QgsGeometry* QgsOgcUtils::geometryFromGML2Point( const QDomElement& geometryElement )
+{
+ QDomNodeList coordList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "coordinates" );
+ if ( coordList.size() < 1 )
+ {
+ return 0;
+ }
+ QDomElement coordElement = coordList.at( 0 ).toElement();
+ std::list pointCoordinate;
+ if ( readGML2Coordinates( pointCoordinate, coordElement ) != 0 )
+ {
+ return 0;
+ }
+
+ if ( pointCoordinate.size() < 1 )
+ {
+ return 0;
+ }
+
+ std::list::const_iterator point_it = pointCoordinate.begin();
+ //char e = QgsApplication::endian();
+ char e = ( htonl( 1 ) == 1 ) ? 0 : 1 ;
+ double x = point_it->x();
+ double y = point_it->y();
+ int size = 1 + sizeof( int ) + 2 * sizeof( double );
+
+ QGis::WkbType type = QGis::WKBPoint;
+ unsigned char* wkb = new unsigned char[size];
+
+ int wkbPosition = 0; //current offset from wkb beginning (in bytes)
+ memcpy( &( wkb )[wkbPosition], &e, 1 );
+ wkbPosition += 1;
+ memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) );
+ wkbPosition += sizeof( double );
+ memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) );
+
+ QgsGeometry* g = new QgsGeometry();
+ g->fromWkb( wkb, size );
+ return g;
+}
+
+QgsGeometry* QgsOgcUtils::geometryFromGML2LineString( const QDomElement& geometryElement )
+{
+ QDomNodeList coordinatesList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "coordinates" );
+ if ( coordinatesList.size() < 1 )
+ {
+ return 0;
+ }
+ QDomElement coordinatesElement = coordinatesList.at( 0 ).toElement();
+ std::list lineCoordinates;
+ if ( readGML2Coordinates( lineCoordinates, coordinatesElement ) != 0 )
+ {
+ return 0;
+ }
+
+ //char e = QgsApplication::endian();
+ char e = ( htonl( 1 ) == 1 ) ? 0 : 1 ;
+ int size = 1 + 2 * sizeof( int ) + lineCoordinates.size() * 2 * sizeof( double );
+
+ QGis::WkbType type = QGis::WKBLineString;
+ unsigned char* wkb = new unsigned char[size];
+
+ int wkbPosition = 0; //current offset from wkb beginning (in bytes)
+ double x, y;
+ int nPoints = lineCoordinates.size();
+
+ //fill the contents into *wkb
+ memcpy( &( wkb )[wkbPosition], &e, 1 );
+ wkbPosition += 1;
+ memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ memcpy( &( wkb )[wkbPosition], &nPoints, sizeof( int ) );
+ wkbPosition += sizeof( int );
+
+ std::list::const_iterator iter;
+ for ( iter = lineCoordinates.begin(); iter != lineCoordinates.end(); ++iter )
+ {
+ x = iter->x();
+ y = iter->y();
+ memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) );
+ wkbPosition += sizeof( double );
+ memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) );
+ wkbPosition += sizeof( double );
+ }
+
+ QgsGeometry* g = new QgsGeometry();
+ g->fromWkb( wkb, size );
+ return g;
+}
+
+QgsGeometry* QgsOgcUtils::geometryFromGML2Polygon( const QDomElement& geometryElement )
+{
+ //read all the coordinates (as QgsPoint) into memory. Each linear ring has an entry in the vector
+ std::vector > ringCoordinates;
+
+ //read coordinates for outer boundary
+ QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "outerBoundaryIs" );
+ if ( outerBoundaryList.size() < 1 ) //outer ring is necessary
+ {
+ return 0;
+ }
+ QDomElement coordinatesElement = outerBoundaryList.at( 0 ).firstChild().firstChild().toElement();
+ if ( coordinatesElement.isNull() )
+ {
+ return 0;
+ }
+ std::list exteriorPointList;
+ if ( readGML2Coordinates( exteriorPointList, coordinatesElement ) != 0 )
+ {
+ return 0;
+ }
+ ringCoordinates.push_back( exteriorPointList );
+
+ //read coordinates for inner boundary
+ QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "innerBoundaryIs" );
+ for ( int i = 0; i < innerBoundaryList.size(); ++i )
+ {
+ std::list interiorPointList;
+ QDomElement coordinatesElement = innerBoundaryList.at( i ).firstChild().firstChild().toElement();
+ if ( coordinatesElement.isNull() )
+ {
+ return 0;
+ }
+ if ( readGML2Coordinates( interiorPointList, coordinatesElement ) != 0 )
+ {
+ return 0;
+ }
+ ringCoordinates.push_back( interiorPointList );
+ }
+
+ //calculate number of bytes to allocate
+ int nrings = ringCoordinates.size();
+ int npoints = 0;//total number of points
+ for ( std::vector >::const_iterator it = ringCoordinates.begin(); it != ringCoordinates.end(); ++it )
+ {
+ npoints += it->size();
+ }
+ int size = 1 + 2 * sizeof( int ) + nrings * sizeof( int ) + 2 * npoints * sizeof( double );
+
+ QGis::WkbType type = QGis::WKBPolygon;
+ unsigned char* wkb = new unsigned char[size];
+
+ //char e = QgsApplication::endian();
+ char e = ( htonl( 1 ) == 1 ) ? 0 : 1 ;
+ int wkbPosition = 0; //current offset from wkb beginning (in bytes)
+ int nPointsInRing = 0;
+ double x, y;
+
+ //fill the contents into *wkb
+ memcpy( &( wkb )[wkbPosition], &e, 1 );
+ wkbPosition += 1;
+ memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ memcpy( &( wkb )[wkbPosition], &nrings, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ for ( std::vector >::const_iterator it = ringCoordinates.begin(); it != ringCoordinates.end(); ++it )
+ {
+ nPointsInRing = it->size();
+ memcpy( &( wkb )[wkbPosition], &nPointsInRing, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ //iterate through the string list converting the strings to x-/y- doubles
+ std::list::const_iterator iter;
+ for ( iter = it->begin(); iter != it->end(); ++iter )
+ {
+ x = iter->x();
+ y = iter->y();
+ //qWarning("currentCoordinate: " + QString::number(x) + " // " + QString::number(y));
+ memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) );
+ wkbPosition += sizeof( double );
+ memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) );
+ wkbPosition += sizeof( double );
+ }
+ }
+
+ QgsGeometry* g = new QgsGeometry();
+ g->fromWkb( wkb, size );
+ return g;
+}
+
+QgsGeometry* QgsOgcUtils::geometryFromGML2MultiPoint( const QDomElement& geometryElement )
+{
+ std::list pointList;
+ std::list currentPoint;
+ QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "pointMember" );
+ if ( pointMemberList.size() < 1 )
+ {
+ return 0;
+ }
+ QDomNodeList pointNodeList;
+ QDomNodeList coordinatesList;
+ for ( int i = 0; i < pointMemberList.size(); ++i )
+ {
+ // element
+ pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS( GML_NAMESPACE, "Point" );
+ if ( pointNodeList.size() < 1 )
+ {
+ continue;
+ }
+ // element
+ coordinatesList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS( GML_NAMESPACE, "coordinates" );
+ if ( coordinatesList.size() < 1 )
+ {
+ continue;
+ }
+ currentPoint.clear();
+ if ( readGML2Coordinates( currentPoint, coordinatesList.at( 0 ).toElement() ) != 0 )
+ {
+ continue;
+ }
+ if ( currentPoint.size() < 1 )
+ {
+ continue;
+ }
+ pointList.push_back(( *currentPoint.begin() ) );
+ }
+
+ //calculate the required wkb size
+ int size = 1 + 2 * sizeof( int ) + pointList.size() * ( 2 * sizeof( double ) + 1 + sizeof( int ) );
+
+ QGis::WkbType type = QGis::WKBMultiPoint;
+ unsigned char* wkb = new unsigned char[size];
+
+ //fill the wkb content
+ //char e = QgsApplication::endian();
+ char e = ( htonl( 1 ) == 1 ) ? 0 : 1 ;
+ int wkbPosition = 0; //current offset from wkb beginning (in bytes)
+ int nPoints = pointList.size(); //number of points
+ double x, y;
+ memcpy( &( wkb )[wkbPosition], &e, 1 );
+ wkbPosition += 1;
+ memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ memcpy( &( wkb )[wkbPosition], &nPoints, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ for ( std::list::const_iterator it = pointList.begin(); it != pointList.end(); ++it )
+ {
+ memcpy( &( wkb )[wkbPosition], &e, 1 );
+ wkbPosition += 1;
+ memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ x = it->x();
+ memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) );
+ wkbPosition += sizeof( double );
+ y = it->y();
+ memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) );
+ wkbPosition += sizeof( double );
+ }
+
+ QgsGeometry* g = new QgsGeometry();
+ g->fromWkb( wkb, size );
+ return g;
+}
+
+QgsGeometry* QgsOgcUtils::geometryFromGML2MultiLineString( const QDomElement& geometryElement )
+{
+ //geoserver has
+ //
+ //
+ //
+
+ //mapserver has directly
+ // > lineCoordinates; //first list: lines, second list: points of one line
+ QDomElement currentLineStringElement;
+ QDomNodeList currentCoordList;
+
+ QDomNodeList lineStringMemberList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "lineStringMember" );
+ if ( lineStringMemberList.size() > 0 ) //geoserver
+ {
+ for ( int i = 0; i < lineStringMemberList.size(); ++i )
+ {
+ QDomNodeList lineStringNodeList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "LineString" );
+ if ( lineStringNodeList.size() < 1 )
+ {
+ return 0;
+ }
+ currentLineStringElement = lineStringNodeList.at( 0 ).toElement();
+ currentCoordList = currentLineStringElement.elementsByTagNameNS( GML_NAMESPACE, "coordinates" );
+ if ( currentCoordList.size() < 1 )
+ {
+ return 0;
+ }
+ std::list currentPointList;
+ if ( readGML2Coordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
+ {
+ return 0;
+ }
+ lineCoordinates.push_back( currentPointList );
+ }
+ }
+ else
+ {
+ QDomNodeList lineStringList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "LineString" );
+ if ( lineStringList.size() > 0 ) //mapserver
+ {
+ for ( int i = 0; i < lineStringList.size(); ++i )
+ {
+ currentLineStringElement = lineStringList.at( i ).toElement();
+ currentCoordList = currentLineStringElement.elementsByTagNameNS( GML_NAMESPACE, "coordinates" );
+ if ( currentCoordList.size() < 1 )
+ {
+ return 0;
+ }
+ std::list currentPointList;
+ if ( readGML2Coordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
+ {
+ return 0;
+ }
+ lineCoordinates.push_back( currentPointList );
+ }
+ }
+ else
+ {
+ return 0;
+ }
+ }
+
+
+ //calculate the required wkb size
+ int size = ( lineCoordinates.size() + 1 ) * ( 1 + 2 * sizeof( int ) );
+ for ( std::list >::const_iterator it = lineCoordinates.begin(); it != lineCoordinates.end(); ++it )
+ {
+ size += it->size() * 2 * sizeof( double );
+ }
+
+ QGis::WkbType type = QGis::WKBMultiLineString;
+ unsigned char* wkb = new unsigned char[size];
+
+ //fill the wkb content
+ //char e = QgsApplication::endian();
+ char e = ( htonl( 1 ) == 1 ) ? 0 : 1 ;
+ int wkbPosition = 0; //current offset from wkb beginning (in bytes)
+ int nLines = lineCoordinates.size();
+ int nPoints; //number of points in a line
+ double x, y;
+ memcpy( &( wkb )[wkbPosition], &e, 1 );
+ wkbPosition += 1;
+ memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ memcpy( &( wkb )[wkbPosition], &nLines, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ for ( std::list >::const_iterator it = lineCoordinates.begin(); it != lineCoordinates.end(); ++it )
+ {
+ memcpy( &( wkb )[wkbPosition], &e, 1 );
+ wkbPosition += 1;
+ memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ nPoints = it->size();
+ memcpy( &( wkb )[wkbPosition], &nPoints, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ for ( std::list::const_iterator iter = it->begin(); iter != it->end(); ++iter )
+ {
+ x = iter->x();
+ //qWarning("x is: " + QString::number(x));
+ y = iter->y();
+ //qWarning("y is: " + QString::number(y));
+ memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) );
+ wkbPosition += sizeof( double );
+ memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) );
+ wkbPosition += sizeof( double );
+ }
+ }
+
+ QgsGeometry* g = new QgsGeometry();
+ g->fromWkb( wkb, size );
+ return g;
+}
+
+QgsGeometry* QgsOgcUtils::geometryFromGML2MultiPolygon( const QDomElement& geometryElement )
+{
+ //first list: different polygons, second list: different rings, third list: different points
+ std::list > > multiPolygonPoints;
+ QDomElement currentPolygonMemberElement;
+ QDomNodeList polygonList;
+ QDomElement currentPolygonElement;
+ QDomNodeList outerBoundaryList;
+ QDomElement currentOuterBoundaryElement;
+ QDomElement currentInnerBoundaryElement;
+ QDomNodeList innerBoundaryList;
+ QDomNodeList linearRingNodeList;
+ QDomElement currentLinearRingElement;
+ QDomNodeList currentCoordinateList;
+
+ QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS( GML_NAMESPACE, "polygonMember" );
+ for ( int i = 0; i < polygonMemberList.size(); ++i )
+ {
+ std::list > currentPolygonList;
+ currentPolygonMemberElement = polygonMemberList.at( i ).toElement();
+ polygonList = currentPolygonMemberElement.elementsByTagNameNS( GML_NAMESPACE, "Polygon" );
+ if ( polygonList.size() < 1 )
+ {
+ continue;
+ }
+ currentPolygonElement = polygonList.at( 0 ).toElement();
+
+ //find exterior ring
+ outerBoundaryList = currentPolygonElement.elementsByTagNameNS( GML_NAMESPACE, "outerBoundaryIs" );
+ if ( outerBoundaryList.size() < 1 )
+ {
+ continue;
+ }
+
+ currentOuterBoundaryElement = outerBoundaryList.at( 0 ).toElement();
+ std::list ringCoordinates;
+
+ linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS( GML_NAMESPACE, "LinearRing" );
+ if ( linearRingNodeList.size() < 1 )
+ {
+ continue;
+ }
+ currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
+ currentCoordinateList = currentLinearRingElement.elementsByTagNameNS( GML_NAMESPACE, "coordinates" );
+ if ( currentCoordinateList.size() < 1 )
+ {
+ continue;
+ }
+ if ( readGML2Coordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
+ {
+ continue;
+ }
+ currentPolygonList.push_back( ringCoordinates );
+
+ //find interior rings
+ QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS( GML_NAMESPACE, "innerBoundaryIs" );
+ for ( int j = 0; j < innerBoundaryList.size(); ++j )
+ {
+ std::list ringCoordinates;
+ currentInnerBoundaryElement = innerBoundaryList.at( j ).toElement();
+ linearRingNodeList = currentInnerBoundaryElement.elementsByTagNameNS( GML_NAMESPACE, "LinearRing" );
+ if ( linearRingNodeList.size() < 1 )
+ {
+ continue;
+ }
+ currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
+ currentCoordinateList = currentLinearRingElement.elementsByTagNameNS( GML_NAMESPACE, "coordinates" );
+ if ( currentCoordinateList.size() < 1 )
+ {
+ continue;
+ }
+ if ( readGML2Coordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
+ {
+ continue;
+ }
+ currentPolygonList.push_back( ringCoordinates );
+ }
+ multiPolygonPoints.push_back( currentPolygonList );
+ }
+
+ int size = 1 + 2 * sizeof( int );
+ //calculate the wkb size
+ for ( std::list > >::const_iterator it = multiPolygonPoints.begin(); it != multiPolygonPoints.end(); ++it )
+ {
+ size += 1 + 2 * sizeof( int );
+ for ( std::list >::const_iterator iter = it->begin(); iter != it->end(); ++iter )
+ {
+ size += sizeof( int ) + 2 * iter->size() * sizeof( double );
+ }
+ }
+
+ QGis::WkbType type = QGis::WKBMultiPolygon;
+ unsigned char* wkb = new unsigned char[size];
+
+ int polygonType = QGis::WKBPolygon;
+ //char e = QgsApplication::endian();
+ char e = ( htonl( 1 ) == 1 ) ? 0 : 1 ;
+ int wkbPosition = 0; //current offset from wkb beginning (in bytes)
+ double x, y;
+ int nPolygons = multiPolygonPoints.size();
+ int nRings;
+ int nPointsInRing;
+
+ //fill the contents into *wkb
+ memcpy( &( wkb )[wkbPosition], &e, 1 );
+ wkbPosition += 1;
+ memcpy( &( wkb )[wkbPosition], &type, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ memcpy( &( wkb )[wkbPosition], &nPolygons, sizeof( int ) );
+ wkbPosition += sizeof( int );
+
+ for ( std::list > >::const_iterator it = multiPolygonPoints.begin(); it != multiPolygonPoints.end(); ++it )
+ {
+ memcpy( &( wkb )[wkbPosition], &e, 1 );
+ wkbPosition += 1;
+ memcpy( &( wkb )[wkbPosition], &polygonType, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ nRings = it->size();
+ memcpy( &( wkb )[wkbPosition], &nRings, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ for ( std::list >::const_iterator iter = it->begin(); iter != it->end(); ++iter )
+ {
+ nPointsInRing = iter->size();
+ memcpy( &( wkb )[wkbPosition], &nPointsInRing, sizeof( int ) );
+ wkbPosition += sizeof( int );
+ for ( std::list::const_iterator iterator = iter->begin(); iterator != iter->end(); ++iterator )
+ {
+ x = iterator->x();
+ y = iterator->y();
+ memcpy( &( wkb )[wkbPosition], &x, sizeof( double ) );
+ wkbPosition += sizeof( double );
+ memcpy( &( wkb )[wkbPosition], &y, sizeof( double ) );
+ wkbPosition += sizeof( double );
+ }
+ }
+ }
+
+ QgsGeometry* g = new QgsGeometry();
+ g->fromWkb( wkb, size );
+ return g;
+}
+
+bool QgsOgcUtils::readGML2Coordinates( std::list& coords, const QDomElement elem )
+{
+ QString coordSeparator = ",";
+ QString tupelSeparator = " ";
+ //"decimal" has to be "."
+
+ coords.clear();
+
+ if ( elem.hasAttribute( "cs" ) )
+ {
+ coordSeparator = elem.attribute( "cs" );
+ }
+ if ( elem.hasAttribute( "ts" ) )
+ {
+ tupelSeparator = elem.attribute( "ts" );
+ }
+
+ QStringList tupels = elem.text().split( tupelSeparator, QString::SkipEmptyParts );
+ QStringList tupel_coords;
+ double x, y;
+ bool conversionSuccess;
+
+ QStringList::const_iterator it;
+ for ( it = tupels.constBegin(); it != tupels.constEnd(); ++it )
+ {
+ tupel_coords = ( *it ).split( coordSeparator, QString::SkipEmptyParts );
+ if ( tupel_coords.size() < 2 )
+ {
+ continue;
+ }
+ x = tupel_coords.at( 0 ).toDouble( &conversionSuccess );
+ if ( !conversionSuccess )
+ {
+ return 1;
+ }
+ y = tupel_coords.at( 1 ).toDouble( &conversionSuccess );
+ if ( !conversionSuccess )
+ {
+ return 1;
+ }
+ coords.push_back( QgsPoint( x, y ) );
+ }
+ return 0;
+}
+
+
+
+
+QDomElement QgsOgcUtils::geometryToGML2( QgsGeometry* geometry, QDomDocument& doc )
+{
+ if ( !geometry || !geometry->asWkb() )
+ return QDomElement();
+
+ bool hasZValue = false;
+ double *x, *y;
+ unsigned char* wkb = geometry->asWkb();
+
+ switch ( geometry->wkbType() )
+ {
+ case QGis::WKBPoint25D:
+ case QGis::WKBPoint:
+ {
+ QDomElement pointElem = doc.createElement( "gml:Point" );
+ QDomElement coordElem = doc.createElement( "gml:coordinates" );
+ coordElem.setAttribute( "cs", "," );
+ coordElem.setAttribute( "ts", " " );
+ QString coordString;
+ x = ( double * )( wkb + 5 );
+ coordString += QString::number( *x, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
+ coordString += ",";
+ y = ( double * )( wkb + 5 + sizeof( double ) );
+ coordString += QString::number( *y, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
+ QDomText coordText = doc.createTextNode( coordString );
+ coordElem.appendChild( coordText );
+ pointElem.appendChild( coordElem );
+ return pointElem;
+ }
+ case QGis::WKBMultiPoint25D:
+ hasZValue = true;
+ case QGis::WKBMultiPoint:
+ {
+ unsigned char *ptr;
+ int idx;
+ int *nPoints;
+
+ QDomElement multiPointElem = doc.createElement( "gml:MultiPoint" );
+ nPoints = ( int* )( wkb + 5 );
+ ptr = wkb + 5 + sizeof( int );
+ for ( idx = 0; idx < *nPoints; ++idx )
+ {
+ ptr += ( 1 + sizeof( int ) );
+ QDomElement pointMemberElem = doc.createElement( "gml:pointMember" );
+ QDomElement pointElem = doc.createElement( "gml:Point" );
+ QDomElement coordElem = doc.createElement( "gml:coordinates" );
+ coordElem.setAttribute( "cs", "," );
+ coordElem.setAttribute( "ts", " " );
+ QString coordString;
+ x = ( double * )( ptr );
+ coordString += QString::number( *x, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
+ coordString += ",";
+ ptr += sizeof( double );
+ y = ( double * )( ptr );
+ coordString += QString::number( *y, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
+ QDomText coordText = doc.createTextNode( coordString );
+ coordElem.appendChild( coordText );
+ pointElem.appendChild( coordElem );
+
+ ptr += sizeof( double );
+ if ( hasZValue )
+ {
+ ptr += sizeof( double );
+ }
+ pointMemberElem.appendChild( pointElem );
+ multiPointElem.appendChild( pointMemberElem );
+ }
+ return multiPointElem;
+ }
+ case QGis::WKBLineString25D:
+ hasZValue = true;
+ case QGis::WKBLineString:
+ {
+ unsigned char *ptr;
+ int *nPoints;
+ int idx;
+
+ QDomElement lineStringElem = doc.createElement( "gml:LineString" );
+ // get number of points in the line
+ ptr = wkb + 5;
+ nPoints = ( int * ) ptr;
+ ptr = wkb + 1 + 2 * sizeof( int );
+ QDomElement coordElem = doc.createElement( "gml:coordinates" );
+ coordElem.setAttribute( "cs", "," );
+ coordElem.setAttribute( "ts", " " );
+ QString coordString;
+ for ( idx = 0; idx < *nPoints; ++idx )
+ {
+ if ( idx != 0 )
+ {
+ coordString += " ";
+ }
+ x = ( double * ) ptr;
+ coordString += QString::number( *x, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
+ coordString += ",";
+ ptr += sizeof( double );
+ y = ( double * ) ptr;
+ coordString += QString::number( *y, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
+ ptr += sizeof( double );
+ if ( hasZValue )
+ {
+ ptr += sizeof( double );
+ }
+ }
+ QDomText coordText = doc.createTextNode( coordString );
+ coordElem.appendChild( coordText );
+ lineStringElem.appendChild( coordElem );
+ return lineStringElem;
+ }
+ case QGis::WKBMultiLineString25D:
+ hasZValue = true;
+ case QGis::WKBMultiLineString:
+ {
+ unsigned char *ptr;
+ int idx, jdx, numLineStrings;
+ int *nPoints;
+
+ QDomElement multiLineStringElem = doc.createElement( "gml:MultiLineString" );
+ numLineStrings = ( int )( wkb[5] );
+ ptr = wkb + 9;
+ for ( jdx = 0; jdx < numLineStrings; jdx++ )
+ {
+ QDomElement lineStringMemberElem = doc.createElement( "gml:lineStringMember" );
+ QDomElement lineStringElem = doc.createElement( "gml:LineString" );
+ ptr += 5; // skip type since we know its 2
+ nPoints = ( int * ) ptr;
+ ptr += sizeof( int );
+ QDomElement coordElem = doc.createElement( "gml:coordinates" );
+ coordElem.setAttribute( "cs", "," );
+ coordElem.setAttribute( "ts", " " );
+ QString coordString;
+ for ( idx = 0; idx < *nPoints; idx++ )
+ {
+ if ( idx != 0 )
+ {
+ coordString += " ";
+ }
+ x = ( double * ) ptr;
+ coordString += QString::number( *x, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
+ ptr += sizeof( double );
+ coordString += ",";
+ y = ( double * ) ptr;
+ coordString += QString::number( *y, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
+ ptr += sizeof( double );
+ if ( hasZValue )
+ {
+ ptr += sizeof( double );
+ }
+ }
+ QDomText coordText = doc.createTextNode( coordString );
+ coordElem.appendChild( coordText );
+ lineStringElem.appendChild( coordElem );
+ lineStringMemberElem.appendChild( lineStringElem );
+ multiLineStringElem.appendChild( lineStringMemberElem );
+ }
+ return multiLineStringElem;
+ }
+ case QGis::WKBPolygon25D:
+ hasZValue = true;
+ case QGis::WKBPolygon:
+ {
+ unsigned char *ptr;
+ int idx, jdx;
+ int *numRings, *nPoints;
+
+ QDomElement polygonElem = doc.createElement( "gml:Polygon" );
+ // get number of rings in the polygon
+ numRings = ( int * )( wkb + 1 + sizeof( int ) );
+ if ( !( *numRings ) ) // sanity check for zero rings in polygon
+ {
+ return QDomElement();
+ }
+ int *ringStart; // index of first point for each ring
+ int *ringNumPoints; // number of points in each ring
+ ringStart = new int[*numRings];
+ ringNumPoints = new int[*numRings];
+ ptr = wkb + 1 + 2 * sizeof( int ); // set pointer to the first ring
+ for ( idx = 0; idx < *numRings; idx++ )
+ {
+ QString boundaryName = "gml:outerBoundaryIs";
+ if ( idx != 0 )
+ {
+ boundaryName = "gml:innerBoundaryIs";
+ }
+ QDomElement boundaryElem = doc.createElement( boundaryName );
+ QDomElement ringElem = doc.createElement( "gml:LinearRing" );
+ // get number of points in the ring
+ nPoints = ( int * ) ptr;
+ ringNumPoints[idx] = *nPoints;
+ ptr += 4;
+ QDomElement coordElem = doc.createElement( "gml:coordinates" );
+ coordElem.setAttribute( "cs", "," );
+ coordElem.setAttribute( "ts", " " );
+ QString coordString;
+ for ( jdx = 0; jdx < *nPoints; jdx++ )
+ {
+ if ( jdx != 0 )
+ {
+ coordString += " ";
+ }
+ x = ( double * ) ptr;
+ coordString += QString::number( *x, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
+ coordString += ",";
+ ptr += sizeof( double );
+ y = ( double * ) ptr;
+ coordString += QString::number( *y, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
+ ptr += sizeof( double );
+ if ( hasZValue )
+ {
+ ptr += sizeof( double );
+ }
+ }
+ QDomText coordText = doc.createTextNode( coordString );
+ coordElem.appendChild( coordText );
+ ringElem.appendChild( coordElem );
+ boundaryElem.appendChild( ringElem );
+ polygonElem.appendChild( boundaryElem );
+ }
+ delete [] ringStart;
+ delete [] ringNumPoints;
+ return polygonElem;
+ }
+ case QGis::WKBMultiPolygon25D:
+ hasZValue = true;
+ case QGis::WKBMultiPolygon:
+ {
+ unsigned char *ptr;
+ int idx, jdx, kdx;
+ int *numPolygons, *numRings, *nPoints;
+
+ QDomElement multiPolygonElem = doc.createElement( "gml:MultiPolygon" );
+ ptr = wkb + 5;
+ numPolygons = ( int * ) ptr;
+ ptr = wkb + 9;
+ for ( kdx = 0; kdx < *numPolygons; kdx++ )
+ {
+ QDomElement polygonMemberElem = doc.createElement( "gml:polygonMember" );
+ QDomElement polygonElem = doc.createElement( "gml:Polygon" );
+ ptr += 5;
+ numRings = ( int * ) ptr;
+ ptr += 4;
+ for ( idx = 0; idx < *numRings; idx++ )
+ {
+ QString boundaryName = "gml:outerBoundaryIs";
+ if ( idx != 0 )
+ {
+ boundaryName = "gml:innerBoundaryIs";
+ }
+ QDomElement boundaryElem = doc.createElement( boundaryName );
+ QDomElement ringElem = doc.createElement( "gml:LinearRing" );
+ nPoints = ( int * ) ptr;
+ ptr += 4;
+ QDomElement coordElem = doc.createElement( "gml:coordinates" );
+ coordElem.setAttribute( "cs", "," );
+ coordElem.setAttribute( "ts", " " );
+ QString coordString;
+ for ( jdx = 0; jdx < *nPoints; jdx++ )
+ {
+ if ( jdx != 0 )
+ {
+ coordString += " ";
+ }
+ x = ( double * ) ptr;
+ coordString += QString::number( *x, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
+ ptr += sizeof( double );
+ coordString += ",";
+ y = ( double * ) ptr;
+ coordString += QString::number( *y, 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) );
+ ptr += sizeof( double );
+ if ( hasZValue )
+ {
+ ptr += sizeof( double );
+ }
+ }
+ QDomText coordText = doc.createTextNode( coordString );
+ coordElem.appendChild( coordText );
+ ringElem.appendChild( coordElem );
+ boundaryElem.appendChild( ringElem );
+ polygonElem.appendChild( boundaryElem );
+ polygonMemberElem.appendChild( polygonElem );
+ multiPolygonElem.appendChild( polygonMemberElem );
+ }
+ }
+ return multiPolygonElem;
+ }
+ default:
+ return QDomElement();
+ }
+
+}
+
+
+QgsRectangle QgsOgcUtils::rectangleFromGMLBox( const QDomNode& boxNode )
+{
+ QgsRectangle rect;
+
+ QDomElement boxElem = boxNode.toElement();
+ if ( boxElem.tagName() != "Box" )
+ return rect;
+
+ QDomElement bElem = boxElem.firstChild().toElement();
+ QString coordSeparator = ",";
+ QString tupelSeparator = " ";
+ if ( bElem.hasAttribute( "cs" ) )
+ {
+ coordSeparator = bElem.attribute( "cs" );
+ }
+ if ( bElem.hasAttribute( "ts" ) )
+ {
+ tupelSeparator = bElem.attribute( "ts" );
+ }
+
+ QString bString = bElem.text();
+ bool ok1, ok2, ok3, ok4;
+ double xmin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 0, 0 ).toDouble( &ok1 );
+ double ymin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 1, 1 ).toDouble( &ok2 );
+ double xmax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 0, 0 ).toDouble( &ok3 );
+ double ymax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 1, 1 ).toDouble( &ok4 );
+
+ if ( ok1 && ok2 && ok3 && ok4 )
+ {
+ rect = QgsRectangle( xmin, ymin, xmax, ymax );
+ rect.normalize();
+ }
+
+ return rect;
+}
diff --git a/src/core/qgsogcutils.h b/src/core/qgsogcutils.h
new file mode 100644
index 00000000000..784d20ab430
--- /dev/null
+++ b/src/core/qgsogcutils.h
@@ -0,0 +1,67 @@
+#ifndef QGSOGCUTILS_H
+#define QGSOGCUTILS_H
+
+class QDomNode;
+class QDomElement;
+class QDomDocument;
+class QString;
+
+#include
+
+class QgsGeometry;
+class QgsPoint;
+class QgsRectangle;
+
+/**
+ * @brief The QgsOgcUtils class provides various utility functions for conversion between
+ * OGC (Open Geospatial Consortium) standards and QGIS internal representations.
+ *
+ * Currently supported standards:
+ * - GML2 - Geography Markup Language (import, export)
+ *
+ * @note added in 2.0
+ */
+class CORE_EXPORT QgsOgcUtils
+{
+public:
+
+
+ /** 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 (...)
+ */
+ static QgsGeometry* geometryFromGML2( const QString& xmlString );
+
+ /** static method that creates geometry from GML2
+ */
+ static QgsGeometry* geometryFromGML2( const QDomNode& geometryNode );
+
+ /** Exports the geometry to mGML2
+ @return true in case of success and false else
+ */
+ static QDomElement geometryToGML2( QgsGeometry* geometry, QDomDocument& doc );
+
+ /** read rectangle from GML2 Box */
+ static QgsRectangle rectangleFromGMLBox( const QDomNode& boxNode );
+
+private:
+ /** static method that creates geometry from GML2 Point */
+ static QgsGeometry* geometryFromGML2Point( const QDomElement& geometryElement );
+ /** static method that creates geometry from GML2 LineString */
+ static QgsGeometry* geometryFromGML2LineString( const QDomElement& geometryElement );
+ /** static method that creates geometry from GML2 Polygon */
+ static QgsGeometry* geometryFromGML2Polygon( const QDomElement& geometryElement );
+ /** static method that creates geometry from GML2 MultiPoint */
+ static QgsGeometry* geometryFromGML2MultiPoint( const QDomElement& geometryElement );
+ /** static method that creates geometry from GML2 MultiLineString */
+ static QgsGeometry* geometryFromGML2MultiLineString( const QDomElement& geometryElement );
+ /** static method that creates geometry from GML2 MultiPolygon */
+ static QgsGeometry* geometryFromGML2MultiPolygon( const QDomElement& geometryElement );
+ /** Reads the element and extracts the coordinates as points
+ @param coords list where the found coordinates are appended
+ @param elem the element
+ @return boolean for success*/
+ static bool readGML2Coordinates( std::list& coords, const QDomElement elem );
+};
+
+#endif // QGSOGCUTILS_H
diff --git a/src/core/qgsrectangle.cpp b/src/core/qgsrectangle.cpp
index f1f321d2520..092cf6ed971 100644
--- a/src/core/qgsrectangle.cpp
+++ b/src/core/qgsrectangle.cpp
@@ -55,32 +55,6 @@ QgsRectangle::QgsRectangle( const QgsRectangle &r )
ymax = r.yMaximum();
}
-QgsRectangle::QgsRectangle( const QDomNode& boxNode )
-{
- QDomElement boxElem = boxNode.toElement();
- if ( boxElem.tagName() == "Box" )
- {
- QDomElement bElem = boxElem.firstChild().toElement();
- QString coordSeparator = ",";
- QString tupelSeparator = " ";
- if ( bElem.hasAttribute( "cs" ) )
- {
- coordSeparator = bElem.attribute( "cs" );
- }
- if ( bElem.hasAttribute( "ts" ) )
- {
- tupelSeparator = bElem.attribute( "ts" );
- }
-
- QString bString = bElem.text();
- bool conversionSuccess;
- xmin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 0, 0 ).toDouble( &conversionSuccess );
- ymin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 1, 1 ).toDouble( &conversionSuccess );
- xmax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 0, 0 ).toDouble( &conversionSuccess );
- ymax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 1, 1 ).toDouble( &conversionSuccess );
- }
- normalize();
-}
void QgsRectangle::set( const QgsPoint& p1, const QgsPoint& p2 )
{
diff --git a/src/core/qgsrectangle.h b/src/core/qgsrectangle.h
index 596f3100c0e..5c05d96a2cd 100644
--- a/src/core/qgsrectangle.h
+++ b/src/core/qgsrectangle.h
@@ -44,9 +44,6 @@ class CORE_EXPORT QgsRectangle
QgsRectangle( const QRectF & qRectF );
//! Copy constructor
QgsRectangle( const QgsRectangle &other );
- //! GML2 constructor
- //@note added in 1.9
- QgsRectangle( const QDomNode& boxNode );
//! Destructor
~QgsRectangle();
//! Set the rectangle from two QgsPoints. The rectangle is
diff --git a/src/mapserver/qgsfilter.cpp b/src/mapserver/qgsfilter.cpp
index 9d91b6d1ae4..0193257ad7b 100644
--- a/src/mapserver/qgsfilter.cpp
+++ b/src/mapserver/qgsfilter.cpp
@@ -21,6 +21,8 @@
#include "qgslogicalfilter.h"
#include "qgsspatialfilter.h"
#include "qgsvectordataprovider.h"
+#include "qgsogcutils.h"
+
#include
#include
#include "qgsvectorlayer.h"
@@ -129,7 +131,7 @@ QgsFilter* QgsFilter::createFilterFromXml( const QDomElement& filterElem, QgsVec
if ( gNodes.size() > 0 )
{
QDomElement gElem = gNodes.at( 0 ).toElement();
- geom = QgsGeometry::fromGML2( gElem );
+ geom = QgsOgcUtils::geometryFromGML2( gElem );
}
}
@@ -139,7 +141,7 @@ QgsFilter* QgsFilter::createFilterFromXml( const QDomElement& filterElem, QgsVec
if ( gNodes.size() > 0 )
{
QDomElement gElem = gNodes.at( 0 ).toElement();
- geom = QgsGeometry::fromGML2( gElem );
+ geom = QgsOgcUtils::geometryFromGML2( gElem );
}
}
@@ -149,7 +151,7 @@ QgsFilter* QgsFilter::createFilterFromXml( const QDomElement& filterElem, QgsVec
if ( gNodes.size() > 0 )
{
QDomElement gElem = gNodes.at( 0 ).toElement();
- geom = QgsGeometry::fromGML2( gElem );
+ geom = QgsOgcUtils::geometryFromGML2( gElem );
}
}
@@ -159,7 +161,7 @@ QgsFilter* QgsFilter::createFilterFromXml( const QDomElement& filterElem, QgsVec
if ( gNodes.size() > 0 )
{
QDomElement gElem = gNodes.at( 0 ).toElement();
- geom = QgsGeometry::fromGML2( gElem );
+ geom = QgsOgcUtils::geometryFromGML2( gElem );
}
}
@@ -169,7 +171,7 @@ QgsFilter* QgsFilter::createFilterFromXml( const QDomElement& filterElem, QgsVec
if ( gNodes.size() > 0 )
{
QDomElement gElem = gNodes.at( 0 ).toElement();
- geom = QgsGeometry::fromGML2( gElem );
+ geom = QgsOgcUtils::geometryFromGML2( gElem );
}
}
@@ -179,7 +181,7 @@ QgsFilter* QgsFilter::createFilterFromXml( const QDomElement& filterElem, QgsVec
if ( gNodes.size() > 0 )
{
QDomElement gElem = gNodes.at( 0 ).toElement();
- geom = QgsGeometry::fromGML2( gElem );
+ geom = QgsOgcUtils::geometryFromGML2( gElem );
}
}
diff --git a/src/mapserver/qgswfsserver.cpp b/src/mapserver/qgswfsserver.cpp
index 548de6cdbb7..c8a93ecb0a7 100644
--- a/src/mapserver/qgswfsserver.cpp
+++ b/src/mapserver/qgswfsserver.cpp
@@ -41,6 +41,8 @@
#include "qgslegendmodel.h"
#include "qgscomposerlegenditem.h"
#include "qgsrequesthandler.h"
+#include "qgsogcutils.h"
+
#include
#include
#include
@@ -509,11 +511,11 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
{
if ( childElem.tagName() == "Box" )
{
- req.setFilterRect( QgsRectangle( childElem ) );
+ req.setFilterRect( QgsOgcUtils::rectangleFromGMLBox( childElem ) );
}
else if ( childElem.tagName() != "PropertyName" )
{
- QgsGeometry *geom = QgsGeometry::fromGML2( childElem );
+ QgsGeometry *geom = QgsOgcUtils::geometryFromGML2( childElem );
req.setFilterRect( geom->boundingBox() );
delete geom;
}
@@ -892,11 +894,11 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format
{
if ( childElem.tagName() == "Box" )
{
- req.setFilterRect( QgsRectangle( childElem ) );
+ req.setFilterRect( QgsOgcUtils::rectangleFromGMLBox( childElem ) );
}
else if ( childElem.tagName() != "PropertyName" )
{
- QgsGeometry* geom = QgsGeometry::fromGML2( childElem );
+ QgsGeometry* geom = QgsOgcUtils::geometryFromGML2( childElem );
req.setFilterRect( geom->boundingBox() );
delete geom;
}
@@ -1335,7 +1337,7 @@ QDomDocument QgsWFSServer::transaction( const QString& requestBody )
if ( !geometryElem.isNull() )
{
- if ( !layer->changeGeometry( *fidIt, QgsGeometry::fromGML2( geometryElem ) ) )
+ if ( !layer->changeGeometry( *fidIt, QgsOgcUtils::geometryFromGML2( geometryElem ) ) )
throw QgsMapServiceException( "RequestNotWellFormed", "Error in change geometry" );
}
}
@@ -1451,7 +1453,7 @@ QDomDocument QgsWFSServer::transaction( const QString& requestBody )
}
else //a geometry attribute
{
- f->setGeometry( QgsGeometry::fromGML2( currentAttributeElement ) );
+ f->setGeometry( QgsOgcUtils::geometryFromGML2( currentAttributeElement ) );
}
}
currentAttributeChild = currentAttributeChild.nextSibling();
@@ -1649,7 +1651,7 @@ QDomElement QgsWFSServer::createFeatureGML2( QgsFeature* feat, QDomDocument& doc
QgsGeometry* geom = feat->geometry();
QDomElement geomElem = doc.createElement( "qgs:geometry" );
- QDomElement gmlElem = geom->exportToGML2( doc );
+ QDomElement gmlElem = QgsOgcUtils::geometryToGML2( geom, doc );
if ( !gmlElem.isNull() )
{
QgsRectangle box = geom->boundingBox();
diff --git a/src/providers/wfs/qgswfsprovider.cpp b/src/providers/wfs/qgswfsprovider.cpp
index 9e591b6d99c..772e6841e94 100644
--- a/src/providers/wfs/qgswfsprovider.cpp
+++ b/src/providers/wfs/qgswfsprovider.cpp
@@ -30,6 +30,8 @@
#include "qgsspatialindex.h"
#include "qgslogger.h"
#include "qgsnetworkaccessmanager.h"
+#include "qgsogcutils.h"
+
#include
#include
#include
@@ -418,7 +420,7 @@ bool QgsWFSProvider::addFeatures( QgsFeatureList &flist )
//add geometry column (as gml)
QDomElement geomElem = transactionDoc.createElementNS( mWfsNamespace, mGeometryAttribute );
- QDomElement gmlElem = featureIt->geometry()->exportToGML2( transactionDoc );
+ QDomElement gmlElem = QgsOgcUtils::geometryToGML2( featureIt->geometry(), transactionDoc );
if ( !gmlElem.isNull() )
{
geomElem.appendChild( gmlElem );
@@ -569,7 +571,7 @@ bool QgsWFSProvider::changeGeometryValues( QgsGeometryMap & geometry_map )
nameElem.appendChild( nameText );
propertyElem.appendChild( nameElem );
QDomElement valueElem = transactionDoc.createElementNS( "http://www.opengis.net/wfs", "Value" );
- QDomElement gmlElem = ( &geomIt.value() )->exportToGML2( transactionDoc );
+ QDomElement gmlElem = QgsOgcUtils::geometryToGML2( &geomIt.value(), transactionDoc );
valueElem.appendChild( gmlElem );
propertyElem.appendChild( valueElem );
updateElem.appendChild( propertyElem );
@@ -1287,7 +1289,7 @@ int QgsWFSProvider::getFeaturesFromGML2( const QDomElement& wfsCollectionElement
}
else //a geometry attribute
{
- f->setGeometry( QgsGeometry::fromGML2( currentAttributeElement ) );
+ f->setGeometry( QgsOgcUtils::geometryFromGML2( currentAttributeElement ) );
}
}
currentAttributeChild = currentAttributeChild.nextSibling();
diff --git a/tests/src/core/CMakeLists.txt b/tests/src/core/CMakeLists.txt
index 93e487e841c..9a9810aa6b8 100644
--- a/tests/src/core/CMakeLists.txt
+++ b/tests/src/core/CMakeLists.txt
@@ -109,3 +109,4 @@ ADD_QGIS_TEST(stylev2test testqgsstylev2.cpp)
ADD_QGIS_TEST(composerhtmltest testqgscomposerhtml.cpp )
ADD_QGIS_TEST(rectangletest testqgsrectangle.cpp)
ADD_QGIS_TEST(composerscalebartest testqgscomposerscalebar.cpp )
+ADD_QGIS_TEST(ogcutilstest testqgsogcutils.cpp)
diff --git a/tests/src/core/testqgsgeometry.cpp b/tests/src/core/testqgsgeometry.cpp
index d64221426ba..33f58256968 100644
--- a/tests/src/core/testqgsgeometry.cpp
+++ b/tests/src/core/testqgsgeometry.cpp
@@ -56,8 +56,6 @@ class TestQgsGeometry: public QObject
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 = "" );
@@ -372,18 +370,6 @@ 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"
diff --git a/tests/src/core/testqgsogcutils.cpp b/tests/src/core/testqgsogcutils.cpp
new file mode 100644
index 00000000000..01e82a07830
--- /dev/null
+++ b/tests/src/core/testqgsogcutils.cpp
@@ -0,0 +1,67 @@
+
+/***************************************************************************
+ testqgsogcutils.cpp
+ --------------------------------------
+ Date : March 2013
+ Copyright : (C) 2013 Martin Dobias
+ Email : wonder.sk at gmail dot com
+ ***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include
+
+//qgis includes...
+#include
+#include
+
+
+/** \ingroup UnitTests
+ * This is a unit test for OGC utilities
+ */
+class TestQgsOgcUtils : public QObject
+{
+ Q_OBJECT
+ private slots:
+
+ void testGeometryFromGML();
+ void testGeometryToGML();
+};
+
+
+void TestQgsOgcUtils::testGeometryFromGML()
+{
+ QgsGeometry* geom = QgsOgcUtils::geometryFromGML2( "123,456" );
+ QVERIFY( geom );
+ QVERIFY( geom->wkbType() == QGis::WKBPoint );
+ QVERIFY( geom->asPoint() == QgsPoint( 123, 456 ) );
+
+ QgsGeometry* geomBox = QgsOgcUtils::geometryFromGML2( "135.2239,34.4879 135.8578,34.8471" );
+ QVERIFY( geomBox );
+ QVERIFY( geomBox->wkbType() == QGis::WKBPolygon );
+}
+
+void TestQgsOgcUtils::testGeometryToGML()
+{
+ QDomDocument doc;
+
+ QDomElement elemInvalid = QgsOgcUtils::geometryToGML2( 0, doc );
+ QVERIFY( elemInvalid.isNull() );
+
+ QgsGeometry* geomPoint = QgsGeometry::fromPoint( QgsPoint( 111, 222 ) );
+ QDomElement elemPoint = QgsOgcUtils::geometryToGML2( geomPoint, doc );
+ delete geomPoint;
+ QVERIFY( !elemPoint.isNull() );
+
+ doc.appendChild( elemPoint );
+ QCOMPARE( doc.toString( -1 ), QString( "111.0,222.0" ) );
+}
+
+
+QTEST_MAIN( TestQgsOgcUtils )
+#include "moc_testqgsogcutils.cxx"