render method
void
render(
- Uint8List pixels,
- int tileSize,
- int px,
- int py,
- PixelProjection projection,
- double latitude,
- double longitude,
- int centerElev,
override
Implementation
@override
void render(Uint8List pixels, int tileSize, int px, int py, PixelProjection projection, double latitude, double longitude, int centerElev) {
// Sample neighbours using a small geographic offset derived from meters-per-pixel.
// This keeps the gradient scale stable across zoom levels.
final mpp = projection.meterPerPixel(LatLong(latitude, longitude));
if (mpp == 0) return;
final dMeters = max(mpp, 1.0);
final dLon = _metersToLongitudeDegrees(latitude, dMeters);
final dLat = _metersToLatitudeDegrees(dMeters);
final eW = _elevationAt(latitude, longitude - dLon, projection) ?? centerElev;
final eE = _elevationAt(latitude, longitude + dLon, projection) ?? centerElev;
final eN = _elevationAt(latitude + dLat, longitude, projection) ?? centerElev;
final eS = _elevationAt(latitude - dLat, longitude, projection) ?? centerElev;
final dzdx = (eE - eW) / (2 * dMeters);
final dzdy = (eN - eS) / (2 * dMeters);
final az = hillshadeAzimuthDeg * pi / 180;
final alt = hillshadeAltitudeDeg * pi / 180;
// Surface normal.
final nx = -dzdx;
final ny = -dzdy;
final nz = 1.0;
final nLen = sqrt(nx * nx + ny * ny + nz * nz);
final ux = cos(alt) * sin(az);
final uy = cos(alt) * cos(az);
final uz = sin(alt);
final dot = (nx / nLen) * ux + (ny / nLen) * uy + (nz / nLen) * uz;
final intensity = (dot.clamp(0.0, 1.0) * 255).round();
_setPixel(pixels, tileSize, px, py, intensity, intensity, intensity, 255);
}