93 const int imgWidth = img.width(), imgHeight = img.height();
94 QRgb *imgPtr =
reinterpret_cast<QRgb *
>( img.bits() );
95 const QRgb *elevPtr =
reinterpret_cast<const QRgb *
>( mElevationImage.constBits() );
97 const int neighbours[] = { -1, 0, 1, 0, 0, -1, 0, 1 };
98 for (
int i = 0; i < imgWidth; ++i )
100 for (
int j = 0; j < imgHeight; ++j )
107 for (
qgssize k = 0; k < 4; ++k )
109 float borderFactor = 1.0f;
110 int iNeighbour = std::clamp( i + distance * neighbours[2 * k], 0, imgWidth - 1 );
111 int jNeighbour = std::clamp( j + distance * neighbours[2 * k + 1], 0, imgHeight - 1 );
112 qgssize neighbourIndex = jNeighbour *
static_cast<qgssize>( imgWidth ) + iNeighbour;
116 if (
isNoData( elevPtr[ neighbourIndex ] ) )
118 if ( neighbours[2 * k] != 0 )
120 int corrI = iNeighbour;
121 int inc = neighbours[2 * k];
122 while ( corrI != i &&
isNoData( elevPtr[ neighbourIndex ] ) )
125 neighbourIndex = jNeighbour *
static_cast<qgssize>( imgWidth ) + corrI;
130 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( std::abs( i - corrI ) ) ;
133 if ( neighbours[2 * k + 1] != 0 )
135 int corrJ = jNeighbour;
136 int inc = neighbours[2 * k + 1];
137 while ( corrJ != j &&
isNoData( elevPtr[ neighbourIndex ] ) )
140 neighbourIndex = corrJ *
static_cast<qgssize>( imgWidth ) + iNeighbour;
145 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( std::abs( j - corrJ ) ) ;
151 if ( neighbours[2 * k] != 0 && std::abs( iNeighbour - i ) < distance )
153 if ( i > iNeighbour )
154 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( i ) ;
155 else if ( i < iNeighbour )
156 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( ( imgWidth - i - 1 ) ) ;
158 if ( neighbours[2 * k + 1] != 0 && std::abs( jNeighbour - j ) < distance )
160 if ( j > jNeighbour )
161 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( j ) ;
162 else if ( j < jNeighbour )
163 borderFactor =
static_cast<float>( distance ) /
static_cast<float>( imgHeight - j - 1 ) ;
167 factor += std::max<float>( 0, -( centerDepth - neighbourDepth ) * borderFactor );
169 float shade = expf( -factor * strength / rendererScale );
171 QRgb
c = imgPtr[ index ];
172 imgPtr[ index ] = qRgba(
static_cast<int>(
static_cast<float>( qRed(
c ) ) * shade ),
173 static_cast<int>(
static_cast<float>( qGreen(
c ) ) * shade ),
174 static_cast<int>(
static_cast<float>( qBlue(
c ) ) * shade )
183 double altRad = altitude * M_PI / 180.0;
184 double cos_altRadian = std::cos( altRad );
185 double sin_altRadian = std::sin( altRad );
186 double cos_alt_mul_z = cos_altRadian * zFactor ;
187 double azimuthRad = -1 * azimuth * M_PI / 180.0;
188 double cos_az_mul_cos_alt_mul_z = std::cos( azimuthRad ) * cos_alt_mul_z;
189 double sin_az_mul_cos_alt_mul_z = std::sin( azimuthRad ) * cos_alt_mul_z;
194 double cos225_az_mul_cos_alt_mul_z_mul_0_5 = -32.87001872802012 * cos_alt_mul_z / 255;
195 double square_z = zFactor * zFactor;
197 QRgb *imgPtr =
reinterpret_cast<QRgb *
>( img.bits() );
198 const QRgb *elevPtr =
reinterpret_cast<const QRgb *
>( mElevationImage.constBits() );
200 const int imgWidth = img.width(), imgHeight = img.height();
202 auto colRowToIndex = [&](
int c,
int r )->
qgssize
204 return static_cast<qgssize>( r ) * imgWidth +
c ;
213 float pixelValues[9];
215 for (
int rowC = 0; rowC < imgHeight ; ++rowC )
217 int rowU = std::max( 0, rowC - 1 );
218 int rowD = std::min( imgHeight - 1, rowC + 1 );
229 for (
int colC = 0; colC < imgWidth ; ++colC )
231 qgssize centerIndex = colRowToIndex( colC, rowC );
232 int colR = std::min( imgWidth - 1, colC + 1 );
234 pixelValues[0] = pixelValues[1];
235 pixelValues[3] = pixelValues[4];
236 pixelValues[6] = pixelValues[7];
238 pixelValues[1] = pixelValues[2];
239 pixelValues[4] = pixelValues[5];
240 pixelValues[7] = pixelValues[8];
242 pixelValues[2] =
decodeElevation( elevPtr[colRowToIndex( colR, rowU )] );
243 pixelValues[5] =
decodeElevation( elevPtr[colRowToIndex( colR, rowC )] );
244 pixelValues[8] =
decodeElevation( elevPtr[colRowToIndex( colR, rowD )] );
246 if ( elevPtr[centerIndex] != 0 )
249 const float x22 = pixelValues[4];
253 const float x11 = ( pixelValues[0] == noData ) ? x22 : pixelValues[0];
254 const float x21 = ( pixelValues[3] == noData ) ? x22 : pixelValues[3];
255 const float x31 = ( pixelValues[6] == noData ) ? x22 : pixelValues[6];
257 const float x12 = ( pixelValues[1] == noData ) ? x22 : pixelValues[1];
258 const float x32 = ( pixelValues[7] == noData ) ? x22 : pixelValues[7];
260 const float x13 = ( pixelValues[2] == noData ) ? x22 : pixelValues[2];
261 const float x23 = ( pixelValues[5] == noData ) ? x22 : pixelValues[5];
262 const float x33 = ( pixelValues[8] == noData ) ? x22 : pixelValues[8];
264 const double derX =
static_cast<double>( ( x13 + x23 + x23 + x33 ) - ( x11 + x21 + x21 + x31 ) ) / ( 8 * cellSizeX );
265 const double derY =
static_cast<double>( ( x31 + x32 + x32 + x33 ) - ( x11 + x12 + x12 + x13 ) ) / ( 8 * -cellSizeY );
268 if ( !multiDirectional )
271 shade = std::clamp( ( sin_altRadian -
272 ( derY * cos_az_mul_cos_alt_mul_z -
273 derX * sin_az_mul_cos_alt_mul_z ) ) /
274 std::sqrt( 1 + square_z * ( derX * derX + derY * derY ) ),
281 const double xx = derX * derX;
282 const double yy = derY * derY;
283 const double xx_plus_yy = xx + yy;
285 if ( xx_plus_yy == 0.0 )
287 shade = std::clamp( sin_altRadian, 0.0, 1.0 );
292 double val225_mul_0_5 = sin_altRadian * 0.5 +
293 ( derX - derY ) * cos225_az_mul_cos_alt_mul_z_mul_0_5;
294 val225_mul_0_5 = ( val225_mul_0_5 <= 0.0 ) ? 0.0 : val225_mul_0_5;
295 double val270_mul_0_5 = sin_altRadian * 0.5 -
296 derX * cos_alt_mul_z * 0.5;
297 val270_mul_0_5 = ( val270_mul_0_5 <= 0.0 ) ? 0.0 : val270_mul_0_5;
298 double val315_mul_0_5 = sin_altRadian * 0.5 +
299 ( derX + derY ) * cos225_az_mul_cos_alt_mul_z_mul_0_5;
300 val315_mul_0_5 = ( val315_mul_0_5 <= 0.0 ) ? 0.0 : val315_mul_0_5;
301 double val360_mul_0_5 = sin_altRadian * 0.5 -
302 derY * cos_alt_mul_z * 0.5;
303 val360_mul_0_5 = ( val360_mul_0_5 <= 0.0 ) ? 0.0 : val360_mul_0_5;
306 const double weight_225 = 0.5 * xx_plus_yy - derX * derY;
307 const double weight_270 = xx;
308 const double weight_315 = xx_plus_yy - weight_225;
309 const double weight_360 = yy;
310 const double cang_mul_127 = (
311 ( weight_225 * val225_mul_0_5 +
312 weight_270 * val270_mul_0_5 +
313 weight_315 * val315_mul_0_5 +
314 weight_360 * val360_mul_0_5 ) / xx_plus_yy ) /
315 ( 1 + square_z * xx_plus_yy );
317 shade = std::clamp( cang_mul_127, 0.0, 1.0 );
321 QRgb
c = imgPtr[ centerIndex ];
322 imgPtr[ centerIndex ] = qRgba(
static_cast<int>(
static_cast<float>( qRed(
c ) ) * shade ),
323 static_cast<int>(
static_cast<float>( qGreen(
c ) ) * shade ),
324 static_cast<int>(
static_cast<float>( qBlue(
c ) ) * shade )