7 #include "ScanlineTextureMapperContext.h"
9 #include "GeoSceneAbstractTileProjection.h"
10 #include "MarbleDebug.h"
11 #include "StackedTile.h"
12 #include "StackedTileLoader.h"
20 ScanlineTextureMapperContext::ScanlineTextureMapperContext(
StackedTileLoader *
const tileLoader,
int tileLevel )
21 : m_tileLoader( tileLoader ),
22 m_textureProjection(tileLoader->tileProjection()->
type()),
23 m_tileSize( tileLoader->tileSize() ),
24 m_tileLevel( tileLevel ),
25 m_globalWidth( m_tileSize.width() * m_tileLoader->tileColumnCount( m_tileLevel ) ),
26 m_globalHeight( m_tileSize.height() * m_tileLoader->tileRowCount( m_tileLevel ) ),
27 m_normGlobalWidth( m_globalWidth / ( 2 * M_PI ) ),
28 m_normGlobalHeight( m_globalHeight / M_PI ),
32 m_toTileCoordinatesLon( 0.5 * m_globalWidth - m_tilePosX ),
33 m_toTileCoordinatesLat( 0.5 * m_globalHeight - m_tilePosY ),
41 void ScanlineTextureMapperContext::pixelValueF(
const qreal lon,
const qreal lat,
42 QRgb*
const scanLine )
51 m_prevPixelX = rad2PixelX( lon );
52 m_prevPixelY = rad2PixelY( lat );
54 qreal posX = m_toTileCoordinatesLon + m_prevPixelX;
55 qreal posY = m_toTileCoordinatesLat + m_prevPixelY;
61 if ( posX >= (qreal)( m_tileSize.width() )
63 || posY >= (qreal)( m_tileSize.height() )
66 nextTile( posX, posY );
69 *scanLine = m_tile->pixelF( posX, posY );
79 void ScanlineTextureMapperContext::pixelValue(
const qreal lon,
const qreal lat,
80 QRgb*
const scanLine )
89 m_prevPixelX = rad2PixelX( lon );
90 m_prevPixelY = rad2PixelY( lat );
91 int iPosX = (int)( m_toTileCoordinatesLon + m_prevPixelX );
92 int iPosY = (int)( m_toTileCoordinatesLat + m_prevPixelY );
98 if ( iPosX >= m_tileSize.width()
100 || iPosY >= m_tileSize.height()
103 nextTile( iPosX, iPosY );
107 *scanLine = m_tile->pixel( iPosX, iPosY );
127 void ScanlineTextureMapperContext::pixelValueApproxF(
const qreal lon,
const qreal lat,
128 QRgb *scanLine,
const int n )
132 qreal stepLat = lat - m_prevLat;
133 qreal stepLon = lon - m_prevLon;
138 const qreal nInverse = 1.0 / (qreal)(n);
140 if ( fabs(stepLon) < M_PI ) {
141 const qreal itStepLon = ( rad2PixelX( lon ) - m_prevPixelX ) * nInverse;
142 const qreal itStepLat = ( rad2PixelY( lat ) - m_prevPixelY ) * nInverse;
148 qreal itLon = m_prevPixelX + m_toTileCoordinatesLon;
149 qreal itLat = m_prevPixelY + m_toTileCoordinatesLat;
151 const int tileWidth = m_tileSize.width();
152 const int tileHeight = m_tileSize.height();
158 QRgb oldRgb = qRgb( 0, 0, 0 );
163 const bool alwaysCheckTileRange =
164 isOutOfTileRangeF( itLon, itLat, itStepLon, itStepLat, n );
166 for (
int j=1; j < n; ++j ) {
167 qreal posX = itLon + itStepLon * j;
168 qreal posY = itLat + itStepLat * j;
169 if ( alwaysCheckTileRange )
170 if ( posX >= tileWidth
172 || posY >= tileHeight
175 nextTile( posX, posY );
176 itLon = m_prevPixelX + m_toTileCoordinatesLon;
177 itLat = m_prevPixelY + m_toTileCoordinatesLat;
178 posX = qBound <qreal>( 0.0, (itLon + itStepLon * j), tileWidth-1.0 );
179 posY = qBound <qreal>( 0.0, (itLat + itStepLat * j), tileHeight-1.0 );
183 *scanLine = m_tile->pixelF( posX, posY );
187 if ( *scanLine != oldRgb ) {
188 if ( oldPosX != -1 ) {
189 *(scanLine - 1) = m_tile->pixelF( oldPosX, oldPosY, *(scanLine - 1) );
192 oldRgb = m_tile->pixelF( posX, posY, *scanLine );
214 stepLon = ( TWOPI - fabs(stepLon) ) * nInverse;
215 stepLat = stepLat * nInverse;
219 if ( m_prevLon < lon ) {
221 for (
int j = 1; j < n; ++j ) {
222 m_prevLat += stepLat;
223 m_prevLon -= stepLon;
224 if ( m_prevLon <= -M_PI )
226 pixelValueF( m_prevLon, m_prevLat, scanLine );
234 qreal curStepLon = lon - n * stepLon;
236 for (
int j = 1; j < n; ++j ) {
237 m_prevLat += stepLat;
238 curStepLon += stepLon;
239 qreal evalLon = curStepLon;
240 if ( curStepLon <= -M_PI )
242 pixelValueF( evalLon, m_prevLat, scanLine );
250 bool ScanlineTextureMapperContext::isOutOfTileRangeF(
const qreal itLon,
const qreal itLat,
251 const qreal itStepLon,
const qreal itStepLat,
254 const qreal minIPosX = itLon + itStepLon;
255 const qreal minIPosY = itLat + itStepLat;
256 const qreal maxIPosX = itLon + itStepLon * ( n - 1 );
257 const qreal maxIPosY = itLat + itStepLat * ( n - 1 );
258 return ( maxIPosX >= m_tileSize.width() || maxIPosX < 0
259 || maxIPosY >= m_tileSize.height() || maxIPosY < 0
260 || minIPosX >= m_tileSize.width() || minIPosX < 0
261 || minIPosY >= m_tileSize.height() || minIPosY < 0 );
265 void ScanlineTextureMapperContext::pixelValueApprox(
const qreal lon,
const qreal lat,
266 QRgb *scanLine,
const int n )
270 qreal stepLat = lat - m_prevLat;
271 qreal stepLon = lon - m_prevLon;
276 const qreal nInverse = 1.0 / (qreal)(n);
278 if ( fabs(stepLon) < M_PI ) {
279 const int itStepLon = (int)( ( rad2PixelX( lon ) - m_prevPixelX ) * nInverse * 128.0 );
280 const int itStepLat = (int)( ( rad2PixelY( lat ) - m_prevPixelY ) * nInverse * 128.0 );
286 int itLon = (int)( ( m_prevPixelX + m_toTileCoordinatesLon ) * 128.0 );
287 int itLat = (int)( ( m_prevPixelY + m_toTileCoordinatesLat ) * 128.0 );
289 const int tileWidth = m_tileSize.width();
290 const int tileHeight = m_tileSize.height();
292 const bool alwaysCheckTileRange =
293 isOutOfTileRange( itLon, itLat, itStepLon, itStepLat, n );
295 if ( !alwaysCheckTileRange ) {
298 for (
int j = 1; j < n; ++j ) {
301 *scanLine = m_tile->pixel( iPosXf >> 7, iPosYf >> 7 );
306 for (
int j = 1; j < n; ++j ) {
307 int iPosX = ( itLon + itStepLon * j ) >> 7;
308 int iPosY = ( itLat + itStepLat * j ) >> 7;
310 if ( iPosX >= tileWidth
312 || iPosY >= tileHeight
315 nextTile( iPosX, iPosY );
316 itLon = (int)( ( m_prevPixelX + m_toTileCoordinatesLon ) * 128.0 );
317 itLat = (int)( ( m_prevPixelY + m_toTileCoordinatesLat ) * 128.0 );
318 iPosX = ( itLon + itStepLon * j ) >> 7;
319 iPosY = ( itLat + itStepLat * j ) >> 7;
325 if (iPosY >= tileHeight) iPosY = tileHeight - 1;
326 if (iPosY < 0) iPosY = 0;
329 *scanLine = m_tile->pixel( iPosX, iPosY );
341 stepLon = ( TWOPI - fabs(stepLon) ) * nInverse;
342 stepLat = stepLat * nInverse;
346 if ( m_prevLon < lon ) {
348 for (
int j = 1; j < n; ++j ) {
349 m_prevLat += stepLat;
350 m_prevLon -= stepLon;
351 if ( m_prevLon <= -M_PI )
353 pixelValue( m_prevLon, m_prevLat, scanLine );
361 qreal curStepLon = lon - n * stepLon;
363 for (
int j = 1; j < n; ++j ) {
364 m_prevLat += stepLat;
365 curStepLon += stepLon;
366 qreal evalLon = curStepLon;
367 if ( curStepLon <= -M_PI )
369 pixelValue( evalLon, m_prevLat, scanLine );
377 bool ScanlineTextureMapperContext::isOutOfTileRange(
const int itLon,
const int itLat,
378 const int itStepLon,
const int itStepLat,
381 const int minIPosX = ( itLon + itStepLon ) >> 7;
382 const int minIPosY = ( itLat + itStepLat ) >> 7;
383 const int maxIPosX = ( itLon + itStepLon * ( n - 1 ) ) >> 7;
384 const int maxIPosY = ( itLat + itStepLat * ( n - 1 ) ) >> 7;
385 return ( maxIPosX >= m_tileSize.width() || maxIPosX < 0
386 || maxIPosY >= m_tileSize.height() || maxIPosY < 0
387 || minIPosX >= m_tileSize.width() || minIPosX < 0
388 || minIPosY >= m_tileSize.height() || minIPosY < 0 );
398 if ( ! viewport->mapCoversViewport() ) {
404 const int width = viewport->width();
407 int nEvalMin = width - 1;
408 for (
int it = 1; it < 48; ++it ) {
409 int nEval = ( width - 1 ) / it + ( width - 1 ) % it;
410 if ( nEval < nEvalMin ) {
432 void ScanlineTextureMapperContext::nextTile(
int &posX,
int &posY )
437 int lon = posX + m_tilePosX;
438 if ( lon >= m_globalWidth )
439 lon -= m_globalWidth;
441 lon += m_globalWidth;
443 int lat = posY + m_tilePosY;
444 if ( lat >= m_globalHeight )
445 lat -= m_globalHeight;
447 lat += m_globalHeight;
452 const int tileCol = lon / m_tileSize.width();
453 const int tileRow = lat / m_tileSize.height();
455 m_tile = m_tileLoader->loadTile( TileId( 0, m_tileLevel, tileCol, tileRow ) );
462 m_tilePosX = tileCol * m_tileSize.width();
463 m_toTileCoordinatesLon = (qreal)(0.5 * m_globalWidth - m_tilePosX);
464 posX = lon - m_tilePosX;
466 m_tilePosY = tileRow * m_tileSize.height();
467 m_toTileCoordinatesLat = (qreal)(0.5 * m_globalHeight - m_tilePosY);
468 posY = lat - m_tilePosY;
471 void ScanlineTextureMapperContext::nextTile( qreal &posX, qreal &posY )
476 int lon = (int)(posX + m_tilePosX);
477 if ( lon >= m_globalWidth )
478 lon -= m_globalWidth;
480 lon += m_globalWidth;
482 int lat = (int)(posY + m_tilePosY);
483 if ( lat >= m_globalHeight )
484 lat -= m_globalHeight;
486 lat += m_globalHeight;
491 const int tileCol = lon / m_tileSize.width();
492 const int tileRow = lat / m_tileSize.height();
494 m_tile = m_tileLoader->loadTile( TileId( 0, m_tileLevel, tileCol, tileRow ) );
501 m_tilePosX = tileCol * m_tileSize.width();
502 m_toTileCoordinatesLon = (qreal)(0.5 * m_globalWidth - m_tilePosX);
503 posX = lon - m_tilePosX;
505 m_tilePosY = tileRow * m_tileSize.height();
506 m_toTileCoordinatesLat = (qreal)(0.5 * m_globalHeight - m_tilePosY);
507 posY = lat - m_tilePosY;