Skip to content

Commit

Permalink
[FEATURE]: possibility to set WMS featureInfo tolerance in request. F…
Browse files Browse the repository at this point in the history
…unded by city of Uster
  • Loading branch information
mhugent committed Feb 23, 2015
1 parent 2481ce6 commit 2d0f08b
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 59 deletions.
124 changes: 72 additions & 52 deletions src/server/qgswmsserver.cpp
Expand Up @@ -1403,6 +1403,7 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )

QgsRectangle* featuresRect = 0;
QgsPoint* infoPoint = 0;

if ( i == -1 || j == -1 )
{
if ( mParameters.contains( "FILTER" ) )
Expand All @@ -1416,7 +1417,11 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )
}
else
{
infoPoint = new QgsPoint();
infoPoint = new QgsPoint();
if( !infoPointToMapCoordinates( i, j, infoPoint, mMapRenderer ) )
{
return 5;
}
}

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

if ( infoPoint && infoPointToLayerCoordinates( i, j, infoPoint, mMapRenderer, currentLayer ) != 0 )
{
continue;
}

//switch depending on vector or raster
QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( currentLayer );

Expand Down Expand Up @@ -1552,7 +1552,12 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )
QgsRasterLayer* rasterLayer = dynamic_cast<QgsRasterLayer*>( currentLayer );
if ( rasterLayer )
{
if ( featureInfoFromRasterLayer( rasterLayer, infoPoint, result, layerElement, version, infoFormat ) != 0 )
if( !infoPoint )
{
continue;
}
QgsPoint layerInfoPoint = mMapRenderer->mapToLayerCoordinates( currentLayer, *infoPoint );
if ( featureInfoFromRasterLayer( rasterLayer, &layerInfoPoint, result, layerElement, version, infoFormat ) != 0 )
{
continue;
}
Expand Down Expand Up @@ -1609,7 +1614,6 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result, QString version )
restoreLayerFilters( originalLayerFilters );
QgsMapLayerRegistry::instance()->removeAllMapLayers();
delete featuresRect;
delete infoPoint;
return 0;
}

Expand Down Expand Up @@ -1916,38 +1920,18 @@ int QgsWMSServer::initializeSLDParser( QStringList& layersList, QStringList& sty
return 0;
}

int QgsWMSServer::infoPointToLayerCoordinates( int i, int j, QgsPoint* layerCoords, QgsMapRenderer* mapRender,
QgsMapLayer* layer ) const
bool QgsWMSServer::infoPointToMapCoordinates( int i, int j, QgsPoint* infoPoint, QgsMapRenderer* mapRenderer )
{
if ( !layerCoords || !mapRender || !layer || !mapRender->coordinateTransform() )
if ( !mapRenderer || !infoPoint )
{
return 1;
return false;
}

//first transform i,j to map output coordinates
// toMapCoordinates() is currently (Oct 18 2012) using average resolution
// to calc point but GetFeatureInfo request may be sent with different
// resolutions in each axis
//QgsPoint mapPoint = mapRender->coordinateTransform()->toMapCoordinates( i, j );
double xRes = mapRender->extent().width() / mapRender->width();
double yRes = mapRender->extent().height() / mapRender->height();
QgsPoint mapPoint( mapRender->extent().xMinimum() + i * xRes,
mapRender->extent().yMaximum() - j * yRes );

QgsDebugMsg( QString( "mapPoint (corner): %1 %2" ).arg( mapPoint.x() ).arg( mapPoint.y() ) );
// use pixel center instead of corner
// Unfortunately going through pixel (integer) we cannot reconstruct precisely
// the coordinate clicked on client and thus result may differ from
// the same raster loaded and queried locally on client
mapPoint.setX( mapPoint.x() + xRes / 2 );
mapPoint.setY( mapPoint.y() - yRes / 2 );

QgsDebugMsg( QString( "mapPoint (pixel center): %1 %2" ).arg( mapPoint.x() ).arg( mapPoint.y() ) );

//and then to layer coordinates
*layerCoords = mapRender->mapToLayerCoordinates( layer, mapPoint );
QgsDebugMsg( QString( "mapPoint: %1 %2" ).arg( mapPoint.x() ).arg( mapPoint.y() ) );
return 0;
double xRes = mapRenderer->extent().width() / mapRenderer->width();
double yRes = mapRenderer->extent().height() / mapRenderer->height();
infoPoint->setX( mapRenderer->extent().xMinimum() + i * xRes + xRes / 2.0 );
infoPoint->setY( mapRenderer->extent().yMaximum() - j * yRes - yRes / 2.0 );
return true;
}

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


