90 const int imgWidth = img.width(), imgHeight = img.height();
91 QRgb *imgPtr =
reinterpret_cast<QRgb *
>( img.bits() );
92 const QRgb *elevPtr =
reinterpret_cast<const QRgb *
>( mElevationImage.constBits() );
94 const int neighbours[] = { -1, 0, 1, 0, 0, -1, 0, 1 };
95 for (
int i = 0; i < imgWidth; ++i )
97 for (
int j = 0; j < imgHeight; ++j )
104 for (
qgssize k = 0; k < 4; ++k )
106 float borderFactor = 1.0f;
107 int iNeighbour = std::clamp( i + distance * neighbours[2 * k], 0, imgWidth - 1 );
108 int jNeighbour = std::clamp( j + distance * neighbours[2 * k + 1], 0, imgHeight - 1 );
109 qgssize neighbourIndex = jNeighbour *
static_cast<qgssize>( imgWidth ) + iNeighbour;
113 if (
isNoData( elevPtr[ neighbourIndex ] ) )
115 if ( neighbours[2 * k] != 0 )
117 int corrI = iNeighbour;
118 int inc = neighbours[2 * k];
119 while ( corrI != i &&
isNoData( elevPtr[ neighbourIndex ] ) )
122 neighbourIndex = jNeighbour *
static_cast<qgssize>( imgWidth ) + corrI;
127 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( std::abs( i - corrI ) ) ;
130 if ( neighbours[2 * k + 1] != 0 )
132 int corrJ = jNeighbour;
133 int inc = neighbours[2 * k + 1];
134 while ( corrJ != j &&
isNoData( elevPtr[ neighbourIndex ] ) )
137 neighbourIndex = corrJ *
static_cast<qgssize>( imgWidth ) + iNeighbour;
142 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( std::abs( j - corrJ ) ) ;
148 if ( neighbours[2 * k] != 0 && std::abs( iNeighbour - i ) < distance )
150 if ( i > iNeighbour )
151 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( i ) ;
152 else if ( i < iNeighbour )
153 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( ( imgWidth - i - 1 ) ) ;
155 if ( neighbours[2 * k + 1] != 0 && std::abs( jNeighbour - j ) < distance )
157 if ( j > jNeighbour )
158 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( j ) ;
159 else if ( j < jNeighbour )
160 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( imgHeight - j - 1 ) ;
164 factor += std::max<float>( 0, -( centerDepth - neighbourDepth ) * borderFactor );
166 float shade = expf( -factor * strength / rendererScale );
168 QRgb
c = imgPtr[ index ];
169 imgPtr[ index ] = qRgba(
static_cast<int>(
static_cast<float>( qRed(
c ) ) * shade ),
170 static_cast<int>(
static_cast<float>( qGreen(
c ) ) * shade ),
171 static_cast<int>(
static_cast<float>( qBlue(
c ) ) * shade )
180 double altRad = altitude * M_PI / 180.0;
181 double cos_altRadian = std::cos( altRad );
182 double sin_altRadian = std::sin( altRad );
183 double cos_alt_mul_z = cos_altRadian * zFactor ;
184 double azimuthRad = -1 * azimuth * M_PI / 180.0;
185 double cos_az_mul_cos_alt_mul_z = std::cos( azimuthRad ) * cos_alt_mul_z;
186 double sin_az_mul_cos_alt_mul_z = std::sin( azimuthRad ) * cos_alt_mul_z;
191 double cos225_az_mul_cos_alt_mul_z_mul_0_5 = -32.87001872802012 * cos_alt_mul_z / 255;
192 double square_z = zFactor * zFactor;
194 QRgb *imgPtr =
reinterpret_cast<QRgb *
>( img.bits() );
195 const QRgb *elevPtr =
reinterpret_cast<const QRgb *
>( mElevationImage.constBits() );
197 const int imgWidth = img.width(), imgHeight = img.height();
199 auto colRowToIndex = [&](
int c,
int r )->
qgssize
201 return static_cast<qgssize>( r ) * imgWidth +
c ;
210 float pixelValues[9];
212 for (
int rowC = 0; rowC < imgHeight ; ++rowC )
214 int rowU = std::max( 0, rowC - 1 );
215 int rowD = std::min( imgHeight - 1, rowC + 1 );
226 for (
int colC = 0; colC < imgWidth ; ++colC )
228 qgssize centerIndex = colRowToIndex( colC, rowC );
229 int colR = std::min( imgWidth - 1, colC + 1 );
231 pixelValues[0] = pixelValues[1];
232 pixelValues[3] = pixelValues[4];
233 pixelValues[6] = pixelValues[7];
235 pixelValues[1] = pixelValues[2];
236 pixelValues[4] = pixelValues[5];
237 pixelValues[7] = pixelValues[8];
239 pixelValues[2] =
decodeElevation( elevPtr[colRowToIndex( colR, rowU )] );
240 pixelValues[5] =
decodeElevation( elevPtr[colRowToIndex( colR, rowC )] );
241 pixelValues[8] =
decodeElevation( elevPtr[colRowToIndex( colR, rowD )] );
243 if ( elevPtr[centerIndex] != 0 )
246 const float x22 = pixelValues[4];
250 const float x11 = ( pixelValues[0] == noData ) ? x22 : pixelValues[0];
251 const float x21 = ( pixelValues[3] == noData ) ? x22 : pixelValues[3];
252 const float x31 = ( pixelValues[6] == noData ) ? x22 : pixelValues[6];
254 const float x12 = ( pixelValues[1] == noData ) ? x22 : pixelValues[1];
255 const float x32 = ( pixelValues[7] == noData ) ? x22 : pixelValues[7];
257 const float x13 = ( pixelValues[2] == noData ) ? x22 : pixelValues[2];
258 const float x23 = ( pixelValues[5] == noData ) ? x22 : pixelValues[5];
259 const float x33 = ( pixelValues[8] == noData ) ? x22 : pixelValues[8];
261 const double derX =
static_cast<double>( ( x13 + x23 + x23 + x33 ) - ( x11 + x21 + x21 + x31 ) ) / ( 8 * cellSizeX );
262 const double derY =
static_cast<double>( ( x31 + x32 + x32 + x33 ) - ( x11 + x12 + x12 + x13 ) ) / ( 8 * -cellSizeY );
265 if ( !multiDirectional )
268 shade = std::clamp( ( sin_altRadian -
269 ( derY * cos_az_mul_cos_alt_mul_z -
270 derX * sin_az_mul_cos_alt_mul_z ) ) /
271 std::sqrt( 1 + square_z * ( derX * derX + derY * derY ) ),
278 const double xx = derX * derX;
279 const double yy = derY * derY;
280 const double xx_plus_yy = xx + yy;
282 if ( xx_plus_yy == 0.0 )
284 shade = std::clamp( sin_altRadian, 0.0, 1.0 );
289 double val225_mul_0_5 = sin_altRadian * 0.5 +
290 ( derX - derY ) * cos225_az_mul_cos_alt_mul_z_mul_0_5;
291 val225_mul_0_5 = ( val225_mul_0_5 <= 0.0 ) ? 0.0 : val225_mul_0_5;
292 double val270_mul_0_5 = sin_altRadian * 0.5 -
293 derX * cos_alt_mul_z * 0.5;
294 val270_mul_0_5 = ( val270_mul_0_5 <= 0.0 ) ? 0.0 : val270_mul_0_5;
295 double val315_mul_0_5 = sin_altRadian * 0.5 +
296 ( derX + derY ) * cos225_az_mul_cos_alt_mul_z_mul_0_5;
297 val315_mul_0_5 = ( val315_mul_0_5 <= 0.0 ) ? 0.0 : val315_mul_0_5;
298 double val360_mul_0_5 = sin_altRadian * 0.5 -
299 derY * cos_alt_mul_z * 0.5;
300 val360_mul_0_5 = ( val360_mul_0_5 <= 0.0 ) ? 0.0 : val360_mul_0_5;
303 const double weight_225 = 0.5 * xx_plus_yy - derX * derY;
304 const double weight_270 = xx;
305 const double weight_315 = xx_plus_yy - weight_225;
306 const double weight_360 = yy;
307 const double cang_mul_127 = (
308 ( weight_225 * val225_mul_0_5 +
309 weight_270 * val270_mul_0_5 +
310 weight_315 * val315_mul_0_5 +
311 weight_360 * val360_mul_0_5 ) / xx_plus_yy ) /
312 ( 1 + square_z * xx_plus_yy );
314 shade = std::clamp( cang_mul_127, 0.0, 1.0 );
318 QRgb
c = imgPtr[ centerIndex ];
319 imgPtr[ centerIndex ] = qRgba(
static_cast<int>(
static_cast<float>( qRed(
c ) ) * shade ),
320 static_cast<int>(
static_cast<float>( qGreen(
c ) ) * shade ),
321 static_cast<int>(
static_cast<float>( qBlue(
c ) ) * shade )