Skip to content

Commit

Permalink
Add API to limit the acceptable scale difference when searching
Browse files Browse the repository at this point in the history
for any matching cache image in QgsMapRendererCache
  • Loading branch information
nyalldawson committed Jan 28, 2021
1 parent ead6d06 commit 339516a
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 14 deletions.
7 changes: 6 additions & 1 deletion python/core/auto_generated/qgsmaprenderercache.sip.in
Expand Up @@ -109,11 +109,16 @@ that has the same extent and scale as the cache's global extent and scale
.. versionadded:: 3.0
%End

bool hasAnyCacheImage( const QString &cacheKey ) const;
bool hasAnyCacheImage( const QString &cacheKey, double minimumScaleThreshold = 0, double maximumScaleThreshold = 0 ) const;
%Docstring
Returns ``True`` if the cache contains an image with the specified ``cacheKey``
with any cache's parameters (extent and scale)

The optional ``minimumScaleThreshold`` and ``maximumScaleThreshold`` arguments can be used to
specify a range of acceptable cached scales vs current cache scale parameter. E.g. if the
``minimumScaleThreshold`` is 0.5 and ``maximumScaleThreshold`` is 2.0, then only cached images
with a scale between 0.5 * current cache scale and 2.0 * current cache scale will be considered.

.. seealso:: :py:func:`transformedCacheImage`

.. versionadded:: 3.18
Expand Down
20 changes: 18 additions & 2 deletions src/core/qgsmaprenderercache.cpp
Expand Up @@ -189,9 +189,25 @@ bool QgsMapRendererCache::hasCacheImage( const QString &cacheKey ) const
}
}

bool QgsMapRendererCache::hasAnyCacheImage( const QString &cacheKey ) const
bool QgsMapRendererCache::hasAnyCacheImage( const QString &cacheKey, double minimumScaleThreshold, double maximumScaleThreshold ) const
{
return mCachedImages.contains( cacheKey );
auto it = mCachedImages.constFind( cacheKey );
if ( it != mCachedImages.constEnd() )
{
const CacheParameters &params = it.value();

// check if cached image is outside desired scale range
if ( minimumScaleThreshold != 0 && mMtp.mapUnitsPerPixel() < params.cachedMtp.mapUnitsPerPixel() * minimumScaleThreshold )
return false;
if ( maximumScaleThreshold != 0 && mMtp.mapUnitsPerPixel() > params.cachedMtp.mapUnitsPerPixel() * maximumScaleThreshold )
return false;

return true;
}
else
{
return false;
}
}

QImage QgsMapRendererCache::cacheImage( const QString &cacheKey ) const
Expand Down
7 changes: 6 additions & 1 deletion src/core/qgsmaprenderercache.h
Expand Up @@ -121,11 +121,16 @@ class CORE_EXPORT QgsMapRendererCache : public QObject
* Returns TRUE if the cache contains an image with the specified \a cacheKey
* with any cache's parameters (extent and scale)
*
* The optional \a minimumScaleThreshold and \a maximumScaleThreshold arguments can be used to
* specify a range of acceptable cached scales vs current cache scale parameter. E.g. if the
* \a minimumScaleThreshold is 0.5 and \a maximumScaleThreshold is 2.0, then only cached images
* with a scale between 0.5 * current cache scale and 2.0 * current cache scale will be considered.
*
* \see transformedCacheImage()
*
* \since QGIS 3.18
*/
bool hasAnyCacheImage( const QString &cacheKey ) const;
bool hasAnyCacheImage( const QString &cacheKey, double minimumScaleThreshold = 0, double maximumScaleThreshold = 0 ) const;

