Skip to content

Commit 27ebd96

Browse files
committed
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.
1 parent 4dce5ec commit 27ebd96

File tree

8 files changed

+54
-52
lines changed

8 files changed

+54
-52
lines changed

python/core/qgsgeometry.sip

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,12 +369,13 @@ class QgsGeometry
369369
*/
370370
QString exportToWkt() const;
371371

372-
/** Exports the geometry to mGeoJSON
373-
* @return true in case of success and false else
372+
/** Exports the geometry to GeoJSON
373+
* @return a QString representing the geometry as GeoJSON
374374
* @note added in 1.8
375375
* @note python binding added in 1.9
376+
* @note precision parameter added in 2.4
376377
*/
377-
QString exportToGeoJSON() const;
378+
QString exportToGeoJSON( const int &precision = 17 ) const;
378379

379380
/** try to convert the geometry to the requested type
380381
* @param destType the geometry type to be converted to

python/core/qgsogcutils.sip

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,22 @@ class QgsOgcUtils
2828
/** Exports the geometry to GML2 or GML3
2929
@return QDomElement
3030
*/
31-
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc, QString format );
31+
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc, QString format, const int &precision = 17 );
3232

3333
/** Exports the geometry to GML2
3434
@return QDomElement
3535
*/
36-
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc );
36+
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc, const int &precision = 17 );
3737

3838
/** Exports the rectangle to GML2 Box
3939
@return QDomElement
4040
*/
41-
static QDomElement rectangleToGMLBox( QgsRectangle* box, QDomDocument& doc );
41+
static QDomElement rectangleToGMLBox( QgsRectangle* box, QDomDocument& doc, const int &precision = 17 );
4242

4343
/** Exports the rectangle to GML2 Envelope
4444
@return QDomElement
4545
*/
46-
static QDomElement rectangleToGMLEnvelope( QgsRectangle* env, QDomDocument& doc );
46+
static QDomElement rectangleToGMLEnvelope( QgsRectangle* env, QDomDocument& doc, const int &precision = 17 );
4747

4848

4949
/** Parse XML with OGC fill into QColor */

src/core/qgis.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,9 +313,9 @@ inline void ( *cast_to_fptr( void *p ) )()
313313
//
314314
// return a string representation of a double
315315
//
316-
inline QString qgsDoubleToString( const double &a )
316+
inline QString qgsDoubleToString( const double &a, const int &precision = 17 )
317317
{
318-
return QString::number( a, 'f', 17 ).remove( QRegExp( "\\.?0+$" ) );
318+
return QString::number( a, 'f', precision ).remove( QRegExp( "\\.?0+$" ) );
319319
}
320320

321321
//

src/core/qgsgeometry.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3745,7 +3745,7 @@ QString QgsGeometry::exportToWkt() const
37453745
}
37463746
}
37473747

3748-
QString QgsGeometry::exportToGeoJSON() const
3748+
QString QgsGeometry::exportToGeoJSON( const int &precision ) const
37493749
{
37503750
QgsDebugMsg( "entered." );
37513751

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

37783778
wkt += "{ \"type\": \"Point\", \"coordinates\": ["
3779-
+ qgsDoubleToString( x ) + ", "
3780-
+ qgsDoubleToString( y )
3779+
+ qgsDoubleToString( x, precision ) + ", "
3780+
+ qgsDoubleToString( y, precision )
37813781
+ "] }";
37823782
return wkt;
37833783
}
@@ -3801,7 +3801,7 @@ QString QgsGeometry::exportToGeoJSON() const
38013801
if ( hasZValue )
38023802
wkbPtr += sizeof( double );
38033803

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

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

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

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

3949-
wkt += "[" + qgsDoubleToString( x ) + ", " + qgsDoubleToString( y ) + "]";
3949+
wkt += "[" + qgsDoubleToString( x, precision ) + ", " + qgsDoubleToString( y, precision ) + "]";
39503950
}
39513951
wkt += " ]";
39523952
}

src/core/qgsgeometry.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -411,12 +411,13 @@ class CORE_EXPORT QgsGeometry
411411
*/
412412
QString exportToWkt() const;
413413

414-
/** Exports the geometry to mGeoJSON
415-
* @return true in case of success and false else
414+
/** Exports the geometry to GeoJSON
415+
* @return a QString representing the geometry as GeoJSON
416416
* @note added in 1.8
417417
* @note python binding added in 1.9
418+
* @note precision parameter added in 2.4
418419
*/
419-
QString exportToGeoJSON() const;
420+
QString exportToGeoJSON( const int &precision = 17 ) const;
420421

