mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Moved GML import/export to a new class: QgsOgcUtils
This commit is contained in:
parent
290f8fd5b8
commit
969df016bc
@ -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
|
||||
|
@ -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 (<Point>...</Point>) or in "gml" namespace (<gml:Point>...</gml:Point>)
|
||||
@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 */
|
||||
|
32
python/core/qgsogcutils.sip
Normal file
32
python/core/qgsogcutils.sip
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
|
||||
class QgsOgcUtils
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include <qgsogcutils.h>
|
||||
%End
|
||||
|
||||
public:
|
||||
|
||||
/** static method that creates geometry from GML2
|
||||
@param XML representation of the geometry. GML elements are expected to be
|
||||
in default namespace (<Point>...</Point>) or in "gml" namespace (<gml:Point>...</gml:Point>)
|
||||
@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 );
|
||||
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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" )
|
||||
{
|
||||
|
@ -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( "<tmp xmlns=\"%1\" xmlns:gml=\"%1\">%2</tmp>").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<QgsPoint> pointCoordinate;
|
||||
if ( readGML2Coordinates( pointCoordinate, coordElement ) != 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( pointCoordinate.size() < 1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
std::list<QgsPoint>::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<QgsPoint> 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<QgsPoint>::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<std::list<QgsPoint> > 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<QgsPoint> 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<QgsPoint> 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<std::list<QgsPoint> >::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<std::list<QgsPoint> >::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<QgsPoint>::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<QgsPoint> pointList;
|
||||
std::list<QgsPoint> 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 )
|
||||
{
|
||||
//<Point> element
|
||||
pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS( GML_NAMESPACE, "Point" );
|
||||
if ( pointNodeList.size() < 1 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//<coordinates> 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<QgsPoint>::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
|
||||
//<gml:MultiLineString>
|
||||
//<gml:lineStringMember>
|
||||
//<gml:LineString>
|
||||
|
||||
//mapserver has directly
|
||||
//<gml:MultiLineString
|
||||
//<gml:LineString
|
||||
|
||||
std::list<std::list<QgsPoint> > 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<QgsPoint> 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<QgsPoint> 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<std::list<QgsPoint> >::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<std::list<QgsPoint> >::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<QgsPoint>::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<std::list<std::list<QgsPoint> > > 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<std::list<QgsPoint> > 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<QgsPoint> 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<QgsPoint> 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<std::list<std::list<QgsPoint> > >::const_iterator it = multiPolygonPoints.begin(); it != multiPolygonPoints.end(); ++it )
|
||||
{
|
||||
size += 1 + 2 * sizeof( int );
|
||||
for ( std::list<std::list<QgsPoint> >::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<std::list<std::list<QgsPoint> > >::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<std::list<QgsPoint> >::const_iterator iter = it->begin(); iter != it->end(); ++iter )
|
||||
{
|
||||
nPointsInRing = iter->size();
|
||||
memcpy( &( wkb )[wkbPosition], &nPointsInRing, sizeof( int ) );
|
||||
wkbPosition += sizeof( int );
|
||||
for ( std::list<QgsPoint>::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<QgsPoint>& 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()
|
||||
{
|
||||
|
@ -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 (<Point>...</Point>) or in "gml" namespace (<gml:Point>...</gml:Point>)
|
||||
@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 <gml:coordinates> element and extracts the coordinates as points
|
||||
@param coords list where the found coordinates are appended
|
||||
@param elem the <gml:coordinates> element
|
||||
@return boolean for success*/
|
||||
bool readGML2Coordinates( std::list<QgsPoint>& coords, const QDomElement elem ) const;
|
||||
|
||||
/** Converts from the WKB geometry to the GEOS geometry.
|
||||
@return true in case of success and false else
|
||||
*/
|
||||
|
969
src/core/qgsogcutils.cpp
Normal file
969
src/core/qgsogcutils.cpp
Normal file
@ -0,0 +1,969 @@
|
||||
#include "qgsogcutils.h"
|
||||
|
||||
#include "qgsgeometry.h"
|
||||
|
||||
#include <QStringList>
|
||||
|
||||
#ifndef Q_WS_WIN
|
||||
#include <netinet/in.h>
|
||||
#else
|
||||
#include <winsock.h>
|
||||
#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( "<tmp xmlns=\"%1\" xmlns:gml=\"%1\">%2</tmp>").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<QgsPoint> pointCoordinate;
|
||||
if ( readGML2Coordinates( pointCoordinate, coordElement ) != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( pointCoordinate.size() < 1 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::list<QgsPoint>::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<QgsPoint> 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<QgsPoint>::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<std::list<QgsPoint> > 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<QgsPoint> 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<QgsPoint> 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<std::list<QgsPoint> >::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<std::list<QgsPoint> >::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<QgsPoint>::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<QgsPoint> pointList;
|
||||
std::list<QgsPoint> 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 )
|
||||
{
|
||||
//<Point> element
|
||||
pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS( GML_NAMESPACE, "Point" );
|
||||
if ( pointNodeList.size() < 1 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
//<coordinates> 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<QgsPoint>::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
|
||||
//<gml:MultiLineString>
|
||||
//<gml:lineStringMember>
|
||||
//<gml:LineString>
|
||||
|
||||
//mapserver has directly
|
||||
//<gml:MultiLineString
|
||||
//<gml:LineString
|
||||
|
||||
std::list<std::list<QgsPoint> > 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<QgsPoint> 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<QgsPoint> 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<std::list<QgsPoint> >::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<std::list<QgsPoint> >::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<QgsPoint>::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<std::list<std::list<QgsPoint> > > 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<std::list<QgsPoint> > 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<QgsPoint> 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<QgsPoint> 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<std::list<std::list<QgsPoint> > >::const_iterator it = multiPolygonPoints.begin(); it != multiPolygonPoints.end(); ++it )
|
||||
{
|
||||
size += 1 + 2 * sizeof( int );
|
||||
for ( std::list<std::list<QgsPoint> >::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<std::list<std::list<QgsPoint> > >::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<std::list<QgsPoint> >::const_iterator iter = it->begin(); iter != it->end(); ++iter )
|
||||
{
|
||||
nPointsInRing = iter->size();
|
||||
memcpy( &( wkb )[wkbPosition], &nPointsInRing, sizeof( int ) );
|
||||
wkbPosition += sizeof( int );
|
||||
for ( std::list<QgsPoint>::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<QgsPoint>& 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;
|
||||
}
|
67
src/core/qgsogcutils.h
Normal file
67
src/core/qgsogcutils.h
Normal file
@ -0,0 +1,67 @@
|
||||
#ifndef QGSOGCUTILS_H
|
||||
#define QGSOGCUTILS_H
|
||||
|
||||
class QDomNode;
|
||||
class QDomElement;
|
||||
class QDomDocument;
|
||||
class QString;
|
||||
|
||||
#include <list>
|
||||
|
||||
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 (<Point>...</Point>) or in "gml" namespace (<gml:Point>...</gml:Point>)
|
||||
*/
|
||||
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 <gml:coordinates> element and extracts the coordinates as points
|
||||
@param coords list where the found coordinates are appended
|
||||
@param elem the <gml:coordinates> element
|
||||
@return boolean for success*/
|
||||
static bool readGML2Coordinates( std::list<QgsPoint>& coords, const QDomElement elem );
|
||||
};
|
||||
|
||||
#endif // QGSOGCUTILS_H
|
@ -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 )
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "qgslogicalfilter.h"
|
||||
#include "qgsspatialfilter.h"
|
||||
#include "qgsvectordataprovider.h"
|
||||
#include "qgsogcutils.h"
|
||||
|
||||
#include <QDomElement>
|
||||
#include <QStringList>
|
||||
#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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include "qgslegendmodel.h"
|
||||
#include "qgscomposerlegenditem.h"
|
||||
#include "qgsrequesthandler.h"
|
||||
#include "qgsogcutils.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
#include <QStringList>
|
||||
@ -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();
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "qgsspatialindex.h"
|
||||
#include "qgslogger.h"
|
||||
#include "qgsnetworkaccessmanager.h"
|
||||
#include "qgsogcutils.h"
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QMessageBox>
|
||||
#include <QDomNodeList>
|
||||
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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( "<Point><coordinates>123,456</coordinates></Point>" );
|
||||
QVERIFY( geom );
|
||||
QVERIFY( geom->wkbType() == QGis::WKBPoint );
|
||||
QVERIFY( geom->asPoint() == QgsPoint( 123, 456 ) );
|
||||
|
||||
QgsGeometry* geomBox = QgsGeometry::fromGML2( "<gml:Box srsName=\"foo\"><gml:coordinates>135.2239,34.4879 135.8578,34.8471</gml:coordinates></gml:Box>" );
|
||||
QVERIFY( geomBox );
|
||||
QVERIFY( geomBox->wkbType() == QGis::WKBPolygon );
|
||||
}
|
||||
|
||||
|
||||
QTEST_MAIN( TestQgsGeometry )
|
||||
#include "moc_testqgsgeometry.cxx"
|
||||
|
67
tests/src/core/testqgsogcutils.cpp
Normal file
67
tests/src/core/testqgsogcutils.cpp
Normal file
@ -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 <QtTest>
|
||||
|
||||
//qgis includes...
|
||||
#include <qgsgeometry.h>
|
||||
#include <qgsogcutils.h>
|
||||
|
||||
|
||||
/** \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( "<Point><coordinates>123,456</coordinates></Point>" );
|
||||
QVERIFY( geom );
|
||||
QVERIFY( geom->wkbType() == QGis::WKBPoint );
|
||||
QVERIFY( geom->asPoint() == QgsPoint( 123, 456 ) );
|
||||
|
||||
QgsGeometry* geomBox = QgsOgcUtils::geometryFromGML2( "<gml:Box srsName=\"foo\"><gml:coordinates>135.2239,34.4879 135.8578,34.8471</gml:coordinates></gml:Box>" );
|
||||
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( "<gml:Point><gml:coordinates cs=\",\" ts=\" \">111.0,222.0</gml:coordinates></gml:Point>" ) );
|
||||
}
|
||||
|
||||
|
||||
QTEST_MAIN( TestQgsOgcUtils )
|
||||
#include "moc_testqgsogcutils.cxx"
|
Loading…
x
Reference in New Issue
Block a user