package com.revolsys.elevation.gridded; import java.awt.image.DataBuffer; import com.revolsys.awt.WebColors; import com.revolsys.util.MathUtil; public class GriddedElevationModelHillshadeDataBuffer extends DataBuffer { private static final double PI_TIMES_2_MINUS_PI_OVER_2 = MathUtil.PI_TIMES_2 - MathUtil.PI_OVER_2; private final GriddedElevationModel elevationModel; private final int width; private final int height; private double zenithRadians; private double azimuthRadians; private double cosZenithRadians; private double sinZenithRadians; private final double oneDivCellSizeTimes8; private final double zFactor = 1; public GriddedElevationModelHillshadeDataBuffer(final GriddedElevationModel elevationModel) { super(TYPE_INT, elevationModel.getGridWidth() * elevationModel.getGridHeight()); this.elevationModel = elevationModel; this.width = elevationModel.getGridWidth(); this.height = elevationModel.getGridHeight(); final int cellSize = elevationModel.getGridCellSize(); this.oneDivCellSizeTimes8 = 1.0 / (8 * cellSize); setZenithDegrees(45.0); setAzimuthDegrees(315.0); } @Override public int getElem(final int bank, final int index) { if (bank == 0) { final GriddedElevationModel elevationModel = this.elevationModel; final int width = this.width; final int height = this.height; final int x = index % width; final int y = height - 1 - (index - x) / width; double a; double b; double c; double d; final double e = elevationModel.getElevationFast(x, y); if (Double.isFinite(e)) { double f; double g; double h; double i; final boolean firstX = x == 0; final boolean firstY = y == 0; final boolean lastX = x == width - 1; final boolean lastY = y == height - 1; if (firstX) { d = e; } else { d = elevationModel.getElevationFast(x - 1, y); } if (lastX) { f = e; } else { f = elevationModel.getElevationFast(x + 1, y); } if (firstY) { g = d; h = e; i = f; } else { if (firstX) { g = e; } else { g = elevationModel.getElevationFast(x - 1, y - 1); } h = elevationModel.getElevationFast(x, y - 1); if (lastX) { i = e; } else { i = elevationModel.getElevationFast(x + 1, y - 1); } } if (lastY) { a = d; b = e; c = f; } else { if (firstX) { a = e; } else { a = elevationModel.getElevationFast(x - 1, y + 1); } b = elevationModel.getElevationFast(x, y + 1); if (lastX) { c = e; } else { c = elevationModel.getElevationFast(x + 1, y + 1); } } final double oneDivCellSizeTimes8 = this.oneDivCellSizeTimes8; final double dzDivDx = (c + 2 * f + i - (a + 2 * d + g)) * oneDivCellSizeTimes8; final double dzDivDy = (g + 2 * h + i - (a + 2 * b + c)) * oneDivCellSizeTimes8; final double slopeRadians = Math .atan(this.zFactor * Math.sqrt(dzDivDx * dzDivDx + dzDivDy * dzDivDy)); double aspectRadians; if (dzDivDx == 0) { if (dzDivDy > 0) { aspectRadians = MathUtil.PI_OVER_2; } else if (dzDivDy < 0) { aspectRadians = PI_TIMES_2_MINUS_PI_OVER_2; } else { aspectRadians = 0; } } else { aspectRadians = Math.atan2(dzDivDy, -dzDivDx); if (aspectRadians < 0) { aspectRadians = MathUtil.PI_TIMES_2 + aspectRadians; } } final int hillshade = (int)(255.0 * (this.cosZenithRadians * Math.cos(slopeRadians) + this.sinZenithRadians * Math.sin(slopeRadians) * Math.cos(this.azimuthRadians - aspectRadians))); return WebColors.colorToRGB(255, hillshade, hillshade, hillshade); } else { return GriddedElevationModel.NULL_COLOUR; } } else { return GriddedElevationModel.NULL_COLOUR; } } private void setAzimuthDegrees(final double azimuth) { this.azimuthRadians = Math.toRadians(360 - azimuth + 90); } @Override public void setElem(final int bank, final int i, final int val) { throw new UnsupportedOperationException(); } private void setZenithDegrees(final double zenith) { this.zenithRadians = Math.toRadians(90 - zenith); this.cosZenithRadians = Math.cos(this.zenithRadians); this.sinZenithRadians = Math.sin(this.zenithRadians); } }