Skip to content

Commit

Permalink
Apply same logic as we use for rendering preview cached versions
Browse files Browse the repository at this point in the history
of vector layers to point cloud layer renders
  • Loading branch information
nyalldawson committed Jan 28, 2021
1 parent ab94b20 commit c642169
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 2 deletions.
1 change: 1 addition & 0 deletions python/core/auto_generated/qgsmaplayerrenderer.sip.in
Expand Up @@ -112,6 +112,7 @@ least partially) some data




};

/************************************************************************
Expand Down
30 changes: 30 additions & 0 deletions src/core/pointcloud/qgspointcloudlayerrenderer.cpp
Expand Up @@ -33,6 +33,7 @@
#include "qgscircle.h"
#include "qgsmapclippingutils.h"


QgsPointCloudLayerRenderer::QgsPointCloudLayerRenderer( QgsPointCloudLayer *layer, QgsRenderContext &context )
: QgsMapLayerRenderer( layer->id(), &context )
, mLayer( layer )
Expand Down Expand Up @@ -60,6 +61,8 @@ QgsPointCloudLayerRenderer::QgsPointCloudLayerRenderer( QgsPointCloudLayer *laye
mCloudExtent = mLayer->dataProvider()->polygonBounds();

mClippingRegions = QgsMapClippingUtils::collectClippingRegionsForLayer( *renderContext(), layer );

mReadyToCompose = false;
}

bool QgsPointCloudLayerRenderer::render()
Expand All @@ -86,13 +89,25 @@ bool QgsPointCloudLayerRenderer::render()
mRenderer->startRender( context );
static_cast< QgsPointCloudExtentRenderer * >( mRenderer.get() )->renderExtent( mCloudExtent, context );
mRenderer->stopRender( context );
mReadyToCompose = true;
return true;
}

// TODO cache!?
QgsPointCloudIndex *pc = mLayer->dataProvider()->index();
if ( !pc || !pc->isValid() )
{
mReadyToCompose = true;
return false;
}

// if the previous layer render was relatively quick (e.g. less than 3 seconds), the we show any previously
// cached version of the layer during rendering instead of the usual progressive updates
if ( mRenderTimeHint > 0 && mRenderTimeHint <= MAX_TIME_TO_USE_CACHED_PREVIEW_IMAGE )
{
mBlockRenderUpdates = true;
mElapsedTimer.start();
}

mRenderer->startRender( context );

Expand Down Expand Up @@ -149,6 +164,7 @@ bool QgsPointCloudLayerRenderer::render()
if ( ( rootErrorInMapCoordinates < 0.0 ) || ( mapUnitsPerPixel < 0.0 ) || ( maximumError < 0.0 ) )
{
QgsDebugMsg( QStringLiteral( "invalid screen error" ) );
mReadyToCompose = true;
return false;
}
double rootErrorPixels = rootErrorInMapCoordinates / mapUnitsPerPixel; // in pixels
Expand Down Expand Up @@ -177,6 +193,14 @@ bool QgsPointCloudLayerRenderer::render()

mRenderer->renderBlock( block.get(), context );
++nodesDrawn;

// as soon as first block is rendered, we can start showing layer updates.
// but if we are blocking render updates (so that a previously cached image is being shown), we wait
// at most e.g. 3 seconds before we start forcing progressive updates.
if ( !mBlockRenderUpdates || mElapsedTimer.elapsed() > MAX_TIME_TO_USE_CACHED_PREVIEW_IMAGE )
{
mReadyToCompose = true;
}
}

QgsDebugMsgLevel( QStringLiteral( "totals: %1 nodes | %2 points | %3ms" ).arg( nodesDrawn )
Expand All @@ -185,6 +209,7 @@ bool QgsPointCloudLayerRenderer::render()

mRenderer->stopRender( context );

mReadyToCompose = true;
return !canceled;
}

Expand All @@ -195,6 +220,11 @@ bool QgsPointCloudLayerRenderer::forceRasterRender() const
return mRenderer ? mRenderer->type() != QLatin1String( "extent" ) : false;
}

void QgsPointCloudLayerRenderer::setLayerRenderingTimeHint( int time )
{
mRenderTimeHint = time;
}

QVector<IndexedPointCloudNode> QgsPointCloudLayerRenderer::traverseTree( const QgsPointCloudIndex *pc,
const QgsRenderContext &context,
IndexedPointCloudNode n,
Expand Down
5 changes: 5 additions & 0 deletions src/core/pointcloud/qgspointcloudlayerrenderer.h
Expand Up @@ -62,6 +62,7 @@ class CORE_EXPORT QgsPointCloudLayerRenderer: public QgsMapLayerRenderer

bool render() override;
bool forceRasterRender() const override;
void setLayerRenderingTimeHint( int time ) override;

private:
QVector<IndexedPointCloudNode> traverseTree( const QgsPointCloudIndex *pc, const QgsRenderContext &context, IndexedPointCloudNode n, double maxErrorPixels, double nodeErrorPixels );
Expand All @@ -80,6 +81,10 @@ class CORE_EXPORT QgsPointCloudLayerRenderer: public QgsMapLayerRenderer
QgsGeometry mCloudExtent;
QList< QgsMapClippingRegion > mClippingRegions;

int mRenderTimeHint = 0;
bool mBlockRenderUpdates = false;
QElapsedTimer mElapsedTimer;

};

#endif // QGSPOINTCLOUDLAYERRENDERER_H
10 changes: 10 additions & 0 deletions src/core/qgsmaplayerrenderer.h
Expand Up @@ -157,6 +157,16 @@ class CORE_EXPORT QgsMapLayerRenderer
*/
bool mReadyToCompose = true;

/**
* Maximum time (in ms) to allow display of a previously cached
* preview image while rendering layers, before switching to
* a progressive rendering display.
*
* \note Not available in Python bindings
* \since QGIS 3.18
*/
static constexpr int MAX_TIME_TO_USE_CACHED_PREVIEW_IMAGE = 3000 SIP_SKIP;

private:

// TODO QGIS 4.0 - make reference instead of pointer!
Expand Down
2 changes: 0 additions & 2 deletions src/core/vector/qgsvectorlayerrenderer.cpp
Expand Up @@ -44,8 +44,6 @@

#include <QPicture>

constexpr int MAX_TIME_TO_USE_CACHED_PREVIEW_IMAGE = 3000;

QgsVectorLayerRenderer::QgsVectorLayerRenderer( QgsVectorLayer *layer, QgsRenderContext &context )
: QgsMapLayerRenderer( layer->id(), &context )
, mLayer( layer )
Expand Down

0 comments on commit c642169

Please sign in to comment.