package org.geoserver.wps.sextante;
import java.awt.geom.Rectangle2D;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.io.File;
import javax.media.jai.PlanarImage;
import javax.media.jai.RasterFactory;
import org.geotools.coverage.CoverageFactoryFinder;
import org.geotools.coverage.GridSampleDimension;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridCoverageFactory;
import org.geotools.coverage.grid.io.AbstractGridCoverageWriter;
import org.geotools.gce.arcgrid.ArcGridWriter;
import org.geotools.gce.geotiff.GeoTiffWriter;
import org.geotools.geometry.Envelope2D;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import es.unex.sextante.dataObjects.AbstractRasterLayer;
import es.unex.sextante.rasterWrappers.GridExtent;
public class GTRasterLayer extends AbstractRasterLayer {
private CoordinateReferenceSystem m_CRS;
private String m_sFilename;
private String m_sName ="";
private PlanarImage m_image;
private GridExtent m_LayerExtent;
private double m_dNoDataValue;
public void create(String name, String filename, GridExtent ge,
int dataType, int numBands, Object crs) {
if (!(crs instanceof CoordinateReferenceSystem)){
crs = DefaultGeographicCRS.WGS84;
}
Raster m_Raster = RasterFactory.createBandedRaster(dataType,
ge.getNX(), ge.getNY(), numBands, null);
Envelope envelope = new Envelope2D((CoordinateReferenceSystem)crs,
ge.getXMin(), ge.getYMin(),
ge.getWidth(), ge.getHeight());
GridCoverageFactory factory = CoverageFactoryFinder.getGridCoverageFactory(null);
GridCoverage2D gc = factory.create(name, (WritableRaster)m_Raster, envelope,
null, null, null, null, null);
m_BaseDataObject = gc;
m_sName = name;
m_sFilename = filename;
m_LayerExtent = ge;
m_image = (PlanarImage) gc.geophysics(true).getRenderedImage();
initNoData((GridCoverage2D)m_BaseDataObject);
}
private void initNoData(GridCoverage2D gc) {
Object value = gc.getProperty("GC_NODATA");
if (value!=null && value instanceof Number) {
m_dNoDataValue = ((Number) value).doubleValue();
return;
}
else {
GridSampleDimension[] dimList = gc.getSampleDimensions();
double[] noDataList;
for (int i=0; i<dimList.length; i++) {
noDataList = dimList[i].getNoDataValues();
if (noDataList != null && noDataList.length>0){
m_dNoDataValue = noDataList[0];
return;
}
}
}
// ensure we got a sensible result, because some GridCoverage2D are not able to provide no-data values
setNoDataValue(Double.NaN);
}
public void create(Object obj) {
if (obj instanceof GridCoverage2D){
m_BaseDataObject = obj;
GridCoverage2D gc = ((GridCoverage2D)obj);
m_CRS = gc.getCoordinateReferenceSystem();
Envelope2D env = gc.getEnvelope2D();
m_LayerExtent = new GridExtent();
m_LayerExtent.setCellSize((env.getMaxX() - env.getMinX())
/ (double)gc.getRenderedImage().getWidth());
m_LayerExtent.setXRange(env.getMinX(), env.getMaxX());
m_LayerExtent.setYRange(env.getMinY(), env.getMaxY());
m_image = (PlanarImage) gc.geophysics(true).getRenderedImage();
m_sName = gc.getName().toString();
initNoData(gc);
}
}
public void fitToGridExtent(GridExtent gridExtent) {
if (gridExtent != null){
WritableRaster raster = RasterFactory.createBandedRaster(getDataType(),
gridExtent.getNX(), gridExtent.getNY(),
getBandsCount(), null);
Envelope envelope = new Envelope2D((CoordinateReferenceSystem)m_CRS,
gridExtent.getXMin(), gridExtent.getYMin(),
gridExtent.getWidth(), gridExtent.getHeight());
GridCoverageFactory factory = CoverageFactoryFinder.getGridCoverageFactory(null);
this.setWindowExtent(gridExtent);
// FIXME: should this also use tiles???
for (int x = 0; x < gridExtent.getNX(); x++) {
for (int y = 0; y < gridExtent.getNY(); y++) {
for (int i = 0; i < getBandsCount(); i++) {
raster.setSample(x, y, i, this.getCellValueAsDouble(x, y, i));
}
}
}
m_BaseDataObject = factory.create(getName(), (WritableRaster)raster, envelope,
null, null, null, null, null);
System.gc();
}
}
public int getBandsCount() {
if (m_BaseDataObject != null){
GridCoverage2D gc = (GridCoverage2D) m_BaseDataObject;
return gc.getNumSampleDimensions();
}
else{
return 0;
}
}
public double getCellValueInLayerCoords(int x, int y, int band) {
if (m_image != null){
Raster tile = getTile(x, y);
if(tile != null) {
return tile.getSampleDouble(x, y, band);
} else {
return getNoDataValue();
}
} else {
return getNoDataValue();
}
}
public int getDataType() {
if (m_image != null){
return m_image.getTile(0, 0).getDataBuffer().getDataType();
}
else{
return DataBuffer.TYPE_DOUBLE;
}
}
public double getLayerCellSize() {
if (m_LayerExtent != null){
return m_LayerExtent.getCellSize();
}
else{
return 0;
}
}
public GridExtent getLayerGridExtent() {
return m_LayerExtent;
}
public double getNoDataValue() {
return m_dNoDataValue;
}
public void setCellValue(int x, int y, int band, double value) {
if (isInWindow(x, y)){
Raster raster = getTile(x, y);
if (raster instanceof WritableRaster){
((WritableRaster)raster).setSample(x, y, band, value);
}
}
}
public void setNoDataValue(double noDataValue) {
m_dNoDataValue = noDataValue;
}
public Object getCRS() {
return m_CRS;
}
public Rectangle2D getFullExtent() {
if (m_BaseDataObject != null){
GridCoverage2D gc = (GridCoverage2D) m_BaseDataObject;
return new Envelope2D(gc.getEnvelope());
}
else{
return null;
}
}
public void open() {}
public void close() {}
public void postProcess() {
try{
AbstractGridCoverageWriter writer;
if (m_sFilename.endsWith("asc")){
writer = new ArcGridWriter(new File(m_sFilename));
}
else{
writer = new GeoTiffWriter(new File(m_sFilename));
}
GridCoverage2D gc = (GridCoverage2D) m_BaseDataObject;
writer.write(gc.geophysics(true), null);
writer.dispose();
}catch (Exception e){
e.printStackTrace();
}
}
public String getFilename() {
return m_sFilename;
}
public String getName() {
return m_sName;
}
public void setName(String sName) {
m_sName = sName;
}
private Raster getTile(int x, int y) {
return m_image.getTile(m_image.XToTileX(x), m_image.YToTileY(y));
}
}