mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-25 00:58:06 -05:00
Add feature bounding box if called with filter and without I/J
This commit is contained in:
parent
57c4ee746f
commit
f32cd2161e
@ -121,21 +121,21 @@ QDomDocument QgsWMSServer::getCapabilities()
|
||||
|
||||
QList<QPair<QString, QString> > queryItems = mapUrl.queryItems();
|
||||
QList<QPair<QString, QString> >::const_iterator queryIt = queryItems.constBegin();
|
||||
for(; queryIt != queryItems.constEnd(); ++queryIt )
|
||||
for ( ; queryIt != queryItems.constEnd(); ++queryIt )
|
||||
{
|
||||
if( queryIt->first.compare("REQUEST", Qt::CaseInsensitive ) == 0 )
|
||||
if ( queryIt->first.compare( "REQUEST", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
mapUrl.removeQueryItem( queryIt->first );
|
||||
}
|
||||
else if( queryIt->first.compare("VERSION", Qt::CaseInsensitive ) == 0 )
|
||||
else if ( queryIt->first.compare( "VERSION", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
mapUrl.removeQueryItem( queryIt->first );
|
||||
}
|
||||
else if( queryIt->first.compare("SERVICE", Qt::CaseInsensitive ) == 0 )
|
||||
else if ( queryIt->first.compare( "SERVICE", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
mapUrl.removeQueryItem( queryIt->first );
|
||||
}
|
||||
else if( queryIt->first.compare("_DC", Qt::CaseInsensitive ) == 0 )
|
||||
else if ( queryIt->first.compare( "_DC", Qt::CaseInsensitive ) == 0 )
|
||||
{
|
||||
mapUrl.removeQueryItem( queryIt->first );
|
||||
}
|
||||
@ -636,11 +636,10 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result )
|
||||
if ( i_it == mParameterMap.end() )
|
||||
{
|
||||
std::map<QString, QString>::const_iterator x_it = mParameterMap.find( "X" );
|
||||
if ( x_it == mParameterMap.end() )
|
||||
if ( x_it != mParameterMap.end() )
|
||||
{
|
||||
return 5;
|
||||
iString = x_it->second;
|
||||
}
|
||||
iString = x_it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -649,18 +648,17 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result )
|
||||
i = iString.toInt( &conversionSuccess );
|
||||
if ( !conversionSuccess )
|
||||
{
|
||||
return 6;
|
||||
i = -1;
|
||||
}
|
||||
|
||||
std::map<QString, QString>::const_iterator j_it = mParameterMap.find( "J" );
|
||||
if ( j_it == mParameterMap.end() )
|
||||
{
|
||||
std::map<QString, QString>::const_iterator y_it = mParameterMap.find( "Y" );
|
||||
if ( y_it == mParameterMap.end() )
|
||||
if ( y_it != mParameterMap.end() )
|
||||
{
|
||||
return 7;
|
||||
jString = y_it->second;
|
||||
}
|
||||
jString = y_it->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -669,9 +667,34 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result )
|
||||
j = jString.toInt( &conversionSuccess );
|
||||
if ( !conversionSuccess )
|
||||
{
|
||||
return 8;
|
||||
j = -1;
|
||||
}
|
||||
|
||||
//Normally, I/J or X/Y are mandatory parameters.
|
||||
//However, in order to make attribute only queries via the FILTER parameter, it is allowed to skip them if the FILTER parameter is there
|
||||
|
||||
QgsRectangle* featuresRect = 0;
|
||||
QgsPoint* infoPoint = 0;
|
||||
if ( i == -1 || j == -1 )
|
||||
{
|
||||
if ( mParameterMap.find( "FILTER" ) != mParameterMap.end() )
|
||||
{
|
||||
featuresRect = new QgsRectangle();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw QgsMapServiceException( "ParameterMissing", "I/J parameters are required for GetFeatureInfo" );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
infoPoint = new QgsPoint();
|
||||
}
|
||||
|
||||
//get the layer registered in QgsMapLayerRegistry and apply possible filters
|
||||
QStringList layerIds = layerSet( layersList, stylesList, mMapRenderer->destinationCrs() );
|
||||
QMap<QString, QString> originalLayerFilters = applyRequestedLayerFilters( layersList, layerIds );
|
||||
|
||||
QDomElement getFeatureInfoElement = result.createElement( "GetFeatureInfoResponse" );
|
||||
result.appendChild( getFeatureInfoElement );
|
||||
|
||||
@ -681,72 +704,86 @@ int QgsWMSServer::getFeatureInfo( QDomDocument& result )
|
||||
|
||||
QList<QgsMapLayer*> layerList;
|
||||
QgsMapLayer* currentLayer = 0;
|
||||
QgsPoint infoPoint; //info point in coordinates of the layer
|
||||
QStringList::const_iterator layerIt;
|
||||
for ( layerIt = queryLayerList.constBegin(); layerIt != queryLayerList.constEnd(); ++layerIt )
|
||||
{
|
||||
//create maplayers from sld parser (several layers are possible in case of feature info on a group)
|
||||
layerList = mConfigParser->mapLayerFromStyle( *layerIt, "" );
|
||||
QList<QgsMapLayer*>::iterator layerListIt = layerList.begin();
|
||||
for(; layerListIt != layerList.end(); ++layerListIt )
|
||||
for ( ; layerListIt != layerList.end(); ++layerListIt )
|
||||
{
|
||||
currentLayer = *layerListIt;
|
||||
if ( !currentLayer || nonIdentifiableLayers.contains( currentLayer->id() ) )
|
||||
{
|
||||
currentLayer = *layerListIt;
|
||||
if ( !currentLayer || nonIdentifiableLayers.contains( currentLayer->id() ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if ( infoPointToLayerCoordinates( i, j, infoPoint, mMapRenderer, currentLayer ) != 0 )
|
||||
{
|
||||
}
|
||||
|
||||
if ( infoPoint && infoPointToLayerCoordinates( i, j, infoPoint, mMapRenderer, currentLayer ) != 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
QgsDebugMsg( "Info point in layer crs: " + QString::number( infoPoint.x() ) + "//" + QString::number( infoPoint.y() ) );
|
||||
}
|
||||
|
||||
QDomElement layerElement = result.createElement( "Layer" );
|
||||
layerElement.setAttribute( "name", currentLayer->name() );
|
||||
getFeatureInfoElement.appendChild( layerElement );
|
||||
QDomElement layerElement = result.createElement( "Layer" );
|
||||
layerElement.setAttribute( "name", currentLayer->name() );
|
||||
getFeatureInfoElement.appendChild( layerElement );
|
||||
|
||||
//switch depending on vector or raster
|
||||
QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
|
||||
if ( vectorLayer )
|
||||
//switch depending on vector or raster
|
||||
QgsVectorLayer* vectorLayer = dynamic_cast<QgsVectorLayer*>( currentLayer );
|
||||
if ( vectorLayer )
|
||||
{
|
||||
//is there alias info for this vector layer?
|
||||
QMap< int, QString > layerAliasInfo;
|
||||
QMap< QString, QMap< int, QString > >::const_iterator aliasIt = aliasInfo.find( currentLayer->id() );
|
||||
if ( aliasIt != aliasInfo.constEnd() )
|
||||
{
|
||||
//is there alias info for this vector layer?
|
||||
QMap< int, QString > layerAliasInfo;
|
||||
QMap< QString, QMap< int, QString > >::const_iterator aliasIt = aliasInfo.find( currentLayer->id() );
|
||||
if ( aliasIt != aliasInfo.constEnd() )
|
||||
{
|
||||
layerAliasInfo = aliasIt.value();
|
||||
}
|
||||
|
||||
//hidden attributes for this layer
|
||||
QSet<QString> layerHiddenAttributes;
|
||||
QMap< QString, QSet<QString> >::const_iterator hiddenIt = hiddenAttributes.find( currentLayer->id() );
|
||||
if ( hiddenIt != hiddenAttributes.constEnd() )
|
||||
{
|
||||
layerHiddenAttributes = hiddenIt.value();
|
||||
}
|
||||
|
||||
if ( featureInfoFromVectorLayer( vectorLayer, infoPoint, featureCount, result, layerElement, mMapRenderer, layerAliasInfo, layerHiddenAttributes ) != 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
layerAliasInfo = aliasIt.value();
|
||||
}
|
||||
else //raster layer
|
||||
|
||||
//hidden attributes for this layer
|
||||
QSet<QString> layerHiddenAttributes;
|
||||
QMap< QString, QSet<QString> >::const_iterator hiddenIt = hiddenAttributes.find( currentLayer->id() );
|
||||
if ( hiddenIt != hiddenAttributes.constEnd() )
|
||||
{
|
||||
QgsRasterLayer* rasterLayer = dynamic_cast<QgsRasterLayer*>( currentLayer );
|
||||
if ( rasterLayer )
|
||||
{
|
||||
if ( featureInfoFromRasterLayer( rasterLayer, infoPoint, result, layerElement ) != 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
layerHiddenAttributes = hiddenIt.value();
|
||||
}
|
||||
|
||||
if ( featureInfoFromVectorLayer( vectorLayer, infoPoint, featureCount, result, layerElement, mMapRenderer, layerAliasInfo, layerHiddenAttributes, featuresRect ) != 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else //raster layer
|
||||
{
|
||||
QgsRasterLayer* rasterLayer = dynamic_cast<QgsRasterLayer*>( currentLayer );
|
||||
if ( rasterLayer )
|
||||
{
|
||||
if ( featureInfoFromRasterLayer( rasterLayer, infoPoint, result, layerElement ) != 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( featuresRect )
|
||||
{
|
||||
QDomElement bBoxElem = result.createElement( "BoundingBox" );
|
||||
bBoxElem.setAttribute( "CRS", mMapRenderer->destinationCrs().authid() );
|
||||
bBoxElem.setAttribute( "minx", featuresRect->xMinimum() );
|
||||
bBoxElem.setAttribute( "maxx", featuresRect->xMaximum() );
|
||||
bBoxElem.setAttribute( "miny", featuresRect->yMinimum() );
|
||||
bBoxElem.setAttribute( "maxy", featuresRect->yMaximum() );
|
||||
getFeatureInfoElement.insertBefore( bBoxElem, QDomNode() ); //insert as first child
|
||||
}
|
||||
|
||||
restoreLayerFilters( originalLayerFilters );
|
||||
delete featuresRect;
|
||||
delete infoPoint;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1101,10 +1138,10 @@ int QgsWMSServer::initializeSLDParser( QStringList& layersList, QStringList& sty
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QgsWMSServer::infoPointToLayerCoordinates( int i, int j, QgsPoint& layerCoords, QgsMapRenderer* mapRender,
|
||||
int QgsWMSServer::infoPointToLayerCoordinates( int i, int j, QgsPoint* layerCoords, QgsMapRenderer* mapRender,
|
||||
QgsMapLayer* layer ) const
|
||||
{
|
||||
if ( !mapRender || !layer || !mapRender->coordinateTransform() )
|
||||
if ( !layerCoords || !mapRender || !layer || !mapRender->coordinateTransform() )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -1112,18 +1149,18 @@ int QgsWMSServer::infoPointToLayerCoordinates( int i, int j, QgsPoint& layerCoor
|
||||
//first transform i,j to map output coordinates
|
||||
QgsPoint mapPoint = mapRender->coordinateTransform()->toMapCoordinates( i, j );
|
||||
//and then to layer coordinates
|
||||
layerCoords = mapRender->mapToLayerCoordinates( layer, mapPoint );
|
||||
*layerCoords = mapRender->mapToLayerCoordinates( layer, mapPoint );
|
||||
return 0;
|
||||
}
|
||||
|
||||
int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
|
||||
const QgsPoint& infoPoint,
|
||||
const QgsPoint* infoPoint,
|
||||
int nFeatures,
|
||||
QDomDocument& infoDocument,
|
||||
QDomElement& layerElement,
|
||||
QgsMapRenderer* mapRender,
|
||||
QMap<int, QString>& aliasMap,
|
||||
QSet<QString>& hiddenAttributes ) const
|
||||
QSet<QString>& hiddenAttributes, QgsRectangle* featureBBox ) const
|
||||
{
|
||||
if ( !layer || !mapRender )
|
||||
{
|
||||
@ -1133,9 +1170,16 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
|
||||
//we need a selection rect (0.01 of map width)
|
||||
QgsRectangle mapRect = mapRender->extent();
|
||||
QgsRectangle layerRect = mapRender->mapToLayerCoordinates( layer, mapRect );
|
||||
double searchRadius = ( layerRect.xMaximum() - layerRect.xMinimum() ) / 200;
|
||||
QgsRectangle searchRect( infoPoint.x() - searchRadius, infoPoint.y() - searchRadius,
|
||||
infoPoint.x() + searchRadius, infoPoint.y() + searchRadius );
|
||||
|
||||
QgsRectangle searchRect;
|
||||
|
||||
//info point could be 0 in case there is only an attribute filter
|
||||
if ( infoPoint )
|
||||
{
|
||||
double searchRadius = ( layerRect.xMaximum() - layerRect.xMinimum() ) / 200;
|
||||
searchRect.set( infoPoint->x() - searchRadius, infoPoint->y() - searchRadius,
|
||||
infoPoint->x() + searchRadius, infoPoint->y() + searchRadius );
|
||||
}
|
||||
|
||||
//do a select with searchRect and go through all the features
|
||||
QgsVectorDataProvider* provider = layer->dataProvider();
|
||||
@ -1150,7 +1194,7 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
|
||||
const QgsFieldMap& fields = provider->fields();
|
||||
bool addWktGeometry = mConfigParser && mConfigParser->featureInfoWithWktGeometry();
|
||||
|
||||
provider->select( provider->attributeIndexes(), searchRect, addWktGeometry, true );
|
||||
provider->select( provider->attributeIndexes(), searchRect, addWktGeometry || featureBBox, true );
|
||||
while ( provider->nextFeature( feature ) )
|
||||
{
|
||||
if ( featureCounter > nFeatures )
|
||||
@ -1188,16 +1232,25 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
|
||||
}
|
||||
|
||||
//also append the wkt geometry as an attribute
|
||||
if ( addWktGeometry )
|
||||
QgsGeometry* geom = feature.geometry();
|
||||
if ( addWktGeometry && geom )
|
||||
{
|
||||
QgsGeometry* geom = feature.geometry();
|
||||
if ( geom )
|
||||
QDomElement geometryElement = infoDocument.createElement( "Attribute" );
|
||||
geometryElement.setAttribute( "name", "geometry" );
|
||||
geometryElement.setAttribute( "value", geom->exportToWkt() );
|
||||
geometryElement.setAttribute( "type", "derived" );
|
||||
featureElement.appendChild( geometryElement );
|
||||
}
|
||||
if ( featureBBox && geom && mapRender ) //extend feature info bounding box if requested
|
||||
{
|
||||
QgsRectangle box = mapRender->layerExtentToOutputExtent( layer, geom->boundingBox() );
|
||||
if ( featureBBox->isEmpty() )
|
||||
{
|
||||
QDomElement geometryElement = infoDocument.createElement( "Attribute" );
|
||||
geometryElement.setAttribute( "name", "geometry" );
|
||||
geometryElement.setAttribute( "value", geom->exportToWkt() );
|
||||
geometryElement.setAttribute( "type", "derived" );
|
||||
featureElement.appendChild( geometryElement );
|
||||
*featureBBox = box;
|
||||
}
|
||||
else
|
||||
{
|
||||
featureBBox->combineExtentWith( &box );
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1207,17 +1260,17 @@ int QgsWMSServer::featureInfoFromVectorLayer( QgsVectorLayer* layer,
|
||||
}
|
||||
|
||||
int QgsWMSServer::featureInfoFromRasterLayer( QgsRasterLayer* layer,
|
||||
const QgsPoint& infoPoint,
|
||||
const QgsPoint* infoPoint,
|
||||
QDomDocument& infoDocument,
|
||||
QDomElement& layerElement ) const
|
||||
{
|
||||
if ( !layer )
|
||||
if ( !infoPoint || !layer )
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
QMap<QString, QString> attributes;
|
||||
layer->identify( infoPoint, attributes );
|
||||
layer->identify( *infoPoint, attributes );
|
||||
|
||||
for ( QMap<QString, QString>::const_iterator it = attributes.constBegin(); it != attributes.constEnd(); ++it )
|
||||
{
|
||||
|
@ -27,11 +27,12 @@ class QgsCoordinateReferenceSystem;
|
||||
class QgsComposerLayerItem;
|
||||
class QgsComposerLegendItem;
|
||||
class QgsComposition;
|
||||
class QgsConfigParser;
|
||||
class QgsMapLayer;
|
||||
class QgsMapRenderer;
|
||||
class QgsPoint;
|
||||
class QgsRasterLayer;
|
||||
class QgsConfigParser;
|
||||
class QgsRectangle;
|
||||
class QgsVectorLayer;
|
||||
class QgsSymbol;
|
||||
class QFile;
|
||||
@ -106,14 +107,15 @@ class QgsWMSServer
|
||||
@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,
|
||||
int infoPointToLayerCoordinates( int i, int j, QgsPoint* layerCoords, QgsMapRenderer* mapRender,
|
||||
QgsMapLayer* layer ) const;
|
||||
/**Appends feature info xml for the layer to the layer element of the feature info dom document
|
||||
@return 0 in case of success*/
|
||||
int featureInfoFromVectorLayer( QgsVectorLayer* layer, const QgsPoint& infoPoint, int nFeatures, QDomDocument& infoDocument, QDomElement& layerElement, QgsMapRenderer* mapRender,
|
||||
QMap<int, QString>& aliasMap, QSet<QString>& hiddenAttributes ) const;
|
||||
@param featureBBox the bounding box of the selected features in output CRS
|
||||
@return 0 in case of success*/
|
||||
int featureInfoFromVectorLayer( QgsVectorLayer* layer, const QgsPoint* infoPoint, int nFeatures, QDomDocument& infoDocument, QDomElement& layerElement, QgsMapRenderer* mapRender,
|
||||
QMap<int, QString>& aliasMap, QSet<QString>& hiddenAttributes, QgsRectangle* featureBBox = 0 ) const;
|
||||
/**Appends feature info xml for the layer to the layer element of the dom document*/
|
||||
int featureInfoFromRasterLayer( QgsRasterLayer* layer, const QgsPoint& infoPoint, QDomDocument& infoDocument, QDomElement& layerElement ) const;
|
||||
int featureInfoFromRasterLayer( QgsRasterLayer* layer, const QgsPoint* infoPoint, QDomDocument& infoDocument, QDomElement& layerElement ) const;
|
||||
|
||||
/**Creates a layer set and returns a stringlist with layer ids that can be passed to a QgsMapRenderer. Usually used in conjunction with readLayersAndStyles*/
|
||||
QStringList layerSet( const QStringList& layersList, const QStringList& stylesList, const QgsCoordinateReferenceSystem& destCRS ) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user