Mercurial > dive4elements > gnv-client
view geo-backend/src/main/java/de/intevation/gnv/geobackend/sde/datasources/RasterObject.java @ 548:ccd976fc0f7b
Implemented bilinear interpolation on raster tiles.
geo-backend/trunk@520 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Sat, 09 Jan 2010 16:12:10 +0000 |
parents | 23d5cc37dd5b |
children | 0dcf068fb552 |
line wrap: on
line source
/** * */ package de.intevation.gnv.geobackend.sde.datasources; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Envelope; import java.io.Serializable; import org.apache.log4j.Logger; /** * @author Tim Englich (tim.englich@intevation.de) * @author Sascha L. Teichmann (sascha.teichmann@intevation.de) */ public class RasterObject implements Serializable { private static Logger log = Logger.getLogger(RasterObject.class); public static final int NEAREST_NEIGHBOR = 0; public static final int BILINEAR = 1; private double mx; private double bx; private double my; private double by; private int columnIndex; private int rowIndex; private int tileWidth; private int tileHeight; private double [] rasterData; public RasterObject() { } public RasterObject( double mx, double bx, double my, double by, int columnIndex, int rowIndex, double [] rasterData, int tileWidth, int tileHeight ){ this.mx = mx; this.bx = bx; this.my = my; this.by = by; this.columnIndex = columnIndex; this.rowIndex = rowIndex; this.rasterData = rasterData; this.tileWidth = tileWidth; this.tileHeight = tileHeight; } public boolean contains(Coordinate coordinate) { double px = mx*coordinate.x + bx; double py = my*coordinate.y + by; return px >= 0d && py >= 0d && px < tileWidth && py < tileHeight; } public final double get(int posX, int posY) { return rasterData[posY*tileWidth + posX]; } public int getTileWidth() { return tileWidth; } public int getTileHeight() { return tileWidth; } public int getColumnIndex() { return columnIndex; } public int getRowIndex() { return rowIndex; } public double getValue(Coordinate coordinate) { return getValue(coordinate, NEAREST_NEIGHBOR); } public final double interpolateBilinear(double px, double py) { if (px < 0.5d) { // left border if (py < 0.5d) { // upper left edge return rasterData[0]; } if (py > tileHeight-0.5d) { // lower left edge return rasterData[rasterData.length-tileWidth]; } // center left int i = (int)(py -= 0.5d); double t = py - i; i *= tileWidth; return (1d-t)*rasterData[i] + t*rasterData[i+tileWidth]; } if (px > tileWidth-0.5d) { // right border if (py < 0.5d) { // upper right edge return rasterData[tileWidth-1]; } if (py > tileHeight-0.5d) { // lower right edge return rasterData[rasterData.length-1]; } // center right int i = (int)(py -= 0.5d); double t = py - i; i = i*tileWidth + tileWidth-1; return (1d-t)*rasterData[i] + t*rasterData[i+tileWidth]; } if (py < 0.5d) { // top border int i = (int)(px -= 0.5d); double t = px - i; return (1d-t)*rasterData[i] + t*rasterData[i+1]; } if (py > tileHeight-0.5d) { // bottom border int i = (int)(px -= 0.5d); double t = px - i; i += rasterData.length-tileWidth; return (1d-t)*rasterData[i] + t*rasterData[i+1]; } // center int i = (int)(py -= 0.5d); int j = (int)(px -= 0.5d); double ti = py - i; double tj = px - j; int idx = i*tileWidth + j; double v1j1 = rasterData[idx]; double v2j1 = rasterData[idx+1]; idx += tileWidth; double v1j2 = rasterData[idx]; double v2j2 = rasterData[idx+1]; double v1 = (1d-tj)*v1j1 + tj*v2j1; double v2 = (1d-tj)*v1j2 + tj*v2j2; return (1d-ti)*v1 + ti*v2; } public double getValue(Coordinate coordinate, int interpolationType) { double px = mx*coordinate.x + bx; double py = my*coordinate.y + by; if (px < 0d || py < 0d || px >= tileWidth || py >= tileHeight) { return Double.NaN; } if (interpolationType == BILINEAR) { return interpolateBilinear(px, py); } int posX = Math.min(tileWidth-1, (int)Math.round(px)); int posY = Math.min(tileHeight-1, (int)Math.round(py)); return get(posX, posY); } }