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];
173 = qRgba(
static_cast<int>(
static_cast<float>( qRed(
c ) ) * shade ),
static_cast<int>(
static_cast<float>( qGreen(
c ) ) * shade ),
static_cast<int>(
static_cast<float>( qBlue(
c ) ) * shade ), qAlpha(
c ) );
181 double altRad = altitude * M_PI / 180.0;
182 double cos_altRadian = std::cos( altRad );
183 double sin_altRadian = std::sin( altRad );
184 double cos_alt_mul_z = cos_altRadian * zFactor;
185 double azimuthRad = -1 * azimuth * M_PI / 180.0;
186 double cos_az_mul_cos_alt_mul_z = std::cos( azimuthRad ) * cos_alt_mul_z;
187 double sin_az_mul_cos_alt_mul_z = std::sin( azimuthRad ) * cos_alt_mul_z;
192 double cos225_az_mul_cos_alt_mul_z_mul_0_5 = -32.87001872802012 * cos_alt_mul_z / 255;
193 double square_z = zFactor * zFactor;
195 QRgb *imgPtr =
reinterpret_cast<QRgb *
>( img.bits() );
196 const QRgb *elevPtr =
reinterpret_cast<const QRgb *
>( mElevationImage.constBits() );
198 const int imgWidth = img.width(), imgHeight = img.height();
200 auto colRowToIndex = [&](
int c,
int r ) ->
qgssize {
return static_cast<qgssize>( r ) * imgWidth +
c; };
208 float pixelValues[9];
210 for (
int rowC = 0; rowC < imgHeight; ++rowC )
212 int rowU = std::max( 0, rowC - 1 );
213 int rowD = std::min( imgHeight - 1, rowC + 1 );
224 for (
int colC = 0; colC < imgWidth; ++colC )
226 qgssize centerIndex = colRowToIndex( colC, rowC );
227 int colR = std::min( imgWidth - 1, colC + 1 );
229 pixelValues[0] = pixelValues[1];
230 pixelValues[3] = pixelValues[4];
231 pixelValues[6] = pixelValues[7];
233 pixelValues[1] = pixelValues[2];
234 pixelValues[4] = pixelValues[5];
235 pixelValues[7] = pixelValues[8];
237 pixelValues[2] =
decodeElevation( elevPtr[colRowToIndex( colR, rowU )] );
238 pixelValues[5] =
decodeElevation( elevPtr[colRowToIndex( colR, rowC )] );
239 pixelValues[8] =
decodeElevation( elevPtr[colRowToIndex( colR, rowD )] );
241 if ( elevPtr[centerIndex] != 0 )
244 const float x22 = pixelValues[4];
248 const float x11 = ( pixelValues[0] == noData ) ? x22 : pixelValues[0];
249 const float x21 = ( pixelValues[3] == noData ) ? x22 : pixelValues[3];
250 const float x31 = ( pixelValues[6] == noData ) ? x22 : pixelValues[6];
252 const float x12 = ( pixelValues[1] == noData ) ? x22 : pixelValues[1];
253 const float x32 = ( pixelValues[7] == noData ) ? x22 : pixelValues[7];
255 const float x13 = ( pixelValues[2] == noData ) ? x22 : pixelValues[2];
256 const float x23 = ( pixelValues[5] == noData ) ? x22 : pixelValues[5];
257 const float x33 = ( pixelValues[8] == noData ) ? x22 : pixelValues[8];
259 const double derX =
static_cast<double>( ( x13 + x23 + x23 + x33 ) - ( x11 + x21 + x21 + x31 ) ) / ( 8 * cellSizeX );
260 const double derY =
static_cast<double>( ( x31 + x32 + x32 + x33 ) - ( x11 + x12 + x12 + x13 ) ) / ( 8 * -cellSizeY );
263 if ( !multiDirectional )
266 shade = std::clamp( ( sin_altRadian - ( derY * cos_az_mul_cos_alt_mul_z - derX * sin_az_mul_cos_alt_mul_z ) ) / std::sqrt( 1 + square_z * ( derX * derX + derY * derY ) ), 0.0, 1.0 );
272 const double xx = derX * derX;
273 const double yy = derY * derY;
274 const double xx_plus_yy = xx + yy;
276 if ( xx_plus_yy == 0.0 )
278 shade = std::clamp( sin_altRadian, 0.0, 1.0 );
283 double val225_mul_0_5 = sin_altRadian * 0.5 + ( derX - derY ) * cos225_az_mul_cos_alt_mul_z_mul_0_5;
284 val225_mul_0_5 = ( val225_mul_0_5 <= 0.0 ) ? 0.0 : val225_mul_0_5;
285 double val270_mul_0_5 = sin_altRadian * 0.5 - derX * cos_alt_mul_z * 0.5;
286 val270_mul_0_5 = ( val270_mul_0_5 <= 0.0 ) ? 0.0 : val270_mul_0_5;
287 double val315_mul_0_5 = sin_altRadian * 0.5 + ( derX + derY ) * cos225_az_mul_cos_alt_mul_z_mul_0_5;
288 val315_mul_0_5 = ( val315_mul_0_5 <= 0.0 ) ? 0.0 : val315_mul_0_5;
289 double val360_mul_0_5 = sin_altRadian * 0.5 - derY * cos_alt_mul_z * 0.5;
290 val360_mul_0_5 = ( val360_mul_0_5 <= 0.0 ) ? 0.0 : val360_mul_0_5;
293 const double weight_225 = 0.5 * xx_plus_yy - derX * derY;
294 const double weight_270 = xx;
295 const double weight_315 = xx_plus_yy - weight_225;
296 const double weight_360 = yy;
297 const double cang_mul_127 = ( ( weight_225 * val225_mul_0_5 + weight_270 * val270_mul_0_5 + weight_315 * val315_mul_0_5 + weight_360 * val360_mul_0_5 ) / xx_plus_yy )
298 / ( 1 + square_z * xx_plus_yy );
300 shade = std::clamp( cang_mul_127, 0.0, 1.0 );
304 QRgb
c = imgPtr[centerIndex];
306 = qRgba(
static_cast<int>(
static_cast<float>( qRed(
c ) ) * shade ),
static_cast<int>(
static_cast<float>( qGreen(
c ) ) * shade ),
static_cast<int>(
static_cast<float>( qBlue(
c ) ) * shade ), qAlpha(
c ) );