/*
* GridMeanOperator.java
*
* Created on February 3, 2006, 10:06 AM
*
*/
package ika.geo.grid;
import ika.geo.*;
/**
*
* @author Bernhard Jenny, Institute of Cartography, ETH Zurich.
*/
public class GridMeanOperator implements GridOperator {
/*
public static void main(String[] args) {
try {
String path = ika.utils.FileUtils.askFile(null, "Select ESRI ASCII Grid File", true);
GeoGrid geoGrid = ika.geoimport.ESRIASCIIGridReader.read(path);
ika.geoexport.ESRIASCIIGridExporter exporter = new ika.geoexport.ESRIASCIIGridExporter();
{
GridMeanOperator op = new GridMeanOperator();
GeoGrid out = op.operate(geoGrid);
exporter.export(out, "/Users/jenny/Desktop/mean5x5.asc");
op.setFilterSize(11);
out = op.operate(geoGrid);
exporter.export(out, "/Users/jenny/Desktop/mean11x11.asc");
}
} catch (IOException ex) {
}
}
*/
private int filterSize = 5;
/** Creates a new instance of GridMeanOperator */
public GridMeanOperator() {
}
public GridMeanOperator(int filterSize) {
setFilterSize(filterSize);
}
public String getName() {
return "Mean";
}
public GeoGrid operate(GeoGrid geoGrid) {
if (geoGrid == null) {
throw new IllegalArgumentException();
}
// make sure filterSize is odd number
if (filterSize % 2 != 1) {
return null;
}
final int halfFilterSize = this.filterSize / 2;
// create the new GeoGrid
final int rows = geoGrid.getRows();
final int cols = geoGrid.getCols();
final double meshSize = geoGrid.getCellSize();
GeoGrid newGrid = new GeoGrid(cols, rows, meshSize);
newGrid.setWest(geoGrid.getWest());
newGrid.setNorth(geoGrid.getNorth());
float[][] srcGrid = geoGrid.getGrid();
float[][] dstGrid = newGrid.getGrid();
// top rows
for (int row = 0; row < halfFilterSize; row++) {
for (int col = 0; col < cols; col++) {
this.operateBorder(geoGrid, newGrid, col, row);
}
}
// bottom rows
for (int row = rows - halfFilterSize; row < rows; row++) {
for (int col = 0; col < cols; col++) {
this.operateBorder(geoGrid, newGrid, col, row);
}
}
// left columns
for (int col = 0; col < halfFilterSize; col++) {
for (int row = halfFilterSize; row < rows - halfFilterSize; row++) {
this.operateBorder(geoGrid, newGrid, col, row);
}
}
// right columns
for (int col = cols - halfFilterSize; col < cols; col++) {
for (int row = halfFilterSize; row < rows - halfFilterSize; row++) {
this.operateBorder(geoGrid, newGrid, col, row);
}
}
// interior of grid
final float npts = this.filterSize * this.filterSize;
for (int row = halfFilterSize; row < rows - halfFilterSize; row++) {
float[] dstRow = dstGrid[row];
for (int col = halfFilterSize; col < cols - halfFilterSize; col++) {
float tot = 0;
for (int r = row - halfFilterSize; r <= row + halfFilterSize; r++) {
float[] srcRow = srcGrid[r];
for (int c = col - halfFilterSize; c <= col + halfFilterSize; c++) {
tot += srcRow[c];
}
}
dstRow[col] = tot / npts;
}
}
return newGrid;
}
public GeoGrid operate(GeoGrid geoGrid, int loops) {
if (loops <= 0) {
return geoGrid.clone();
}
for (int i = 0; i < loops; i++) {
geoGrid = this.operate(geoGrid);
}
return geoGrid;
}
public int getFilterSize() {
return filterSize;
}
public void setFilterSize(int filterSize) {
if (filterSize % 2 == 0 || filterSize < 3) {
throw new IllegalArgumentException("illegal filter size");
}
this.filterSize = filterSize;
}
private void operateBorder(GeoGrid src, GeoGrid dst, int col, int row) {
final int halfFilterSize = filterSize / 2;
float[][] srcGrid = src.getGrid();
float[][] dstGrid = dst.getGrid();
final int cols = src.getCols();
final int rows = src.getRows();
int npts = 0;
float tot = 0;
for (int r = row - halfFilterSize; r <= row + halfFilterSize; r++) {
if (r > 0 && r < rows) {
float[] srcRow = srcGrid[r];
for (int c = col - halfFilterSize; c <= col + halfFilterSize; c++) {
if (c > 0 && c < cols) {
tot += srcRow[c];
++npts;
}
}
}
}
dstGrid[row][col] = tot / npts;
}
}