Skip to content
Permalink
Browse files

Bug #10974 QGIS WFS Server provides too much precision

In the GetFeature request QGIS WFS Server uses the static method: QgsDoubleToString. This method returns double with a precision fixed to 17.

We do not need that much precision for coordinates. Firstly because we are not able to measure a position on earth with a lower micron precision. Secondly because it unnecessarily overload response.

I propose to add the ability to specify the precision in the QgsDoubleToString method.
  • Loading branch information
rldhont committed Jul 29, 2014
1 parent 4dce5ec commit 27ebd9657db57a1925f7f0172a697363a63844b3
@@ -369,12 +369,13 @@ class QgsGeometry
*/
QString exportToWkt() const;

/** Exports the geometry to mGeoJSON
* @return true in case of success and false else
/** Exports the geometry to GeoJSON
* @return a QString representing the geometry as GeoJSON
* @note added in 1.8
* @note python binding added in 1.9
* @note precision parameter added in 2.4
*/
QString exportToGeoJSON() const;
QString exportToGeoJSON( const int &precision = 17 ) const;

/** try to convert the geometry to the requested type
* @param destType the geometry type to be converted to
@@ -28,22 +28,22 @@ class QgsOgcUtils
/** Exports the geometry to GML2 or GML3
@return QDomElement
*/
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc, QString format );
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc, QString format, const int &precision = 17 );

/** Exports the geometry to GML2
@return QDomElement
*/
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc );
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc, const int &precision = 17 );

/** Exports the rectangle to GML2 Box
@return QDomElement
*/
static QDomElement rectangleToGMLBox( QgsRectangle* box, QDomDocument& doc );
static QDomElement rectangleToGMLBox( QgsRectangle* box, QDomDocument& doc, const int &precision = 17 );

/** Exports the rectangle to GML2 Envelope
@return QDomElement
*/
static QDomElement rectangleToGMLEnvelope( QgsRectangle* env, QDomDocument& doc );
static QDomElement rectangleToGMLEnvelope( QgsRectangle* env, QDomDocument& doc, const int &precision = 17 );


/** Parse XML with OGC fill into QColor */
@@ -313,9 +313,9 @@ inline void ( *cast_to_fptr( void *p ) )()
//
// return a string representation of a double
//
inline QString qgsDoubleToString( const double &a )
inline QString qgsDoubleToString( const double &a, const int &precision = 17 )
{
return QString::number( a, 'f', 17 ).remove( QRegExp( "\\.?0+$" ) );
return QString::number( a, 'f', precision ).remove( QRegExp( "\\.?0+$" ) );
}

//
@@ -3745,7 +3745,7 @@ QString QgsGeometry::exportToWkt() const
}
}

QString QgsGeometry::exportToGeoJSON() const
QString QgsGeometry::exportToGeoJSON( const int &precision ) const
{
QgsDebugMsg( "entered." );

@@ -3776,8 +3776,8 @@ QString QgsGeometry::exportToGeoJSON() const
wkbPtr >> x >> y;

wkt += "{ \"type\": \"Point\", \"coordinates\": ["
+ qgsDoubleToString( x ) + ", "
+ qgsDoubleToString( y )
+ qgsDoubleToString( x, precision ) + ", "
+ qgsDoubleToString( y, precision )
+ "] }";
return wkt;
}
@@ -3801,7 +3801,7 @@ QString QgsGeometry::exportToGeoJSON() const
if ( hasZValue )
wkbPtr += sizeof( double );

wkt += "[" + qgsDoubleToString( x ) + ", " + qgsDoubleToString( y ) + "]";
wkt += "[" + qgsDoubleToString( x, precision ) + ", " + qgsDoubleToString( y, precision ) + "]";
}
wkt += " ] }";
return wkt;
@@ -3839,7 +3839,7 @@ QString QgsGeometry::exportToGeoJSON() const
if ( hasZValue )
wkbPtr += sizeof( double );

wkt += "[" + qgsDoubleToString( x ) + ", " + qgsDoubleToString( y ) + "]";
wkt += "[" + qgsDoubleToString( x, precision ) + ", " + qgsDoubleToString( y, precision ) + "]";
}
wkt += " ]";
}
@@ -3865,7 +3865,7 @@ QString QgsGeometry::exportToGeoJSON() const
if ( hasZValue )
wkbPtr += sizeof( double );

wkt += "[" + qgsDoubleToString( x ) + ", " + qgsDoubleToString( y ) + "]";
wkt += "[" + qgsDoubleToString( x, precision ) + ", " + qgsDoubleToString( y, precision ) + "]";
}
wkt += " ] }";
return wkt;
@@ -3899,7 +3899,7 @@ QString QgsGeometry::exportToGeoJSON() const
if ( hasZValue )
wkbPtr += sizeof( double );

