33 const QgsPointXY topLeftLonLat( -180, 180.0 / M_PI * std::atan( std::sinh( M_PI ) ) );
34 const QgsPointXY bottomRightLonLat( 180, 180.0 / M_PI * std::atan( std::sinh( -M_PI ) ) );
37 mXSpan = ( bottomRight.
x() - topLeft.
x() );
51 ds.
uri =
"https://s3.amazonaws.com/elevation-tiles-prod/terrarium/{z}/{x}/{y}.png";
60 const QString uri = QString(
"type=xyz&url=%1&zmin=%2&zmax=%3" ).arg( mDataSource.
uri ).arg( mDataSource.
zMin ).arg( mDataSource.
zMax );
65 void QgsTerrainDownloader::adjustExtentAndResolution(
double mupp,
const QgsRectangle &extentOrig,
QgsRectangle &extent,
int &res )
67 const double xMin = floor( extentOrig.
xMinimum() / mupp ) * mupp;
68 const double xMax = ceil( extentOrig.
xMaximum() / mupp ) * mupp;
70 const double yMin = floor( extentOrig.
yMinimum() / mupp ) * mupp;
71 const double yMax = ceil( extentOrig.
yMaximum() / mupp ) * mupp;
74 res = round( ( xMax - xMin ) / mupp );
78 double QgsTerrainDownloader::findBestTileResolution(
double requestedMupp )
const
81 for ( ; zoom <= 15; ++zoom )
83 const double tileMupp = mXSpan / ( 256 * ( 1 << zoom ) );
84 if ( tileMupp <= requestedMupp )
88 if ( zoom > 15 ) zoom = 15;
89 const double finalMupp = mXSpan / ( 256 * ( 1 << zoom ) );
94 void QgsTerrainDownloader::tileImageToHeightMap(
const QImage &img, QByteArray &heightMap )
100 const QRgb *rgb =
reinterpret_cast<const QRgb *
>( img.constBits() );
101 const int count = img.width() * img.height();
102 heightMap.resize(
sizeof(
float ) * count );
103 float *hData =
reinterpret_cast<float *
>( heightMap.data() );
104 for (
int i = 0; i < count; ++i )
106 const QRgb
c = rgb[i];
107 if ( qAlpha(
c ) == 255 )
109 const float h = qRed(
c ) * 256 + qGreen(
c ) + qBlue(
c ) / 256.f - 32768;
114 *hData++ = std::numeric_limits<float>::quiet_NaN();
122 if ( !mOnlineDtm || !mOnlineDtm->isValid() )
129 if ( destCrs != mOnlineDtm->crs() )
137 const double requestedMupp = extentTr.
width() / res;
138 const double finalMupp = findBestTileResolution( requestedMupp );
143 const int resOrig = res;
144 adjustExtentAndResolution( finalMupp, extentTr, extent, res );
148 QgsRasterBlock *b = mOnlineDtm->dataProvider()->block( 1, extent, res, res );
149 const QImage img = b->
image();
151 if ( !tmpFilenameImg.isEmpty() )
152 img.save( tmpFilenameImg );
156 QByteArray heightMap;
157 tileImageToHeightMap( img, heightMap );
163 if ( !tmpFilenameTif.isEmpty() )
168 if ( !hSrcDS || !hDstDS )
170 QgsDebugMsg(
"failed to create GDAL dataset for heightmap" );
174 const CPLErr err = GDALRasterIO( GDALGetRasterBand( hSrcDS.get(), 1 ), GF_Write, 0, 0, res, res, heightMap.data(), res, res, GDT_Float32, 0, 0 );
175 if ( err != CE_None )
177 QgsDebugMsg(
"failed to write heightmap data to GDAL dataset" );
185 QByteArray heightMapOut;
186 heightMapOut.resize( resOrig * resOrig *
sizeof(
float ) );
187 char *data = heightMapOut.data();
191 const CPLErr err2 = GDALRasterIO( GDALGetRasterBand( hDstDS.get(), 1 ), GF_Read, 0, 0, resOrig, resOrig, data, resOrig, resOrig, GDT_Float32, 0, 0 );
192 if ( err2 != CE_None )
194 QgsDebugMsg(
"failed to read heightmap data from GDAL dataset" );