/*
* GridSlopeLineOperator.java
*
* Created on May 25, 2006, 2:23 PM
*
*/
package ika.geo.grid;
import ika.geo.GeoGrid;
import ika.geo.GeoObject;
/**
* Generates a new grid with the relative position in a slope of the source grid.
* @author Bernhard Jenny, Institute of Cartography, ETH Zurich
*/
public class GridSlopeLineOperator implements GridOperator {
private float minVerDiff = 0;
private double minSlope = 0;
/** Creates a new instance of GridSlopeLineOperator */
public GridSlopeLineOperator() {
}
public String getName() {
return "Slope Line";
}
public GeoObject operate(GeoGrid geoGrid) {
if (geoGrid == null)
throw new IllegalArgumentException();
final int nrows = geoGrid.getRows();
final int ncols = geoGrid.getCols();
GeoGrid newGrid = new GeoGrid(ncols, nrows, geoGrid.getCellSize());
newGrid.setWest(geoGrid.getWest());
newGrid.setNorth(geoGrid.getNorth());
float[][] srcGrid = geoGrid.getGrid();
float[][] dstGrid = newGrid.getGrid();
for (int row = 1; row < nrows - 1; ++row) {
/*
if (row % 5 == 0)
System.out.println ("row " + row);
*/
for (int col = 1; col < ncols - 1; ++col) {
nextDown(geoGrid, newGrid, col, row);
}
}
return newGrid;
}
/*
private int nextUp(GeoGrid elevationGrid, GeoGrid counterGrid,
int currentCol, int currentRow) {
long elevRows = elevationGrid.getRows();
long elevCols = elevationGrid.getCols();
float maxDiff = 0f;
float hCenter = elevationGrid.getValue(currentCol, currentRow);
float h, diff;
int nextRow = currentRow;
int nextCol = currentCol;
final float sqrt2 = (float)Math.sqrt(2);
h = elevationGrid.getValue(currentCol + 1, currentRow);
diff = h - hCenter;
if (diff > maxDiff && diff >= this.minVerDiff) {
maxDiff = diff;
nextCol = currentCol + 1;
}
h = elevationGrid.getValue(currentCol - 1, currentRow);
diff = h - hCenter;
if (diff > maxDiff && diff >= this.minVerDiff) {
maxDiff = diff;
nextCol = currentCol - 1;
}
h = elevationGrid.getValue(currentCol, currentRow + 1);
diff = h - hCenter;
if (diff > maxDiff && diff >= this.minVerDiff) {
maxDiff = diff;
nextRow = currentRow + 1;
}
h = elevationGrid.getValue(currentCol, currentRow - 1);
diff = h - hCenter;
if (diff > maxDiff && diff >= this.minVerDiff) {
maxDiff = diff;
nextRow = currentRow - 1;
}
h = elevationGrid.getValue(currentCol + 1, currentRow + 1);
diff = h - hCenter;
if (diff > maxDiff * sqrt2 && diff >= this.minVerDiff * sqrt2) {
maxDiff = diff;
nextCol = currentCol + 1;
nextRow = currentRow + 1;
}
h = elevationGrid.getValue(currentCol + 1, currentRow - 1);
diff = h - hCenter;
if (diff > maxDiff * sqrt2 && diff >= this.minVerDiff * sqrt2) {
maxDiff = diff;
nextCol = currentCol + 1;
nextRow = currentRow - 1;
}
h = elevationGrid.getValue(currentCol - 1, currentRow + 1);
diff = h - hCenter;
if (diff > maxDiff * sqrt2 && diff >= this.minVerDiff * sqrt2) {
maxDiff = diff;
nextCol = currentCol - 1;
nextRow = currentRow + 1;
}
h = elevationGrid.getValue(currentCol - 1, currentRow - 1);
diff = h - hCenter;
if (diff > maxDiff * sqrt2 && diff >= this.minVerDiff * sqrt2) {
maxDiff = diff;
nextCol = currentCol - 1;
nextRow = currentRow - 1;
}
// test if a neighbor was found with a difference in elevation that is big enough.
if (maxDiff == 0) {
counterGrid.setValue(0, currentCol, currentRow);
return 0;
}
// make sure we don't leave the grid
if (nextRow == 0 || nextRow == elevRows - 1
|| nextCol == 0 || nextCol == elevCols - 1) {
counterGrid.setValue(0, currentCol, currentRow);
return 0;
}
float nextCount = counterGrid.getValue(nextCol, nextRow);
if (nextCount > 0) {
counterGrid.setValue(nextCount + 1, currentCol, currentRow);
return (int)nextCount + 1;
}
int stepsUp = nextUp(elevationGrid, counterGrid, nextCol, nextRow) + 1;
counterGrid.setValue(stepsUp, currentCol, currentRow);
return stepsUp;
}
*/
private int nextDown(GeoGrid elevationGrid, GeoGrid counterGrid,
int currentCol, int currentRow) {
final float sqrt2 = (float)Math.sqrt(2);
long elevRows = elevationGrid.getRows();
long elevCols = elevationGrid.getCols();
float maxDiff = 0f;
float hCenter = elevationGrid.getValue(currentCol, currentRow);
// find biggest elevation difference to all 8 neighbors
float h, diff;
int nextRow = currentRow;
int nextCol = currentCol;
h = elevationGrid.getValue(currentCol + 1, currentRow);
diff = h - hCenter;
if (diff < maxDiff && -diff >= this.minVerDiff) {
maxDiff = diff;
nextCol = currentCol + 1;
}
h = elevationGrid.getValue(currentCol - 1, currentRow);
diff = h - hCenter;
if (diff < maxDiff && -diff >= this.minVerDiff) {
maxDiff = diff;
nextCol = currentCol - 1;
}
h = elevationGrid.getValue(currentCol, currentRow + 1);
diff = h - hCenter;
if (diff < maxDiff && -diff >= this.minVerDiff) {
maxDiff = diff;
nextRow = currentRow + 1;
}
h = elevationGrid.getValue(currentCol, currentRow - 1);
diff = h - hCenter;
if (diff < maxDiff && -diff >= this.minVerDiff) {
maxDiff = diff;
nextRow = currentRow - 1;
}
h = elevationGrid.getValue(currentCol + 1, currentRow + 1);
diff = h - hCenter;
if (diff < maxDiff * sqrt2 && -diff >= this.minVerDiff * sqrt2) {
maxDiff = diff;
nextCol = currentCol + 1;
nextRow = currentRow + 1;
}
h = elevationGrid.getValue(currentCol + 1, currentRow - 1);
diff = h - hCenter;
if (diff < maxDiff * sqrt2 && -diff >= this.minVerDiff * sqrt2) {
maxDiff = diff;
nextCol = currentCol + 1;
nextRow = currentRow - 1;
}
h = elevationGrid.getValue(currentCol - 1, currentRow + 1);
diff = h - hCenter;
if (diff < maxDiff * sqrt2 && -diff >= this.minVerDiff * sqrt2) {
maxDiff = diff;
nextCol = currentCol - 1;
nextRow = currentRow + 1;
}
h = elevationGrid.getValue(currentCol - 1, currentRow - 1);
diff = h - hCenter;
if (diff < maxDiff * sqrt2 && -diff >= this.minVerDiff * sqrt2) {
maxDiff = diff;
nextCol = currentCol - 1;
nextRow = currentRow - 1;
}
// test if a neighbor was found with a difference in elevation that is big enough.
if (maxDiff == 0) {
counterGrid.setValue(0, currentCol, currentRow);
return 0;
}
// test for minimum slope
final double slope = elevationGrid.getSlope(currentCol, currentRow);
if (slope < minSlope) {
counterGrid.setValue(0, currentCol, currentRow);
return 0;
}
// make sure we don't leave the grid
if (nextRow == 0 || nextRow == elevRows - 1
|| nextCol == 0 || nextCol == elevCols - 1) {
counterGrid.setValue(0, currentCol, currentRow);
return 0;
}
float nextCount = counterGrid.getValue(nextCol, nextRow);
if (nextCount > 0) {
counterGrid.setValue(nextCount + 1, currentCol, currentRow);
return (int)nextCount + 1;
}
final int stepsDown = nextDown(elevationGrid, counterGrid, nextCol, nextRow) + 1;
counterGrid.setValue(stepsDown, currentCol, currentRow);
return stepsDown;
}
public float getMinVerDiff() {
return minVerDiff;
}
public void setMinVerDiff(float minVerDiff) {
this.minVerDiff = minVerDiff;
}
/**
* @return the minSlope
*/
public double getMinSlope() {
return minSlope;
}
/**
* @param minSlope the minSlope to set
*/
public void setMinSlope(double minSlope) {
this.minSlope = minSlope;
}
}