• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.14
  • kdeedu
  • marble
  • src
  • lib
  • marble
SphericalScanlineTextureMapper.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2007 Torsten Rahn <tackat@kde.org>
9 // Copyright 2011 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
10 //
11 
12 
13 #include "SphericalScanlineTextureMapper.h"
14 
15 #include <cmath>
16 
17 #include <QtCore/qmath.h>
18 #include <QRunnable>
19 
20 #include "MarbleGlobal.h"
21 #include "GeoPainter.h"
22 #include "GeoDataPolygon.h"
23 #include "GeoDataDocument.h"
24 #include "MarbleDebug.h"
25 #include "Quaternion.h"
26 #include "ScanlineTextureMapperContext.h"
27 #include "StackedTileLoader.h"
28 #include "StackedTile.h"
29 #include "TextureColorizer.h"
30 #include "ViewportParams.h"
31 #include "MathHelper.h"
32 
33 
34 using namespace Marble;
35 
36 class SphericalScanlineTextureMapper::RenderJob : public QRunnable
37 {
38 public:
39  RenderJob( StackedTileLoader *tileLoader, int tileLevel, QImage *canvasImage, const ViewportParams *viewport, MapQuality mapQuality, int yTop, int yBottom );
40 
41  virtual void run();
42 
43 private:
44  StackedTileLoader *const m_tileLoader;
45  const int m_tileLevel;
46  QImage *const m_canvasImage;
47  const ViewportParams *const m_viewport;
48  const MapQuality m_mapQuality;
49  int const m_yTop;
50  int const m_yBottom;
51 };
52 
53 SphericalScanlineTextureMapper::RenderJob::RenderJob( StackedTileLoader *tileLoader, int tileLevel, QImage *canvasImage, const ViewportParams *viewport, MapQuality mapQuality, int yTop, int yBottom )
54  : m_tileLoader( tileLoader ),
55  m_tileLevel( tileLevel ),
56  m_canvasImage( canvasImage ),
57  m_viewport( viewport ),
58  m_mapQuality( mapQuality ),
59  m_yTop( yTop ),
60  m_yBottom( yBottom )
61 {
62 }
63 
64 SphericalScanlineTextureMapper::SphericalScanlineTextureMapper( StackedTileLoader *tileLoader )
65  : TextureMapperInterface()
66  , m_tileLoader( tileLoader )
67  , m_radius( 0 )
68  , m_threadPool()
69 {
70 }
71 
72 void SphericalScanlineTextureMapper::mapTexture( GeoPainter *painter,
73  const ViewportParams *viewport,
74  int tileZoomLevel,
75  const QRect &dirtyRect,
76  TextureColorizer *texColorizer )
77 {
78  if ( m_canvasImage.size() != viewport->size() || m_radius != viewport->radius() ) {
79  const QImage::Format optimalFormat = ScanlineTextureMapperContext::optimalCanvasImageFormat( viewport );
80 
81  if ( m_canvasImage.size() != viewport->size() || m_canvasImage.format() != optimalFormat ) {
82  m_canvasImage = QImage( viewport->size(), optimalFormat );
83  }
84 
85  if ( !viewport->mapCoversViewport() ) {
86  m_canvasImage.fill( 0 );
87  }
88 
89  m_radius = viewport->radius();
90  m_repaintNeeded = true;
91  }
92 
93  if ( m_repaintNeeded ) {
94  mapTexture( viewport, tileZoomLevel, painter->mapQuality() );
95 
96  if ( texColorizer ) {
97  texColorizer->colorize( &m_canvasImage, viewport, painter->mapQuality() );
98  }
99 
100  m_repaintNeeded = false;
101  }
102 
103  const int radius = viewport->radius();
104 
105  QRect rect( viewport->width() / 2 - radius, viewport->height() / 2 - radius,
106  2 * radius, 2 * radius);
107 #if QT_VERSION < 0x050000
108  rect = rect.intersect( dirtyRect );
109 #else
110  rect = rect.intersected( dirtyRect );
111 #endif
112  painter->drawImage( rect, m_canvasImage, rect );
113 }
114 
115 void SphericalScanlineTextureMapper::mapTexture( const ViewportParams *viewport, int tileZoomLevel, MapQuality mapQuality )
116 {
117  // Reset backend
118  m_tileLoader->resetTilehash();
119 
120  // Initialize needed constants:
121 
122  const int imageHeight = m_canvasImage.height();
123  const qint64 radius = viewport->radius();
124 
125  // Calculate the actual y-range of the map on the screen
126  const int skip = ( mapQuality == LowQuality ) ? 1
127  : 0;
128  const int yTop = ( imageHeight / 2 - radius >= 0 ) ? imageHeight / 2 - radius
129  : 0;
130  const int yBottom = ( yTop == 0 ) ? imageHeight - skip
131  : yTop + radius + radius - skip;
132 
133  const int numThreads = m_threadPool.maxThreadCount();
134  const int yStep = qCeil(qreal( yBottom - yTop ) / qreal(numThreads));
135  for ( int i = 0; i < numThreads; ++i ) {
136  const int yStart = yTop + i * yStep;
137  const int yEnd = qMin(yBottom, yTop + (i + 1) * yStep);
138  QRunnable *const job = new RenderJob( m_tileLoader, tileZoomLevel, &m_canvasImage, viewport, mapQuality, yStart, yEnd );
139  m_threadPool.start( job );
140  }
141 
142  m_threadPool.waitForDone();
143 
144  m_tileLoader->cleanupTilehash();
145 }
146 
147 void SphericalScanlineTextureMapper::RenderJob::run()
148 {
149  const int imageHeight = m_canvasImage->height();
150  const int imageWidth = m_canvasImage->width();
151  const qint64 radius = m_viewport->radius();
152  const qreal inverseRadius = 1.0 / (qreal)(radius);
153 
154  const bool interlaced = ( m_mapQuality == LowQuality );
155  const bool highQuality = ( m_mapQuality == HighQuality
156  || m_mapQuality == PrintQuality );
157  const bool printQuality = ( m_mapQuality == PrintQuality );
158 
159  // Evaluate the degree of interpolation
160  const int n = ScanlineTextureMapperContext::interpolationStep( m_viewport, m_mapQuality );
161 
162  // Calculate north pole position to decrease pole distortion later on
163  Quaternion northPole = Quaternion::fromSpherical( 0.0, M_PI * 0.5 );
164  northPole.rotateAroundAxis( m_viewport->planetAxis().inverse() );
165  const int northPoleX = imageWidth / 2 + (int)( radius * northPole.v[Q_X] );
166  const int northPoleY = imageHeight / 2 - (int)( radius * northPole.v[Q_Y] );
167 
168  // Calculate axis matrix to represent the planet's rotation.
169  matrix planetAxisMatrix;
170  m_viewport->planetAxis().toMatrix( planetAxisMatrix );
171 
172  // initialize needed variables that are modified during texture mapping:
173 
174  ScanlineTextureMapperContext context( m_tileLoader, m_tileLevel );
175  qreal lon = 0.0;
176  qreal lat = 0.0;
177 
178  // Scanline based algorithm to texture map a sphere
179  for ( int y = m_yTop; y < m_yBottom ; ++y ) {
180 
181  // Evaluate coordinates for the 3D position vector of the current pixel
182  const qreal qy = inverseRadius * (qreal)( imageHeight / 2 - y );
183  const qreal qr = 1.0 - qy * qy;
184 
185  // rx is the radius component in x direction
186  const int rx = (int)sqrt( (qreal)( radius * radius
187  - ( ( y - imageHeight / 2 )
188  * ( y - imageHeight / 2 ) ) ) );
189 
190  // Calculate the actual x-range of the map within the current scanline.
191  //
192  // If the circular border of the earth disk is still visible then xLeft
193  // equals the scanline position of the most left pixel that gets covered
194  // by the earth disk. In terms of math this equals the half image width minus
195  // the radius component on the current scanline in x direction ("rx").
196  //
197  // If the zoom factor is high enough then the whole screen gets covered
198  // by the earth and the border of the earth disk isn't visible anymore.
199  // In that situation xLeft equals zero.
200  // For xRight the situation is similar.
201 
202  const int xLeft = ( imageWidth / 2 - rx > 0 ) ? imageWidth / 2 - rx
203  : 0;
204  const int xRight = ( imageWidth / 2 - rx > 0 ) ? xLeft + rx + rx
205  : imageWidth;
206 
207  QRgb * scanLine = (QRgb*)( m_canvasImage->scanLine( y ) ) + xLeft;
208 
209  const int xIpLeft = ( imageWidth / 2 - rx > 0 ) ? n * (int)( xLeft / n + 1 )
210  : 1;
211  const int xIpRight = ( imageWidth / 2 - rx > 0 ) ? n * (int)( xRight / n - 1 )
212  : n * (int)( xRight / n - 1 ) + 1;
213 
214  // Decrease pole distortion due to linear approximation ( y-axis )
215  bool crossingPoleArea = false;
216  if ( northPole.v[Q_Z] > 0
217  && northPoleY - ( n * 0.75 ) <= y
218  && northPoleY + ( n * 0.75 ) >= y )
219  {
220  crossingPoleArea = true;
221  }
222 
223  int ncount = 0;
224 
225  for ( int x = xLeft; x < xRight; ++x ) {
226  // Prepare for interpolation
227 
228  const int leftInterval = xIpLeft + ncount * n;
229 
230  bool interpolate = false;
231  if ( x >= xIpLeft && x <= xIpRight ) {
232 
233  // Decrease pole distortion due to linear approximation ( x-axis )
234 // mDebug() << QString("NorthPole X: %1, LeftInterval: %2").arg( northPoleX ).arg( leftInterval );
235  if ( crossingPoleArea
236  && northPoleX >= leftInterval + n
237  && northPoleX < leftInterval + 2 * n
238  && x < leftInterval + 3 * n )
239  {
240  interpolate = false;
241  }
242  else {
243  x += n - 1;
244  interpolate = !printQuality;
245  ++ncount;
246  }
247  }
248  else
249  interpolate = false;
250 
251  // Evaluate more coordinates for the 3D position vector of
252  // the current pixel.
253  const qreal qx = (qreal)( x - imageWidth / 2 ) * inverseRadius;
254  const qreal qr2z = qr - qx * qx;
255  const qreal qz = ( qr2z > 0.0 ) ? sqrt( qr2z ) : 0.0;
256 
257  // Create Quaternion from vector coordinates and rotate it
258  // around globe axis
259  Quaternion qpos( 0.0, qx, qy, qz );
260  qpos.rotateAroundAxis( planetAxisMatrix );
261 
262  qpos.getSpherical( lon, lat );
263 // mDebug() << QString("lon: %1 lat: %2").arg(lon).arg(lat);
264  // Approx for n-1 out of n pixels within the boundary of
265  // xIpLeft to xIpRight
266 
267  if ( interpolate ) {
268  if (highQuality)
269  context.pixelValueApproxF( lon, lat, scanLine, n );
270  else
271  context.pixelValueApprox( lon, lat, scanLine, n );
272 
273  scanLine += ( n - 1 );
274  }
275 
276 // Comment out the pixelValue line and run Marble if you want
277 // to understand the interpolation:
278 
279 // Uncomment the crossingPoleArea line to check precise
280 // rendering around north pole:
281 
282 // if ( !crossingPoleArea )
283  if ( x < imageWidth ) {
284  if ( highQuality )
285  context.pixelValueF( lon, lat, scanLine );
286  else
287  context.pixelValue( lon, lat, scanLine );
288  }
289 
290  ++scanLine;
291  }
292 
293  // copy scanline to improve performance
294  if ( interlaced && y + 1 < m_yBottom ) {
295 
296  const int pixelByteSize = m_canvasImage->bytesPerLine() / imageWidth;
297 
298  memcpy( m_canvasImage->scanLine( y + 1 ) + xLeft * pixelByteSize,
299  m_canvasImage->scanLine( y ) + xLeft * pixelByteSize,
300  ( xRight - xLeft ) * pixelByteSize );
301  ++y;
302  }
303  }
304 }
GeoDataDocument.h
Quaternion.h
interpolate
void interpolate(MarbleWidget *widget, qreal value)
Definition: examples/cpp/animation-video/main.cpp:68
Marble::matrix
xmmfloat matrix[3]
Definition: Quaternion.h:38
Marble::ViewportParams::size
QSize size() const
Definition: ViewportParams.cpp:260
GeoDataPolygon.h
Marble::GeoPainter
A painter that allows to draw geometric primitives on the map.
Definition: GeoPainter.h:98
Marble::TextureColorizer::colorize
void colorize(QImage *origimg, const ViewportParams *viewport, MapQuality mapQuality)
Definition: TextureColorizer.cpp:228
Marble::PrintQuality
Print quality.
Definition: MarbleGlobal.h:87
Marble::MapQuality
MapQuality
This enum is used to choose the map quality shown in the view.
Definition: MarbleGlobal.h:82
ScanlineTextureMapperContext.h
MarbleDebug.h
TextureColorizer.h
Marble::StackedTileLoader
Tile loading from a quad tree.
Definition: StackedTileLoader.h:59
QRunnable
Marble::ViewportParams::height
int height() const
Definition: ViewportParams.cpp:255
Marble::Quaternion::rotateAroundAxis
void rotateAroundAxis(const Quaternion &q)
Definition: Quaternion.cpp:191
Marble::LowQuality
Low resolution (e.g. interlaced)
Definition: MarbleGlobal.h:84
QRect
Marble::ViewportParams::width
int width() const
Definition: ViewportParams.cpp:250
QThreadPool::maxThreadCount
maxThreadCount
QImage::fill
void fill(uint pixelValue)
Marble::TextureMapperInterface
Definition: TextureMapperInterface.h:27
SphericalScanlineTextureMapper.h
MathHelper.h
Marble::ViewportParams::mapCoversViewport
bool mapCoversViewport() const
Definition: ViewportParams.cpp:398
Marble::ScanlineTextureMapperContext::optimalCanvasImageFormat
static QImage::Format optimalCanvasImageFormat(const ViewportParams *viewport)
Definition: ScanlineTextureMapperContext.cpp:429
Marble::radius
static qreal radius(qreal zoom)
Definition: thumbnailer.cpp:99
Marble::StackedTileLoader::cleanupTilehash
void cleanupTilehash()
Cleans up the internal tile hash.
Definition: StackedTileLoader.cpp:100
Marble::Q_Z
Definition: Quaternion.h:32
QtConcurrent::run
QFuture< T > run(Function function,...)
GeoPainter.h
MarbleGlobal.h
QRect::intersected
QRect intersected(const QRect &rectangle) const
Marble::ViewportParams
A public class that controls what is visible in the viewport of a Marble map.
Definition: ViewportParams.h:44
Marble::Q_Y
Definition: Quaternion.h:31
Marble::GeoPainter::drawImage
void drawImage(const GeoDataCoordinates &centerPosition, const QImage &image)
Draws an image at the given position. The image is placed with its center located at the given center...
Definition: GeoPainter.cpp:428
Marble::TextureColorizer
Definition: TextureColorizer.h:33
Marble::Q_X
Definition: Quaternion.h:30
ViewportParams.h
This file contains the headers for ViewportParams.
QImage
QThreadPool::waitForDone
void waitForDone()
Marble::SphericalScanlineTextureMapper::SphericalScanlineTextureMapper
SphericalScanlineTextureMapper(StackedTileLoader *tileLoader)
Definition: SphericalScanlineTextureMapper.cpp:64
Marble::TextureMapperInterface::m_repaintNeeded
bool m_repaintNeeded
Definition: TextureMapperInterface.h:42
Marble::ViewportParams::radius
int radius() const
Definition: ViewportParams.cpp:195
Marble::HighQuality
High quality (e.g. antialiasing for lines)
Definition: MarbleGlobal.h:86
Marble::ScanlineTextureMapperContext::interpolationStep
static int interpolationStep(const ViewportParams *viewport, MapQuality mapQuality)
Definition: ScanlineTextureMapperContext.cpp:401
StackedTile.h
Marble::Quaternion
Definition: Quaternion.h:41
QImage::size
QSize size() const
M_PI
#define M_PI
Definition: GeoDataCoordinates.h:26
QRect::intersect
QRect intersect(const QRect &rectangle) const
Marble::Quaternion::v
xmmfloat v
Definition: Quaternion.h:87
Marble::ScanlineTextureMapperContext
Definition: ScanlineTextureMapperContext.h:30
QImage::height
int height() const
Marble::GeoPainter::mapQuality
MapQuality mapQuality() const
Returns the map quality.
Definition: GeoPainter.cpp:191
QThreadPool::start
void start(QRunnable *runnable, int priority)
QImage::format
Format format() const
Marble::SphericalScanlineTextureMapper::mapTexture
virtual void mapTexture(GeoPainter *painter, const ViewportParams *viewport, int tileZoomLevel, const QRect &dirtyRect, TextureColorizer *texColorizer)
Definition: SphericalScanlineTextureMapper.cpp:72
Marble::StackedTileLoader::resetTilehash
void resetTilehash()
Resets the internal tile hash.
Definition: StackedTileLoader.cpp:90
Marble::Quaternion::fromSpherical
static Quaternion fromSpherical(qreal lon, qreal lat)
used to generate Quaternion from longitude and latitude
Definition: Quaternion.cpp:38
StackedTileLoader.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:42 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal