The goal of flow modeling is to quantify how much water flows through any point of the terrain. Flow reveals a lot of information about the terrain: The points with a lot of flow will be on the river network, while the points with low flow will be on the ridge network of the terrain. Knowledge about flow on the terrain turns out to be the fundamental step in many geographical processes. Unfortunately, flow data is not available from satellites, like elevation data. The location of rivers can be obtained by flying a plane and identifying rivers, but you can imagine that is a very very expensive process. That is why people have looked into ways to model flow based on the elevation of the terrain.

For a grid terrain flow is expressed by a flow grid which has the same size as the elevation grid.

Grid flowGridThe value of this flow grid at position (i,j) represents the total amount of flow that flows through point (i,j).

Imagine that initially every single point in the grid has 1 unit
of water. So the very first thing that you want to do in
`computeFlow()` after you create the flow grid is

for (int i=0; i < rows; i++) for (int j=0; j < cols; j++) if point is not NODATA then flowGrid.set(i,j, 1); else flowGrid.set(i,j,NODATA);Here assume you have a setter on a Grid

The question is how to model the flow of water? The simplest way to
model the flow is to assume that every single point in the grid
distributes its water (initial, as well as incoming) to a
*single* neighbor, namely its steepest downslope neighbor. If
there are ties, they are broken arbitrarily.

- If a point is nodata (undefined), its flow should be nodata (undefined); In anycase, a nodata point does not send its flow to any neighbor, so all nodata points should end up with flow = nodata.
- If a point has no neighbors that are lower than it, then it does not send its flow anywhere.

So you see, with this model water follows the steepest way down, either to the edge of the terrain or to a pit. Because water flows "down", there cannot be cycles.

The goal is to compute, for each point in the grid, the
*total* amount of water that flows through that point.

The first method that you'll write will be:

boolean flowsInto(int i, int j, int k, int l)which returns true if cell (i,j) flows into cell (k,l), that is, if cell (k, l) is the steepest downslope neighbor of cell (i,j). The way this method works is the following: it looks at all 8 neighbors of cell (i,j) and computes the lowest neighbor; this is the direction where water would go from cell (i,j). Then it checks whether this neighbor is equal to (k,l), in which case it returns true; otherwise it returns false.

Once you have method `flowsInto` written and tested, you can
start working on computing flow. You will write a method that computes
a flow-accumulation grid based on the (elevation) grid:

Grid computeFlow() { // create flow grid; you will need to write this constructor Grid flowGRid = new Grid (rows, cols, etc); //initialize flow grid for (int i=0; i< rows; i++) { for (int j=0; j < cols; j++) { ... } } //compute flow grid for (int i=0; i< rows; i++) { for (int j=0; j < cols; j++) { //compute flow of point (i,j) int flow = computeFlow(i, j, ...); flowGrid.set(i,j, flow); } } return flowGrid; }Naturally, you will write a

The basic thing to note is when recursion stops. When no neighbor flows into the current cell there are no subsequent recursive calls.

The most important thing to think about is how to avoid computing the flow of a cell multiple times. One obvious way is to mark the grid: initially the entire grid is unmarked; whenever you determine the final value of the flow of cell (i,j), you set mark[i][j] = true. This way you know, if you ever need flow[i][j], whether you've computed it before or not. Marking the grid is just one way to do it ---it may make things clearer, or not. If you think you can do without marking the grid, do so.

For debugging reasons, you should first get test2.asc to compute flow correctly. Some test files are here. Here is how the grid test2.asc looks like:

The grid is: 9 9 9 9 9 8 7 6 7 8 7 6 5 6 7 6 5 4 5 6 5 4 3 4 5Here is what the flow should look like:

The grid is: 1 1 1 1 1 1 2 4 2 1 1 2 9 2 1 1 2 14 2 1 1 3 25 3 1Note that point (4, 2) has height 3, and receives flow from all its neighbors, as it is the lowest neighbor for each of them. So 2 + 3 + 14 + 2 + 3 = 24. Add to this the initial 1 unit of flow at point (4, 2) and you got 25.

If you got test2.asc to run correctly, then your program is almost correct except maybe nodata values. If you feel like running it on the big grid set1.asc, here is how it will look like:

java Grid set1.asc

Here is another rendering of the resulting flow (different color map):

Grid elev = new Grid(set1.asc"); elev.render(); Grid flow = elev.computeFlow(); flow.render();It is up to you how you deal with the different rendering methods for an elevation grid vs a flow grid. One idea is to keep a