Skip to content

Commit 2d0f08b

Browse files
committed
[FEATURE]: possibility to set WMS featureInfo tolerance in request. Funded by city of Uster
1 parent 2481ce6 commit 2d0f08b

File tree

2 files changed

+76
-59
lines changed

2 files changed

+76
-59
lines changed

src/server/qgswmsserver.cpp

+72-52
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,7 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )
14031403

14041404
QgsRectangle* featuresRect = 0;
14051405
QgsPoint* infoPoint = 0;
1406+
14061407
if ( i == -1 || j == -1 )
14071408
{
14081409
if ( mParameters.contains( "FILTER" ) )
@@ -1416,7 +1417,11 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )
14161417
}
14171418
else
14181419
{
1419-
infoPoint = new QgsPoint();
1420+
infoPoint = new QgsPoint();
1421+
if( !infoPointToMapCoordinates( i, j, infoPoint, mMapRenderer ) )
1422+
{
1423+
return 5;
1424+
}
14201425
}
14211426

14221427
//get the layer registered in QgsMapLayerRegistry and apply possible filters
@@ -1501,11 +1506,6 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )
15011506
continue;
15021507
}
15031508

1504-
if ( infoPoint && infoPointToLayerCoordinates( i, j, infoPoint, mMapRenderer, currentLayer ) != 0 )
1505-
{
1506-
continue;
1507-
}
1508-
15091509
//switch depending on vector or raster
15101510
QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
15111511

@@ -1552,7 +1552,12 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )
15521552
QgsRasterLayer* rasterLayer = dynamic_cast<QgsRasterLayer*>( currentLayer );
15531553
if ( rasterLayer )
15541554
{
1555-
if ( featureInfoFromRasterLayer( rasterLayer, infoPoint, result, layerElement, version, infoFormat ) != 0 )
1555+
if( !infoPoint )
1556+
{
1557+
continue;
1558+
}
1559+
QgsPoint layerInfoPoint = mMapRenderer->mapToLayerCoordinates( currentLayer, *infoPoint );
1560+
if ( featureInfoFromRasterLayer( rasterLayer, &layerInfoPoint, result, layerElement, version, infoFormat ) != 0 )
15561561
{
15571562
continue;
15581563
}
@@ -1609,7 +1614,6 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )
16091614
restoreLayerFilters( originalLayerFilters );
16101615
QgsMapLayerRegistry::instance()->removeAllMapLayers();
16111616
delete featuresRect;
1612-
delete infoPoint;
16131617
return 0;
16141618
}
16151619

@@ -1916,38 +1920,18 @@ int QgsWMSServer::initializeSLDParser( QStringList& layersList, QStringList& sty
19161920
return 0;
19171921
}
19181922

1919-
int QgsWMSServer::infoPointToLayerCoordinates( int i, int j, QgsPoint* layerCoords, QgsMapRenderer* mapRender,
1920-
QgsMapLayer* layer ) const
1923+
bool QgsWMSServer::infoPointToMapCoordinates( int i, int j, QgsPoint* infoPoint, QgsMapRenderer* mapRenderer )
19211924
{
1922-
if ( !layerCoords || !mapRender || !layer || !mapRender->coordinateTransform() )
1925+
if ( !mapRenderer || !infoPoint )
19231926
{
1924-
return 1;
1927+
return false;
19251928
}
19261929

1927-
//first transform i,j to map output coordinates
1928-
// toMapCoordinates() is currently (Oct 18 2012) using average resolution
1929-
// to calc point but GetFeatureInfo request may be sent with different
1930-
// resolutions in each axis
1931-
//QgsPoint mapPoint = mapRender->coordinateTransform()->toMapCoordinates( i, j );
1932-
double xRes = mapRender->extent().width() / mapRender->width();
1933-
double yRes = mapRender->extent().height() / mapRender->height();
1934-
QgsPoint mapPoint( mapRender->extent().xMinimum() + i * xRes,
1935-
mapRender->extent().yMaximum() - j * yRes );
1936-
1937-
QgsDebugMsg( QString( "mapPoint (corner): %1 %2" ).arg( mapPoint.x() ).arg( mapPoint.y() ) );
1938-
// use pixel center instead of corner
1939-
// Unfortunately going through pixel (integer) we cannot reconstruct precisely
1940-
// the coordinate clicked on client and thus result may differ from
1941-
// the same raster loaded and queried locally on client
1942-
mapPoint.setX( mapPoint.x() + xRes / 2 );
1943-
mapPoint.setY( mapPoint.y() - yRes / 2 );
1944-
1945-
QgsDebugMsg( QString( "mapPoint (pixel center): %1 %2" ).arg( mapPoint.x() ).arg( mapPoint.y() ) );
1946-
1947-
//and then to layer coordinates
1948-
*layerCoords = mapRender->mapToLayerCoordinates( layer, mapPoint );
1949-
QgsDebugMsg( QString( "mapPoint: %1 %2" ).arg( mapPoint.x() ).arg( mapPoint.y() ) );
1950-
return 0;
1930+
double xRes = mapRenderer->extent().width() / mapRenderer->width();
1931+
double yRes = mapRenderer->extent().height() / mapRenderer->height();
1932+
infoPoint->setX( mapRenderer->extent().xMinimum() + i * xRes + xRes / 2.0 );
1933+
infoPoint->setY( mapRenderer->extent().yMaximum() - j * yRes - yRes / 2.0 );
1934+
return true;
19511935
}
19521936

