Skip to content
Permalink
Browse files

[Globe] Rework qgis tilesource update logic

  • Loading branch information
manisandro committed Jun 23, 2016
1 parent c131ee2 commit afa0335b70f2dee02583db2aa4b375378cee84b3
@@ -602,6 +602,18 @@ void GlobePlugin::applyProjectSettings()
}
}

QgsRectangle GlobePlugin::getQGISLayerExtent() const
{
QList<QgsRectangle> extents = mLayerExtents.values();
QgsRectangle fullExtent = extents.isEmpty() ? QgsRectangle() : extents.front();
for ( int i = 1, n = extents.size(); i < n; ++i )
{
if ( !extents[i].isNull() )
fullExtent.combineExtentWith( extents[i] );
}
return fullExtent;
}

void GlobePlugin::showCurrentCoordinates( const osgEarth::GeoPoint& geoPoint )
{
osg::Vec3d pos = geoPoint.vec3d();
@@ -743,25 +755,12 @@ void GlobePlugin::setupProxy()
settings.endGroup();
}

void GlobePlugin::refreshQGISMapLayer( QgsRectangle rect )
void GlobePlugin::refreshQGISMapLayer( const QgsRectangle& dirtyRect )
{
if ( mTileSource )
{
if ( rect.isEmpty() )
{
if ( mLayerExtents.isEmpty() )
{
return;
}

rect = mLayerExtents.values().front();
foreach ( const QgsRectangle& extent, mLayerExtents.values() )
{
rect.combineExtentWith( extent );
}
}
mOsgViewer->getDatabasePager()->clear();
mTileSource->refresh( rect );
mTileSource->refresh( dirtyRect );
mOsgViewer->requestRedraw();
}
}
@@ -885,11 +884,7 @@ void GlobePlugin::updateLayers()
if ( mOsgViewer )
{
// Get previous full extent
QgsRectangle fullExtent = mLayerExtents.isEmpty() ? QgsRectangle() : mLayerExtents.values().front();
foreach ( const QgsRectangle& rect, mLayerExtents.values() )
{
fullExtent.combineExtentWith( rect );
}
QgsRectangle dirtyExtent = getQGISLayerExtent();
mLayerExtents.clear();

QStringList drapedLayers;
@@ -939,19 +934,16 @@ void GlobePlugin::updateLayers()
drapedLayers.append( mapLayer->id() );
QgsRectangle extent = QgsCoordinateTransformCache::instance()->transform( mapLayer->crs().authid(), GEO_EPSG_CRS_AUTHID )->transform( mapLayer->extent() );
mLayerExtents.insert( mapLayer->id(), extent );
if ( fullExtent.isEmpty() )
{
fullExtent = extent;
}
else
{
fullExtent.combineExtentWith( extent );
}
}
}

mTileSource->setLayerSet( drapedLayers );
refreshQGISMapLayer( fullExtent );
QgsRectangle newExtent = getQGISLayerExtent();
if ( dirtyExtent.isNull() )
dirtyExtent = newExtent;
else if ( !newExtent.isNull() )
dirtyExtent.combineExtentWith( newExtent );
refreshQGISMapLayer( dirtyExtent );
}
}

@@ -981,8 +973,9 @@ void GlobePlugin::layerChanged( QgsMapLayer* mapLayer )
QStringList layerSet = mTileSource->layerSet();
layerSet.removeAll( mapLayer->id() );
mTileSource->setLayerSet( layerSet );
refreshQGISMapLayer( mLayerExtents[mapLayer->id()] );
QgsRectangle dirtyExtent = mLayerExtents[mapLayer->id()];
mLayerExtents.remove( mapLayer->id() );
refreshQGISMapLayer( dirtyExtent );
}
mMapNode->getMap()->removeModelLayer( mMapNode->getMap()->getModelLayerByName( mapLayer->id().toStdString() ) );
addModelLayer( static_cast<QgsVectorLayer*>( mapLayer ), layerConfig );
@@ -1007,13 +1000,16 @@ void GlobePlugin::layerChanged( QgsMapLayer* mapLayer )
// Remove any model layer of that layer, in case one existed
mMapNode->getMap()->removeModelLayer( mMapNode->getMap()->getModelLayerByName( mapLayer->id().toStdString() ) );
QgsRectangle layerExtent = QgsCoordinateTransformCache::instance()->transform( mapLayer->crs().authid(), GEO_EPSG_CRS_AUTHID )->transform( mapLayer->extent() );
QgsRectangle updateExtent = layerExtent;
QgsRectangle dirtyExtent = layerExtent;
if ( mLayerExtents.contains( mapLayer->id() ) )
{
updateExtent.combineExtentWith( mLayerExtents[mapLayer->id()] );
if ( dirtyExtent.isNull() )
dirtyExtent = mLayerExtents[mapLayer->id()];
else if ( !mLayerExtents[mapLayer->id()].isNull() )
dirtyExtent.combineExtentWith( mLayerExtents[mapLayer->id()] );
}
mLayerExtents[mapLayer->id()] = layerExtent;
refreshQGISMapLayer( updateExtent );
refreshQGISMapLayer( dirtyExtent );
}
}
}
@@ -157,6 +157,7 @@ class GLOBE_EXPORT GlobePlugin : public QObject, public QgisPlugin
void addModelLayer( QgsVectorLayer* mapLayer , QgsGlobeVectorLayerConfig *layerConfig );
void setupControls();
void applyProjectSettings();
QgsRectangle getQGISLayerExtent() const;