421422
/** try to convert the geometry to the requested type
422423
* @param destType the geometry type to be converted to

src/core/qgsogcutils.cpp

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -993,7 +993,7 @@ QgsRectangle QgsOgcUtils::rectangleFromGMLEnvelope( const QDomNode& envelopeNode
993993
return rect;
994994
}
995995

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

10081008
QString coordString;
1009-
coordString += qgsDoubleToString( box->xMinimum() );
1009+
coordString += qgsDoubleToString( box->xMinimum(), precision );
10101010
coordString += ",";
1011-
coordString += qgsDoubleToString( box->yMinimum() );
1011+
coordString += qgsDoubleToString( box->yMinimum(), precision );
10121012
coordString += " ";
1013-
coordString += qgsDoubleToString( box->xMaximum() );
1013+
coordString += qgsDoubleToString( box->xMaximum(), precision );
10141014
coordString += ",";
1015-
coordString += qgsDoubleToString( box->yMaximum() );
1015+
coordString += qgsDoubleToString( box->yMaximum(), precision );
10161016

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

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

10341034
QDomElement lowerCornerElem = doc.createElement( "gml:lowerCorner" );
1035-
posList = qgsDoubleToString( env->xMinimum() );
1035+
posList = qgsDoubleToString( env->xMinimum(), precision );
10361036
posList += " ";
1037-
posList += qgsDoubleToString( env->yMinimum() );
1037+
posList += qgsDoubleToString( env->yMinimum(), precision );
10381038
QDomText lowerCornerText = doc.createTextNode( posList );
10391039
lowerCornerElem.appendChild( lowerCornerText );
10401040
envElem.appendChild( lowerCornerElem );
10411041

10421042
QDomElement upperCornerElem = doc.createElement( "gml:upperCorner" );
1043-
posList = qgsDoubleToString( env->xMaximum() );
1043+
posList = qgsDoubleToString( env->xMaximum(), precision );
10441044
posList += " ";
1045-
posList += qgsDoubleToString( env->yMaximum() );
1045+
posList += qgsDoubleToString( env->yMaximum(), precision );
10461046
QDomText upperCornerText = doc.createTextNode( posList );
10471047
upperCornerElem.appendChild( upperCornerText );
10481048
envElem.appendChild( upperCornerElem );
10491049

10501050
return envElem;
10511051
}
10521052

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

11011101
double x, y;
11021102
wkbPtr >> x >> y;
1103-
QDomText coordText = doc.createTextNode( qgsDoubleToString( x ) + cs + qgsDoubleToString( y ) );
1103+
QDomText coordText = doc.createTextNode( qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision ) );
11041104

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

11251125
double x, y;
11261126
wkbPtr >> x >> y;
1127-
QDomText coordText = doc.createTextNode( qgsDoubleToString( x ) + cs + qgsDoubleToString( y ) );
1127+
QDomText coordText = doc.createTextNode( qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision ) );
11281128

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

11601160
double x, y;
11611161
wkbPtr >> x >> y;
1162-
coordString += qgsDoubleToString( x ) + cs + qgsDoubleToString( y );
1162+
coordString += qgsDoubleToString( x, precision ) + cs + qgsDoubleToString( y, precision );
11631163

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

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

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

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

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

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

1342-
QDomElement QgsOgcUtils::geometryToGML( QgsGeometry *geometry, QDomDocument &doc )
1342+
QDomElement QgsOgcUtils::geometryToGML( QgsGeometry *geometry, QDomDocument &doc, const int &precision )
13431343
{
1344-
return geometryToGML( geometry, doc, "GML2" );
1344+
return geometryToGML( geometry, doc, "GML2", precision );
13451345
}
13461346

13471347
QDomElement QgsOgcUtils::createGMLCoordinates( const QgsPolyline &points, QDomDocument &doc )

src/core/qgsogcutils.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,22 +51,22 @@ class CORE_EXPORT QgsOgcUtils
5151
/** Exports the geometry to GML2 or GML3
5252
@return QDomElement
5353
*/
54-
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc, QString format );
54+
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc, QString format, const int &precision = 17 );
5555

5656
/** Exports the geometry to GML2
5757
@return QDomElement
5858
*/
59-
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc );
59+
static QDomElement geometryToGML( QgsGeometry* geometry, QDomDocument& doc, const int &precision = 17 );
6060

6161
/** Exports the rectangle to GML2 Box
6262
@return QDomElement
6363
*/
64-
static QDomElement rectangleToGMLBox( QgsRectangle* box, QDomDocument& doc );
64+
static QDomElement rectangleToGMLBox( QgsRectangle* box, QDomDocument& doc, const int &precision = 17 );
6565