19531937
int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
@@ -1970,27 +1954,13 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
19701954
QgsRectangle mapRect = mapRender->extent();
19711955
QgsRectangle layerRect = mapRender->mapToLayerCoordinates( layer, mapRect );
19721956

1957+
19731958
QgsRectangle searchRect;
19741959

19751960
//info point could be 0 in case there is only an attribute filter
19761961
if ( infoPoint )
19771962
{
1978-
double searchRadius = 0;
1979-
if ( layer->geometryType() == QGis::Polygon )
1980-
{
1981-
searchRadius = layerRect.width() / 400;
1982-
}
1983-
else if ( layer->geometryType() == QGis::Line )
1984-
{
1985-
searchRadius = layerRect.width() / 200;
1986-
}
1987-
else
1988-
{
1989-
searchRadius = layerRect.width() / 100;
1990-
}
1991-
1992-
searchRect.set( infoPoint->x() - searchRadius, infoPoint->y() - searchRadius,
1993-
infoPoint->x() + searchRadius, infoPoint->y() + searchRadius );
1963+
searchRect = featureInfoSearchRect( layer, mapRender, renderContext, *infoPoint );
19941964
}
19951965
else if ( mParameters.contains( "BBOX" ) )
19961966
{
@@ -3112,3 +3082,53 @@ int QgsWMSServer::getWMSPrecision( int defaultValue = 8 ) const
31123082
}
31133083
return WMSPrecision;
31143084
}
3085+
3086+
QgsRectangle QgsWMSServer::featureInfoSearchRect( QgsVectorLayer* ml, QgsMapRenderer* mr, const QgsRenderContext& rct, const QgsPoint& infoPoint ) const
3087+
{
3088+
if ( !ml || !mr )
3089+
{
3090+
return QgsRectangle();
3091+
}
3092+
3093+
double mapUnitTolerance = 0.0;
3094+
if ( ml->geometryType() == QGis::Polygon )
3095+
{
3096+
QMap<QString, QString>::const_iterator tolIt = mParameters.find( "POLYGON_TOLERANCE" );
3097+
if ( tolIt != mParameters.constEnd() )
3098+
{
3099+
mapUnitTolerance = tolIt.value().toInt() * rct.mapToPixel().mapUnitsPerPixel();
3100+
}
3101+
else
3102+
{
3103+
mapUnitTolerance = mr->extent().width() / 400.0;
3104+
}
3105+
}
3106+
else if ( ml->geometryType() == QGis::Line )
3107+
{
3108+
QMap<QString, QString>::const_iterator tolIt = mParameters.find( "LINE_TOLERANCE" );
3109+
if ( tolIt != mParameters.constEnd() )
3110+
{
3111+
mapUnitTolerance = tolIt.value().toInt() * rct.mapToPixel().mapUnitsPerPixel();
3112+
}
3113+
else
3114+
{
3115+
mapUnitTolerance = mr->extent().width() / 200.0;
3116+
}
3117+
}
3118+
else //points
3119+
{
3120+
QMap<QString, QString>::const_iterator tolIt = mParameters.find( "POINT_TOLERANCE" );
3121+
if ( tolIt != mParameters.constEnd() )
3122+
{
3123+
mapUnitTolerance = tolIt.value().toInt() * rct.mapToPixel().mapUnitsPerPixel();
3124+
}
3125+
else
3126+
{
3127+
mapUnitTolerance = mr->extent().width() / 100.0;
3128+
}
3129+
}
3130+
3131+
QgsRectangle mapRectangle( infoPoint.x() - mapUnitTolerance, infoPoint.y() - mapUnitTolerance,
3132+
infoPoint.x() + mapUnitTolerance, infoPoint.y() + mapUnitTolerance );
3133+
return( mr->mapToLayerCoordinates( ml, mapRectangle ) );
3134+
}

src/server/qgswmsserver.h

+4-7
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,7 @@ class QgsWMSServer: public QgsOWSServer
134134
set to the layer and style names according to the SLD
135135
@return 0 in case of success*/
136136
int initializeSLDParser( QStringList& layersList, QStringList& stylesList );
137-
/**Calculates the location of a feature info point in layer coordinates
138-
@param i pixel x-coordinate
139-
@param j pixel y-coordinate
140-
@param layerCoords calculated layer coordinates are assigned to this point
141-
@return 0 in case of success*/
142-
int infoPointToLayerCoordinates( int i, int j, QgsPoint* layerCoords, QgsMapRenderer* mapRender,
143-
QgsMapLayer* layer ) const;
137+
static bool infoPointToMapCoordinates( int i, int j, QgsPoint* infoPoint, QgsMapRenderer* mapRenderer );
144138
/**Appends feature info xml for the layer to the layer element of the feature info dom document
145139
@param featureBBox the bounding box of the selected features in output CRS
146140
@return 0 in case of success*/
@@ -257,6 +251,9 @@ class QgsWMSServer: public QgsOWSServer
257251

258252
/** Return precision to use for GetFeatureInfo request */
259253
int getWMSPrecision( int defaultValue ) const;
254+
255+
/**Gets layer search rectangle (depending on request parameter, layer type, map and layer crs)*/
256+
QgsRectangle featureInfoSearchRect( QgsVectorLayer* ml, QgsMapRenderer* mr, const QgsRenderContext& rct, const QgsPoint& infoPoint ) const;
260257
};
261258

262259
#endif

0 commit comments

Comments
 (0)