wkt += "[" + qgsDoubleToString( x ) + ", " + qgsDoubleToString( y ) + "]";
wkt += "[" + qgsDoubleToString( x, precision ) + ", " + qgsDoubleToString( y, precision ) + "]";
}
wkt += " ]";
}
@@ -3946,7 +3946,7 @@ QString QgsGeometry::exportToGeoJSON() const
if ( hasZValue )
wkbPtr += sizeof( double );

wkt += "[" + qgsDoubleToString( x ) + ", " + qgsDoubleToString( y ) + "]";
wkt += "[" + qgsDoubleToString( x, precision ) + ", " + qgsDoubleToString( y, precision ) + "]";
}
wkt += " ]";
}
@@ -411,12 +411,13 @@ class CORE_EXPORT QgsGeometry
*/
QString exportToWkt() const;

/** Exports the geometry to mGeoJSON
* @return true in case of success and false else
/** Exports the geometry to GeoJSON
* @return a QString representing the geometry as GeoJSON
* @note added in 1.8
* @note python binding added in 1.9
* @note precision parameter added in 2.4
*/
QString exportToGeoJSON() const;
QString exportToGeoJSON( const int &precision = 17 ) const;

/** try to convert the geometry to the requested type
* @param destType the geometry type to be converted to
@@ -993,7 +993,7 @@ QgsRectangle QgsOgcUtils::rectangleFromGMLEnvelope( const QDomNode& envelopeNode
return rect;
}

QDomElement QgsOgcUtils::rectangleToGMLBox( QgsRectangle* box, QDomDocument& doc )
QDomElement QgsOgcUtils::rectangleToGMLBox( QgsRectangle* box, QDomDocument& doc, const int &precision )
{
if ( !box )
{
@@ -1006,13 +1006,13 @@ QDomElement QgsOgcUtils::rectangleToGMLBox( QgsRectangle* box, QDomDocument& doc
coordElem.setAttribute( "ts", " " );

QString coordString;
coordString += qgsDoubleToString( box->xMinimum() );
coordString += qgsDoubleToString( box->xMinimum(), precision );
coordString += ",";
coordString += qgsDoubleToString( box->yMinimum() );
coordString += qgsDoubleToString( box->yMinimum(), precision );
coordString += " ";
coordString += qgsDoubleToString( box->xMaximum() );
coordString += qgsDoubleToString( box->xMaximum(), precision );
coordString += ",";
coordString += qgsDoubleToString( box->yMaximum() );
coordString += qgsDoubleToString( box->yMaximum(), precision );

QDomText coordText = doc.createTextNode( coordString );
coordElem.appendChild( coordText );
@@ -1021,7 +1021,7 @@ QDomElement QgsOgcUtils::rectangleToGMLBox( QgsRectangle* box, QDomDocument& doc
return boxElem;
}

QDomElement QgsOgcUtils::rectangleToGMLEnvelope( QgsRectangle* env, QDomDocument& doc )
QDomElement QgsOgcUtils::rectangleToGMLEnvelope( QgsRectangle* env, QDomDocument& doc, const int &precision )
{
if ( !env )
{
@@ -1032,25 +1032,25 @@ QDomElement QgsOgcUtils::rectangleToGMLEnvelope( QgsRectangle* env, QDomDocument
QString posList;

QDomElement lowerCornerElem = doc.createElement( "gml:lowerCorner" );
posList = qgsDoubleToString( env->xMinimum() );
posList = qgsDoubleToString( env->xMinimum(), precision );
posList += " ";
posList += qgsDoubleToString( env->yMinimum() );
posList += qgsDoubleToString( env->yMinimum(), precision );
QDomText lowerCornerText = doc.createTextNode( posList );
lowerCornerElem.appendChild( lowerCornerText );
envElem.appendChild( lowerCornerElem );

QDomElement upperCornerElem = doc.createElement( "gml:upperCorner" );
posList = qgsDoubleToString( env->xMaximum() );
posList = qgsDoubleToString( env->xMaximum(), precision );
posList += " ";
posList += qgsDoubleToString( env->yMaximum() );
posList += qgsDoubleToString( env->yMaximum(), precision );
QDomText upperCornerText = doc.createTextNode( posList );
upperCornerElem.appendChild( upperCornerText );
envElem.appendChild( upperCornerElem );

return envElem;
}

QDomElement QgsOgcUtils::geometryToGML( QgsGeometry* geometry, QDomDocument& doc, QString format )
QDomElement QgsOgcUtils::geometryToGML( QgsGeometry* geometry, QDomDocument& doc, QString format, const int &precision )
{
if ( !geometry || !geometry->asWkb() )
return QDomElement();
@@ -1100,7 +1100,7 @@ QDomElement QgsOgcUtils::geometryToGML( QgsGeometry* geometry, QDomDocument& doc

double x, y;
wkbPtr >> x >> y;
QDomText coordText = doc.createTextNode( qgsDoubleToString( x ) + cs + qgsDoubleToString( y ) );
QDomText coordText = doc.createTextNode( qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision ) );

coordElem.appendChild( coordText );
pointElem.appendChild( coordElem );
@@ -1124,7 +1124,7 @@ QDomElement QgsOgcUtils::geometryToGML( QgsGeometry* geometry, QDomDocument& doc

double x, y;
wkbPtr >> x >> y;
QDomText coordText = doc.createTextNode( qgsDoubleToString( x ) + cs + qgsDoubleToString( y ) );
QDomText coordText = doc.createTextNode( qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision ) );

coordElem.appendChild( coordText );
pointElem.appendChild( coordElem );
@@ -1159,7 +1159,7 @@ QDomElement QgsOgcUtils::geometryToGML( QgsGeometry* geometry, QDomDocument& doc

double x, y;
wkbPtr >> x >> y;
coordString += qgsDoubleToString( x ) + cs + qgsDoubleToString( y );
coordString += qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision );

if ( hasZValue )
{
@@ -1201,7 +1201,7 @@ QDomElement QgsOgcUtils::geometryToGML( QgsGeometry* geometry, QDomDocument& doc
double x, y;
wkbPtr >> x >> y;

coordString += qgsDoubleToString( x ) + cs + qgsDoubleToString( y );
coordString += qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision );

if ( hasZValue )
{
@@ -1257,7 +1257,7 @@ QDomElement QgsOgcUtils::geometryToGML( QgsGeometry* geometry, QDomDocument& doc
double x, y;
wkbPtr >> x >> y;

coordString += qgsDoubleToString( x ) + cs + qgsDoubleToString( y );
coordString += qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision );
if ( hasZValue )
{
wkbPtr += sizeof( double );
@@ -1316,7 +1316,7 @@ QDomElement QgsOgcUtils::geometryToGML( QgsGeometry* geometry, QDomDocument& doc
double x, y;
wkbPtr >> x >> y;

coordString += qgsDoubleToString( x ) + cs + qgsDoubleToString( y );
coordString += qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision );

if ( hasZValue )
{
@@ -1339,9 +1339,9 @@ QDomElement QgsOgcUtils::geometryToGML( QgsGeometry* geometry, QDomDocument& doc
}
}

QDomElement QgsOgcUtils::geometryToGML( QgsGeometry *geometry, QDomDocument &doc )
QDomElement QgsOgcUtils::geometryToGML( QgsGeometry *geometry, QDomDocument &doc, const int &precision )
{
return geometryToGML( geometry, doc, "GML2" );
return geometryToGML( geometry, doc, "GML2", precision );
}

QDomElement QgsOgcUtils::createGMLCoordinates( const QgsPolyline &points, QDomDocument &doc )
@@ -51,22 +51,22 @@ class CORE_EXPORT QgsOgcUtils
/** Exports the geometry to GML2 or GML3
@return QDomElement
*/
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc, QString format );
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc, QString format, const int &precision = 17 );

