/*
* GridMedianOperator.java
*
* Created on August 12, 2008
*
*/
package ika.geo.grid;
import ika.geo.GeoGrid;
import ika.geoimport.ESRIASCIIGridReader;
/**
*
* @author Bernhard Jenny, Institute of Cartography, ETH Zurich.
*/
public class AccumulationFlowOperator implements GridOperator {
public static void main(String[] args) {
try {
GeoGrid geoGrid = ESRIASCIIGridReader.read("/Users/jenny/Desktop/1024x1024.asc");
GeoGrid accflow = new AccumulationFlowOperator().operate(geoGrid);
ika.geo.GeoImage image = new GridToImageOperator().operate(accflow);
ika.utils.ImageUtils.displayImageInWindow(image.getBufferedImage());
} catch (Exception exc) {
exc.printStackTrace();
}
}
private enum FlowDirection {
NONE, TOPRIGHT, RIGHT, BOTTOMRIGHT, BOTTOM, BOTTOMLEFT, LEFT, TOPLEFT, TOP
};
public AccumulationFlowOperator() {
}
public String getName() {
return "Accumulation Flow";
}
public GeoGrid operate(GeoGrid geoGrid) {
if (geoGrid == null) {
throw new IllegalArgumentException();
}
final int cols = geoGrid.getCols();
final int rows = geoGrid.getRows();
final double meshSize = geoGrid.getCellSize();
GeoGrid newGrid = new GeoGrid(cols, rows, meshSize);
newGrid.setWest(geoGrid.getWest());
newGrid.setNorth(geoGrid.getNorth());
for (int row = 1; row < rows - 1; row++) {
System.out.println(row);
for (int col = 1; col < cols - 1; col++) {
incrementFlow(geoGrid, newGrid, col, row);
}
}
return newGrid;
}
private void incrementFlow(GeoGrid dem, GeoGrid accflow, int col, int row) {
for (;;) {
FlowDirection dir = FlowDirection.NONE;
try {
dir = this.getFlowDirection(dem, col, row);
} catch (IndexOutOfBoundsException exc) {
break;
}
switch (dir) {
case NONE:
break;
case TOPRIGHT:
col++;
row--;
break;
case RIGHT:
col++;
break;
case BOTTOMRIGHT:
col++;
row++;
break;
case BOTTOM:
row++;
break;
case BOTTOMLEFT:
col--;
row++;
break;
case LEFT:
col--;
break;
case TOPLEFT:
col--;
row--;
break;
case TOP:
row--;
break;
}
try {
float v = accflow.getValue(col, row);
accflow.setValue(v + 1, col, row);
} catch (IndexOutOfBoundsException exc) {
break;
}
}
}
private FlowDirection getFlowDirection(GeoGrid geoGrid, int col, int row) {
// search for direction of flow
final float hc = geoGrid.getValue(col, row);
FlowDirection dir = FlowDirection.NONE;
float diff = 0;
float d = geoGrid.getValue(col + 1, row - 1) - hc;
if (d < diff) {
diff = d;
dir = FlowDirection.TOPRIGHT;
}
d = geoGrid.getValue(col + 1, row) - hc;
if (d < diff) {
diff = d;
dir = FlowDirection.RIGHT;
}
d = geoGrid.getValue(col + 1, row + 1) - hc;
if (d < diff) {
diff = d;
dir = FlowDirection.BOTTOMRIGHT;
}
d = geoGrid.getValue(col, row + 1) - hc;
if (d < diff) {
diff = d;
dir = FlowDirection.BOTTOM;
}
d = geoGrid.getValue(col - 1, row + 1) - hc;
if (d < diff) {
diff = d;
dir = FlowDirection.BOTTOMLEFT;
}
d = geoGrid.getValue(col - 1, row) - hc;
if (d < diff) {
diff = d;
dir = FlowDirection.LEFT;
}
d = geoGrid.getValue(col - 1, row - 1) - hc;
if (d < diff) {
diff = d;
dir = FlowDirection.TOPLEFT;
}
d = geoGrid.getValue(col, row - 1) - hc;
if (d < diff) {
diff = d;
dir = FlowDirection.TOP;
}
return dir;
}
}