280 lines
5.9 KiB
Java
280 lines
5.9 KiB
Java
package org.gcube.dataanalysis.geo.connectors.asc;
|
|
|
|
import java.util.Arrays;
|
|
|
|
/**
|
|
* Represents my best guess at the ESRI ASCII raster format. I couldn't find any sensible documentation, so it supports the following features:
|
|
* <ul>
|
|
* <li>cellsize, xll and xll are stored as doubles, and largely ignored
|
|
* <li>NDATA has a string representation (as it is typically read in from an ascii string) and is internally represented as Double.NaN, as this is safer and easier to deal with than the -9999 found in most rasters.
|
|
* </ul>
|
|
*
|
|
* @author dmrust
|
|
*
|
|
*/
|
|
public class AscRaster {
|
|
protected double[][] data;
|
|
protected double xll;
|
|
protected double yll;
|
|
protected double cellsize;
|
|
protected double dx = -1;
|
|
protected double dy = -1;
|
|
protected int cols;
|
|
protected int rows;
|
|
|
|
public static final String DEFAULT_NODATA = "-9999";
|
|
protected String NDATA = DEFAULT_NODATA;
|
|
|
|
public void print() {
|
|
System.out.println("Rows: " + rows + " cols: " + cols + " cellsize " + cellsize + " dx " + dx + " dy " + dy);
|
|
for (double[] row : data) {
|
|
for (double val : row)
|
|
System.out.print(val + " ");
|
|
System.out.println("");
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Creates an empty raster
|
|
*/
|
|
public AscRaster() {
|
|
|
|
}
|
|
|
|
/**
|
|
* Creates a raster from the given data
|
|
*
|
|
* @param cellsize
|
|
* @param xll
|
|
* @param yll
|
|
*/
|
|
public AscRaster(double cellsize, double dx, double dy, double xll, double yll) {
|
|
this();
|
|
setCellsize(cellsize);
|
|
setXll(xll);
|
|
setYll(yll);
|
|
setdx(dx);
|
|
setdy(dy);
|
|
}
|
|
|
|
/**
|
|
* Creates a raster from the given data
|
|
*
|
|
* @param data
|
|
* @param cellsize
|
|
* @param xll
|
|
* @param yll
|
|
*/
|
|
public AscRaster(double[][] data, double cellsize, double dx, double dy, double xll, double yll) {
|
|
this(cellsize, dx, dy, xll, yll);
|
|
setData(data);
|
|
}
|
|
|
|
/**
|
|
* Creates a raster from the given data
|
|
*
|
|
* @param data
|
|
* @param cellsize
|
|
* @param xll
|
|
* @param yll
|
|
*/
|
|
public AscRaster(int[][] data, double cellsize, double dx, double dy, double xll, double yll) {
|
|
this(cellsize, dx, dy, xll, yll);
|
|
setData(data);
|
|
}
|
|
|
|
public static AscRaster getTempRaster(double[][] data, double xll, double yll, double size) {
|
|
return getTempRaster(data, xll, yll, size, DEFAULT_NODATA);
|
|
}
|
|
|
|
public static AscRaster getTempRaster(double[][] data, double xll, double yll, double size, String ndata) {
|
|
AscRaster a = new AscRaster();
|
|
a.data = data;
|
|
a.xll = xll;
|
|
a.yll = yll;
|
|
a.cellsize = size;
|
|
a.NDATA = ndata;
|
|
a.rows = data.length;
|
|
a.cols = data[0].length;
|
|
return a;
|
|
}
|
|
|
|
/**
|
|
* Sets the parameters of this raster (rows, columns, corner, cellsize, NDATA etc) to be the same as the other raster. This includes initialising the data array with NDATAs
|
|
*
|
|
* @param other
|
|
*/
|
|
public void init(AscRaster other) {
|
|
xll = other.xll;
|
|
yll = other.yll;
|
|
cellsize = other.cellsize;
|
|
NDATA = other.NDATA;
|
|
setSize(other.getRows(), other.getCols());
|
|
}
|
|
|
|
/**
|
|
* Initialises the Raster to Double.NaN (i.e. NDATA)
|
|
*/
|
|
public void initData() {
|
|
initData(Double.NaN);
|
|
}
|
|
|
|
/**
|
|
* Initialises the raster so the entire data array contains 'value'
|
|
*
|
|
* @param value
|
|
*/
|
|
public void initData(double value) {
|
|
data = new double[rows][];
|
|
for (int i = 0; i < rows; i++) {
|
|
data[i] = new double[cols];
|
|
|
|
Arrays.fill(data[i], value);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the underlying data array - NOTE: this is *NOT* a copy, if you change it, you change the data
|
|
*
|
|
* @return the data array
|
|
*/
|
|
public double[][] getData() {
|
|
return data;
|
|
}
|
|
|
|
public double[][] getInvertedAxisData() {
|
|
double[][] dataInv = new double[data.length][data[0].length];
|
|
for (int i = data.length - 1; i >= 0; i--) {
|
|
dataInv[data.length - 1 - i] = data[i];
|
|
}
|
|
return dataInv;
|
|
}
|
|
|
|
public void setValue(int row, int column, double value) {
|
|
if (row < rows && column < cols)
|
|
data[row][column] = value;
|
|
}
|
|
|
|
public double getValue(int row, int column) {
|
|
if (row < rows && column < cols)
|
|
if (data[row][column]!= Double.parseDouble(NDATA))
|
|
return data[row][column];
|
|
else
|
|
return Double.NaN;
|
|
|
|
return Double.NaN;
|
|
}
|
|
|
|
/**
|
|
* Copies the given data into the underlying data array. Also updates the number of rows and columns.
|
|
*
|
|
* @param data
|
|
*/
|
|
public void setData(double[][] data) {
|
|
rows = data.length;
|
|
cols = data[0].length;
|
|
initData();
|
|
for (int i = 0; i < rows; i++)
|
|
for (int j = 0; j < cols; j++)
|
|
this.data[i][j] = data[i][j];
|
|
}
|
|
|
|
/**
|
|
* Copies the given data into the underlying data array. Also updates the number of rows and columns.
|
|
*
|
|
* @param data
|
|
*/
|
|
public void setData(int[][] data) {
|
|
rows = data.length;
|
|
cols = data[0].length;
|
|
initData();
|
|
for (int i = 0; i < rows; i++)
|
|
for (int j = 0; j < cols; j++)
|
|
this.data[i][j] = data[i][j];
|
|
}
|
|
|
|
public double getXll() {
|
|
return xll;
|
|
}
|
|
|
|
public void setXll(double xll) {
|
|
this.xll = xll;
|
|
}
|
|
|
|
public double getYll() {
|
|
return yll;
|
|
}
|
|
|
|
public void setYll(double yll) {
|
|
this.yll = yll;
|
|
}
|
|
|
|
public double getCellsize() {
|
|
return cellsize;
|
|
}
|
|
|
|
public void setCellsize(double cellsize) {
|
|
this.cellsize = cellsize;
|
|
}
|
|
|
|
public double getdx() {
|
|
return dx;
|
|
}
|
|
|
|
public void setdx(double dx) {
|
|
this.dx = dx;
|
|
}
|
|
|
|
public double getdy() {
|
|
return dy;
|
|
}
|
|
|
|
public void setdy(double dy) {
|
|
this.dy = dy;
|
|
}
|
|
|
|
public int getCols() {
|
|
return cols;
|
|
}
|
|
|
|
public int getRows() {
|
|
return rows;
|
|
}
|
|
|
|
/**
|
|
* Sets the size of the raster, and also initialises the array with NDATA
|
|
*
|
|
* @param nrows
|
|
* @param columns
|
|
*/
|
|
public void setSize(int nrows, int columns) {
|
|
this.rows = nrows;
|
|
this.cols = columns;
|
|
initData();
|
|
}
|
|
|
|
public String getNDATA() {
|
|
return NDATA;
|
|
}
|
|
|
|
public void setNDATA(String nDATA) {
|
|
NDATA = nDATA;
|
|
}
|
|
|
|
public int longitude2Index(double longitude) {
|
|
double factor = dx;
|
|
if (dx<0)
|
|
factor = cellsize;
|
|
return (int) Math.round((longitude - xll) / factor);
|
|
}
|
|
|
|
public int latitude2Index(double latitude) {
|
|
double factor = dy;
|
|
if (dy<0)
|
|
factor = cellsize;
|
|
return (rows-1) - (int) Math.round((latitude - yll) / factor);
|
|
|
|
}
|
|
}
|