@@ -366,13 +366,15 @@ void QgsWcsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
366
366
{
367
367
QgsDebugMsg ( " Entered" );
368
368
369
- /*
370
- if ( myExpectedSize != myImageSize ) // should not happen
369
+ // Requested extent must at least partialy overlap coverage extent, otherwise
370
+ // server gives error. QGIS usually does not request blocks outside raster extent
371
+ // (higher level checks) but it is better to do check here as well
372
+ if ( !viewExtent.intersects ( mCoverageExtent ) )
371
373
{
372
- QgsMessageLog::logMessage( tr( "unexpected image size" ), tr( "WCS" ) );
374
+ // TODO: set block to null values
375
+ memset ( block, 0 , pixelWidth * pixelHeight * typeSize ( dataType ( bandNo ) ) / 8 );
373
376
return ;
374
377
}
375
- */
376
378
377
379
// abort running (untiled) request
378
380
if ( mCacheReply )
@@ -382,17 +384,15 @@ void QgsWcsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
382
384
mCacheReply = 0 ;
383
385
}
384
386
385
- // Can we reuse the previously cached image ?
386
- if ( mCachedGdalDataset &&
387
- mCachedViewExtent == viewExtent &&
388
- mCachedViewWidth == pixelWidth &&
389
- mCachedViewHeight = = pixelHeight )
387
+ // Can we reuse the previously cached coverage ?
388
+ if ( ! mCachedGdalDataset ||
389
+ mCachedViewExtent != viewExtent ||
390
+ mCachedViewWidth != pixelWidth ||
391
+ mCachedViewHeight ! = pixelHeight )
390
392
{
391
- // return mCachedImage ;
393
+ getCache ( bandNo, viewExtent, pixelWidth, pixelHeight ) ;
392
394
}
393
395
394
- getCache ( bandNo, viewExtent, pixelWidth, pixelHeight );
395
-
396
396
if ( mCachedGdalDataset )
397
397
{
398
398
// TODO band
@@ -408,17 +408,22 @@ void QgsWcsProvider::readBlock( int bandNo, QgsRectangle const & viewExtent, in
408
408
}
409
409
else
410
410
{
411
- QgsDebugMsg ( tr ( " Recieved coverage has wrong size" ) );
411
+ QgsMessageLog::logMessage ( tr ( " Received coverage has wrong size" ), tr ( " WCS " ) );
412
412
return ;
413
413
}
414
414
}
415
415
}
416
416
417
417
void QgsWcsProvider::getCache ( int bandNo, QgsRectangle const & viewExtent, int pixelWidth, int pixelHeight )
418
418
{
419
+ QgsDebugMsg ( " Entered" );
419
420
// delete cached data
420
421
clearCache ();
421
422
423
+ mCachedViewExtent = viewExtent;
424
+ mCachedViewWidth = pixelWidth;
425
+ mCachedViewHeight = pixelHeight;
426
+
422
427
// --------------- BOUNDING BOX --------------------------------
423
428
// according to the WCS spec for 1.1, some CRS have inverted axis
424
429
// box:
@@ -1484,6 +1489,105 @@ QString QgsWcsProvider::metadata()
1484
1489
return metadata;
1485
1490
}
1486
1491
1492
+ bool QgsWcsProvider::identify ( const QgsPoint& thePoint, QMap<QString, QString>& theResults )
1493
+ {
1494
+ QgsDebugMsg ( " Entered" );
1495
+ theResults.clear ();
1496
+
1497
+ if ( !extent ().contains ( thePoint ) )
1498
+ {
1499
+ // Outside the raster
1500
+ for ( int i = 1 ; i <= bandCount (); i++ )
1501
+ {
1502
+ theResults[ generateBandName ( i )] = tr ( " out of extent" );
1503
+ }
1504
+ return true ;
1505
+ }
1506
+
1507
+ // It would be nice to use last cached block if possible, unfortunately we don't know
1508
+ // at which resolution identify() is called. It may happen, that user zoomed in with
1509
+ // layer switched off, canvas resolution increased, but provider cache was not refreshed.
1510
+ // In that case the resolution is too low and identify() could give wron results.
1511
+ // So we have to read always a block of data around the point on highest resolution
1512
+ // if not already cached.
1513
+ // TODO: change provider identify() prototype to pass also the resolution
1514
+
1515
+ int width, height;
1516
+ if ( mHasSize )
1517
+ {
1518
+ width = mWidth ;
1519
+ height = mHeight ;
1520
+ }
1521
+ else
1522
+ {
1523
+ // Bad in any case, either not precise or too much data requests
1524
+ width = height = 1000 ;
1525
+ }
1526
+ double xRes = mCoverageExtent .width () / width;
1527
+ double yRes = mCoverageExtent .height () / height;
1528
+
1529
+ if ( !mCachedGdalDataset ||
1530
+ !mCachedViewExtent .contains ( thePoint ) ||
1531
+ mCachedViewWidth == 0 || mCachedViewHeight == 0 ||
1532
+ mCachedViewExtent .width () / mCachedViewWidth - xRes > TINY_VALUE ||
1533
+ mCachedViewExtent .height () / mCachedViewHeight - yRes > TINY_VALUE )
1534
+ {
1535
+ int half = 50 ;
1536
+ QgsRectangle extent ( thePoint.x () - xRes * half, thePoint.y () - yRes * half,
1537
+ thePoint.x () + xRes * half, thePoint.y () + yRes * half );
1538
+ getCache ( 1 , extent, 2 *half, 2 *half );
1539
+
1540
+ }
1541
+
1542
+ if ( !mCachedGdalDataset ||
1543
+ !mCachedViewExtent .contains ( thePoint ) )
1544
+ {
1545
+ return false ; // should not happen
1546
+ }
1547
+
1548
+ double x = thePoint.x ();
1549
+ double y = thePoint.y ();
1550
+
1551
+ // Calculate the row / column where the point falls
1552
+ xRes = ( mCachedViewExtent .xMaximum () - mCachedViewExtent .xMinimum () ) / mCachedViewWidth ;
1553
+ yRes = ( mCachedViewExtent .yMaximum () - mCachedViewExtent .yMinimum () ) / mCachedViewHeight ;
1554
+
1555
+ // Offset, not the cell index -> flor
1556
+ int col = ( int ) floor (( x - mCachedViewExtent .xMinimum () ) / xRes );
1557
+ int row = ( int ) floor (( mCachedViewExtent .yMaximum () - y ) / yRes );
1558
+
1559
+ QgsDebugMsg ( " row = " + QString::number ( row ) + " col = " + QString::number ( col ) );
1560
+
1561
+ for ( int i = 1 ; i <= GDALGetRasterCount ( mCachedGdalDataset ); i++ )
1562
+ {
1563
+ GDALRasterBandH gdalBand = GDALGetRasterBand ( mCachedGdalDataset , i );
1564
+ double value;
1565
+
1566
+ CPLErr err = GDALRasterIO ( gdalBand, GF_Read, col, row, 1 , 1 ,
1567
+ &value, 1 , 1 , GDT_Float64, 0 , 0 );
1568
+
1569
+ if ( err != CPLE_None )
1570
+ {
1571
+ QgsLogger::warning ( " RasterIO error: " + QString::fromUtf8 ( CPLGetLastErrorMsg () ) );
1572
+ }
1573
+
1574
+ QString v;
1575
+
1576
+ if ( mValidNoDataValue && ( fabs ( value - mNoDataValue [i-1 ] ) <= TINY_VALUE || value != value ) )
1577
+ {
1578
+ v = tr ( " null (no data)" );
1579
+ }
1580
+ else
1581
+ {
1582
+ v.setNum ( value );
1583
+ }
1584
+
1585
+ theResults[ generateBandName ( i )] = v;
1586
+ }
1587
+
1588
+ return true ;
1589
+ }
1590
+
1487
1591
QString QgsWcsProvider::identifyAsText ( const QgsPoint &point )
1488
1592
{
1489
1593
Q_UNUSED ( point );
0 commit comments