fix identify for mesh layers (#9047)

This commit is contained in:
Peter Petrik 2019-02-01 15:18:26 +01:00 committed by GitHub
parent 4495699bfe
commit 3103b00f00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 285 additions and 26 deletions

View File

@ -39,6 +39,7 @@ after selecting a point, performs the identification:
{
VectorLayer,
RasterLayer,
MeshLayer,
AllLayers
};
typedef QFlags<QgsMapToolIdentify::Type> LayerType;
@ -103,9 +104,9 @@ this has been made private and two publics methods are offered
:param x: x coordinates of mouseEvent
:param y: y coordinates of mouseEvent
:param mode: Identification mode. Can use Qgis default settings or a defined mode.
:param layerType: Only performs identification in a certain type of layers (raster, vector). Default value is AllLayers.
:param layerType: Only performs identification in a certain type of layers (raster, vector, mesh). Default value is AllLayers.
:return: a list of IdentifyResult*
:return: a list of IdentifyResult
%End
QList<QgsMapToolIdentify::IdentifyResult> identify( const QgsGeometry &geometry, IdentifyMode mode, LayerType layerType );
@ -144,9 +145,9 @@ this has been made private and two publics methods are offered
:param y: y coordinates of mouseEvent
:param mode: Identification mode. Can use Qgis default settings or a defined mode.
:param layerList: Performs the identification within the given list of layers.
:param layerType: Only performs identification in a certain type of layers (raster, vector).
:param layerType: Only performs identification in a certain type of layers (raster, vector, mesh).
:return: a list of IdentifyResult*
:return: a list of IdentifyResult
%End
@ -158,6 +159,15 @@ Call the right method depending on layer type
bool identifyRasterLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsRasterLayer *layer, QgsPointXY point, const QgsRectangle &viewExtent, double mapUnitsPerPixel );
bool identifyVectorLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsVectorLayer *layer, const QgsPointXY &point );
bool identifyMeshLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsMeshLayer *layer, const QgsPointXY &point );
%Docstring
Identifies data from active scalar and vector dataset from the mesh layer
Works only if layer was already rendered (triangular mesh is created)
.. versionadded:: 3.6
%End
QMap< QString, QString > derivedAttributesForPoint( const QgsPoint &point );
%Docstring
Returns derived attributes map for a clicked point in map coordinates. May be 2D or 3D point.

View File