private slots:
void setGlobeEnabled( bool enabled );
@@ -165,7 +166,7 @@ class GLOBE_EXPORT GlobePlugin : public QObject, public QgisPlugin
void applySettings();
void layerChanged( QgsMapLayer* mapLayer = 0 );
void rebuildQGISLayer();
void refreshQGISMapLayer( QgsRectangle rect = QgsRectangle() );
void refreshQGISMapLayer( const QgsRectangle &dirtyRect );
void updateTileStats( int queued, int tot );

signals:
@@ -56,9 +56,9 @@ QgsGlobeTileImage::QgsGlobeTileImage( QgsGlobeTileSource* tileSource, const QgsR
, mTileSource( tileSource )
, mTileExtent( tileExtent )
, mTileSize( tileSize )
, mImageUpdatePending( false )
, mLod( tileLod )
{
mTileSource->addTile( this );
#ifdef GLOBE_SHOW_TILE_STATS
QgsGlobeTileStatistics::instance()->updateTileCount( + 1 );
#endif
@@ -69,10 +69,8 @@ QgsGlobeTileImage::QgsGlobeTileImage( QgsGlobeTileSource* tileSource, const QgsR
GL_BGRA, GL_UNSIGNED_BYTE,
mTileData, osg::Image::NO_DELETE );

mLastUpdateTime = osgEarth::DateTime().asTimeStamp();
mTileSource->mTileUpdateManager.addTile( const_cast<QgsGlobeTileImage*>( this ) );
mDpi = 72;
mImageUpdatePending = true;
#else
QImage qImage( mTileData, mTileSize, mTileSize, QImage::Format_ARGB32_Premultiplied );
QPainter painter( &qImage );
@@ -84,35 +82,19 @@ QgsGlobeTileImage::QgsGlobeTileImage( QgsGlobeTileSource* tileSource, const QgsR
mTileData, osg::Image::NO_DELETE );
flipVertical();
mDpi = qImage.logicalDpiX();
mLastUpdateTime = osgEarth::DateTime().asTimeStamp();
#endif
}

QgsGlobeTileImage::~QgsGlobeTileImage()
{
mTileSource->removeTile( this );
mTileSource->mTileUpdateManager.removeTile( this );
delete[] mTileData;
#ifdef GLOBE_SHOW_TILE_STATS
QgsGlobeTileStatistics::instance()->updateTileCount( -1 );
#endif
}

bool QgsGlobeTileImage::requiresUpdateCall() const
{
if ( mLastUpdateTime < mTileSource->mLastModifiedTime )
{
mLastUpdateTime = mTileSource->mLastModifiedTime;
if ( !mTileExtent.intersects( mTileSource->mLastUpdateExtent ) )
{
return false;
}
mTileSource->mTileUpdateManager.addTile( const_cast<QgsGlobeTileImage*>( this ) );
mImageUpdatePending = true;
return true;
}
return mImageUpdatePending;
}

QgsMapSettings QgsGlobeTileImage::createSettings( int dpi , const QStringList &layerSet ) const
{
QgsMapSettings settings;
@@ -143,7 +125,6 @@ void QgsGlobeTileImage::update( osg::NodeVisitor * )
mTileData, osg::Image::NO_DELETE );
flipVertical();
mUpdatedImage = QImage();
mImageUpdatePending = false;
}
}

@@ -237,14 +218,17 @@ void QgsGlobeTileUpdateManager::renderingFinished()
QgsGlobeTileSource::QgsGlobeTileSource( QgsMapCanvas* canvas, const osgEarth::TileSourceOptions& options )
: TileSource( options )
, mCanvas( canvas )
, mLastModifiedTime( 0 )
{
osgEarth::GeoExtent geoextent( osgEarth::SpatialReference::get( "wgs84" ), -180., -90., 180., 90. );
osgEarth::DataExtentList extents;
extents.push_back( geoextent );
getDataExtents() = extents;
dirtyDataExtents();
}

osgEarth::TileSource::Status QgsGlobeTileSource::initialize( const osgDB::Options* /*dbOptions*/ )
{
setProfile( osgEarth::Registry::instance()->getGlobalGeodeticProfile() );
mLastModifiedTime = osgEarth::DateTime().asTimeStamp();
return STATUS_OK;
}

@@ -266,36 +250,40 @@ osg::Image* QgsGlobeTileSource::createImage( const osgEarth::TileKey& key, osgEa
return new QgsGlobeTileImage( this, tileExtent, getPixelsPerTile(), key.getLOD() );
}

