package org.geotools.demo.coverage;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRenderedImage;
import java.awt.image.renderable.RenderableImage;
import java.util.ArrayList;
import java.util.List;
import javax.media.jai.TiledImage;
import javax.media.jai.iterator.RandomIterFactory;
import javax.media.jai.iterator.WritableRandomIter;
import org.geotools.coverage.grid.GridCoordinates2D;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.ViewType;
import org.geotools.geometry.DirectPosition2D;
import org.opengis.coverage.CannotEvaluateException;
import org.opengis.geometry.DirectPosition;
import org.opengis.referencing.operation.TransformException;
/**
*
* @author Michael Bedward
*/
/**
* @author Michael Bedward
*/
public class WritableGridCoverage2D extends GridCoverage2D {
private GridCoverage2D wrapped;
private static final int MAX_PENDING_VALUES = 10000;
private static class PendingValue {
Object pos;
boolean isGeographic;
Object value;
}
private List<PendingValue> pendingValues = new ArrayList<PendingValue>();
/**
* Constructor: wraps the given grid
*
* @param grid the original grid
*/
public WritableGridCoverage2D(GridCoverage2D grid) {
super(grid.getName().toString(), grid);
this.wrapped = grid;
}
@Override
public Object evaluate(DirectPosition point) throws CannotEvaluateException {
flushCache(true);
return super.evaluate(point);
}
@Override
public byte[] evaluate(DirectPosition coord, byte[] dest) throws CannotEvaluateException {
flushCache(true);
return super.evaluate(coord, dest);
}
@Override
public int[] evaluate(DirectPosition coord, int[] dest) throws CannotEvaluateException {
flushCache(true);
return super.evaluate(coord, dest);
}
@Override
public float[] evaluate(DirectPosition coord, float[] dest) throws CannotEvaluateException {
flushCache(true);
return super.evaluate(coord, dest);
}
@Override
public double[] evaluate(DirectPosition coord, double[] dest) throws CannotEvaluateException {
flushCache(true);
return super.evaluate(coord, dest);
}
@Override
public int[] evaluate(Point2D coord, int[] dest) throws CannotEvaluateException {
flushCache(true);
return super.evaluate(coord, dest);
}
@Override
public float[] evaluate(Point2D coord, float[] dest) throws CannotEvaluateException {
flushCache(true);
return super.evaluate(coord, dest);
}
@Override
public double[] evaluate(Point2D coord, double[] dest) throws CannotEvaluateException {
flushCache(true);
return super.evaluate(coord, dest);
}
@Override
public int[] evaluate(GridCoordinates2D coord, int[] dest) {
flushCache(true);
return super.evaluate(coord, dest);
}
@Override
public float[] evaluate(GridCoordinates2D coord, float[] dest) {
flushCache(true);
return super.evaluate(coord, dest);
}
@Override
public double[] evaluate(GridCoordinates2D coord, double[] dest) {
flushCache(true);
return super.evaluate(coord, dest);
}
/**
* @deprecated
*/
@Override
public GridCoverage2D geophysics(boolean geo) {
flushCache(true);
return super.geophysics(geo);
}
@Override
public RenderableImage getRenderableImage(int xAxis, int yAxis) {
flushCache(true);
return super.getRenderableImage(xAxis, yAxis);
}
@Override
public RenderedImage getRenderedImage() {
flushCache(true);
return super.getRenderedImage();
}
@Override
public boolean isDataEditable() {
return true;
}
@Override
public void prefetch(Rectangle2D area) {
// not implemented
}
@Override
public void show(String title, int xAxis, int yAxis) {
flushCache(true);
super.show(title, xAxis, yAxis);
}
@Override
public void show(String title) {
flushCache(true);
super.show(title);
}
@Override
public GridCoverage2D view(ViewType type) {
flushCache(true);
return super.view(type);
}
public void setValue(DirectPosition worldPos, int value) {
doSetWorldValue(worldPos, value);
}
public void setValue(DirectPosition worldPos, float value) {
doSetWorldValue(worldPos, value);
}
public void setValue(DirectPosition worldPos, double value) {
doSetWorldValue(worldPos, value);
}
public void setValue(GridCoordinates2D gridPos, int value) {
doSetGridValue(gridPos, value);
}
public void setValue(GridCoordinates2D gridPos, float value) {
doSetGridValue(gridPos, value);
}
public void setValue(GridCoordinates2D gridPos, double value) {
doSetGridValue(gridPos, value);
}
private void doSetWorldValue(DirectPosition pos, Number value) {
PendingValue pv = new PendingValue();
pv.pos = new DirectPosition2D(pos);
pv.isGeographic = true;
pv.value = value;
pendingValues.add(pv);
flushCache(false);
}
private void doSetGridValue(GridCoordinates2D gridPos, Number value) {
PendingValue pv = new PendingValue();
pv.pos = new GridCoordinates2D(gridPos);
pv.isGeographic = false;
pv.value = value;
pendingValues.add(pv);
flushCache(false);
}
private void flushCache(boolean force) {
if (pendingValues.size() >= MAX_PENDING_VALUES || (force && pendingValues.size() > 0)) {
WritableRenderedImage writableImage = null;
if (super.isDataEditable()) {
writableImage = (WritableRenderedImage) image;
} else {
writableImage = new TiledImage(wrapped.getRenderedImage(), true);
}
WritableRandomIter writeIter = RandomIterFactory.createWritable(writableImage, null);
int dataType = writableImage.getSampleModel().getDataType();
GridCoordinates2D gridPos = null;
for (PendingValue pv : pendingValues) {
if (pv.isGeographic) {
try {
gridPos = wrapped.getGridGeometry().worldToGrid((DirectPosition) pv.pos);
} catch (TransformException ex) {
throw new RuntimeException("Could not transform location [" +
pv.pos + "] to grid coords");
}
} else {
gridPos = (GridCoordinates2D) pv.pos;
}
switch (dataType) {
case DataBuffer.TYPE_INT:
writeIter.setSample(gridPos.x, gridPos.y, 0, (Integer)pv.value);
break;
case DataBuffer.TYPE_FLOAT:
writeIter.setSample(gridPos.x, gridPos.y, 0, (Float)pv.value);
break;
case DataBuffer.TYPE_DOUBLE:
writeIter.setSample(gridPos.x, gridPos.y, 0, (Double)pv.value);
break;
}
}
pendingValues.clear();
}
}
}