Reintroduce geometry caching while rendering (used esp. for snapping)

This commit is contained in:
Martin Dobias 2014-01-20 17:47:19 +07:00
parent 4bfba09bd3
commit d4b1bb47f4
5 changed files with 66 additions and 12 deletions

View File

@ -14,6 +14,7 @@
#include "qgsmaplayerrenderer.h"
#include "qgsmaprenderercache.h"
#include "qgspallabeling.h"
#include "qgsvectorlayerrenderer.h"
QgsMapRendererJob::QgsMapRendererJob( const QgsMapSettings& settings )
@ -438,6 +439,17 @@ void QgsMapRendererJob::drawNewLabeling( const QgsMapSettings& settings, QgsRend
}
}
void QgsMapRendererJob::updateLayerGeometryCaches()
{
foreach ( QString id, mGeometryCaches.keys() )
{
const QgsGeometryCache& cache = mGeometryCaches[id];
if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( id ) ) )
*vl->cache() = cache;
}
mGeometryCaches.clear();
}
bool QgsMapRendererJob::needTemporaryImage( QgsMapLayer* ml )
{
@ -525,6 +537,8 @@ LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter* painter, QgsPalLabelin
qDebug("CACHE VALID: %d", cacheValid);
}
mGeometryCaches.clear();
while ( li.hasPrevious() )
{
QString layerId = li.previous();
@ -629,6 +643,14 @@ LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter* painter, QgsPalLabelin
job.renderer = ml->createMapRenderer( job.context );
if ( mRequestedGeomCacheForLayers.contains( ml->id() ) )
{
if ( QgsVectorLayerRenderer* vlr = dynamic_cast<QgsVectorLayerRenderer*>( job.renderer ) )
{
vlr->setGeometryCachePointer( &mGeometryCaches[ ml->id() ] );
}
}
/*
// TODO: split extent
if ( split )
@ -675,6 +697,8 @@ void QgsMapRendererJob::cleanupJobs( LayerRenderJobs& jobs )
}
jobs.clear();
updateLayerGeometryCaches();
}
/////////////

View File

@ -12,6 +12,7 @@
#include "qgsmapsettings.h"
#include "qgsgeometrycache.h"
class QgsLabelingResults;
class QgsMapLayerRenderer;
@ -77,6 +78,9 @@ public:
//! Does not take ownership of the object.
void setCache( QgsMapRendererCache* cache );
//! Set which vector layers should be cached while rendering
//! @note The way how geometries are cached is really suboptimal - this method may be removed in future releases
void setRequestedGeometryCacheForLayers( const QStringList& layerIds ) { mRequestedGeomCacheForLayers = layerIds; }
//! Find out how log it took to finish the job (in miliseconds)
int renderingTime() const { return mRenderingTime; }
@ -108,11 +112,19 @@ protected:
static void drawOldLabeling( const QgsMapSettings& settings, QgsRenderContext& renderContext );
static void drawNewLabeling( const QgsMapSettings& settings, QgsRenderContext& renderContext, QgsPalLabeling* labelingEngine );
//! called when rendering has finished to update all layers' geometry caches
void updateLayerGeometryCaches();
QgsMapSettings mSettings;
Errors mErrors;
QgsMapRendererCache* mCache;
//! list of layer IDs for which the geometry cache should be updated
QStringList mRequestedGeomCacheForLayers;
//! map of geometry caches
QMap<QString, QgsGeometryCache> mGeometryCaches;
QTime mRenderingStart;
int mRenderingTime;
};

View File

@ -35,11 +35,6 @@ QgsVectorLayerRenderer::QgsVectorLayerRenderer( QgsVectorLayer* layer, QgsRender
mSelectedFeatureIds = layer->selectedFeaturesIds();
mDrawVertexMarkers = ( layer->editBuffer() != 0 );
mCacheFeatures = ( layer->editBuffer() != 0 );
if ( mCacheFeatures )
{
mCache = new QgsGeometryCache();
}
mGeometryType = layer->geometryType();
@ -70,11 +65,8 @@ QgsVectorLayerRenderer::QgsVectorLayerRenderer( QgsVectorLayer* layer, QgsRender
QgsDebugMsg( "rendering v2:\n" + mRendererV2->dump() );
if ( mCacheFeatures )
if ( mDrawVertexMarkers )
{
// Destroy all cached geometries and clear the references to them
mCache->setCachedGeometriesRect( mContext.extent() );
// set editing vertex markers style
mRendererV2->setVertexMarkerAppearance( mVertexMarkerStyle, mVertexMarkerSize );
}
@ -91,7 +83,6 @@ QgsVectorLayerRenderer::QgsVectorLayerRenderer( QgsVectorLayer* layer, QgsRender
QgsVectorLayerRenderer::~QgsVectorLayerRenderer()
{
delete mRendererV2;
delete mCache;
delete mSource;
}
@ -142,6 +133,17 @@ bool QgsVectorLayerRenderer::render()
return true;
}
void QgsVectorLayerRenderer::setGeometryCachePointer( QgsGeometryCache* cache )
{
mCache = cache;
if ( mCache )
{
// Destroy all cached geometries and clear the references to them
mCache->setCachedGeometriesRect( mContext.extent() );
}
}
void QgsVectorLayerRenderer::drawRendererV2( QgsFeatureIterator& fit )
@ -166,7 +168,7 @@ void QgsVectorLayerRenderer::drawRendererV2( QgsFeatureIterator& fit )
// render feature
bool rendered = mRendererV2->renderFeature( fet, mContext, -1, sel, drawMarker );
if ( mCacheFeatures )
if ( mCache )
{
// Cache this for the use of (e.g.) modifying the feature's uncommitted geometry.
mCache->cacheGeometry( fet.id(), *fet.geometry() );
@ -236,7 +238,7 @@ void QgsVectorLayerRenderer::drawRendererV2Levels( QgsFeatureIterator& fit )
}
features[sym].append( fet );
if ( mCacheFeatures )
if ( mCache )
{
// Cache this for the use of (e.g.) modifying the feature's uncommitted geometry.
mCache->cacheGeometry( fet.id(), *fet.geometry() );

View File

@ -34,6 +34,10 @@ public:
virtual bool render();
//! where to save the cached geometries
//! @note The way how geometries are cached is really suboptimal - this method may be removed in future releases
void setGeometryCachePointer( QgsGeometryCache* cache );
private:
/**Registers label and diagram layer

View File

@ -652,6 +652,18 @@ void QgsMapCanvas::refreshMap()
mJob = new QgsMapRendererSequentialJob( mSettings );
connect(mJob, SIGNAL( finished() ), SLOT( rendererJobFinished() ) );
mJob->setCache( mCache );
QStringList layersForGeometryCache;
foreach ( QString id, mSettings.layers() )
{
if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( id ) ) )
{
if ( vl->isEditable() )
layersForGeometryCache << id;
}
}
mJob->setRequestedGeometryCacheForLayers( layersForGeometryCache );
mJob->start();
mMapUpdateTimer.start();