/*
* ESRIASCIIGridExporter.java
*
* Created on August 14, 2005, 4:17 PM
*
*/
package ika.geoexport;
import java.io.*;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
/**
* ESRIASCIIGridWriter writes a grid of float values to a ESRI ASCII grid file.
* It does not write a GeoGrid or another object modeling a grid, but is used
* in "immediate mode", i.e. the user of this class directly calls methods to
* write grid values. The constructor writes the header of the file.
* @author Bernhard Jenny, Institute of Cartography, ETH Zurich.
*/
public final class ESRIASCIIGridWriter {
/**
* Counts the number of values written to the file.
*/
private int valueCounter = 0;
/**
* The number of columns of the grid.
*/
private int cols;
/**
* The number of rows of the grid.
*/
private int rows;
/**
* The value that is written if the corresponding value is not valid.
*/
private String noDataString;
/**
* Write to this PrintWriter.
*/
private PrintWriter writer;
private DecimalFormat formatter;
/**
* A system dependent separator string, typically '\n' or '\r' or a
* combination of the two.
*/
private static final String lineSeparator = System.getProperty("line.separator");
/** Creates a new instance of ESRIASCIIGridExporter and writes the header
of the file.
*/
public ESRIASCIIGridWriter(PrintWriter writer,
int cols, int rows,
double west, double south,
double cellSize, float noDataValue) {
if (cols <= 1 || rows <= 1 || cellSize <= 0) {
throw new IllegalArgumentException();
}
this.setNumberFormat("##0.#");
this.writer = writer;
this.cols = cols;
this.rows = rows;
this.noDataString = Float.toString(noDataValue) + " "; // append a space
writer.write("ncols " + cols + lineSeparator);
writer.write("nrows " + rows + lineSeparator);
writer.write("xllcorner " + west + lineSeparator);
writer.write("yllcorner " + south + lineSeparator);
writer.write("cellsize " + cellSize + lineSeparator);
writer.write("nodata_value " + noDataValue + lineSeparator);
}
public void setNumberFormat(String pattern) {
formatter = new DecimalFormat(pattern);
DecimalFormatSymbols dfs = formatter.getDecimalFormatSymbols();
dfs.setDecimalSeparator('.');
formatter.setDecimalFormatSymbols(dfs);
}
/**
* Writes a value to the grid file. Throws an exception if all possible
* values have already been written.
* @param v The value to write to the file. Can be NaN or infinite. Should
* be different from the noDataValue parameter passed in the constructor.
*/
public void write(float v) {
this.assertGridNotFull();
if (Float.isNaN(v) || Float.isInfinite(v)) {
writer.write(this.noDataString);
} else {
writer.write(formatter.format(v));
}
writer.write(' ');
++valueCounter;
}
/**
* Write a noDataValue to the grid file.
*/
public void writeNoData() {
this.assertGridNotFull();
writer.write(this.noDataString);
++valueCounter;
}
/**
* Writes a system-dependent new-line character to the file. This should
* be called at the end of each row.
*/
public void newLine() {
writer.write (lineSeparator);
}
/**
* Make sure not all values have already been written to the grid file.
*/
private void assertGridNotFull() {
if (this.valueCounter >= this.cols * this.rows) {
throw new IllegalStateException("ASCII grid is complete.");
}
}
}