10#include"MercatorScanlineTextureMapper.h"
19#include "GeoPainter.h"
20#include "MarbleDebug.h"
21#include "ScanlineTextureMapperContext.h"
22#include "StackedTileLoader.h"
23#include "TextureColorizer.h"
25#include "MathHelper.h"
30class MercatorScanlineTextureMapper::RenderJob :
public QRunnable
39 const int m_tileLevel;
40 QImage *
const m_canvasImage;
43 const int m_yPaintedTop;
44 const int m_yPaintedBottom;
48 : m_tileLoader( tileLoader ),
49 m_tileLevel( tileLevel ),
50 m_canvasImage( canvasImage ),
51 m_viewport( viewport ),
52 m_mapQuality( mapQuality ),
53 m_yPaintedTop( yTop ),
54 m_yPaintedBottom( yBottom )
58MercatorScanlineTextureMapper::MercatorScanlineTextureMapper(
StackedTileLoader *tileLoader )
59 : TextureMapperInterface(),
60 m_tileLoader( tileLoader ),
66void MercatorScanlineTextureMapper::mapTexture(
GeoPainter *painter,
69 const QRect &dirtyRect,
70 TextureColorizer *texColorizer )
72 if ( m_canvasImage.
size() != viewport->size() || m_radius != viewport->radius() ) {
73 const QImage::Format optimalFormat = ScanlineTextureMapperContext::optimalCanvasImageFormat( viewport );
75 if ( m_canvasImage.
size() != viewport->size() || m_canvasImage.
format() != optimalFormat ) {
76 m_canvasImage =
QImage( viewport->size(), optimalFormat );
79 if ( !viewport->mapCoversViewport() ) {
80 m_canvasImage.
fill( 0 );
83 m_radius = viewport->radius();
84 m_repaintNeeded =
true;
87 if ( m_repaintNeeded ) {
88 mapTexture( viewport, tileZoomLevel, painter->
mapQuality() );
91 texColorizer->colorize( &m_canvasImage, viewport, painter->
mapQuality() );
94 m_repaintNeeded =
false;
97 painter->
drawImage( dirtyRect, m_canvasImage, dirtyRect );
100void MercatorScanlineTextureMapper::mapTexture(
const ViewportParams *viewport,
int tileZoomLevel,
MapQuality mapQuality )
107 const int imageHeight = m_canvasImage.
height();
112 qreal realYTop, realYBottom, dummyX;
118 const int yTop = qBound(qreal(0.0), realYTop, qreal(imageHeight));
119 int yPaintedTop = yTop;
120 int yPaintedBottom = qBound(qreal(0.0), realYBottom, qreal(imageHeight));
122 yPaintedTop = qBound(0, yPaintedTop, imageHeight);
123 yPaintedBottom = qBound(0, yPaintedBottom, imageHeight);
126 const int yStep = ( yPaintedBottom - yPaintedTop ) / numThreads;
127 for (
int i = 0; i < numThreads; ++i ) {
128 const int yStart = yPaintedTop + i * yStep;
129 const int yEnd = (i == numThreads - 1) ? yPaintedBottom : yPaintedTop + (i + 1) * yStep;
130 QRunnable *
const job =
new RenderJob( m_tileLoader, tileZoomLevel, &m_canvasImage, viewport, mapQuality, yStart, yEnd );
131 m_threadPool.
start( job );
135 const int clearStart = ( yPaintedTop - m_oldYPaintedTop <= 0 ) ? yPaintedBottom : 0;
136 const int clearStop = ( yPaintedTop - m_oldYPaintedTop <= 0 ) ? imageHeight : yTop;
138 QRgb *
const itClearBegin = (QRgb*)( m_canvasImage.
scanLine( clearStart ) );
139 QRgb *
const itClearEnd = (QRgb*)( m_canvasImage.
scanLine( clearStop ) );
141 for ( QRgb * it = itClearBegin; it < itClearEnd; ++it ) {
147 m_oldYPaintedTop = yPaintedTop;
153void MercatorScanlineTextureMapper::RenderJob::run()
157 const int imageHeight = m_canvasImage->
height();
158 const int imageWidth = m_canvasImage->
width();
159 const qint64 radius = m_viewport->radius();
161 const float rad2Pixel = (float)( 2 * radius ) / M_PI;
162 const qreal pixel2Rad = 1.0/rad2Pixel;
164 const bool interlaced = ( m_mapQuality ==
LowQuality );
165 const bool highQuality = ( m_mapQuality ==
HighQuality
167 const bool printQuality = ( m_mapQuality ==
PrintQuality );
170 const int n = ScanlineTextureMapperContext::interpolationStep( m_viewport, m_mapQuality );
173 const qreal centerLon = m_viewport->centerLongitude();
174 const qreal centerLat = m_viewport->centerLatitude();
176 const int yCenterOffset = (int)( asinh( tan( centerLat ) ) * rad2Pixel );
178 qreal leftLon = + centerLon - ( imageWidth / 2 * pixel2Rad );
179 while ( leftLon < -M_PI ) leftLon += 2 * M_PI;
180 while ( leftLon > M_PI ) leftLon -= 2 * M_PI;
182 const int maxInterpolationPointX = n * (int)( imageWidth / n - 1 ) + 1;
187 ScanlineTextureMapperContext context( m_tileLoader, m_tileLevel );
192 for (
int y = m_yPaintedTop; y < m_yPaintedBottom; ++y ) {
194 QRgb * scanLine = (QRgb*)( m_canvasImage->
scanLine( y ) );
197 const qreal lat = gd ( ( (imageHeight / 2 + yCenterOffset) - y )
200 for (
int x = 0; x < imageWidth; ++x ) {
202 bool interpolate =
false;
203 if ( x > 0 && x <= maxInterpolationPointX ) {
205 lon += (n - 1) * pixel2Rad;
206 interpolate = !printQuality;
212 if ( lon < -M_PI ) lon += 2 * M_PI;
213 if ( lon > M_PI ) lon -= 2 * M_PI;
217 context.pixelValueApproxF( lon, lat, scanLine, n );
219 context.pixelValueApprox( lon, lat, scanLine, n );
221 scanLine += ( n - 1 );
224 if ( x < imageWidth ) {
226 context.pixelValueF( lon, lat, scanLine );
228 context.pixelValue( lon, lat, scanLine );
236 if ( interlaced && y + 1 < m_yPaintedBottom ) {
238 const int pixelByteSize = m_canvasImage->
bytesPerLine() / imageWidth;
240 memcpy( m_canvasImage->
scanLine( y + 1 ),
242 imageWidth * pixelByteSize );
This file contains the headers for AbstractProjection.
This file contains the headers for ViewportParams.
qreal minLat() const
Returns the arbitrarily chosen minimum (southern) latitude.
qreal maxLat() const
Returns the arbitrarily chosen maximum (northern) latitude.
A 3d point representation.
A painter that allows to draw geometric primitives on the map.
MapQuality mapQuality() const
Returns the map quality.
void drawImage(const GeoDataCoordinates ¢erPosition, const QImage &image)
Draws an image at the given position. The image is placed with its center located at the given center...
Tile loading from a quad tree.
void cleanupTilehash()
Cleans up the internal tile hash.
void resetTilehash()
Resets the internal tile hash.
A public class that controls what is visible in the viewport of a Marble map.
bool screenCoordinates(const qreal lon, const qreal lat, qreal &x, qreal &y) const
Get the screen coordinates corresponding to geographical coordinates in the map.
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.
@ HighQuality
High quality (e.g. antialiasing for lines)
@ PrintQuality
Print quality.
@ LowQuality
Low resolution (e.g. interlaced)
qsizetype bytesPerLine() const const
void fill(Qt::GlobalColor color)
void start(Callable &&callableToRun, int priority)
bool waitForDone(int msecs)