/*
* Copyright 2011 by Mark Coletti, Keith Sullivan, Sean Luke, and
* George Mason University Mason University Licensed under the Academic
* Free License version 3.0
*
* See the file "LICENSE" for more information
*
* $Id$
*
*/
package sim.io.geo;
import com.vividsolutions.jts.geom.Envelope;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import sim.field.geo.GeomGridField;
import sim.field.grid.AbstractGrid2D;
import sim.field.grid.DoubleGrid2D;
import sim.field.grid.IntGrid2D;
/** Importer for ESRI Arc/Info ASCII GRID formatted files
*
*/
public class ArcInfoASCGridImporter //extends GeomImporter
{
/** Not intended to be instantiated as there is no local state
*/
private ArcInfoASCGridImporter() {}
/** Read geospatial grid data from fileName into given field
*
* Note that NODATA values are read in as is without substitution.
*
* @param source is the data stream for the file
* @param type denotes the base type as either integer or double-based
* @param field to be populated
*
*
*/
public static void read(InputStream source, final GeomGridField.GridDataType type, GeomGridField field)
{
try
{
int width = 0;
int height = 0;
Scanner scanner = new Scanner(source);
scanner.useLocale(Locale.US);
scanner.next(); // skip "ncols"
width = scanner.nextInt();
scanner.next(); // skip "nrows"
height = scanner.nextInt();
double xllcorner = 0.0; // X lower left corner
double yllcorner = 0.0; // Y " " "
double cellSize = 0.0; // dimensions of grid cell in coordinate
// system units
scanner.next(); // skip "xllcorner"
xllcorner = scanner.nextDouble();
scanner.next(); // skip "yllcorner"
yllcorner = scanner.nextDouble();
scanner.next(); // skip "cellsize"
cellSize = scanner.nextDouble();
// Skip the optional NODATA line if it exists
if ( scanner.hasNext("NODATA_value") )
{
// Have to do this twice to get past the NODATA line
String nextLine = scanner.nextLine();
nextLine = scanner.nextLine();
// System.out.println("nextLine: " + nextLine);
}
// We should now be at the first line of data. Given how the user
// wants to interpret the data (i.e., as integers or floats) we'll
// have to obviously read the datat a little differently.
AbstractGrid2D grid = null;
switch (type)
{
case INTEGER:
grid = new IntGrid2D(width, height);
readIntegerBased(scanner, width, height, (IntGrid2D) grid);
break;
case DOUBLE:
grid = new DoubleGrid2D(width, height);
readDoubleBased(scanner, width, height, (DoubleGrid2D) grid);
break;
}
field.setGrid(grid);
// Before we go, ensure that we've got the MBR and cell dimensions
// all sorted.
field.setPixelHeight(cellSize);
field.setPixelWidth(cellSize);
Envelope MBR = new Envelope(xllcorner, xllcorner + cellSize * width,
yllcorner + cellSize * height, yllcorner);
field.setMBR(MBR);
scanner.close();
} catch (IOException ex)
{ // XXX Yes, but is this due to missing file or some other problem?
Logger.getLogger(ArcInfoASCGridImporter.class.getName()).log(Level.SEVERE, null, ex);
throw new RuntimeException(ex);
}
}
/** Reads integer-based geospatial data from ARC/INFO ASCII GRID file
*
* intGrid2D.field populated with data found in reader.
*
* @throws IOException if problem reading data
*
* @see read()
*/
private static void readIntegerBased(Scanner scanner, int width, int height, IntGrid2D intGrid2D) throws IOException
{
int currentInt;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
currentInt = scanner.nextInt();
intGrid2D.set(x, y, currentInt);
}
}
}
/** Reads real-based geospatial data from ARC/INFO ASCII GRID file
*
* doubleGrid2D.field populated with data found in reader.
*
* @throws IOException if problem reading data
*
* @see read()
*/
private static void readDoubleBased(Scanner scanner, int width, int height, DoubleGrid2D doubleGrid2D) throws IOException
{
double currentDouble;
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
currentDouble = scanner.nextDouble();
doubleGrid2D.set(x, y, currentDouble);
}
}
}
}