[Bugfix][Server] Use floor and ceil for round extent coordinates in services capabilities

This commit is contained in:
rldhont 2019-11-15 16:51:20 +01:00
parent 747f785eb6
commit 656f9e04bc
8 changed files with 73 additions and 29 deletions

View File

@ -19,6 +19,8 @@
namespace QgsServerProjectUtils
{
bool owsServiceCapabilities( const QgsProject &project );
%Docstring
Returns if owsService capabilities are enabled.

View File

@ -18,6 +18,18 @@
#include "qgsserverprojectutils.h"
#include "qgsproject.h"
double QgsServerProjectUtils::ceilWithPrecision( double number, int places )
{
double scaleFactor = std::pow( 10.0, places );
return ( std::ceil( number * scaleFactor ) / scaleFactor );
}
double QgsServerProjectUtils::floorWithPrecision( double number, int places )
{
double scaleFactor = std::pow( 10.0, places );
return ( std::floor( number * scaleFactor ) / scaleFactor );
}
bool QgsServerProjectUtils::owsServiceCapabilities( const QgsProject &project )
{
return project.readBoolEntry( QStringLiteral( "WMSServiceCapabilities" ), QStringLiteral( "/" ), false );

View File

@ -20,8 +20,10 @@
#include <QString>
#include <QHash>
#include <cmath>
#include "qgis_server.h"
#include "qgis_sip.h"
class QgsProject;
class QgsRectangle;
@ -42,6 +44,20 @@ class QgsRectangle;
namespace QgsServerProjectUtils
{
/**
* Returns a double greater than \a number to the specified number of \a places.
*
* \since QGIS 3.10.1
*/
SERVER_EXPORT double ceilWithPrecision( double number, int places ) SIP_SKIP;
/**
* Returns a double less than \a number to the specified number of \a places.
*
* \since QGIS 3.10.1
*/
SERVER_EXPORT double floorWithPrecision( double number, int places ) SIP_SKIP;
/**
* Returns if owsService capabilities are enabled.
* \param project the QGIS project

View File

@ -90,11 +90,11 @@ namespace QgsWcs
QDomElement lonLatElem = doc.createElement( QStringLiteral( "lonLatEnvelope" ) );
lonLatElem.setAttribute( QStringLiteral( "srsName" ), QStringLiteral( "urn:ogc:def:crs:OGC:1.3:CRS84" ) );
QDomElement lowerPosElem = doc.createElement( QStringLiteral( "gml:pos" ) );
QDomText lowerPosText = doc.createTextNode( qgsDoubleToString( BBox.xMinimum(), wgs84precision ) + " " + qgsDoubleToString( BBox.yMinimum(), wgs84precision ) );
QDomText lowerPosText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( BBox.xMinimum(), wgs84precision ), wgs84precision ) + " " + qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( BBox.yMinimum(), wgs84precision ), wgs84precision ) );
lowerPosElem.appendChild( lowerPosText );
lonLatElem.appendChild( lowerPosElem );
QDomElement upperPosElem = doc.createElement( QStringLiteral( "gml:pos" ) );
QDomText upperPosText = doc.createTextNode( qgsDoubleToString( BBox.xMaximum(), wgs84precision ) + " " + qgsDoubleToString( BBox.yMaximum(), wgs84precision ) );
QDomText upperPosText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( BBox.xMaximum(), wgs84precision ), wgs84precision ) + " " + qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( BBox.yMaximum(), wgs84precision ), wgs84precision ) );
upperPosElem.appendChild( upperPosText );
lonLatElem.appendChild( upperPosElem );
layerElem.appendChild( lonLatElem );
@ -122,11 +122,11 @@ namespace QgsWcs
QDomElement envelopeElem = doc.createElement( QStringLiteral( "gml:Envelope" ) );
envelopeElem.setAttribute( QStringLiteral( "srsName" ), layerCrs.authid() );
QDomElement lowerCornerElem = doc.createElement( QStringLiteral( "gml:pos" ) );
QDomText lowerCornerText = doc.createTextNode( qgsDoubleToString( layerBBox.xMinimum(), precision ) + " " + qgsDoubleToString( layerBBox.yMinimum(), precision ) );
QDomText lowerCornerText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( layerBBox.xMinimum(), precision ), wgs84precision ) + " " + qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( layerBBox.yMinimum(), wgs84precision ), precision ) );
lowerCornerElem.appendChild( lowerCornerText );
envelopeElem.appendChild( lowerCornerElem );
QDomElement upperCornerElem = doc.createElement( QStringLiteral( "gml:pos" ) );
QDomText upperCornerText = doc.createTextNode( qgsDoubleToString( layerBBox.xMaximum(), precision ) + " " + qgsDoubleToString( layerBBox.yMaximum(), precision ) );
QDomText upperCornerText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( layerBBox.xMaximum(), precision ), wgs84precision ) + " " + qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( layerBBox.yMaximum(), wgs84precision ), precision ) );
upperCornerElem.appendChild( upperCornerText );
envelopeElem.appendChild( upperCornerElem );
spatialDomainElem.appendChild( envelopeElem );
@ -159,7 +159,7 @@ namespace QgsWcs
QDomElement originElem = doc.createElement( QStringLiteral( "gml:origin" ) );
QDomElement originPosElem = doc.createElement( QStringLiteral( "gml:pos" ) );
QDomText originPosText = doc.createTextNode( qgsDoubleToString( layerBBox.xMinimum(), precision ) + " " + qgsDoubleToString( layerBBox.yMaximum(), precision ) );
QDomText originPosText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( layerBBox.xMinimum(), precision ), precision ) + " " + qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( layerBBox.yMinimum(), precision ), precision ) );
originPosElem.appendChild( originPosText );
spatialDomainElem.appendChild( originElem );

View File

@ -611,11 +611,11 @@ namespace QgsWfs
QDomElement bBoxElement = doc.createElement( QStringLiteral( "ows:WGS84BoundingBox" ) );
bBoxElement.setAttribute( QStringLiteral( "dimensions" ), QStringLiteral( "2" ) );
QDomElement lCornerElement = doc.createElement( QStringLiteral( "ows:LowerCorner" ) );
QDomText lCornerText = doc.createTextNode( qgsDoubleToString( wgs84BoundingRect.xMinimum(), wgs84precision ) + " " + qgsDoubleToString( wgs84BoundingRect.yMinimum(), wgs84precision ) );
QDomText lCornerText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( wgs84BoundingRect.xMinimum(), wgs84precision ), wgs84precision ) + " " + qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( wgs84BoundingRect.yMinimum(), wgs84precision ), wgs84precision ) );
lCornerElement.appendChild( lCornerText );
bBoxElement.appendChild( lCornerElement );
QDomElement uCornerElement = doc.createElement( QStringLiteral( "ows:UpperCorner" ) );
QDomText uCornerText = doc.createTextNode( qgsDoubleToString( wgs84BoundingRect.xMaximum(), wgs84precision ) + " " + qgsDoubleToString( wgs84BoundingRect.yMaximum(), wgs84precision ) );
QDomText uCornerText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( wgs84BoundingRect.xMaximum(), wgs84precision ), wgs84precision ) + " " + qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( wgs84BoundingRect.yMaximum(), wgs84precision ), wgs84precision ) );
uCornerElement.appendChild( uCornerText );
bBoxElement.appendChild( uCornerElement );
layerElem.appendChild( bBoxElement );

View File

@ -363,10 +363,10 @@ namespace QgsWfs
//create LatLongBoundingBox
QgsRectangle layerExtent = layer->extent();
QDomElement bBoxElement = doc.createElement( QStringLiteral( "LatLongBoundingBox" ) );
bBoxElement.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( layerExtent.xMinimum(), precision ) );
bBoxElement.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( layerExtent.yMinimum(), precision ) );
bBoxElement.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( layerExtent.xMaximum(), precision ) );
bBoxElement.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( layerExtent.yMaximum(), precision ) );
bBoxElement.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( layerExtent.xMinimum(), precision ), precision ) );
bBoxElement.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( layerExtent.yMinimum(), precision ), precision ) );
bBoxElement.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( layerExtent.xMaximum(), precision ), precision ) );
bBoxElement.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( layerExtent.yMaximum(), precision ), precision ) );
layerElem.appendChild( bBoxElement );
// layer metadata URL

View File

@ -1455,28 +1455,28 @@ namespace QgsWms
if ( version == QLatin1String( "1.1.1" ) ) // WMS Version 1.1.1
{
ExGeoBBoxElement = doc.createElement( QStringLiteral( "LatLonBoundingBox" ) );
ExGeoBBoxElement.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( wgs84BoundingRect.xMinimum(), wgs84precision ) );
ExGeoBBoxElement.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( wgs84BoundingRect.xMaximum(), wgs84precision ) );
ExGeoBBoxElement.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( wgs84BoundingRect.yMinimum(), wgs84precision ) );
ExGeoBBoxElement.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( wgs84BoundingRect.yMaximum(), wgs84precision ) );
ExGeoBBoxElement.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( wgs84BoundingRect.xMinimum(), wgs84precision ), wgs84precision ) );
ExGeoBBoxElement.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( wgs84BoundingRect.yMinimum(), wgs84precision ), wgs84precision ) );
ExGeoBBoxElement.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( wgs84BoundingRect.xMaximum(), wgs84precision ), wgs84precision ) );
ExGeoBBoxElement.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( wgs84BoundingRect.yMaximum(), wgs84precision ), wgs84precision ) );
}
else // WMS Version 1.3.0
{
ExGeoBBoxElement = doc.createElement( QStringLiteral( "EX_GeographicBoundingBox" ) );
QDomElement wBoundLongitudeElement = doc.createElement( QStringLiteral( "westBoundLongitude" ) );
QDomText wBoundLongitudeText = doc.createTextNode( qgsDoubleToString( wgs84BoundingRect.xMinimum(), wgs84precision ) );
QDomText wBoundLongitudeText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( wgs84BoundingRect.xMinimum(), wgs84precision ), wgs84precision ) );
wBoundLongitudeElement.appendChild( wBoundLongitudeText );
ExGeoBBoxElement.appendChild( wBoundLongitudeElement );
QDomElement eBoundLongitudeElement = doc.createElement( QStringLiteral( "eastBoundLongitude" ) );
QDomText eBoundLongitudeText = doc.createTextNode( qgsDoubleToString( wgs84BoundingRect.xMaximum(), wgs84precision ) );
QDomText eBoundLongitudeText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( wgs84BoundingRect.xMaximum(), wgs84precision ), wgs84precision ) );
eBoundLongitudeElement.appendChild( eBoundLongitudeText );
ExGeoBBoxElement.appendChild( eBoundLongitudeElement );
QDomElement sBoundLatitudeElement = doc.createElement( QStringLiteral( "southBoundLatitude" ) );
QDomText sBoundLatitudeText = doc.createTextNode( qgsDoubleToString( wgs84BoundingRect.yMinimum(), wgs84precision ) );
QDomText sBoundLatitudeText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( wgs84BoundingRect.yMinimum(), wgs84precision ), wgs84precision ) );
sBoundLatitudeElement.appendChild( sBoundLatitudeText );
ExGeoBBoxElement.appendChild( sBoundLatitudeElement );
QDomElement nBoundLatitudeElement = doc.createElement( QStringLiteral( "northBoundLatitude" ) );
QDomText nBoundLatitudeText = doc.createTextNode( qgsDoubleToString( wgs84BoundingRect.yMaximum(), wgs84precision ) );
QDomText nBoundLatitudeText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( wgs84BoundingRect.yMaximum(), wgs84precision ), wgs84precision ) );
nBoundLatitudeElement.appendChild( nBoundLatitudeText );
ExGeoBBoxElement.appendChild( nBoundLatitudeElement );
}
@ -1569,10 +1569,10 @@ namespace QgsWms
crsExtent.invert();
}
bBoxElement.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( crsExtent.xMinimum(), precision ) );
bBoxElement.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( crsExtent.yMinimum(), precision ) );
bBoxElement.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( crsExtent.xMaximum(), precision ) );
bBoxElement.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( crsExtent.yMaximum(), precision ) );
bBoxElement.setAttribute( QStringLiteral( "minx" ), qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( crsExtent.xMinimum(), precision ), precision ) );
bBoxElement.setAttribute( QStringLiteral( "miny" ), qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( crsExtent.yMinimum(), precision ), precision ) );
bBoxElement.setAttribute( QStringLiteral( "maxx" ), qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( crsExtent.xMaximum(), precision ), precision ) );
bBoxElement.setAttribute( QStringLiteral( "maxy" ), qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( crsExtent.yMaximum(), precision ), precision ) );
QDomElement lastBBoxElem = layerElem.lastChildElement( QStringLiteral( "BoundingBox" ) );
if ( !lastBBoxElem.isNull() )

View File

@ -376,13 +376,14 @@ namespace QgsWmts
}
// WGS84 bounding box
int wgs84precision = 6;
QDomElement wgs84BBoxElement = doc.createElement( QStringLiteral( "ows:WGS84BoundingBox" ) );
QDomElement wgs84LowerCornerElement = doc.createElement( QStringLiteral( "LowerCorner" ) );
QDomText wgs84LowerCornerText = doc.createTextNode( qgsDoubleToString( wmtsLayer.wgs84BoundingRect.xMinimum(), 6 ) + ' ' + qgsDoubleToString( wmtsLayer.wgs84BoundingRect.yMinimum(), 6 ) );
QDomText wgs84LowerCornerText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( wmtsLayer.wgs84BoundingRect.xMinimum(), wgs84precision ), wgs84precision ) + ' ' + qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( wmtsLayer.wgs84BoundingRect.yMinimum(), wgs84precision ), wgs84precision ) );
wgs84LowerCornerElement.appendChild( wgs84LowerCornerText );
wgs84BBoxElement.appendChild( wgs84LowerCornerElement );
QDomElement wgs84UpperCornerElement = doc.createElement( QStringLiteral( "UpperCorner" ) );
QDomText wgs84UpperCornerText = doc.createTextNode( qgsDoubleToString( wmtsLayer.wgs84BoundingRect.xMaximum(), 6 ) + ' ' + qgsDoubleToString( wmtsLayer.wgs84BoundingRect.yMaximum(), 6 ) );
QDomText wgs84UpperCornerText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( wmtsLayer.wgs84BoundingRect.xMaximum(), wgs84precision ), wgs84precision ) + ' ' + qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( wmtsLayer.wgs84BoundingRect.yMaximum(), wgs84precision ), wgs84precision ) );
wgs84UpperCornerElement.appendChild( wgs84UpperCornerText );
wgs84BBoxElement.appendChild( wgs84UpperCornerElement );
layerElem.appendChild( wgs84BBoxElement );
@ -405,14 +406,20 @@ namespace QgsWmts
continue;
}
int precision = 3;
if ( crs.isGeographic() )
{
precision = 6;
}
QDomElement bboxElement = doc.createElement( QStringLiteral( "ows:BoundingBox" ) );
bboxElement.setAttribute( QStringLiteral( "crs" ), tms.ref );
QDomElement lowerCornerElement = doc.createElement( QStringLiteral( "LowerCorner" ) );
QDomText lowerCornerText = doc.createTextNode( qgsDoubleToString( rect.xMinimum(), 6 ) + ' ' + qgsDoubleToString( rect.yMinimum(), 6 ) );
QDomText lowerCornerText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( rect.xMinimum(), precision ), precision ) + ' ' + qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( rect.yMinimum(), precision ), precision ) );
lowerCornerElement.appendChild( lowerCornerText );
bboxElement.appendChild( lowerCornerElement );
QDomElement upperCornerElement = doc.createElement( QStringLiteral( "UpperCorner" ) );
QDomText upperCornerText = doc.createTextNode( qgsDoubleToString( rect.xMaximum(), 6 ) + ' ' + qgsDoubleToString( rect.yMaximum(), 6 ) );
QDomText upperCornerText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( rect.xMaximum(), precision ), precision ) + ' ' + qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( rect.yMaximum(), precision ), precision ) );
upperCornerElement.appendChild( upperCornerText );
bboxElement.appendChild( upperCornerElement );
layerElem.appendChild( bboxElement );
@ -526,6 +533,13 @@ namespace QgsWmts
crsElem.appendChild( crsText );
tmsElement.appendChild( crsElem );
QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( tms.ref );
int precision = 3;
if ( crs.isGeographic() )
{
precision = 6;
}
//wmts:TileMatrix
int tmIdx = 0;
for ( const tileMatrixDef &tm : tms.tileMatrixList )
@ -545,12 +559,12 @@ namespace QgsWmts
QDomElement tmTopLeftCornerElem = doc.createElement( QStringLiteral( "TopLeftCorner" ) );
if ( tms.hasAxisInverted )
{
QDomText tmTopLeftCornerText = doc.createTextNode( qgsDoubleToString( tm.top, 6 ) + ' ' + qgsDoubleToString( tm.left, 6 ) );
QDomText tmTopLeftCornerText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( tm.top, precision ), precision ) + ' ' + qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( tm.left, precision ), precision ) );
tmTopLeftCornerElem.appendChild( tmTopLeftCornerText );
}
else
{
QDomText tmTopLeftCornerText = doc.createTextNode( qgsDoubleToString( tm.left, 6 ) + ' ' + qgsDoubleToString( tm.top, 6 ) );
QDomText tmTopLeftCornerText = doc.createTextNode( qgsDoubleToString( QgsServerProjectUtils::floorWithPrecision( tm.left, precision ), precision ) + ' ' + qgsDoubleToString( QgsServerProjectUtils::ceilWithPrecision( tm.top, precision ), precision ) );
tmTopLeftCornerElem.appendChild( tmTopLeftCornerText );
}
tmElement.appendChild( tmTopLeftCornerElem );