diff --git a/src/core/qgsgeometry.cpp b/src/core/qgsgeometry.cpp index ad1b041..d6f8e94 100644 --- a/src/core/qgsgeometry.cpp +++ b/src/core/qgsgeometry.cpp @@ -4226,10 +4226,10 @@ QString QgsGeometry::exportToGeoJSON() { mWkt += "{ \"type\": \"Point\", \"coordinates\": ["; x = ( double * )( mGeometry + 5 ); - mWkt += QString::number( *x, 'f', 6 ); + mWkt += QString::number( *x, 'f' ); mWkt += ", "; y = ( double * )( mGeometry + 5 + sizeof( double ) ); - mWkt += QString::number( *y, 'f', 6 ); + mWkt += QString::number( *y, 'f' ); mWkt += "] }"; return mWkt; } @@ -4256,11 +4256,11 @@ QString QgsGeometry::exportToGeoJSON() } mWkt += "["; x = ( double * ) ptr; - mWkt += QString::number( *x, 'f', 6 ); + mWkt += QString::number( *x, 'f' ); mWkt += ", "; ptr += sizeof( double ); y = ( double * ) ptr; - mWkt += QString::number( *y, 'f', 6 ); + mWkt += QString::number( *y, 'f' ); ptr += sizeof( double ); if ( hasZValue ) { @@ -4313,11 +4313,11 @@ QString QgsGeometry::exportToGeoJSON() } mWkt += "["; x = ( double * ) ptr; - mWkt += QString::number( *x, 'f', 6 ); + mWkt += QString::number( *x, 'f' ); mWkt += ", "; ptr += sizeof( double ); y = ( double * ) ptr; - mWkt += QString::number( *y, 'f', 6 ); + mWkt += QString::number( *y, 'f' ); ptr += sizeof( double ); if ( hasZValue ) { @@ -4353,11 +4353,11 @@ QString QgsGeometry::exportToGeoJSON() } mWkt += "["; x = ( double * )( ptr ); - mWkt += QString::number( *x, 'f', 6 ); + mWkt += QString::number( *x, 'f' ); mWkt += ", "; ptr += sizeof( double ); y = ( double * )( ptr ); - mWkt += QString::number( *y, 'f', 6 ); + mWkt += QString::number( *y, 'f' ); ptr += sizeof( double ); if ( hasZValue ) { @@ -4399,11 +4399,11 @@ QString QgsGeometry::exportToGeoJSON() } mWkt += "["; x = ( double * ) ptr; - mWkt += QString::number( *x, 'f', 6 ); + mWkt += QString::number( *x, 'f' ); ptr += sizeof( double ); mWkt += ", "; y = ( double * ) ptr; - mWkt += QString::number( *y, 'f', 6 ); + mWkt += QString::number( *y, 'f' ); ptr += sizeof( double ); if ( hasZValue ) { @@ -4457,11 +4457,11 @@ QString QgsGeometry::exportToGeoJSON() } mWkt += "["; x = ( double * ) ptr; - mWkt += QString::number( *x, 'f', 6 ); + mWkt += QString::number( *x, 'f' ); ptr += sizeof( double ); mWkt += ", "; y = ( double * ) ptr; - mWkt += QString::number( *y, 'f', 6 ); + mWkt += QString::number( *y, 'f' ); ptr += sizeof( double ); if ( hasZValue ) { diff --git a/src/mapserver/qgswfsserver.cpp b/src/mapserver/qgswfsserver.cpp index ff30583..6ca2ebe 100644 --- a/src/mapserver/qgswfsserver.cpp +++ b/src/mapserver/qgswfsserver.cpp @@ -332,7 +332,37 @@ QDomDocument QgsWFSServer::describeFeatureType() //xsd:element QDomElement geomElem = doc.createElement( "element"/*xsd:element*/ ); geomElem.setAttribute( "name", "geometry" ); - geomElem.setAttribute( "type", "gml:GeometryPropertyType" ); + QGis::WkbType wkbType = layer->wkbType(); + switch ( wkbType ) + { + case QGis::WKBPoint25D: + case QGis::WKBPoint: + geomElem.setAttribute( "type", "gml:PointPropertyType" ); + break; + case QGis::WKBLineString25D: + case QGis::WKBLineString: + geomElem.setAttribute( "type", "gml:LineStringPropertyType" ); + break; + case QGis::WKBPolygon25D: + case QGis::WKBPolygon: + geomElem.setAttribute( "type", "gml:PolygonPropertyType" ); + break; + case QGis::WKBMultiPoint25D: + case QGis::WKBMultiPoint: + geomElem.setAttribute( "type", "gml:MultiPointPropertyType" ); + break; + case QGis::WKBMultiLineString25D: + case QGis::WKBMultiLineString: + geomElem.setAttribute( "type", "gml:MultiLineStringPropertyType" ); + break; + case QGis::WKBMultiPolygon25D: + case QGis::WKBMultiPolygon: + geomElem.setAttribute( "type", "gml:MultiPolygonPropertyType" ); + break; + default: + geomElem.setAttribute( "type", "gml:GeometryPropertyType" ); + break; + } geomElem.setAttribute( "minOccurs", "0" ); geomElem.setAttribute( "maxOccurs", "1" ); sequenceElem.appendChild( geomElem ); @@ -544,9 +574,11 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format } } + if ( bboxOk ) + searchRect.set( minx, miny, maxx, maxy ); QgsCoordinateReferenceSystem layerCrs = layer->crs(); - startGetFeature( request, format ); + startGetFeature( request, format, layerCrs, &searchRect ); if ( fidOk ) { @@ -590,8 +622,6 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format } else { - if ( bboxOk ) - searchRect.set( minx, miny, maxx, maxy ); provider->select( attrIndexes, searchRect, mWithGeom, true ); while ( provider->nextFeature( feature ) && featureCounter < maxFeat ) { @@ -609,25 +639,102 @@ int QgsWFSServer::getFeature( QgsRequestHandler& request, const QString& format return 0; } -void QgsWFSServer::startGetFeature( QgsRequestHandler& request, const QString& format ) +void QgsWFSServer::startGetFeature( QgsRequestHandler& request, const QString& format, QgsCoordinateReferenceSystem& crs, QgsRectangle* rect ) { QByteArray result; QString fcString; if ( format == "GeoJSON" ) { fcString = "{\"type\": \"FeatureCollection\",\n"; + fcString += " \"bbox\": [ "+ QString::number( rect->xMinimum(), 'f' ) +", "+ QString::number( rect->yMinimum(), 'f' ) +", "+ QString::number( rect->xMaximum(), 'f' ) +", "+ QString::number( rect->yMaximum(), 'f' ) +"],\n"; fcString += " \"features\": [\n"; result = fcString.toUtf8(); request.startGetFeatureResponse( &result, format ); } else { + //Prepare url + //Some client requests already have http:// in the REQUEST_URI variable + QString hrefString; + QString requestUrl = getenv( "REQUEST_URI" ); + QUrl mapUrl( requestUrl ); + mapUrl.setHost( QString( getenv( "SERVER_NAME" ) ) ); + + //Add non-default ports to url + QString portString = getenv( "SERVER_PORT" ); + if ( !portString.isEmpty() ) + { + bool portOk; + int portNumber = portString.toInt( &portOk ); + if ( portOk ) + { + if ( portNumber != 80 ) + { + mapUrl.setPort( portNumber ); + } + } + } + + if ( QString( getenv( "HTTPS" ) ).compare( "on", Qt::CaseInsensitive ) == 0 ) + { + mapUrl.setScheme( "https" ); + } + else + { + mapUrl.setScheme( "http" ); + } + + QList > queryItems = mapUrl.queryItems(); + QList >::const_iterator queryIt = queryItems.constBegin(); + for ( ; queryIt != queryItems.constEnd(); ++queryIt ) + { + if ( queryIt->first.compare( "REQUEST", Qt::CaseInsensitive ) == 0 ) + { + mapUrl.removeQueryItem( queryIt->first ); + mapUrl.addQueryItem( queryIt->first, "DescribeFeatureType" ); + } + else if ( queryIt->first.compare( "FORMAT", Qt::CaseInsensitive ) == 0 ) + { + mapUrl.removeQueryItem( queryIt->first ); + } + else if ( queryIt->first.compare( "OUTPUTFORMAT", Qt::CaseInsensitive ) == 0 ) + { + mapUrl.removeQueryItem( queryIt->first ); + } + else if ( queryIt->first.compare( "BBOX", Qt::CaseInsensitive ) == 0 ) + { + mapUrl.removeQueryItem( queryIt->first ); + } + else if ( queryIt->first.compare( "FEATUREID", Qt::CaseInsensitive ) == 0 ) + { + mapUrl.removeQueryItem( queryIt->first ); + } + else if ( queryIt->first.compare( "FILTER", Qt::CaseInsensitive ) == 0 ) + { + mapUrl.removeQueryItem( queryIt->first ); + } + else if ( queryIt->first.compare( "MAXFEATURES", Qt::CaseInsensitive ) == 0 ) + { + mapUrl.removeQueryItem( queryIt->first ); + } + else if ( queryIt->first.compare( "PROPERTYNAME", Qt::CaseInsensitive ) == 0 ) + { + mapUrl.removeQueryItem( queryIt->first ); + } + else if ( queryIt->first.compare( "_DC", Qt::CaseInsensitive ) == 0 ) + { + mapUrl.removeQueryItem( queryIt->first ); + } + } + mapUrl.addQueryItem( "OUTPUTFORMAT", "XMLSCHEMA" ); + hrefString = mapUrl.toString(); + //wfs:FeatureCollection fcString = "geometry(); if ( geom && mWithGeom ) { + QgsRectangle box = geom->boundingBox(); + + fStr += " \"bbox\": [ "+ QString::number( box.xMinimum(), 'f' ) +", "+ QString::number( box.yMinimum(), 'f' ) +", "+ QString::number( box.xMaximum(), 'f' ) +", "+ QString::number( box.yMaximum(), 'f' ) +"],\n"; + fStr += " \"geometry\": "; fStr += geom->exportToGeoJSON(); fStr += ",\n"; @@ -760,14 +886,25 @@ QDomElement QgsWFSServer::createFeatureElem( QgsFeature* feat, QDomDocument& doc if ( mWithGeom ) { //add geometry column (as gml) + QgsGeometry* geom = feat->geometry(); + QDomElement geomElem = doc.createElement( "qgs:geometry" ); - QDomElement gmlElem = createGeometryElem( feat->geometry(), doc ); + QDomElement gmlElem = createGeometryElem( geom, doc ); if ( !gmlElem.isNull() ) { + QgsRectangle box = geom->boundingBox(); + QDomElement bbElem = doc.createElement( "gml:boundedBy" ); + QDomElement boxElem = createBoxElem( &box, doc ); + if ( crs.isValid() ) { + boxElem.setAttribute( "srsName", crs.authid() ); gmlElem.setAttribute( "srsName", crs.authid() ); } + + bbElem.appendChild( boxElem ); + typeNameElement.appendChild( bbElem ); + geomElem.appendChild( gmlElem ); typeNameElement.appendChild( geomElem ); } @@ -794,6 +931,27 @@ QDomElement QgsWFSServer::createFeatureElem( QgsFeature* feat, QDomDocument& doc return featureElement; } +QDomElement QgsWFSServer::createBoxElem( QgsRectangle* box, QDomDocument& doc ) /*const*/ +{ + if ( !box ) + { + return QDomElement(); + } + + QDomElement boxElem = doc.createElement( "gml:Box" ); + QVector v; + QgsPoint p1; + p1.set( box->xMinimum(), box->yMinimum() ); + v.append( p1 ); + QgsPoint p2; + p2.set( box->xMaximum(), box->yMaximum() ); + v.append( p2 ); + QDomElement coordElem = createCoordinateElem( v, doc ); + boxElem.appendChild( coordElem ); + + return boxElem; +} + QDomElement QgsWFSServer::createGeometryElem( QgsGeometry* geom, QDomDocument& doc ) /*const*/ { if ( !geom ) @@ -932,13 +1090,13 @@ QDomElement QgsWFSServer::createPolygonElem( QgsGeometry* geom, QDomDocument& do QString boundaryName; if ( i == 0 ) { - boundaryName = "outerBoundaryIs"; + boundaryName = "gml:outerBoundaryIs"; } else { - boundaryName = "innerBoundaryIs"; + boundaryName = "gml:innerBoundaryIs"; } - QDomElement boundaryElem = doc.createElementNS( "http://www.opengis.net/gml", boundaryName ); + QDomElement boundaryElem = doc.createElement( boundaryName ); QDomElement ringElem = doc.createElement( "gml:LinearRing" ); QDomElement coordElem = createCoordinateElem( poly.at( i ), doc ); ringElem.appendChild( coordElem ); @@ -980,7 +1138,7 @@ QDomElement QgsWFSServer::createCoordinateElem( const QVector points, coordElem.setAttribute( "ts", " " ); //precision 4 for meters / feet, precision 8 for degrees - int precision = 8; + int precision = 6; /* if ( mSourceCRS.mapUnits() == QGis::Meters || mSourceCRS.mapUnits() == QGis::Feet ) @@ -997,9 +1155,9 @@ QDomElement QgsWFSServer::createCoordinateElem( const QVector points, { coordString += " "; } - coordString += QString::number( pointIt->x(), 'f', precision ); + coordString += QString::number( pointIt->x(), 'f'); coordString += ","; - coordString += QString::number( pointIt->y(), 'f', precision ); + coordString += QString::number( pointIt->y(), 'f' ); } QDomText coordText = doc.createTextNode( coordString ); diff --git a/src/mapserver/qgswfsserver.h b/src/mapserver/qgswfsserver.h index 1dc3df2..6c6898c 100644 --- a/src/mapserver/qgswfsserver.h +++ b/src/mapserver/qgswfsserver.h @@ -36,6 +36,7 @@ class QgsVectorLayer; class QgsCoordinateReferenceSystem; class QgsField; class QgsFeature; +class QgsRectangle; class QgsGeometry; class QgsSymbol; class QgsRequestHandler; @@ -80,7 +81,7 @@ class QgsWFSServer protected: - void startGetFeature( QgsRequestHandler& request, const QString& format ); + void startGetFeature( QgsRequestHandler& request, const QString& format, QgsCoordinateReferenceSystem& crs, QgsRectangle* rect ); void sendGetFeature( QgsRequestHandler& request, const QString& format, QgsFeature* feat, int featIdx, QgsCoordinateReferenceSystem& crs, QMap< int, QgsField > fields, QSet hiddenAttributes ); void endGetFeature( QgsRequestHandler& request, const QString& format ); @@ -90,6 +91,7 @@ class QgsWFSServer //methods to write GML2 QDomElement createFeatureElem( QgsFeature* feat, QDomDocument& doc, QgsCoordinateReferenceSystem& crs, QMap< int, QgsField > fields, QSet hiddenAttributes ) /*const*/; + QDomElement createBoxElem( QgsRectangle* box, QDomDocument& doc ) /* const */; QDomElement createGeometryElem( QgsGeometry* g, QDomDocument& doc ) /*const*/; QDomElement createLineStringElem( QgsGeometry* geom, QDomDocument& doc ) const; QDomElement createMultiLineStringElem( QgsGeometry* geom, QDomDocument& doc ) const;