Commit d4b6aea7 authored by Bernhard Beschow's avatar Bernhard Beschow

allow tiles of different levels to be directly used for rendering

This patch is a prerequisite for using a backing store during tile rendering.
parent 320c83a6
......@@ -32,8 +32,11 @@ ScanlineTextureMapperContext::ScanlineTextureMapperContext( StackedTileLoader *
m_normGlobalWidth( m_globalWidth / ( 2 * M_PI ) ),
m_normGlobalHeight( m_globalHeight / M_PI ),
m_tile( 0 ),
m_deltaLevel( 0 ),
m_tilePosX( 65535 ),
m_tilePosY( 65535 ),
m_vTileStartX( 0 ),
m_vTileStartY( 0 ),
m_toTileCoordinatesLon( 0.5 * m_globalWidth - m_tilePosX ),
m_toTileCoordinatesLat( 0.5 * m_globalHeight - m_tilePosY ),
m_prevLat( 0.0 ),
......@@ -66,7 +69,8 @@ void ScanlineTextureMapperContext::pixelValueF( const qreal lon, const qreal lat
nextTile( posX, posY );
}
if ( m_tile ) {
*scanLine = m_tile->pixelF( posX, posY );
*scanLine = m_tile->pixelF( ( (int)posX + m_vTileStartX ) / ( 1 << m_deltaLevel ),
( (int)posY + m_vTileStartY ) / ( 1 << m_deltaLevel ) );
}
else {
*scanLine = 0;
......@@ -102,7 +106,8 @@ void ScanlineTextureMapperContext::pixelValue( const qreal lon, const qreal lat,
}
if ( m_tile ) {
*scanLine = m_tile->pixel( iPosX, iPosY );
*scanLine = m_tile->pixel( ( iPosX + m_vTileStartX ) >> m_deltaLevel,
( iPosY + m_vTileStartY ) >> m_deltaLevel );
}
else {
*scanLine = 0;
......@@ -181,16 +186,21 @@ void ScanlineTextureMapperContext::pixelValueApproxF( const qreal lon, const qre
oldPosX = -1;
}
*scanLine = m_tile->pixel( posX, posY );
*scanLine = m_tile->pixel( ( (int)posX + m_vTileStartX ) >> m_deltaLevel,
( (int)posY + m_vTileStartY ) >> m_deltaLevel );
// Just perform bilinear interpolation if there's a color change compared to the
// last pixel that was evaluated. This speeds up things greatly for maps like OSM
if ( *scanLine != oldRgb ) {
if ( oldPosX != -1 ) {
*(scanLine - 1) = m_tile->pixelF( oldPosX, oldPosY, *(scanLine - 1) );
*(scanLine - 1) = m_tile->pixelF( ( oldPosX + m_vTileStartX ) / ( 1 << m_deltaLevel ),
( oldPosY + m_vTileStartY ) / ( 1 << m_deltaLevel ),
*(scanLine - 1) );
oldPosX = -1;
}
oldRgb = m_tile->pixelF( posX, posY, *scanLine );
oldRgb = m_tile->pixelF( ( posX + m_vTileStartX ) / ( 1 << m_deltaLevel ),
( posY + m_vTileStartY ) / ( 1 << m_deltaLevel ),
*scanLine );
*scanLine = oldRgb;
}
else {
......@@ -302,7 +312,8 @@ void ScanlineTextureMapperContext::pixelValueApprox( const qreal lon, const qrea
for ( int j = 1; j < n; ++j ) {
iPosXf += itStepLon;
iPosYf += itStepLat;
*scanLine = m_tile->pixel( iPosXf >> 7, iPosYf >> 7 );
*scanLine = m_tile->pixel( ( ( iPosXf >> 7 ) + m_vTileStartX ) >> m_deltaLevel,
( ( iPosYf >> 7 ) + m_vTileStartY ) >> m_deltaLevel );
++scanLine;
}
}
......@@ -323,7 +334,8 @@ void ScanlineTextureMapperContext::pixelValueApprox( const qreal lon, const qrea
iPosY = ( itLat + itStepLat * j ) >> 7;
}
*scanLine = m_tile->pixel( iPosX, iPosY );
*scanLine = m_tile->pixel( ( iPosX + m_vTileStartX ) >> m_deltaLevel,
( iPosY + m_vTileStartY ) >> m_deltaLevel );
++scanLine;
}
}
......@@ -437,7 +449,8 @@ void ScanlineTextureMapperContext::nextTile( int &posX, int &posY )
int tileCol = lon / m_tileSize.width();
int tileRow = lat / m_tileSize.height();
m_tile = m_tileLoader->loadTile( TileId( 0, m_tileLevel, tileCol, tileRow ) );
m_deltaLevel = 0;
m_tile = m_tileLoader->loadTile( TileId( 0, m_tileLevel - m_deltaLevel, tileCol >> m_deltaLevel, tileRow >> m_deltaLevel ) );
m_tile->setUsed( true );
// Update position variables:
......@@ -446,10 +459,12 @@ void ScanlineTextureMapperContext::nextTile( int &posX, int &posY )
// ( origin upper left, measured in pixels )
m_tilePosX = tileCol * m_tileSize.width();
m_vTileStartX = ( tileCol - ( ( tileCol >> m_deltaLevel ) << m_deltaLevel ) ) * m_tileSize.width();
m_toTileCoordinatesLon = (qreal)(0.5 * m_globalWidth - m_tilePosX);
posX = lon - m_tilePosX;
m_tilePosY = tileRow * m_tileSize.height();
m_vTileStartY = ( tileRow - ( ( tileRow >> m_deltaLevel ) << m_deltaLevel ) ) * m_tileSize.height();
m_toTileCoordinatesLat = (qreal)(0.5 * m_globalHeight - m_tilePosY);
posY = lat - m_tilePosY;
}
......@@ -477,7 +492,8 @@ void ScanlineTextureMapperContext::nextTile( qreal &posX, qreal &posY )
int tileCol = lon / m_tileSize.width();
int tileRow = lat / m_tileSize.height();
m_tile = m_tileLoader->loadTile( TileId( 0, m_tileLevel, tileCol, tileRow ) );
m_deltaLevel = 0;
m_tile = m_tileLoader->loadTile( TileId( 0, m_tileLevel - m_deltaLevel, tileCol >> m_deltaLevel, tileRow >> m_deltaLevel ) );
m_tile->setUsed( true );
// Update position variables:
......@@ -486,10 +502,12 @@ void ScanlineTextureMapperContext::nextTile( qreal &posX, qreal &posY )
// ( origin upper left, measured in pixels )
m_tilePosX = tileCol * m_tileSize.width();
m_vTileStartX = ( tileCol - ( ( tileCol >> m_deltaLevel ) << m_deltaLevel ) ) * m_tileSize.width();
m_toTileCoordinatesLon = (qreal)(0.5 * m_globalWidth - m_tilePosX);
posX = lon - m_tilePosX;
m_tilePosY = tileRow * m_tileSize.height();
m_vTileStartY = ( tileRow - ( ( tileRow >> m_deltaLevel ) << m_deltaLevel ) ) * m_tileSize.height();
m_toTileCoordinatesLat = (qreal)(0.5 * m_globalHeight - m_tilePosY);
posY = lat - m_tilePosY;
}
......@@ -81,6 +81,7 @@ private:
qreal const m_normGlobalHeight;
StackedTile *m_tile;
int m_deltaLevel;
// Coordinate transformations:
......@@ -88,6 +89,8 @@ private:
// ( with origin in upper left corner, measured in pixel)
int m_tilePosX;
int m_tilePosY;
int m_vTileStartX;
int m_vTileStartY;
// Converts global texture coordinates
// ( with origin in center, measured in pixel)
......
......@@ -122,7 +122,17 @@ void TileScalingTextureMapper::mapTexture( QPainter *painter, ViewParams *viewPa
StackedTile *const tile = m_tileLoader->loadTile( stackedId );
tile->setUsed( true );
imagePainter.drawImage( rect, *tile->resultTile() );
const QImage *const toScale = tile->resultTile();
const int deltaLevel = stackedId.zoomLevel() - tile->id().zoomLevel();
const int restTileX = stackedId.x() % ( 1 << deltaLevel );
const int restTileY = stackedId.y() % ( 1 << deltaLevel );
const int partWidth = toScale->width() >> deltaLevel;
const int partHeight = toScale->height() >> deltaLevel;
const int startX = restTileX * partWidth;
const int startY = restTileY * partHeight;
QImage const part = toScale->copy( startX, startY, partWidth, partHeight ).scaled( toScale->size() );
imagePainter.drawImage( rect, part );
}
}
......@@ -148,11 +158,22 @@ void TileScalingTextureMapper::mapTexture( QPainter *painter, ViewParams *viewPa
const QSize size = QSize( qRound( rect.right() - rect.left() ), qRound( rect.bottom() - rect.top() ) );
const int cacheHash = 2 * ( size.width() % 2 ) + ( size.height() % 2 );
const TileId cacheId = TileId( cacheHash, stackedId.zoomLevel(), stackedId.x(), stackedId.y() );
QPixmap *im_cached = (*m_cache)[cacheId];
QPixmap *im = im_cached;
if ( im == 0 )
im = new QPixmap( QPixmap::fromImage( tile->resultTile()->scaled( size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) ) );
if ( im == 0 ) {
const QImage *const toScale = tile->resultTile();
const int deltaLevel = stackedId.zoomLevel() - tile->id().zoomLevel();
const int restTileX = stackedId.x() % ( 1 << deltaLevel );
const int restTileY = stackedId.y() % ( 1 << deltaLevel );
const int partWidth = toScale->width() >> deltaLevel;
const int partHeight = toScale->height() >> deltaLevel;
const int startX = restTileX * partWidth;
const int startY = restTileY * partHeight;
QImage const part = toScale->copy( startX, startY, partWidth, partHeight ).scaled( toScale->size() );
im = new QPixmap( QPixmap::fromImage( part.scaled( size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) ) );
}
painter->drawPixmap( rect.topLeft(), *im );
if (im != im_cached)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment