10#include "GenericScanlineTextureMapper.h"
17#include "GeoPainter.h"
18#include "MarbleDirs.h"
19#include "MarbleDebug.h"
20#include "ScanlineTextureMapperContext.h"
21#include "StackedTileLoader.h"
22#include "TextureColorizer.h"
25#include "MathHelper.h"
30class GenericScanlineTextureMapper::RenderJob :
public QRunnable
39 const int m_tileLevel;
40 QImage *
const m_canvasImage;
48 : m_tileLoader( tileLoader ),
49 m_tileLevel( tileLevel ),
50 m_canvasImage( canvasImage ),
51 m_viewport( viewport ),
52 m_mapQuality( mapQuality ),
59GenericScanlineTextureMapper::GenericScanlineTextureMapper(
StackedTileLoader *tileLoader )
60 : TextureMapperInterface()
61 , m_tileLoader( tileLoader )
67void GenericScanlineTextureMapper::mapTexture(
GeoPainter *painter,
70 const QRect &dirtyRect,
71 TextureColorizer *texColorizer )
73 if ( m_canvasImage.
size() != viewport->size() || m_radius != viewport->radius() ) {
74 const QImage::Format optimalFormat = ScanlineTextureMapperContext::optimalCanvasImageFormat( viewport );
76 if ( m_canvasImage.
size() != viewport->size() || m_canvasImage.
format() != optimalFormat ) {
77 m_canvasImage =
QImage( viewport->size(), optimalFormat );
80 if ( !viewport->mapCoversViewport() ) {
81 m_canvasImage.
fill( 0 );
84 m_radius = viewport->radius();
85 m_repaintNeeded =
true;
88 if ( m_repaintNeeded ) {
89 mapTexture( viewport, tileZoomLevel, painter->
mapQuality() );
92 texColorizer->colorize( &m_canvasImage, viewport, painter->
mapQuality() );
95 m_repaintNeeded =
false;
98 const int radius = viewport->radius() * viewport->currentProjection()->clippingRadius();
100 QRect rect( viewport->width() / 2 - radius, viewport->height() / 2 - radius,
101 2 * radius, 2 * radius);
102 rect = rect.intersected( dirtyRect );
103 painter->
drawImage( rect, m_canvasImage, rect );
106void GenericScanlineTextureMapper::mapTexture(
const ViewportParams *viewport,
int tileZoomLevel,
MapQuality mapQuality )
111 const int imageHeight = viewport->height();
112 const qint64 radius = viewport->radius() * viewport->currentProjection()->clippingRadius();
115 const int skip = ( mapQuality ==
LowQuality ) ? 1
117 const int yTop = ( imageHeight / 2 - radius >= 0 ) ? imageHeight / 2 - radius
119 const int yBottom = ( yTop == 0 ) ? imageHeight - skip
120 : yTop + radius + radius - skip;
123 const int yStep = qCeil(qreal( yBottom - yTop ) / qreal(numThreads));
124 for (
int i = 0; i < numThreads; ++i ) {
125 const int yStart = yTop + i * yStep;
126 const int yEnd = qMin(yBottom, yTop + (i + 1) * yStep);
127 QRunnable *
const job =
new RenderJob( m_tileLoader, tileZoomLevel, &m_canvasImage, viewport, mapQuality, yStart, yEnd );
128 m_threadPool.
start( job );
136void GenericScanlineTextureMapper::RenderJob::run()
138 const int imageWidth = m_canvasImage->
width();
139 const int imageHeight = m_canvasImage->
height();
140 const qint64 radius = m_viewport->radius();
142 const bool interlaced = ( m_mapQuality ==
LowQuality );
143 const bool highQuality = ( m_mapQuality ==
HighQuality
145 const bool printQuality = ( m_mapQuality ==
PrintQuality );
148 const int n = ScanlineTextureMapperContext::interpolationStep( m_viewport, m_mapQuality );
151 qreal northPoleX, northPoleY;
152 bool globeHidesNorthPole;
154 m_viewport->
screenCoordinates(northPole, northPoleX, northPoleY, globeHidesNorthPole );
158 ScanlineTextureMapperContext context( m_tileLoader, m_tileLevel );
160 qreal clipRadius = radius * m_viewport->currentProjection()->clippingRadius();
164 for (
int y = m_yTop; y < m_yBottom; ++y ) {
167 const int rx = (int)sqrt( (qreal)( clipRadius * clipRadius
168 - ( ( y - imageHeight / 2 )
169 * ( y - imageHeight / 2 ) ) ) );
183 const int xLeft = ( imageWidth / 2 - rx > 0 ) ? imageWidth / 2 - rx
185 const int xRight = ( imageWidth / 2 - rx > 0 ) ? xLeft + rx + rx
188 QRgb * scanLine = (QRgb*)( m_canvasImage->
scanLine( y ) ) + xLeft;
190 const int xIpLeft = ( imageWidth / 2 - rx > 0 ) ? n * (
int)( xLeft / n + 1 )
192 const int xIpRight = ( imageWidth / 2 - rx > 0 ) ? n * (
int)( xRight / n - 1 )
193 : n * (int)( xRight / n - 1 ) + 1;
196 bool crossingPoleArea =
false;
197 if ( !globeHidesNorthPole
198 && northPoleY - ( n * 0.75 ) <= y
199 && northPoleY + ( n * 0.75 ) >= y )
201 crossingPoleArea =
true;
207 for (
int x = xLeft; x < xRight; ++x ) {
210 const int leftInterval = xIpLeft + ncount * n;
212 bool interpolate =
false;
214 if ( x >= xIpLeft && x <= xIpRight ) {
217 if ( crossingPoleArea
218 && northPoleX >= leftInterval + n
219 && northPoleX < leftInterval + 2 * n
220 && x < leftInterval + 3 * n )
226 interpolate = !printQuality;
235 m_viewport->
geoCoordinates(x,y, lon, lat, GeoDataCoordinates::Radian);
239 context.pixelValueApproxF( lon, lat, scanLine, n );
241 context.pixelValueApprox( lon, lat, scanLine, n );
243 scanLine += ( n - 1 );
246 if ( x < imageWidth ) {
248 context.pixelValueF( lon, lat, scanLine );
250 context.pixelValue( lon, lat, scanLine );
257 if ( interlaced && y + 1 < m_yBottom ) {
259 const int pixelByteSize = m_canvasImage->
bytesPerLine() / imageWidth;
261 memcpy( m_canvasImage->
scanLine( y + 1 ) + xLeft * pixelByteSize,
262 m_canvasImage->
scanLine( y ) + xLeft * pixelByteSize,
263 ( xRight - xLeft ) * pixelByteSize );
This file contains the headers for AbstractProjection.
This file contains the headers for ViewParameters.
This file contains the headers for ViewportParams.
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.
bool geoCoordinates(const int x, const int y, qreal &lon, qreal &lat, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Degree) const
Get the earth coordinates corresponding to a pixel 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)