7#include "ScanlineTextureMapperContext.h"
9#include "GeoSceneAbstractTileProjection.h"
10#include "MarbleDebug.h"
11#include "StackedTile.h"
12#include "StackedTileLoader.h"
19ScanlineTextureMapperContext::ScanlineTextureMapperContext(
StackedTileLoader *
const tileLoader,
int tileLevel)
20 : m_tileLoader(tileLoader)
21 , m_textureProjection(tileLoader->tileProjection()->
type())
23 m_tileSize(tileLoader->tileSize())
25 m_tileLevel(tileLevel)
26 , m_globalWidth(m_tileSize.width() * m_tileLoader->tileColumnCount(m_tileLevel))
27 , m_globalHeight(m_tileSize.height() * m_tileLoader->tileRowCount(m_tileLevel))
28 , m_normGlobalWidth(m_globalWidth / (2 * M_PI))
29 , m_normGlobalHeight(m_globalHeight / M_PI)
33 , m_toTileCoordinatesLon(0.5 * m_globalWidth - m_tilePosX)
34 , m_toTileCoordinatesLat(0.5 * m_globalHeight - m_tilePosY)
42void ScanlineTextureMapperContext::pixelValueF(
const qreal lon,
const qreal lat, 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()) || posX < 0.0 || posY >= (qreal)(m_tileSize.
height()) || posY < 0.0) {
65 *scanLine = m_tile->
pixelF(posX, posY);
74void ScanlineTextureMapperContext::pixelValue(
const qreal lon,
const qreal lat, QRgb *
const scanLine)
83 m_prevPixelX = rad2PixelX(lon);
84 m_prevPixelY = rad2PixelY(lat);
85 int iPosX = (int)(m_toTileCoordinatesLon + m_prevPixelX);
86 int iPosY = (int)(m_toTileCoordinatesLat + m_prevPixelY);
92 if (iPosX >= m_tileSize.
width() || iPosX < 0 || iPosY >= m_tileSize.
height() || iPosY < 0) {
93 nextTile(iPosX, iPosY);
97 *scanLine = m_tile->
pixel(iPosX, iPosY);
116void ScanlineTextureMapperContext::pixelValueApproxF(
const qreal lon,
const qreal lat, QRgb *scanLine,
const int n)
120 qreal stepLat = lat - m_prevLat;
121 qreal stepLon = lon - m_prevLon;
126 const qreal nInverse = 1.0 / (qreal)(n);
128 if (fabs(stepLon) < M_PI) {
129 const qreal itStepLon = (rad2PixelX(lon) - m_prevPixelX) * nInverse;
130 const qreal itStepLat = (rad2PixelY(lat) - m_prevPixelY) * nInverse;
136 qreal itLon = m_prevPixelX + m_toTileCoordinatesLon;
137 qreal itLat = m_prevPixelY + m_toTileCoordinatesLat;
139 const int tileWidth = m_tileSize.
width();
140 const int tileHeight = m_tileSize.
height();
146 QRgb oldRgb = qRgb(0, 0, 0);
151 const bool alwaysCheckTileRange = isOutOfTileRangeF(itLon, itLat, itStepLon, itStepLat, n);
153 for (
int j = 1; j < n; ++j) {
154 qreal posX = itLon + itStepLon * j;
155 qreal posY = itLat + itStepLat * j;
156 if (alwaysCheckTileRange)
157 if (posX >= tileWidth || posX < 0.0 || posY >= tileHeight || posY < 0.0) {
158 nextTile(posX, posY);
159 itLon = m_prevPixelX + m_toTileCoordinatesLon;
160 itLat = m_prevPixelY + m_toTileCoordinatesLat;
161 posX = qBound<qreal>(0.0, (itLon + itStepLon * j), tileWidth - 1.0);
162 posY = qBound<qreal>(0.0, (itLat + itStepLat * j), tileHeight - 1.0);
166 *scanLine = m_tile->
pixelF(posX, posY);
170 if (*scanLine != oldRgb) {
172 *(scanLine - 1) = m_tile->
pixelF(oldPosX, oldPosY, *(scanLine - 1));
175 oldRgb = m_tile->
pixelF(posX, posY, *scanLine);
196 stepLon = (TWOPI - fabs(stepLon)) * nInverse;
197 stepLat = stepLat * nInverse;
201 if (m_prevLon < lon) {
202 for (
int j = 1; j < n; ++j) {
203 m_prevLat += stepLat;
204 m_prevLon -= stepLon;
205 if (m_prevLon <= -M_PI)
207 pixelValueF(m_prevLon, m_prevLat, scanLine);
215 qreal curStepLon = lon - n * stepLon;
217 for (
int j = 1; j < n; ++j) {
218 m_prevLat += stepLat;
219 curStepLon += stepLon;
220 qreal evalLon = curStepLon;
221 if (curStepLon <= -M_PI)
223 pixelValueF(evalLon, m_prevLat, scanLine);
230bool ScanlineTextureMapperContext::isOutOfTileRangeF(
const qreal itLon,
const qreal itLat,
const qreal itStepLon,
const qreal itStepLat,
const int n)
const
232 const qreal minIPosX = itLon + itStepLon;
233 const qreal minIPosY = itLat + itStepLat;
234 const qreal maxIPosX = itLon + itStepLon * (n - 1);
235 const qreal maxIPosY = itLat + itStepLat * (n - 1);
236 return (maxIPosX >= m_tileSize.
width() || maxIPosX < 0 || maxIPosY >= m_tileSize.
height() || maxIPosY < 0 || minIPosX >= m_tileSize.
width() || minIPosX < 0
237 || minIPosY >= m_tileSize.
height() || minIPosY < 0);
240void ScanlineTextureMapperContext::pixelValueApprox(
const qreal lon,
const qreal lat, QRgb *scanLine,
const int n)
244 qreal stepLat = lat - m_prevLat;
245 qreal stepLon = lon - m_prevLon;
250 const qreal nInverse = 1.0 / (qreal)(n);
252 if (fabs(stepLon) < M_PI) {
253 const int itStepLon = (int)((rad2PixelX(lon) - m_prevPixelX) * nInverse * 128.0);
254 const int itStepLat = (int)((rad2PixelY(lat) - m_prevPixelY) * nInverse * 128.0);
260 int itLon = (int)((m_prevPixelX + m_toTileCoordinatesLon) * 128.0);
261 int itLat = (int)((m_prevPixelY + m_toTileCoordinatesLat) * 128.0);
263 const int tileWidth = m_tileSize.
width();
264 const int tileHeight = m_tileSize.
height();
266 const bool alwaysCheckTileRange = isOutOfTileRange(itLon, itLat, itStepLon, itStepLat, n);
268 if (!alwaysCheckTileRange) {
271 for (
int j = 1; j < n; ++j) {
274 *scanLine = m_tile->
pixel(iPosXf >> 7, iPosYf >> 7);
278 for (
int j = 1; j < n; ++j) {
279 int iPosX = (itLon + itStepLon * j) >> 7;
280 int iPosY = (itLat + itStepLat * j) >> 7;
282 if (iPosX >= tileWidth || iPosX < 0 || iPosY >= tileHeight || iPosY < 0) {
283 nextTile(iPosX, iPosY);
284 itLon = (int)((m_prevPixelX + m_toTileCoordinatesLon) * 128.0);
285 itLat = (int)((m_prevPixelY + m_toTileCoordinatesLat) * 128.0);
286 iPosX = (itLon + itStepLon * j) >> 7;
287 iPosY = (itLat + itStepLat * j) >> 7;
293 if (iPosY >= tileHeight)
294 iPosY = tileHeight - 1;
299 *scanLine = m_tile->
pixel(iPosX, iPosY);
311 stepLon = (TWOPI - fabs(stepLon)) * nInverse;
312 stepLat = stepLat * nInverse;
316 if (m_prevLon < lon) {
317 for (
int j = 1; j < n; ++j) {
318 m_prevLat += stepLat;
319 m_prevLon -= stepLon;
320 if (m_prevLon <= -M_PI)
322 pixelValue(m_prevLon, m_prevLat, scanLine);
330 qreal curStepLon = lon - n * stepLon;
332 for (
int j = 1; j < n; ++j) {
333 m_prevLat += stepLat;
334 curStepLon += stepLon;
335 qreal evalLon = curStepLon;
336 if (curStepLon <= -M_PI)
338 pixelValue(evalLon, m_prevLat, scanLine);
345bool ScanlineTextureMapperContext::isOutOfTileRange(
const int itLon,
const int itLat,
const int itStepLon,
const int itStepLat,
const int n)
const
347 const int minIPosX = (itLon + itStepLon) >> 7;
348 const int minIPosY = (itLat + itStepLat) >> 7;
349 const int maxIPosX = (itLon + itStepLon * (n - 1)) >> 7;
350 const int maxIPosY = (itLat + itStepLat * (n - 1)) >> 7;
351 return (maxIPosX >= m_tileSize.
width() || maxIPosX < 0 || maxIPosY >= m_tileSize.
height() || maxIPosY < 0 || minIPosX >= m_tileSize.
width() || minIPosX < 0
352 || minIPosY >= m_tileSize.
height() || minIPosY < 0);
361 if (!viewport->mapCoversViewport()) {
367 const int width = viewport->width();
370 int nEvalMin = width - 1;
371 for (
int it = 1; it < 48; ++it) {
372 int nEval = (width - 1) / it + (width - 1) % it;
373 if (nEval < nEvalMin) {
391void ScanlineTextureMapperContext::nextTile(
int &posX,
int &posY)
396 int lon = posX + m_tilePosX;
397 if (lon >= m_globalWidth)
398 lon -= m_globalWidth;
400 lon += m_globalWidth;
402 int lat = posY + m_tilePosY;
403 if (lat >= m_globalHeight)
404 lat -= m_globalHeight;
406 lat += m_globalHeight;
411 const int tileCol = lon / m_tileSize.
width();
412 const int tileRow = lat / m_tileSize.
height();
414 m_tile = m_tileLoader->
loadTile(TileId(0, m_tileLevel, tileCol, tileRow));
421 m_tilePosX = tileCol * m_tileSize.
width();
422 m_toTileCoordinatesLon = (qreal)(0.5 * m_globalWidth - m_tilePosX);
423 posX = lon - m_tilePosX;
425 m_tilePosY = tileRow * m_tileSize.
height();
426 m_toTileCoordinatesLat = (qreal)(0.5 * m_globalHeight - m_tilePosY);
427 posY = lat - m_tilePosY;
430void ScanlineTextureMapperContext::nextTile(qreal &posX, qreal &posY)
435 int lon = (int)(posX + m_tilePosX);
436 if (lon >= m_globalWidth)
437 lon -= m_globalWidth;
439 lon += m_globalWidth;
441 int lat = (int)(posY + m_tilePosY);
442 if (lat >= m_globalHeight)
443 lat -= m_globalHeight;
445 lat += m_globalHeight;
450 const int tileCol = lon / m_tileSize.
width();
451 const int tileRow = lat / m_tileSize.
height();
453 m_tile = m_tileLoader->
loadTile(TileId(0, m_tileLevel, tileCol, tileRow));
460 m_tilePosX = tileCol * m_tileSize.
width();
461 m_toTileCoordinatesLon = (qreal)(0.5 * m_globalWidth - m_tilePosX);
462 posX = lon - m_tilePosX;
464 m_tilePosY = tileRow * m_tileSize.
height();
465 m_toTileCoordinatesLat = (qreal)(0.5 * m_globalHeight - m_tilePosY);
466 posY = lat - m_tilePosY;
This file contains the headers for ViewParameters.
This file contains the headers for ViewportParams.
Tile loading from a quad tree.
const StackedTile * loadTile(TileId const &stackedTileId)
Loads a tile and returns it.
uint pixelF(qreal x, qreal y) const
Returns the color value of the result tile at a given floating point position.
uint pixel(int x, int y) const
Returns the color value of the result tile at the given integer position.
A public class that controls what is visible in the viewport of a Marble map.
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
Binds a QML item to a specific geodetic location in screen coordinates.
MapQuality
This enum is used to choose the map quality shown in the view.
@ PrintQuality
Print quality.