16
16
#include < QtTest/QtTest>
17
17
#include " qgsapplication.h"
18
18
#include " qgsvectorlayer.h"
19
+ #include " qgsrasterlayer.h"
19
20
#include " qgsfeature.h"
20
21
#include " qgsgeometry.h"
21
22
#include " qgsvectordataprovider.h"
24
25
#include " qgsunittypes.h"
25
26
#include " qgsmaptoolidentifyaction.h"
26
27
28
+ #include " cpl_conv.h"
29
+
27
30
class TestQgsMapToolIdentifyAction : public QObject
28
31
{
29
32
Q_OBJECT
@@ -40,9 +43,38 @@ class TestQgsMapToolIdentifyAction : public QObject
40
43
void lengthCalculation (); // test calculation of derived length attributes
41
44
void perimeterCalculation (); // test calculation of derived perimeter attribute
42
45
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
43
49
44
50
private:
45
51
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
+
46
78
};
47
79
48
80
void TestQgsMapToolIdentifyAction::initTestCase ()
@@ -241,6 +273,109 @@ void TestQgsMapToolIdentifyAction::areaCalculation()
241
273
QVERIFY ( qgsDoubleNear ( area, 389.6117 , 0.001 ) );
242
274
}
243
275
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
+
244
379
245
380
QTEST_MAIN ( TestQgsMapToolIdentifyAction )
246
381
#include " testqgsmaptoolidentifyaction.moc"
0 commit comments