/** Exports the geometry to GML2
@return QDomElement
*/
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc );
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc, const int &precision = 17 );

/** Exports the rectangle to GML2 Box
@return QDomElement
*/
static QDomElement rectangleToGMLBox( QgsRectangle* box, QDomDocument& doc );
static QDomElement rectangleToGMLBox( QgsRectangle* box, QDomDocument& doc, const int &precision = 17 );

/** Exports the rectangle to GML2 Envelope
@return QDomElement
*/
static QDomElement rectangleToGMLEnvelope( QgsRectangle* env, QDomDocument& doc );
static QDomElement rectangleToGMLEnvelope( QgsRectangle* env, QDomDocument& doc, const int &precision = 17 );


/** Parse XML with OGC fill into QColor */
@@ -1074,7 +1074,7 @@ void QgsWFSServer::startGetFeature( QgsRequestHandler& request, const QString& f
if ( format == "GeoJSON" )
{
fcString = "{\"type\": \"FeatureCollection\",\n";
fcString += " \"bbox\": [ " + QString::number( rect->xMinimum(), 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) ) + ", " + QString::number( rect->yMinimum(), 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) ) + ", " + QString::number( rect->xMaximum(), 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) ) + ", " + QString::number( rect->yMaximum(), 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) ) + "],\n";
fcString += " \"bbox\": [ " + qgsDoubleToString( rect->xMinimum(), 8 ) + ", " + qgsDoubleToString( rect->yMinimum(), 8 ) + ", " + qgsDoubleToString( rect->xMaximum(), 8 ) + ", " + qgsDoubleToString( rect->yMaximum(), 8 ) + "],\n";
fcString += " \"features\": [\n";
result = fcString.toUtf8();
request.startGetFeatureResponse( &result, format );
@@ -1167,7 +1167,7 @@ void QgsWFSServer::startGetFeature( QgsRequestHandler& request, const QString& f
QDomElement bbElem = doc.createElement( "gml:boundedBy" );
if ( format == "GML3" )
{
QDomElement envElem = QgsOgcUtils::rectangleToGMLEnvelope( rect, doc );
QDomElement envElem = QgsOgcUtils::rectangleToGMLEnvelope( rect, doc, 8 );
if ( !envElem.isNull() )
{
if ( crs.isValid() )
@@ -1180,7 +1180,7 @@ void QgsWFSServer::startGetFeature( QgsRequestHandler& request, const QString& f
}
else
{
QDomElement boxElem = QgsOgcUtils::rectangleToGMLBox( rect, doc );
QDomElement boxElem = QgsOgcUtils::rectangleToGMLBox( rect, doc, 8 );
if ( !boxElem.isNull() )
{
if ( crs.isValid() )
@@ -1691,10 +1691,10 @@ QString QgsWFSServer::createFeatureGeoJSON( QgsFeature* feat, QgsCoordinateRefer
{
QgsRectangle box = geom->boundingBox();

fStr += " \"bbox\": [ " + QString::number( box.xMinimum(), 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) ) + ", " + QString::number( box.yMinimum(), 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) ) + ", " + QString::number( box.xMaximum(), 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) ) + ", " + QString::number( box.yMaximum(), 'f', 8 ).remove( QRegExp( "[0]{1,7}$" ) ) + "],\n";
fStr += " \"bbox\": [ " + qgsDoubleToString( box.xMinimum(), 8 ) + ", " + qgsDoubleToString( box.yMinimum(), 8 ) + ", " + qgsDoubleToString( box.xMaximum(), 8 ) + ", " + qgsDoubleToString( box.yMaximum(), 8 ) + "],\n";

fStr += " \"geometry\": ";
fStr += geom->exportToGeoJSON();
fStr += geom->exportToGeoJSON( 8 );
fStr += ",\n";
}

@@ -1757,12 +1757,12 @@ QDomElement QgsWFSServer::createFeatureGML2( QgsFeature* feat, QDomDocument& doc
QgsGeometry* geom = feat->geometry();

QDomElement geomElem = doc.createElement( "qgs:geometry" );
QDomElement gmlElem = QgsOgcUtils::geometryToGML( geom, doc );
QDomElement gmlElem = QgsOgcUtils::geometryToGML( geom, doc, 8 );
if ( !gmlElem.isNull() )
{
QgsRectangle box = geom->boundingBox();
QDomElement bbElem = doc.createElement( "gml:boundedBy" );
QDomElement boxElem = QgsOgcUtils::rectangleToGMLBox( &box, doc );
QDomElement boxElem = QgsOgcUtils::rectangleToGMLBox( &box, doc, 8 );

if ( crs.isValid() )
{
@@ -1816,12 +1816,12 @@ QDomElement QgsWFSServer::createFeatureGML3( QgsFeature* feat, QDomDocument& doc
QgsGeometry* geom = feat->geometry();

QDomElement geomElem = doc.createElement( "qgs:geometry" );
QDomElement gmlElem = QgsOgcUtils::geometryToGML( geom, doc, "GML3" );
QDomElement gmlElem = QgsOgcUtils::geometryToGML( geom, doc, "GML3", 8 );
if ( !gmlElem.isNull() )
{
QgsRectangle box = geom->boundingBox();
QDomElement bbElem = doc.createElement( "gml:boundedBy" );
QDomElement boxElem = QgsOgcUtils::rectangleToGMLEnvelope( &box, doc );
QDomElement boxElem = QgsOgcUtils::rectangleToGMLEnvelope( &box, doc, 8 );

if ( crs.isValid() )
{

0 comments on commit 27ebd96

Please sign in to comment.
You can’t perform that action at this time.