/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2007-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.referencing.operation.builder.algorithm;
import java.awt.image.DataBuffer;
import java.awt.image.WritableRaster;
import java.util.Map;
import javax.media.jai.RasterFactory;
import org.geotools.geometry.DirectPosition2D;
import org.opengis.coverage.Coverage;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.operation.TransformException;
/**
* Super class for implementing interpolation algorithms. Subclass has to implement just the
* {@link #getValue(DirectPosition)} method.
*
* @source $URL$
* @version $Id$
* @author jezekjan
*
*/
public abstract class AbstractInterpolation {
/** Known values at positions*/
private final Map<DirectPosition, Float> positions;
/** Grid spacing in x */
private double dx;
/** grid spacing in y */
private double dy;
/** Envelope of interpolated area*/
private final Envelope env;
/** Number of rows*/
private int xNumCells;
/** Number of cells*/
private int yNumCells;
/**Calculated values in 1D array*/
private float[] gridValues;
/**Calculated values in 2D array*/
private float[][] grid2D;
/**Calculated values in raster*/
private WritableRaster raster;
/**
*
* @param positions keys - point (DirectPosition), values - point values
*/
public AbstractInterpolation(Map <DirectPosition, Float> positions) {
this.positions = positions;
this.dx = 0;
this.dy = 0;
this.env = null;
this.xNumCells = 0;
this.yNumCells = 0;
}
public AbstractInterpolation(Map <DirectPosition, Float> positions, int xNumOfCells,
int yNumOfCells, Envelope env) {
this.positions = positions;
this.xNumCells = xNumOfCells;
this.yNumCells = yNumOfCells;
this.env = env;
dx = env.getLength(0) / xNumOfCells;
dy = env.getLength(1) / yNumOfCells;
//gridValues = new float[xNumCells*yNumCells];
}
/**
* Sets the spacing between grid cells and rows.
* @param dx Spacing between rows
* @param dy Spacing between cells
*/
public void setSpacing(double dx, double dy) {
this.dx = dx;
this.dy = dy;
this.xNumCells = (int) Math.floor(env.getLength(0) / dx);
this.yNumCells = (int) Math.floor(env.getLength(1) / dy);
}
/**
* Sets the number of rows and cells. The spacing is calculated by dividing the envelope
* @param xNumOfCells Number of grid cells
* @param yNumOfCells Number of grid rows
*/
public void setDensity(int xNumOfCells, int yNumOfCells) {
this.xNumCells = xNumOfCells;
this.yNumCells = yNumOfCells;
dx = env.getLength(0) / xNumOfCells;
dy = env.getLength(1) / yNumOfCells;
}
/**
* Returns array of float of interpolated grid values.
* The values are in row order. The dimension
* id number of columns * number of rows.
* @return Values of grid coordinates
*/
private float[] buildGrid() {
gridValues = new float[(xNumCells + 1) * (yNumCells + 1)];
for (int i = 0; i <= yNumCells; i++) {
for (int j = 0; j <= xNumCells; j++) {
DirectPosition dp = new DirectPosition2D(
env.getLowerCorner().getOrdinate(0) + (j * dx),
env.getUpperCorner().getOrdinate(1) - (i * dy));
int index = (i * (1 + xNumCells)) + j;
float value = getValue(dp);
gridValues[index] = value;
}
}
return gridValues;
}
private void buildCoverage() {
gridValues = new float[(xNumCells + 1) * (yNumCells + 1)];
for (int i = 0; i <= yNumCells; i++) {
for (int j = 0; j <= xNumCells; j++) {
gridValues[(i * (1 + xNumCells)) + j] = getValue(new DirectPosition2D(env.getLowerCorner()
.getOrdinate(0)
+ (j * dx), env.getLowerCorner().getOrdinate(1) + (i * dy)));
}
}
}
/**
*
* @return
*/
public float[] getGrid() {
if (gridValues == null) {
gridValues = buildGrid();
}
return gridValues;
}
/**
*
* @return grid in the form of WritableRaster
*/
public WritableRaster getRaster() {
if (raster == null) {
final float[] gridPositions = getGrid();
raster = RasterFactory.createBandedRaster(DataBuffer.TYPE_FLOAT, yNumCells + 1,
xNumCells + 1, 1, null);
raster.setSamples(0, 0, yNumCells + 1, xNumCells + 1, 0, gridPositions);
}
return raster;
}
/**
*
* @return
* @throws TransformException
*/
public float[][] get2DGrid() {
if ((grid2D == null) || (grid2D.length == 0)) {
final float[] warpPositions = getGrid();
grid2D = new float[yNumCells + 1][xNumCells + 1];
for (int i = 0; i <= yNumCells; i++) {
for (int j = 0; j <= xNumCells; j++) {
int index = (int) ((i * (xNumCells + 1)) + (j));
float value = getGrid()[index];
grid2D[i][j] = value;
}
}
}
return grid2D;
}
/**
* Return interpolated value in position p
* @param p position where we want to compute the value
* @return the value at position p
*/
public float intepolateValue(DirectPosition p) {
return getValue(p);
}
/**
* Real computation is performed here. Real algorithm has to be implemented her.
* @param p position where we want to compute the value
* @return the value at position p
*/
abstract public float getValue(DirectPosition p);
public double getDx() {
return dx;
}
public double getDy() {
return dy;
}
public Envelope getEnv() {
return env;
}
public int getXNumCells() {
return xNumCells;
}
public int getYNumCells() {
return yNumCells;
}
public Map<DirectPosition, Float> getPositions() {
return positions;
}
}