File indexing completed on 2024-04-21 03:49:55
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2007 Andrew Manson <g.real.ate@gmail.com> 0004 // SPDX-FileCopyrightText: 2011 Bernhard Beschow <bbeschow@cs.tu-berlin.de> 0005 // 0006 0007 #ifndef MARBLE_SCANLINETEXTUREMAPPERCONTEXT_H 0008 #define MARBLE_SCANLINETEXTUREMAPPERCONTEXT_H 0009 0010 #include <QSize> 0011 #include <QImage> 0012 0013 #include "GeoSceneTileDataset.h" 0014 #include "MarbleMath.h" 0015 #include "MathHelper.h" 0016 0017 namespace Marble 0018 { 0019 0020 class StackedTile; 0021 class StackedTileLoader; 0022 class ViewportParams; 0023 0024 0025 class ScanlineTextureMapperContext 0026 { 0027 public: 0028 ScanlineTextureMapperContext( StackedTileLoader * const tileLoader, int tileLevel ); 0029 0030 void pixelValueF( const qreal lon, const qreal lat, 0031 QRgb* const scanLine ); 0032 void pixelValue( const qreal lon, const qreal lat, 0033 QRgb* const scanLine ); 0034 0035 void pixelValueApproxF( const qreal lon, const qreal lat, 0036 QRgb *scanLine, const int n ); 0037 void pixelValueApprox( const qreal lon, const qreal lat, 0038 QRgb *scanLine, const int n ); 0039 0040 static int interpolationStep( const ViewportParams *viewport, MapQuality mapQuality ); 0041 0042 static QImage::Format optimalCanvasImageFormat( const ViewportParams *viewport ); 0043 0044 int globalWidth() const; 0045 int globalHeight() const; 0046 0047 private: 0048 // method for fast integer calculation 0049 void nextTile( int& posx, int& posy ); 0050 0051 // method for precise interpolation 0052 void nextTile( qreal& posx, qreal& posy ); 0053 0054 // Converts Radian to global texture coordinates 0055 // ( with origin in center, measured in pixel) 0056 qreal rad2PixelX( const qreal lon ) const; 0057 qreal rad2PixelY( const qreal lat ) const; 0058 0059 // Checks whether the pixelValueApprox method will make use of more than 0060 // one tile 0061 bool isOutOfTileRange( const int itLon, const int itLat, 0062 const int itStepLon, const int itStepLat, 0063 const int n ) const; 0064 0065 bool isOutOfTileRangeF( const qreal itLon, const qreal itLat, 0066 const qreal itStepLon, const qreal itStepLat, 0067 const int n ) const; 0068 0069 private: 0070 StackedTileLoader *const m_tileLoader; 0071 GeoSceneAbstractTileProjection::Type const m_textureProjection; 0072 /// size of the tiles of the current texture layer 0073 QSize const m_tileSize; 0074 0075 int const m_tileLevel; 0076 int const m_globalWidth; 0077 int const m_globalHeight; 0078 qreal const m_normGlobalWidth; 0079 qreal const m_normGlobalHeight; 0080 0081 const StackedTile *m_tile; 0082 0083 // Coordinate transformations: 0084 0085 // Position of the tile in global Texture Coordinates 0086 // ( with origin in upper left corner, measured in pixel) 0087 int m_tilePosX; 0088 int m_tilePosY; 0089 0090 // Converts global texture coordinates 0091 // ( with origin in center, measured in pixel) 0092 // to tile coordinates ( measured in pixel ) 0093 qreal m_toTileCoordinatesLon; 0094 qreal m_toTileCoordinatesLat; 0095 0096 // Previous coordinates 0097 qreal m_prevLat; 0098 qreal m_prevLon; 0099 qreal m_prevPixelX; 0100 qreal m_prevPixelY; 0101 }; 0102 0103 inline int ScanlineTextureMapperContext::globalWidth() const 0104 { 0105 return m_globalWidth; 0106 } 0107 0108 inline int ScanlineTextureMapperContext::globalHeight() const 0109 { 0110 return m_globalHeight; 0111 } 0112 0113 inline qreal ScanlineTextureMapperContext::rad2PixelX( const qreal lon ) const 0114 { 0115 return lon * m_normGlobalWidth; 0116 } 0117 0118 inline qreal ScanlineTextureMapperContext::rad2PixelY( const qreal lat ) const 0119 { 0120 switch ( m_textureProjection ) { 0121 case GeoSceneAbstractTileProjection::Equirectangular: 0122 return -lat * m_normGlobalHeight; 0123 case GeoSceneAbstractTileProjection::Mercator: 0124 if ( fabs( lat ) < 1.4835 ) { 0125 // We develop the inverse Gudermannian into a MacLaurin Series: 0126 // In spite of the many elements needed to get decent 0127 // accuracy this is still faster by far than calculating the 0128 // trigonometric expression: 0129 // return - asinh( tan( lat ) ) * 0.5 * m_normGlobalHeight; 0130 0131 // We are using the Horner Scheme as a polynom representation 0132 0133 return - gdInv( lat ) * 0.5 * m_normGlobalHeight; 0134 } 0135 if ( lat >= +1.4835 ) 0136 // asinh( tan (1.4835)) => 3.1309587 0137 return - 3.1309587 * 0.5 * m_normGlobalHeight; 0138 if ( lat <= -1.4835 ) 0139 // asinh( tan( -1.4835 )) => −3.1309587 0140 return 3.1309587 * 0.5 * m_normGlobalHeight; 0141 } 0142 0143 // Dummy value to avoid a warning. 0144 return 0.0; 0145 } 0146 0147 } 0148 0149 #endif