QgsRectangle searchRect;

//info point could be 0 in case there is only an attribute filter
if ( infoPoint )
{
double searchRadius = 0;
if ( layer->geometryType() == QGis::Polygon )
{
searchRadius = layerRect.width() / 400;
}
else if ( layer->geometryType() == QGis::Line )
{
searchRadius = layerRect.width() / 200;
}
else
{
searchRadius = layerRect.width() / 100;
}

searchRect.set( infoPoint->x() - searchRadius, infoPoint->y() - searchRadius,
infoPoint->x() + searchRadius, infoPoint->y() + searchRadius );
searchRect = featureInfoSearchRect( layer, mapRender, renderContext, *infoPoint );
}
else if ( mParameters.contains( "BBOX" ) )
{
Expand Down Expand Up @@ -3112,3 +3082,53 @@ int QgsWMSServer::getWMSPrecision( int defaultValue = 8 ) const
}
return WMSPrecision;
}

QgsRectangle QgsWMSServer::featureInfoSearchRect( QgsVectorLayer* ml, QgsMapRenderer* mr, const QgsRenderContext& rct, const QgsPoint& infoPoint ) const
{
if ( !ml || !mr )
{
return QgsRectangle();
}

double mapUnitTolerance = 0.0;
if ( ml->geometryType() == QGis::Polygon )
{
QMap<QString, QString>::const_iterator tolIt = mParameters.find( "POLYGON_TOLERANCE" );
if ( tolIt != mParameters.constEnd() )
{
mapUnitTolerance = tolIt.value().toInt() * rct.mapToPixel().mapUnitsPerPixel();
}
else
{
mapUnitTolerance = mr->extent().width() / 400.0;
}
}
else if ( ml->geometryType() == QGis::Line )
{
QMap<QString, QString>::const_iterator tolIt = mParameters.find( "LINE_TOLERANCE" );
if ( tolIt != mParameters.constEnd() )
{
mapUnitTolerance = tolIt.value().toInt() * rct.mapToPixel().mapUnitsPerPixel();
}
else
{
mapUnitTolerance = mr->extent().width() / 200.0;
}
}
else //points
{
QMap<QString, QString>::const_iterator tolIt = mParameters.find( "POINT_TOLERANCE" );
if ( tolIt != mParameters.constEnd() )
{
mapUnitTolerance = tolIt.value().toInt() * rct.mapToPixel().mapUnitsPerPixel();
}
else
{
mapUnitTolerance = mr->extent().width() / 100.0;
}
}

QgsRectangle mapRectangle( infoPoint.x() - mapUnitTolerance, infoPoint.y() - mapUnitTolerance,
infoPoint.x() + mapUnitTolerance, infoPoint.y() + mapUnitTolerance );
return( mr->mapToLayerCoordinates( ml, mapRectangle ) );
}
11 changes: 4 additions & 7 deletions src/server/qgswmsserver.h
Expand Up @@ -134,13 +134,7 @@ class QgsWMSServer: public QgsOWSServer
set to the layer and style names according to the SLD
@return 0 in case of success*/
int initializeSLDParser( QStringList& layersList, QStringList& stylesList );
/**Calculates the location of a feature info point in layer coordinates
@param i pixel x-coordinate
@param j pixel y-coordinate
@param layerCoords calculated layer coordinates are assigned to this point
@return 0 in case of success*/
int infoPointToLayerCoordinates( int i, int j, QgsPoint* layerCoords, QgsMapRenderer* mapRender,
QgsMapLayer* layer ) const;
static bool infoPointToMapCoordinates( int i, int j, QgsPoint* infoPoint, QgsMapRenderer* mapRenderer );
/**Appends feature info xml for the layer to the layer element of the feature info dom document
@param featureBBox the bounding box of the selected features in output CRS
@return 0 in case of success*/
Expand Down Expand Up @@ -257,6 +251,9 @@ class QgsWMSServer: public QgsOWSServer

/** Return precision to use for GetFeatureInfo request */
int getWMSPrecision( int defaultValue ) const;

/**Gets layer search rectangle (depending on request parameter, layer type, map and layer crs)*/
QgsRectangle featureInfoSearchRect( QgsVectorLayer* ml, QgsMapRenderer* mr, const QgsRenderContext& rct, const QgsPoint& infoPoint ) const;
};

#endif

0 comments on commit 2d0f08b

Please sign in to comment.