/**
* Returns the cached image for the specified \a cacheKey. The \a cacheKey usually
Expand Down
49 changes: 39 additions & 10 deletions tests/src/core/testqgsmaprenderercache.cpp
Expand Up @@ -20,12 +20,12 @@
#include "qgsmaptopixel.h"
#include "qgsrectangle.h"

class TestQgsMapRendereCache: public QObject
class TestQgsMapRendererCache: public QObject
{
Q_OBJECT

public:
TestQgsMapRendereCache();
TestQgsMapRendererCache();

private slots:
void initTestCase();// will be called before the first testfunction is executed.
Expand All @@ -37,28 +37,28 @@ class TestQgsMapRendereCache: public QObject
};


TestQgsMapRendereCache::TestQgsMapRendereCache() = default;
TestQgsMapRendererCache::TestQgsMapRendererCache() = default;

void TestQgsMapRendereCache::initTestCase()
void TestQgsMapRendererCache::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();
}

void TestQgsMapRendereCache::cleanupTestCase()
void TestQgsMapRendererCache::cleanupTestCase()
{
QgsApplication::exitQgis();
}

void TestQgsMapRendereCache::init()
void TestQgsMapRendererCache::init()
{
}

void TestQgsMapRendereCache::cleanup()
void TestQgsMapRendererCache::cleanup()
{
}

void TestQgsMapRendereCache::testCache()
void TestQgsMapRendererCache::testCache()
{
QgsMapRendererCache cache;
QImage imgRed( 100, 100, QImage::Format::Format_ARGB32_Premultiplied );
Expand All @@ -80,12 +80,14 @@ void TestQgsMapRendereCache::testCache()
QVERIFY( !cache.hasCacheImage( imgRedKey ) );
QVERIFY( cache.hasCacheImage( imgBlueKey ) );
QVERIFY( cache.hasAnyCacheImage( imgBlueKey ) );
QVERIFY( cache.hasAnyCacheImage( imgBlueKey, 0.9, 1.1 ) );

cache.setCacheImage( imgRedKey, imgRed );
QVERIFY( cache.hasCacheImage( imgRedKey ) );
QVERIFY( cache.hasCacheImage( imgBlueKey ) );
QVERIFY( cache.hasAnyCacheImage( imgBlueKey ) );
QVERIFY( cache.hasAnyCacheImage( imgRedKey ) );
QVERIFY( cache.hasAnyCacheImage( imgRedKey, 0.9, 1.1 ) );

{
QImage img = cache.cacheImage( imgBlueKey );
Expand All @@ -104,12 +106,39 @@ void TestQgsMapRendereCache::testCache()
QVERIFY( !cache.hasCacheImage( imgRedKey ) );
QVERIFY( !cache.hasCacheImage( imgBlueKey ) );
QVERIFY( cache.hasAnyCacheImage( imgBlueKey ) );
QVERIFY( cache.hasAnyCacheImage( imgRedKey ) );
QVERIFY( cache.hasAnyCacheImage( imgBlueKey, 0.9, 1.1 ) );
QVERIFY( cache.hasAnyCacheImage( imgRedKey, 0.9, 1.1 ) );

QImage transformed = cache.transformedCacheImage( imgBlueKey, mtp2 );
QVERIFY( transformed.pixelColor( 30, 20 ) == Qt::transparent );
QVERIFY( transformed.pixelColor( 10, 20 ) == Qt::blue );

QgsMapToPixel mtp3( 2, 70, 50, 100, 100, 0.0 ); // scale by 2
cache.updateParameters( extent2, mtp3 );
QVERIFY( !cache.hasCacheImage( imgRedKey ) );
QVERIFY( !cache.hasCacheImage( imgBlueKey ) );
QVERIFY( cache.hasAnyCacheImage( imgBlueKey ) );
// outside of range
QVERIFY( !cache.hasAnyCacheImage( imgBlueKey, 0.9, 1.1 ) );
QVERIFY( !cache.hasAnyCacheImage( imgRedKey, 0.9, 1.1 ) );
QVERIFY( cache.hasAnyCacheImage( imgBlueKey, 0.9, 0 ) );
QVERIFY( cache.hasAnyCacheImage( imgRedKey, 0.9, 0 ) );
QVERIFY( cache.hasAnyCacheImage( imgBlueKey, 0.9, 2.0 ) );
QVERIFY( cache.hasAnyCacheImage( imgRedKey, 0.9, 2.0 ) );

QgsMapToPixel mtp4( 0.5, 70, 50, 100, 100, 0.0 ); // scale by 0.5
cache.updateParameters( extent2, mtp4 );
QVERIFY( !cache.hasCacheImage( imgRedKey ) );
QVERIFY( !cache.hasCacheImage( imgBlueKey ) );
QVERIFY( cache.hasAnyCacheImage( imgBlueKey ) );
// outside of range
QVERIFY( !cache.hasAnyCacheImage( imgBlueKey, 0.9, 1.1 ) );
QVERIFY( !cache.hasAnyCacheImage( imgRedKey, 0.9, 1.1 ) );
QVERIFY( cache.hasAnyCacheImage( imgBlueKey, 0, 1.1 ) );
QVERIFY( cache.hasAnyCacheImage( imgRedKey, 0, 1.1 ) );
QVERIFY( cache.hasAnyCacheImage( imgBlueKey, 0.5, 1.1 ) );
QVERIFY( cache.hasAnyCacheImage( imgRedKey, 0.5, 1.1 ) );

/* we can replace the cache image */
cache.setCacheImage( imgBlueKey, transformed );
QVERIFY( cache.hasCacheImage( imgBlueKey ) );
Expand All @@ -126,5 +155,5 @@ void TestQgsMapRendereCache::testCache()
}


QGSTEST_MAIN( TestQgsMapRendereCache )
QGSTEST_MAIN( TestQgsMapRendererCache )
#include "testqgsmaprenderercache.moc"

0 comments on commit 339516a

Please sign in to comment.