86 const int imgWidth = img.width(), imgHeight = img.height();
87 QRgb *imgPtr =
reinterpret_cast<QRgb *
>( img.bits() );
88 const QRgb *elevPtr =
reinterpret_cast<const QRgb *
>( mElevationImage.constBits() );
90 const int neighbours[] = { -1, 0, 1, 0, 0, -1, 0, 1 };
91 for (
int i = 0; i < imgWidth; ++i )
93 for (
int j = 0; j < imgHeight; ++j )
100 for (
qgssize k = 0; k < 4; ++k )
102 float borderFactor = 1.0f;
103 int iNeighbour = std::clamp( i + distance * neighbours[2 * k], 0, imgWidth - 1 );
104 int jNeighbour = std::clamp( j + distance * neighbours[2 * k + 1], 0, imgHeight - 1 );
105 qgssize neighbourIndex = jNeighbour *
static_cast<qgssize>( imgWidth ) + iNeighbour;
109 if (
isNoData( elevPtr[ neighbourIndex ] ) )
111 if ( neighbours[2 * k] != 0 )
113 int corrI = iNeighbour;
114 int inc = neighbours[2 * k];
115 while ( corrI != i &&
isNoData( elevPtr[ neighbourIndex ] ) )
118 neighbourIndex = jNeighbour *
static_cast<qgssize>( imgWidth ) + corrI;
123 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( std::abs( i - corrI ) ) ;
126 if ( neighbours[2 * k + 1] != 0 )
128 int corrJ = jNeighbour;
129 int inc = neighbours[2 * k + 1];
130 while ( corrJ != j &&
isNoData( elevPtr[ neighbourIndex ] ) )
133 neighbourIndex = corrJ *
static_cast<qgssize>( imgWidth ) + iNeighbour;
138 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( std::abs( j - corrJ ) ) ;
144 if ( neighbours[2 * k] != 0 && std::abs( iNeighbour - i ) < distance )
146 if ( i > iNeighbour )
147 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( i ) ;
148 else if ( i < iNeighbour )
149 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( ( imgWidth - i - 1 ) ) ;
151 if ( neighbours[2 * k + 1] != 0 && std::abs( jNeighbour - j ) < distance )
153 if ( j > jNeighbour )
154 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( j ) ;
155 else if ( j < jNeighbour )
156 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( imgHeight - j - 1 ) ;
160 factor += std::max<float>( 0, -( centerDepth - neighbourDepth ) * borderFactor );
162 float shade = expf( -factor * strength / rendererScale );
164 QRgb
c = imgPtr[ index ];
165 imgPtr[ index ] = qRgba(
static_cast<int>(
static_cast<float>( qRed(
c ) ) * shade ),
166 static_cast<int>(
static_cast<float>( qGreen(
c ) ) * shade ),
167 static_cast<int>(
static_cast<float>( qBlue(
c ) ) * shade )
176 double altRad = altitude * M_PI / 180.0;
177 double cos_altRadian = std::cos( altRad );
178 double sin_altRadian = std::sin( altRad );
179 double cos_alt_mul_z = cos_altRadian * zFactor ;
180 double azimuthRad = -1 * azimuth * M_PI / 180.0;
181 double cos_az_mul_cos_alt_mul_z = std::cos( azimuthRad ) * cos_alt_mul_z;
182 double sin_az_mul_cos_alt_mul_z = std::sin( azimuthRad ) * cos_alt_mul_z;
187 double cos225_az_mul_cos_alt_mul_z_mul_0_5 = -32.87001872802012 * cos_alt_mul_z / 255;
188 double square_z = zFactor * zFactor;
190 QRgb *imgPtr =
reinterpret_cast<QRgb *
>( img.bits() );
191 const QRgb *elevPtr =
reinterpret_cast<const QRgb *
>( mElevationImage.constBits() );
193 const int imgWidth = img.width(), imgHeight = img.height();
195 auto colRowToIndex = [&](
int c,
int r )->
qgssize
197 return static_cast<qgssize>( r ) * imgWidth +
c ;
206 float pixelValues[9];
208 for (
int rowC = 0; rowC < imgHeight ; ++rowC )
210 int rowU = std::max( 0, rowC - 1 );
211 int rowD = std::min( imgHeight - 1, rowC + 1 );
222 for (
int colC = 0; colC < imgWidth ; ++colC )
224 qgssize centerIndex = colRowToIndex( colC, rowC );
225 int colR = std::min( imgWidth - 1, colC + 1 );
227 pixelValues[0] = pixelValues[1];
228 pixelValues[3] = pixelValues[4];
229 pixelValues[6] = pixelValues[7];
231 pixelValues[1] = pixelValues[2];
232 pixelValues[4] = pixelValues[5];
233 pixelValues[7] = pixelValues[8];
235 pixelValues[2] =
decodeElevation( elevPtr[colRowToIndex( colR, rowU )] );
236 pixelValues[5] =
decodeElevation( elevPtr[colRowToIndex( colR, rowC )] );
237 pixelValues[8] =
decodeElevation( elevPtr[colRowToIndex( colR, rowD )] );
239 if ( elevPtr[centerIndex] != 0 )
242 const float x22 = pixelValues[4];
246 const float x11 = ( pixelValues[0] == noData ) ? x22 : pixelValues[0];
247 const float x21 = ( pixelValues[3] == noData ) ? x22 : pixelValues[3];
248 const float x31 = ( pixelValues[6] == noData ) ? x22 : pixelValues[6];
250 const float x12 = ( pixelValues[1] == noData ) ? x22 : pixelValues[1];
251 const float x32 = ( pixelValues[7] == noData ) ? x22 : pixelValues[7];
253 const float x13 = ( pixelValues[2] == noData ) ? x22 : pixelValues[2];
254 const float x23 = ( pixelValues[5] == noData ) ? x22 : pixelValues[5];
255 const float x33 = ( pixelValues[8] == noData ) ? x22 : pixelValues[8];
257 const double derX =
static_cast<double>( ( x13 + x23 + x23 + x33 ) - ( x11 + x21 + x21 + x31 ) ) / ( 8 * cellSizeX );
258 const double derY =
static_cast<double>( ( x31 + x32 + x32 + x33 ) - ( x11 + x12 + x12 + x13 ) ) / ( 8 * -cellSizeY );
261 if ( !multiDirectional )
264 shade = std::clamp( ( sin_altRadian -
265 ( derY * cos_az_mul_cos_alt_mul_z -
266 derX * sin_az_mul_cos_alt_mul_z ) ) /
267 std::sqrt( 1 + square_z * ( derX * derX + derY * derY ) ),
274 const double xx = derX * derX;
275 const double yy = derY * derY;
276 const double xx_plus_yy = xx + yy;
278 if ( xx_plus_yy == 0.0 )
280 shade = std::clamp( sin_altRadian, 0.0, 1.0 );
285 double val225_mul_0_5 = sin_altRadian * 0.5 +
286 ( derX - derY ) * cos225_az_mul_cos_alt_mul_z_mul_0_5;
287 val225_mul_0_5 = ( val225_mul_0_5 <= 0.0 ) ? 0.0 : val225_mul_0_5;
288 double val270_mul_0_5 = sin_altRadian * 0.5 -
289 derX * cos_alt_mul_z * 0.5;
290 val270_mul_0_5 = ( val270_mul_0_5 <= 0.0 ) ? 0.0 : val270_mul_0_5;
291 double val315_mul_0_5 = sin_altRadian * 0.5 +
292 ( derX + derY ) * cos225_az_mul_cos_alt_mul_z_mul_0_5;
293 val315_mul_0_5 = ( val315_mul_0_5 <= 0.0 ) ? 0.0 : val315_mul_0_5;
294 double val360_mul_0_5 = sin_altRadian * 0.5 -
295 derY * cos_alt_mul_z * 0.5;
296 val360_mul_0_5 = ( val360_mul_0_5 <= 0.0 ) ? 0.0 : val360_mul_0_5;
299 const double weight_225 = 0.5 * xx_plus_yy - derX * derY;
300 const double weight_270 = xx;
301 const double weight_315 = xx_plus_yy - weight_225;
302 const double weight_360 = yy;
303 const double cang_mul_127 = (
304 ( weight_225 * val225_mul_0_5 +
305 weight_270 * val270_mul_0_5 +
306 weight_315 * val315_mul_0_5 +
307 weight_360 * val360_mul_0_5 ) / xx_plus_yy ) /
308 ( 1 + square_z * xx_plus_yy );
310 shade = std::clamp( cang_mul_127, 0.0, 1.0 );
314 QRgb
c = imgPtr[ centerIndex ];
315 imgPtr[ centerIndex ] = qRgba(
static_cast<int>(
static_cast<float>( qRed(
c ) ) * shade ),
316 static_cast<int>(
static_cast<float>( qGreen(
c ) ) * shade ),
317 static_cast<int>(
static_cast<float>( qBlue(
c ) ) * shade )