1616#include < QtTest/QtTest>
1717#include " qgsapplication.h"
1818#include " qgsvectorlayer.h"
19+ #include " qgsrasterlayer.h"
1920#include " qgsfeature.h"
2021#include " qgsgeometry.h"
2122#include " qgsvectordataprovider.h"
2425#include " qgsunittypes.h"
2526#include " qgsmaptoolidentifyaction.h"
2627
28+ #include " cpl_conv.h"
29+
2730class TestQgsMapToolIdentifyAction : public QObject
2831{
2932 Q_OBJECT
@@ -40,9 +43,38 @@ class TestQgsMapToolIdentifyAction : public QObject
4043 void lengthCalculation (); // test calculation of derived length attributes
4144 void perimeterCalculation (); // test calculation of derived perimeter attribute
4245 void areaCalculation (); // test calculation of derived area attribute
46+ void identifyRasterFloat32 (); // test pixel identification and decimal precision
47+ void identifyRasterFloat64 (); // test pixel identification and decimal precision
48+ void identifyInvalidPolygons (); // test selecting invalid polygons
4349
4450 private:
4551 QgsMapCanvas* canvas;
52+
53+ QString testIdentifyRaster ( QgsRasterLayer* layer, double xGeoref, double yGeoref );
54+ QList<QgsMapToolIdentify::IdentifyResult> testIdentifyVector ( QgsVectorLayer* layer, double xGeoref, double yGeoref );
55+
56+ // Release return with delete []
57+ unsigned char *
58+ hex2bytes ( const char *hex, int *size )
59+ {
60+ QByteArray ba = QByteArray::fromHex ( hex );
61+ unsigned char *out = new unsigned char [ba.size ()];
62+ memcpy ( out, ba.data (), ba.size () );
63+ *size = ba.size ();
64+ return out;
65+ }
66+
67+ // TODO: make this a QgsGeometry member...
68+ QgsGeometry geomFromHexWKB ( const char *hexwkb )
69+ {
70+ int wkbsize;
71+ unsigned char *wkb = hex2bytes ( hexwkb, &wkbsize );
72+ QgsGeometry geom;
73+ // NOTE: QgsGeometry takes ownership of wkb
74+ geom.fromWkb ( wkb, wkbsize );
75+ return geom;
76+ }
77+
4678};
4779
4880void TestQgsMapToolIdentifyAction::initTestCase ()
@@ -241,6 +273,109 @@ void TestQgsMapToolIdentifyAction::areaCalculation()
241273 QVERIFY ( qgsDoubleNear ( area, 389.6117 , 0.001 ) );
242274}
243275
276+ // private
277+ QString TestQgsMapToolIdentifyAction::testIdentifyRaster ( QgsRasterLayer* layer, double xGeoref, double yGeoref )
278+ {
279+ QScopedPointer< QgsMapToolIdentifyAction > action ( new QgsMapToolIdentifyAction ( canvas ) );
280+ QgsPoint mapPoint = canvas->getCoordinateTransform ()->transform ( xGeoref, yGeoref );
281+ QList<QgsMapToolIdentify::IdentifyResult> result = action->identify ( mapPoint.x (), mapPoint.y (), QList<QgsMapLayer*>() << layer );
282+ if ( result.length () != 1 )
283+ return " " ;
284+ return result[0 ].mAttributes [" Band 1" ];
285+ }
286+
287+ // private
288+ QList<QgsMapToolIdentify::IdentifyResult>
289+ TestQgsMapToolIdentifyAction::testIdentifyVector ( QgsVectorLayer* layer, double xGeoref, double yGeoref )
290+ {
291+ QScopedPointer< QgsMapToolIdentifyAction > action ( new QgsMapToolIdentifyAction ( canvas ) );
292+ QgsPoint mapPoint = canvas->getCoordinateTransform ()->transform ( xGeoref, yGeoref );
293+ QList<QgsMapToolIdentify::IdentifyResult> result = action->identify ( mapPoint.x (), mapPoint.y (), QList<QgsMapLayer*>() << layer );
294+ return result;
295+ }
296+
297+ void TestQgsMapToolIdentifyAction::identifyRasterFloat32 ()
298+ {
299+ // create a temporary layer
300+ QString raster = QString ( TEST_DATA_DIR ) + " /raster/test.asc" ;
301+
302+ // By default the QgsRasterLayer forces AAIGRID_DATATYPE=Float64
303+ CPLSetConfigOption ( " AAIGRID_DATATYPE" , " Float32" );
304+ QScopedPointer< QgsRasterLayer> tempLayer ( new QgsRasterLayer ( raster ) );
305+ CPLSetConfigOption ( " AAIGRID_DATATYPE" , nullptr );
306+
307+ QVERIFY ( tempLayer->isValid () );
308+
309+ canvas->setExtent ( QgsRectangle ( 0 , 0 , 7 , 1 ) );
310+
311+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 0.5 , 0.5 ), QString ( " -999.9" ) );
312+
313+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 1.5 , 0.5 ), QString ( " -999.987" ) );
314+
315+ // More than 6 significant digits : precision loss in Float32
316+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 2.5 , 0.5 ), QString ( " 1.2345678" ) ); // in .asc file : 1.2345678
317+
318+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 3.5 , 0.5 ), QString ( " 123456" ) );
319+
320+ // More than 6 significant digits: no precision loss here for that particular value
321+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 4.5 , 0.5 ), QString ( " 1234567" ) );
322+
323+ // More than 6 significant digits: no precision loss here for that particular value
324+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 5.5 , 0.5 ), QString ( " -999.9876" ) );
325+
326+ // More than 6 significant digits: no precision loss here
327+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 6.5 , 0.5 ), QString ( " 1.2345678901234" ) ); // in .asc file : 1.2345678901234
328+ }
329+
330+ void TestQgsMapToolIdentifyAction::identifyRasterFloat64 ()
331+ {
332+ // create a temporary layer
333+ QString raster = QString ( TEST_DATA_DIR ) + " /raster/test.asc" ;
334+ QScopedPointer< QgsRasterLayer> tempLayer ( new QgsRasterLayer ( raster ) );
335+ QVERIFY ( tempLayer->isValid () );
336+
337+ canvas->setExtent ( QgsRectangle ( 0 , 0 , 7 , 1 ) );
338+
339+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 0.5 , 0.5 ), QString ( " -999.9" ) );
340+
341+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 1.5 , 0.5 ), QString ( " -999.987" ) );
342+
343+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 2.5 , 0.5 ), QString ( " 1.2345678" ) );
344+
345+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 3.5 , 0.5 ), QString ( " 123456" ) );
346+
347+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 4.5 , 0.5 ), QString ( " 1234567" ) );
348+
349+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 5.5 , 0.5 ), QString ( " -999.9876" ) );
350+
351+ QCOMPARE ( testIdentifyRaster ( tempLayer.data (), 6.5 , 0.5 ), QString ( " 1.2345678901234" ) );
352+ }
353+
354+ void TestQgsMapToolIdentifyAction::identifyInvalidPolygons ()
355+ {
356+ // create a temporary layer
357+ QScopedPointer< QgsVectorLayer > memoryLayer ( new QgsVectorLayer ( " Polygon?field=pk:int" , " vl" , " memory" ) );
358+ QVERIFY ( memoryLayer->isValid () );
359+ QgsFeature f1 ( memoryLayer->dataProvider ()->fields (), 1 );
360+ f1.setAttribute ( " pk" , 1 );
361+ f1.setGeometry ( geomFromHexWKB (
362+ " 010300000001000000030000000000000000000000000000000000000000000000000024400000000000000000000000000000244000000000000024400000000000000000"
363+ ) );
364+ // TODO: check why we need the ->dataProvider() part, since
365+ // there's a QgsVectorLayer::addFeatures method too
366+ // memoryLayer->addFeatures( QgsFeatureList() << f1 );
367+ memoryLayer->dataProvider ()->addFeatures ( QgsFeatureList () << f1 );
368+
369+ canvas->setExtent ( QgsRectangle ( 0 , 0 , 10 , 10 ) );
370+ QList<QgsMapToolIdentify::IdentifyResult> identified;
371+ identified = testIdentifyVector ( memoryLayer.data (), 4 , 6 );
372+ QCOMPARE ( identified.length (), 0 );
373+ identified = testIdentifyVector ( memoryLayer.data (), 6 , 4 );
374+ QCOMPARE ( identified.length (), 1 );
375+ QCOMPARE ( identified[0 ].mFeature .attribute ( " pk" ), QVariant ( 1 ) );
376+
377+ }
378+
244379
245380QTEST_MAIN ( TestQgsMapToolIdentifyAction )
246381#include " testqgsmaptoolidentifyaction.moc"
0 commit comments