6666
/** Exports the rectangle to GML2 Envelope
6767
@return QDomElement
6868
*/
69-
static QDomElement rectangleToGMLEnvelope( QgsRectangle* env, QDomDocument& doc );
69+
static QDomElement rectangleToGMLEnvelope( QgsRectangle* env, QDomDocument& doc, const int &precision = 17 );
7070

7171

7272
/** Parse XML with OGC fill into QColor */

src/mapserver/qgswfsserver.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,7 +1074,7 @@ void QgsWFSServer::startGetFeature( QgsRequestHandler& request, const QString& f
10741074
if ( format == "GeoJSON" )
10751075
{
10761076
fcString = "{\"type\": \"FeatureCollection\",\n";
1077-
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";
1077+
fcString += " \"bbox\": [ " + qgsDoubleToString( rect->xMinimum(), 8 ) + ", " + qgsDoubleToString( rect->yMinimum(), 8 ) + ", " + qgsDoubleToString( rect->xMaximum(), 8 ) + ", " + qgsDoubleToString( rect->yMaximum(), 8 ) + "],\n";
10781078
fcString += " \"features\": [\n";
10791079
result = fcString.toUtf8();
10801080
request.startGetFeatureResponse( &result, format );
@@ -1167,7 +1167,7 @@ void QgsWFSServer::startGetFeature( QgsRequestHandler& request, const QString& f
11671167
QDomElement bbElem = doc.createElement( "gml:boundedBy" );
11681168
if ( format == "GML3" )
11691169
{
1170-
QDomElement envElem = QgsOgcUtils::rectangleToGMLEnvelope( rect, doc );
1170+
QDomElement envElem = QgsOgcUtils::rectangleToGMLEnvelope( rect, doc, 8 );
11711171
if ( !envElem.isNull() )
11721172
{
11731173
if ( crs.isValid() )
@@ -1180,7 +1180,7 @@ void QgsWFSServer::startGetFeature( QgsRequestHandler& request, const QString& f
11801180
}
11811181
else
11821182
{
1183-
QDomElement boxElem = QgsOgcUtils::rectangleToGMLBox( rect, doc );
1183+
QDomElement boxElem = QgsOgcUtils::rectangleToGMLBox( rect, doc, 8 );
11841184
if ( !boxElem.isNull() )
11851185
{
11861186
if ( crs.isValid() )
@@ -1691,10 +1691,10 @@ QString QgsWFSServer::createFeatureGeoJSON( QgsFeature* feat, QgsCoordinateRefer
16911691
{
16921692
QgsRectangle box = geom->boundingBox();
16931693

1694-
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";
1694+
fStr += " \"bbox\": [ " + qgsDoubleToString( box.xMinimum(), 8 ) + ", " + qgsDoubleToString( box.yMinimum(), 8 ) + ", " + qgsDoubleToString( box.xMaximum(), 8 ) + ", " + qgsDoubleToString( box.yMaximum(), 8 ) + "],\n";
16951695

16961696
fStr += " \"geometry\": ";
1697-
fStr += geom->exportToGeoJSON();
1697+
fStr += geom->exportToGeoJSON( 8 );
16981698
fStr += ",\n";
16991699
}
17001700

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

17591759
QDomElement geomElem = doc.createElement( "qgs:geometry" );
1760-
QDomElement gmlElem = QgsOgcUtils::geometryToGML( geom, doc );
1760+
QDomElement gmlElem = QgsOgcUtils::geometryToGML( geom, doc, 8 );
17611761
if ( !gmlElem.isNull() )
17621762
{
17631763
QgsRectangle box = geom->boundingBox();
17641764
QDomElement bbElem = doc.createElement( "gml:boundedBy" );
1765-
QDomElement boxElem = QgsOgcUtils::rectangleToGMLBox( &box, doc );
1765+
QDomElement boxElem = QgsOgcUtils::rectangleToGMLBox( &box, doc, 8 );
17661766

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

18181818
QDomElement geomElem = doc.createElement( "qgs:geometry" );
1819-
QDomElement gmlElem = QgsOgcUtils::geometryToGML( geom, doc, "GML3" );
1819+
QDomElement gmlElem = QgsOgcUtils::geometryToGML( geom, doc, "GML3", 8 );
18201820
if ( !gmlElem.isNull() )
18211821
{
18221822
QgsRectangle box = geom->boundingBox();
18231823
QDomElement bbElem = doc.createElement( "gml:boundedBy" );
1824-
QDomElement boxElem = QgsOgcUtils::rectangleToGMLEnvelope( &box, doc );
1824+
QDomElement boxElem = QgsOgcUtils::rectangleToGMLEnvelope( &box, doc, 8 );
18251825

18261826
if ( crs.isValid() )
18271827
{

0 commit comments

Comments
 (0)