@ -33,6 +33,7 @@
#include "qgsmapcanvas.h"
#include "qgsmaplayeractionregistry.h"
#include "qgsmaplayer.h"
#include "qgsmeshlayer.h"
#include "qgsnetworkaccessmanager.h"
#include "qgsproject.h"
#include "qgsrasterdataprovider.h"
@ -476,6 +477,9 @@ void QgsIdentifyResultsDialog::addFeature( const QgsMapToolIdentify::IdentifyRes
break;
case QgsMapLayer::MeshLayer:
addFeature( qobject_cast<QgsMeshLayer *>( result.mLayer ), result.mLabel, result.mAttributes, result.mDerivedAttributes );
break;
case QgsMapLayer::PluginLayer:
break;
}
@ -923,6 +927,49 @@ void QgsIdentifyResultsDialog::addFeature( QgsRasterLayer *layer,
}
}
void QgsIdentifyResultsDialog::addFeature( QgsMeshLayer *layer,
const QString &label,
const QMap< QString, QString > &attributes,
const QMap< QString, QString > &derivedAttributes )
{
QTreeWidgetItem *layItem = layerItem( layer );
if ( !layItem )
{
layItem = new QTreeWidgetItem( QStringList() << QString::number( lstResults->topLevelItemCount() ) << layer->name() );
layItem->setData( 0, Qt::UserRole, QVariant::fromValue( qobject_cast<QObject *>( layer ) ) );
lstResults->addTopLevelItem( layItem );
connect( layer, &QObject::destroyed, this, &QgsIdentifyResultsDialog::layerDestroyed );
connect( layer, &QgsMapLayer::crsChanged, this, &QgsIdentifyResultsDialog::layerDestroyed );
}
QgsIdentifyResultsFeatureItem *featItem = new QgsIdentifyResultsFeatureItem( QgsFields(),
QgsFeature(),
layer->crs(),
QStringList() << label << QString() );
layItem->addChild( featItem );
// attributes
for ( QMap<QString, QString>::const_iterator it = attributes.begin(); it != attributes.end(); ++it )
{
featItem->addChild( new QTreeWidgetItem( QStringList() << it.key() << it.value() ) );
}
if ( derivedAttributes.size() >= 0 )
{
QgsTreeWidgetItem *derivedItem = new QgsTreeWidgetItem( QStringList() << tr( "(Derived)" ) );
derivedItem->setData( 0, Qt::UserRole, "derived" );
derivedItem->setAlwaysOnTopPriority( 0 );
featItem->addChild( derivedItem );
for ( QMap< QString, QString>::const_iterator it = derivedAttributes.begin(); it != derivedAttributes.end(); ++it )
{
derivedItem->addChild( new QTreeWidgetItem( QStringList() << it.key() << it.value() ) );
}
}
}
void QgsIdentifyResultsDialog::editingToggled()
{
QTreeWidgetItem *layItem = layerItem( sender() );
@ -1397,6 +1444,14 @@ QgsRasterLayer *QgsIdentifyResultsDialog::rasterLayer( QTreeWidgetItem *item )
return qobject_cast<QgsRasterLayer *>( item->data( 0, Qt::UserRole ).value<QObject *>() );
}
QgsMeshLayer *QgsIdentifyResultsDialog::meshLayer( QTreeWidgetItem *item )
{
item = layerItem( item );
if ( !item )
return nullptr;
return qobject_cast<QgsMeshLayer *>( item->data( 0, Qt::UserRole ).value<QObject *>() );
}
QTreeWidgetItem *QgsIdentifyResultsDialog::retrieveAttributes( QTreeWidgetItem *item, QgsAttributeMap &attributes, int &idx )
{
QTreeWidgetItem *featItem = featureItem( item );

View File

@ -45,6 +45,7 @@ class QgsVectorLayer;
class QgsRasterLayer;
class QgsHighlight;
class QgsMapCanvas;
class QgsMeshLayer;
class QgsDockWidget;
class QgsMapLayerAction;
class QgsEditorWidgetSetup;
@ -123,18 +124,21 @@ class APP_EXPORT QgsIdentifyResultsDialog: public QDialog, private Ui::QgsIdenti
public:
//! Constructor - takes it own copy of the QgsAttributeAction so
// that it is independent of whoever created it.
/**
* Constructor -
* takes its own copy of the QgsAttributeAction so
* that it is independent of whoever created it.
*/
QgsIdentifyResultsDialog( QgsMapCanvas *canvas, QWidget *parent = nullptr, Qt::WindowFlags f = nullptr );
~QgsIdentifyResultsDialog() override;
//! Add add feature from vector layer
//! Adds feature from vector layer
void addFeature( QgsVectorLayer *layer,
const QgsFeature &f,
const QMap< QString, QString > &derivedAttributes );
//! Add add feature from other layer
//! Adds feature from raster layer
void addFeature( QgsRasterLayer *layer,
const QString &label,
const QMap< QString, QString > &attributes,
@ -143,7 +147,16 @@ class APP_EXPORT QgsIdentifyResultsDialog: public QDialog, private Ui::QgsIdenti
const QgsFeature &feature = QgsFeature(),
const QMap<QString, QVariant> &params = ( QMap<QString, QVariant>() ) );
//! Add feature from identify results
/**
* Adds results from mesh layer
* \since QGIS 3.6
*/
void addFeature( QgsMeshLayer *layer,
const QString &label,
const QMap< QString, QString > &attributes,
const QMap< QString, QString > &derivedAttributes );
//! Adds feature from identify results
void addFeature( const QgsMapToolIdentify::IdentifyResult &result );
//! Map tool was deactivated
@ -261,6 +274,7 @@ class APP_EXPORT QgsIdentifyResultsDialog: public QDialog, private Ui::QgsIdenti
QgsMapLayer *layer( QTreeWidgetItem *item );
QgsVectorLayer *vectorLayer( QTreeWidgetItem *item );
QgsRasterLayer *rasterLayer( QTreeWidgetItem *item );
QgsMeshLayer *meshLayer( QTreeWidgetItem *item );
QTreeWidgetItem *featureItem( QTreeWidgetItem *item );
QTreeWidgetItem *layerItem( QTreeWidgetItem *item );
QTreeWidgetItem *layerItem( QObject *layer );

View File

@ -27,6 +27,7 @@
#include "qgsmaptoolidentify.h"
#include "qgsmaptopixel.h"
#include "qgsmessageviewer.h"
#include "qgsmeshlayer.h"
#include "qgsmaplayer.h"
#include "qgsrasterdataprovider.h"
#include "qgsrasterlayer.h"
@ -214,6 +215,10 @@ bool QgsMapToolIdentify::identifyLayer( QList<IdentifyResult> *results, QgsMapLa
{
return identifyVectorLayer( results, qobject_cast<QgsVectorLayer *>( layer ), geometry );
}
else if ( layer->type() == QgsMapLayer::MeshLayer && layerType.testFlag( MeshLayer ) )
{
return identifyMeshLayer( results, qobject_cast<QgsMeshLayer *>( layer ), geometry );
}
else
{
return false;
@ -225,6 +230,89 @@ bool QgsMapToolIdentify::identifyVectorLayer( QList<QgsMapToolIdentify::Identify
return identifyVectorLayer( results, layer, QgsGeometry::fromPointXY( point ) );
}
bool QgsMapToolIdentify::identifyMeshLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsMeshLayer *layer, const QgsGeometry &geometry )
{
const QgsPointXY point = geometry.asPoint(); // mesh layers currently only support identification by point
return identifyMeshLayer( results, layer, point );
}
bool QgsMapToolIdentify::identifyMeshLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsMeshLayer *layer, const QgsPointXY &point )
{
QgsDebugMsgLevel( "point = " + point.toString(), 4 );
if ( !layer || !layer->dataProvider() )
return false;
const QgsMeshRendererSettings rendererSettings = layer->rendererSettings();
const QgsMeshDatasetIndex scalarDatasetIndex = rendererSettings.activeScalarDataset();
const QgsMeshDatasetIndex vectorDatasetIndex = rendererSettings.activeVectorDataset();
if ( ! scalarDatasetIndex.isValid() && ! vectorDatasetIndex.isValid() )
return false;
QMap< QString, QString > scalarAttributes, vectorAttributes;
QString scalarGroup;
if ( scalarDatasetIndex.isValid() )
{
scalarGroup = layer->dataProvider()->datasetGroupMetadata( scalarDatasetIndex.group() ).name();
const QgsMeshDatasetValue scalarValue = layer->datasetValue( scalarDatasetIndex, point );
const double scalar = scalarValue.scalar();
if ( std::isnan( scalar ) )
scalarAttributes.insert( tr( "Scalar Value" ), tr( "no data" ) );
else
scalarAttributes.insert( tr( "Scalar Value" ), QString::number( scalar ) );
}
QString vectorGroup;
if ( vectorDatasetIndex.isValid() )
{
vectorGroup = layer->dataProvider()->datasetGroupMetadata( vectorDatasetIndex.group() ).name();
const QgsMeshDatasetValue vectorValue = layer->datasetValue( vectorDatasetIndex, point );
const double vectorX = vectorValue.x();
const double vectorY = vectorValue.y();
if ( std::isnan( vectorX ) || std::isnan( vectorY ) )
vectorAttributes.insert( tr( "Vector Value" ), tr( "no data" ) );
else
{
vectorAttributes.insert( tr( "Vector Magnitude" ), QString::number( vectorValue.scalar() ) );
vectorAttributes.insert( tr( "Vector x-component" ), QString::number( vectorY ) );
vectorAttributes.insert( tr( "Vector y-component" ), QString::number( vectorX ) );
}
}
const QMap< QString, QString > derivedAttributes = derivedAttributesForPoint( QgsPoint( point ) );
if ( scalarGroup == vectorGroup )
{
const IdentifyResult result( qobject_cast<QgsMapLayer *>( layer ),
scalarGroup,
vectorAttributes,
derivedAttributes );
results->append( result );
}
else
{
if ( !scalarGroup.isEmpty() )
{
const IdentifyResult result( qobject_cast<QgsMapLayer *>( layer ),
scalarGroup,
scalarAttributes,
derivedAttributes );
results->append( result );
}
if ( !vectorGroup.isEmpty() )
{
const IdentifyResult result( qobject_cast<QgsMapLayer *>( layer ),
vectorGroup,
vectorAttributes,
derivedAttributes );
results->append( result );
}
}
return true;
}
QMap<QString, QString> QgsMapToolIdentify::derivedAttributesForPoint( const QgsPoint &point )
{
QMap< QString, QString > derivedAttributes;

View File

@ -30,6 +30,7 @@ class QgsRasterLayer;
class QgsVectorLayer;
class QgsMapLayer;
class QgsMapCanvas;
class QgsMeshLayer;
class QgsHighlight;
class QgsIdentifyMenu;
class QgsDistanceArea;
@ -63,7 +64,8 @@ class GUI_EXPORT QgsMapToolIdentify : public QgsMapTool
{
VectorLayer = 1,
RasterLayer = 2,
AllLayers = VectorLayer | RasterLayer
MeshLayer = 4, //!< \since QGIS 3.6
AllLayers = VectorLayer | RasterLayer | MeshLayer
};
Q_DECLARE_FLAGS( LayerType, Type )
Q_FLAG( LayerType )
@ -114,13 +116,14 @@ class GUI_EXPORT QgsMapToolIdentify : public QgsMapTool
/**
* Performs the identification.
To avoid being forced to specify IdentifyMode with a list of layers
this has been made private and two publics methods are offered
\param x x coordinates of mouseEvent
\param y y coordinates of mouseEvent
\param mode Identification mode. Can use Qgis default settings or a defined mode.
\param layerType Only performs identification in a certain type of layers (raster, vector). Default value is AllLayers.
\returns a list of IdentifyResult*/
* To avoid being forced to specify IdentifyMode with a list of layers
* this has been made private and two publics methods are offered
* \param x x coordinates of mouseEvent
* \param y y coordinates of mouseEvent
* \param mode Identification mode. Can use Qgis default settings or a defined mode.
* \param layerType Only performs identification in a certain type of layers (raster, vector, mesh). Default value is AllLayers.
* \returns a list of IdentifyResult
*/
QList<QgsMapToolIdentify::IdentifyResult> identify( int x, int y, IdentifyMode mode, LayerType layerType = AllLayers );
//! Performs identification based on a geometry (in map coordinates)
@ -147,14 +150,15 @@ class GUI_EXPORT QgsMapToolIdentify : public QgsMapTool
/**
* Performs the identification.
To avoid being forced to specify IdentifyMode with a list of layers
this has been made private and two publics methods are offered
\param x x coordinates of mouseEvent
\param y y coordinates of mouseEvent
\param mode Identification mode. Can use Qgis default settings or a defined mode.
\param layerList Performs the identification within the given list of layers.
\param layerType Only performs identification in a certain type of layers (raster, vector).
\returns a list of IdentifyResult*/
* To avoid being forced to specify IdentifyMode with a list of layers
* this has been made private and two publics methods are offered
* \param x x coordinates of mouseEvent
* \param y y coordinates of mouseEvent
* \param mode Identification mode. Can use Qgis default settings or a defined mode.
* \param layerList Performs the identification within the given list of layers.
* \param layerType Only performs identification in a certain type of layers (raster, vector, mesh).
* \returns a list of IdentifyResult
*/
QList<QgsMapToolIdentify::IdentifyResult> identify( int x, int y, IdentifyMode mode, const QList<QgsMapLayer *> &layerList, LayerType layerType = AllLayers );
QgsIdentifyMenu *mIdentifyMenu = nullptr;
@ -165,6 +169,14 @@ class GUI_EXPORT QgsMapToolIdentify : public QgsMapTool
bool identifyRasterLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsRasterLayer *layer, QgsPointXY point, const QgsRectangle &viewExtent, double mapUnitsPerPixel );
bool identifyVectorLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsVectorLayer *layer, const QgsPointXY &point );
/**
* Identifies data from active scalar and vector dataset from the mesh layer
*
* Works only if layer was already rendered (triangular mesh is created)
* \since QGIS 3.6
*/
bool identifyMeshLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsMeshLayer *layer, const QgsPointXY &point );
//! Returns derived attributes map for a clicked point in map coordinates. May be 2D or 3D point.
QMap< QString, QString > derivedAttributesForPoint( const QgsPoint &point );
@ -194,6 +206,7 @@ class GUI_EXPORT QgsMapToolIdentify : public QgsMapTool
bool identifyLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsMapLayer *layer, const QgsGeometry &geometry, const QgsRectangle &viewExtent, double mapUnitsPerPixel, QgsMapToolIdentify::LayerType layerType = AllLayers );
bool identifyRasterLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsRasterLayer *layer, const QgsGeometry &geometry, const QgsRectangle &viewExtent, double mapUnitsPerPixel );
bool identifyVectorLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsVectorLayer *layer, const QgsGeometry &geometry );
bool identifyMeshLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsMeshLayer *layer, const QgsGeometry &geometry );
/**
* Desired units for distance display.

View File

@ -23,6 +23,7 @@
#include "qgsvectordataprovider.h"
#include "qgsproject.h"
#include "qgsmapcanvas.h"
#include "qgsmeshlayer.h"
#include "qgsunittypes.h"
#include "qgsmaptoolidentifyaction.h"
#include "qgssettings.h"
@ -54,6 +55,7 @@ class TestQgsMapToolIdentifyAction : public QObject
void areaCalculation(); //test calculation of derived area attribute
void identifyRasterFloat32(); // test pixel identification and decimal precision
void identifyRasterFloat64(); // test pixel identification and decimal precision
void identifyMesh(); // test identification for mesh layer
void identifyInvalidPolygons(); // test selecting invalid polygons
void clickxy(); // test if clicked_x and clicked_y variables are propagated
void closestPoint();
@ -67,6 +69,7 @@ class TestQgsMapToolIdentifyAction : public QObject
QString testIdentifyRaster( QgsRasterLayer *layer, double xGeoref, double yGeoref );
QList<QgsMapToolIdentify::IdentifyResult> testIdentifyVector( QgsVectorLayer *layer, double xGeoref, double yGeoref );
QList<QgsMapToolIdentify::IdentifyResult> testIdentifyMesh( QgsMeshLayer *layer, double xGeoref, double yGeoref );
// Release return with delete []
unsigned char *
@ -89,7 +92,6 @@ class TestQgsMapToolIdentifyAction : public QObject
geom.fromWkb( wkb, wkbsize );
return geom;
}
};
void TestQgsMapToolIdentifyAction::initTestCase()
@ -502,6 +504,15 @@ QString TestQgsMapToolIdentifyAction::testIdentifyRaster( QgsRasterLayer *layer,
return result[0].mAttributes[QStringLiteral( "Band 1" )];
}
// private
QList<QgsMapToolIdentify::IdentifyResult> TestQgsMapToolIdentifyAction::testIdentifyMesh( QgsMeshLayer *layer, double xGeoref, double yGeoref )
{
std::unique_ptr< QgsMapToolIdentifyAction > action( new QgsMapToolIdentifyAction( canvas ) );
QgsPointXY mapPoint = canvas->getCoordinateTransform()->transform( xGeoref, yGeoref );
QList<QgsMapToolIdentify::IdentifyResult> result = action->identify( mapPoint.x(), mapPoint.y(), QList<QgsMapLayer *>() << layer );
return result;
}
// private
QList<QgsMapToolIdentify::IdentifyResult>
TestQgsMapToolIdentifyAction::testIdentifyVector( QgsVectorLayer *layer, double xGeoref, double yGeoref )
@ -571,6 +582,74 @@ void TestQgsMapToolIdentifyAction::identifyRasterFloat64()
QCOMPARE( testIdentifyRaster( tempLayer.get(), 6.5, 0.5 ), QString( "1.2345678901234" ) );
}
void TestQgsMapToolIdentifyAction::identifyMesh()
{
//create a temporary layer
const QString mesh = QStringLiteral( TEST_DATA_DIR ) + "/mesh/quad_and_triangle.2dm";
QgsMeshLayer *tempLayer = new QgsMeshLayer( mesh, "testlayer", "mdal" );
QVERIFY( tempLayer->isValid() );
const QString vectorDs = QStringLiteral( TEST_DATA_DIR ) + "/mesh/quad_and_triangle_vertex_vector.dat";
tempLayer->dataProvider()->addDataset( vectorDs );
// we need to setup renderer otherwise triangular mesh
// will not be populated and identify will not work
QgsMapSettings mapSettings;
mapSettings.setExtent( tempLayer->extent() );
mapSettings.setDestinationCrs( tempLayer->crs() );
mapSettings.setOutputDpi( 96 );
// here we check that datasets automatically get our default color ramp applied ("Plasma")
QgsRenderContext context = QgsRenderContext::fromMapSettings( mapSettings );
tempLayer->createMapRenderer( context );
// only scalar dataset
QgsMeshRendererSettings settings = tempLayer->rendererSettings();
settings.setActiveScalarDataset( QgsMeshDatasetIndex( 0, 0 ) );
tempLayer->setRendererSettings( settings );
QList<QgsMapToolIdentify::IdentifyResult> results;
results = testIdentifyMesh( tempLayer, 500, 500 );
QCOMPARE( results.size(), 1 );
QCOMPARE( results[0].mAttributes[ QStringLiteral( "Scalar Value" )], QStringLiteral( "no data" ) );
results = testIdentifyMesh( tempLayer, 2400, 2400 );
QCOMPARE( results.size(), 1 );
QCOMPARE( results[0].mAttributes[ QStringLiteral( "Scalar Value" )], QStringLiteral( "42" ) );
// scalar + vector same
settings.setActiveScalarDataset( QgsMeshDatasetIndex( 1, 0 ) );
settings.setActiveVectorDataset( QgsMeshDatasetIndex( 1, 0 ) );
tempLayer->setRendererSettings( settings );
results = testIdentifyMesh( tempLayer, 500, 500 );
QCOMPARE( results.size(), 1 );
QCOMPARE( results[0].mAttributes[ QStringLiteral( "Vector Value" )], QStringLiteral( "no data" ) );
results = testIdentifyMesh( tempLayer, 2400, 2400 );
QCOMPARE( results.size(), 1 );
QCOMPARE( results[0].mAttributes[ QStringLiteral( "Vector Magnitude" )], QStringLiteral( "3" ) );
QCOMPARE( results[0].mAttributes[ QStringLiteral( "Vector x-component" )], QStringLiteral( "1.8" ) );
QCOMPARE( results[0].mAttributes[ QStringLiteral( "Vector y-component" )], QStringLiteral( "2.4" ) );
// scalar + vector different
settings.setActiveScalarDataset( QgsMeshDatasetIndex( 0, 0 ) );
settings.setActiveVectorDataset( QgsMeshDatasetIndex( 1, 0 ) );
tempLayer->setRendererSettings( settings );
results = testIdentifyMesh( tempLayer, 2400, 2400 );
QCOMPARE( results.size(), 2 );
QCOMPARE( results[0].mAttributes[ QStringLiteral( "Scalar Value" )], QStringLiteral( "42" ) );
QCOMPARE( results[1].mAttributes[ QStringLiteral( "Vector Magnitude" )], QStringLiteral( "3" ) );
QCOMPARE( results[1].mAttributes[ QStringLiteral( "Vector x-component" )], QStringLiteral( "1.8" ) );
QCOMPARE( results[1].mAttributes[ QStringLiteral( "Vector y-component" )], QStringLiteral( "2.4" ) );
// only vector
settings.setActiveScalarDataset( QgsMeshDatasetIndex() );
settings.setActiveVectorDataset( QgsMeshDatasetIndex( 1, 0 ) );
tempLayer->setRendererSettings( settings );
results = testIdentifyMesh( tempLayer, 2400, 2400 );
QCOMPARE( results.size(), 1 );
QCOMPARE( results[0].mAttributes[ QStringLiteral( "Vector Magnitude" )], QStringLiteral( "3" ) );
QCOMPARE( results[0].mAttributes[ QStringLiteral( "Vector x-component" )], QStringLiteral( "1.8" ) );
QCOMPARE( results[0].mAttributes[ QStringLiteral( "Vector y-component" )], QStringLiteral( "2.4" ) );
}
void TestQgsMapToolIdentifyAction::identifyInvalidPolygons()
{
//create a temporary layer