bool QgsGlobeTileSource::hasDataInExtent( const osgEarth::GeoExtent &extent ) const
void QgsGlobeTileSource::refresh( const QgsRectangle& dirtyExtent )
{
osgEarth::Bounds bounds = extent.bounds();
QgsRectangle requestExtent( bounds.xMin(), bounds.yMin(), bounds.xMax(), bounds.yMax() );
return requestExtent.intersects( mViewExtent );
mTileUpdateManager.updateLayerSet( mLayerSet );
mTileListLock.lock();
foreach ( QgsGlobeTileImage* tile, mTiles )
{
if ( tile->extent().intersects( dirtyExtent ) )
{
mTileUpdateManager.addTile( tile );
}
}
mTileListLock.unlock();
}

bool QgsGlobeTileSource::hasData( const osgEarth::TileKey& key ) const
void QgsGlobeTileSource::setLayerSet( const QStringList &layerSet )
{
const osgEarth::GeoExtent& tileExtent = key.getExtent();
QgsRectangle rect( tileExtent.xMin(), tileExtent.yMin(), tileExtent.xMax(), tileExtent.yMax() );
return rect.intersects( mViewExtent );
mLayerSet = layerSet;
}

void QgsGlobeTileSource::refresh( const QgsRectangle& updateExtent )
const QStringList& QgsGlobeTileSource::layerSet() const
{
osgEarth::TimeStamp old = mLastModifiedTime;
mLastModifiedTime = osgEarth::DateTime().asTimeStamp();
mTileUpdateManager.updateLayerSet( mLayerSet );
mLastUpdateExtent = updateExtent;
QgsDebugMsg( QString( "Updated QGIS map layer modified time from %1 to %2" ).arg( old ).arg( mLastModifiedTime ) );
mViewExtent = QgsCoordinateTransformCache::instance()->transform( mCanvas->mapSettings().destinationCrs().authid(), GEO_EPSG_CRS_AUTHID )->transform( mCanvas->fullExtent() );
return mLayerSet;
}

void QgsGlobeTileSource::setLayerSet( const QStringList &layerSet )
void QgsGlobeTileSource::addTile( QgsGlobeTileImage* tile )
{
mLayerSet = layerSet;
mTileListLock.lock();
mTiles.append( tile );
mTileListLock.unlock();
}

const QStringList& QgsGlobeTileSource::layerSet() const
void QgsGlobeTileSource::removeTile( QgsGlobeTileImage* tile )
{
return mLayerSet;
mTileListLock.lock();
mTiles.removeOne( tile );
mTileListLock.unlock();
}
@@ -60,10 +60,11 @@ class QgsGlobeTileImage : public osg::Image
public:
QgsGlobeTileImage( QgsGlobeTileSource* tileSource, const QgsRectangle& tileExtent, int tileSize, int tileLod );
~QgsGlobeTileImage();
bool requiresUpdateCall() const;
bool requiresUpdateCall() const { return !mUpdatedImage.isNull(); }
QgsMapSettings createSettings( int dpi, const QStringList &layerSet ) const;
void setUpdatedImage( const QImage& image ) { mUpdatedImage = image; }
int dpi() const { return mDpi; }
const QgsRectangle& extent() { return mTileExtent; }

void update( osg::NodeVisitor * );

@@ -72,10 +73,8 @@ class QgsGlobeTileImage : public osg::Image
private:
QgsGlobeTileSource* mTileSource;
QgsRectangle mTileExtent;
mutable osgEarth::TimeStamp mLastUpdateTime;
int mTileSize;
unsigned char* mTileData;
mutable bool mImageUpdatePending;
int mLod;
int mDpi;
QImage mUpdatedImage;
@@ -114,25 +113,24 @@ class QgsGlobeTileSource : public osgEarth::TileSource
Status initialize( const osgDB::Options *dbOptions ) override;
osg::Image* createImage( const osgEarth::TileKey& key, osgEarth::ProgressCallback* progress ) override;
osg::HeightField* createHeightField( const osgEarth::TileKey &/*key*/, osgEarth::ProgressCallback* /*progress*/ ) override { return 0; }
bool hasDataInExtent( const osgEarth::GeoExtent &extent ) const override;
bool hasData( const osgEarth::TileKey& key ) const override;

bool isDynamic() const override { return true; }
osgEarth::TimeStamp getLastModifiedTime() const override { return mLastModifiedTime; }

void refresh( const QgsRectangle &updateExtent );
void refresh( const QgsRectangle &dirtyExtent );
void setLayerSet( const QStringList& layerSet );
const QStringList &layerSet() const;

private:
friend class QgsGlobeTileImage;

QMutex mTileListLock;
QList<QgsGlobeTileImage*> mTiles;
QgsMapCanvas* mCanvas;
osgEarth::TimeStamp mLastModifiedTime;
QgsRectangle mViewExtent;
QgsRectangle mLastUpdateExtent;
QStringList mLayerSet;
QgsGlobeTileUpdateManager mTileUpdateManager;

void addTile( QgsGlobeTileImage* tile );
void removeTile( QgsGlobeTileImage* tile );
};

#endif // QGSGLOBETILESOURCE_H

0 comments on commit afa0335

Please sign in to comment.
You can’t perform that action at this time.