package org.geotoolkit.coverage;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.awt.image.WritableRaster;
import org.opengis.coverage.grid.GridCoordinates;
import org.opengis.coverage.grid.GridCoverage;
import org.opengis.coverage.grid.GridEnvelope;
import org.opengis.coverage.grid.GridGeometry;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.apache.sis.geometry.GeneralDirectPosition;
import org.apache.sis.internal.referencing.GeodeticObjectBuilder;
import org.apache.sis.measure.NumberRange;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.storage.DataStoreException;
import org.geotoolkit.coverage.grid.GeneralGridGeometry;
import org.geotoolkit.coverage.memory.MPCoverageStore;
import org.geotoolkit.util.NamesExt;
import org.geotoolkit.image.BufferedImages;
import org.geotoolkit.storage.coverage.CoverageStore;
import org.geotoolkit.storage.coverage.GridMosaic;
import org.geotoolkit.storage.coverage.Pyramid;
import org.geotoolkit.storage.coverage.PyramidalCoverageReference;
import org.junit.Assert;
import org.junit.Test;
/**
*
* @author Johann Sorel (Geomatys)
*/
public class PyramidReaderTest extends org.geotoolkit.test.TestBase {
private static final float DELTA = 0.000000001f;
/**
* 4D calc test
* @throws Exception
*/
@Test
public void coverage4DTest() throws Exception{
//create a small pyramid
final CoverageStore store = new MPCoverageStore();
final CoordinateReferenceSystem horizontal = CommonCRS.WGS84.normalizedGeographic();
final CoordinateReferenceSystem vertical = CommonCRS.Vertical.ELLIPSOIDAL.crs();
final CoordinateReferenceSystem temporal = CommonCRS.Temporal.JAVA.crs();
final CoordinateReferenceSystem crs = new GeodeticObjectBuilder().addName("4dcrs")
.createCompoundCRS(horizontal, vertical, temporal);
final int width = 28;
final int height = 13;
final PyramidalCoverageReference ref1 = (PyramidalCoverageReference) store.create(NamesExt.create("test1"));
create4DPyramid(ref1, crs, width, height, new double[][]{
{-5,-9, 12},
{-5, 0, -7},
{-5,21, 51},
{62,-9, -3},
{62, 0, 5},
{62,21, 17},
});
final GeneralGridGeometry gridGeomReader = ref1.acquireReader().getGridGeometry(0);
final GridEnvelope gridEnvReader = gridGeomReader.getExtent();
final MathTransform gridToCrsReader = gridGeomReader.getGridToCRS();
final GridCoverage result = ref1.acquireReader().read(0, null);
Assert.assertEquals(crs,result.getCoordinateReferenceSystem());
final GridGeometry gridGeom = result.getGridGeometry();
final GridEnvelope gridEnv = gridGeom.getExtent();
final MathTransform gridToCrs = gridGeom.getGridToCRS();
//-- we must have the same grid grometry definition between the reader and the coverage
Assert.assertEquals(gridEnvReader, gridEnv);
final GridCoordinates lowerCorner = gridEnv.getLow();
final GridCoordinates highCorner = gridEnv.getHigh();
//check grid envelope
Assert.assertEquals(0, lowerCorner.getCoordinateValue(0));
Assert.assertEquals(0, lowerCorner.getCoordinateValue(1));
Assert.assertEquals(0, lowerCorner.getCoordinateValue(2));
Assert.assertEquals(0, lowerCorner.getCoordinateValue(3));
Assert.assertEquals(111,highCorner.getCoordinateValue(0)); //28 * 4 -1
Assert.assertEquals(38, highCorner.getCoordinateValue(1)); //13 * 3 -1
Assert.assertEquals(1, highCorner.getCoordinateValue(2)); // 2 slices
Assert.assertEquals(2, highCorner.getCoordinateValue(3)); // 3 slices
//check transform
final double[] buffer = new double[4];
gridToCrs.transform(new double[]{0, 0, 0, 0} , 0, buffer, 0, 1);
Assert.assertArrayEquals(new double[]{-49.5, 59.5, 28.5, -4.5}, buffer, DELTA);
gridToCrs.transform(new double[]{0, 0, 0, 1} , 0, buffer, 0, 1);
Assert.assertArrayEquals(new double[]{-49.5, 59.5, 28.5, 10.5}, buffer, DELTA);
gridToCrs.transform(new double[]{0, 0, 0, 2} , 0, buffer, 0, 1);
Assert.assertArrayEquals(new double[]{-49.5, 59.5, 28.5, 21}, buffer, DELTA);
gridToCrs.transform(new double[]{0, 0, 1, 0} , 0, buffer, 0, 1);
Assert.assertArrayEquals(new double[]{-49.5, 59.5, 62, -4.5}, buffer, DELTA);
gridToCrs.transform(new double[]{0, 0, 1, 1} , 0, buffer, 0, 1);
Assert.assertArrayEquals(new double[]{-49.5, 59.5, 62, 10.5}, buffer, DELTA);
gridToCrs.transform(new double[]{0, 0, 1, 2} , 0, buffer, 0, 1);
Assert.assertArrayEquals(new double[]{-49.5, 59.5, 62, 21}, buffer, DELTA);
//we must obtain the same results with the gridToCrs from the reader
gridToCrsReader.transform(new double[]{0, 0, 0, 0} , 0, buffer, 0, 1);
Assert.assertArrayEquals(new double[]{-49.5, 59.5, 28.5, -4.5},buffer, DELTA);
gridToCrsReader.transform(new double[]{0, 0, 0, 1} , 0, buffer, 0, 1);
Assert.assertArrayEquals(new double[]{-49.5, 59.5, 28.5, 10.5}, buffer, DELTA);
gridToCrsReader.transform(new double[]{0, 0, 0, 2} , 0, buffer, 0, 1);
Assert.assertArrayEquals(new double[]{-49.5, 59.5, 28.5, 21}, buffer, DELTA);
gridToCrsReader.transform(new double[]{0, 0, 1, 0} , 0, buffer, 0, 1);
Assert.assertArrayEquals(new double[]{-49.5, 59.5, 62, -4.5},buffer, DELTA);
gridToCrsReader.transform(new double[]{0, 0, 1, 1} , 0, buffer, 0, 1);
Assert.assertArrayEquals(new double[]{-49.5, 59.5, 62, 10.5}, buffer, DELTA);
gridToCrsReader.transform(new double[]{0, 0, 1, 2} , 0, buffer, 0, 1);
Assert.assertArrayEquals(new double[]{-49.5, 59.5, 62, 21}, buffer, DELTA);
//check each block range
Assert.assertTrue(result instanceof GridCoverageStack);
final GridCoverageStack stackT = (GridCoverageStack) result;
final CoverageStack.Element[] elementsT = stackT.getElements();
Assert.assertEquals(-9.0,elementsT[0].getZCenter());
Assert.assertEquals( 0.0,elementsT[1].getZCenter());
Assert.assertEquals(21.0,elementsT[2].getZCenter());
Assert.assertEquals(NumberRange.create(-13.5, true, -4.5, false),elementsT[0].getZRange()); // [ (-9-((0+9)/2) ... (-9+((0+ 9)/2) [
Assert.assertEquals(NumberRange.create( -4.5, true, 10.5, false),elementsT[1].getZRange()); // [ ( 0-((0+9)/2) ... ( 0+((0+21)/2) [
Assert.assertEquals(NumberRange.create( 10.5, true, 31.5, false),elementsT[2].getZRange()); // [ (21-((0+9)/2) ... (21+((0+21)/2) [
final GridCoverageStack stackT0 = (GridCoverageStack) stackT.coveragesAt(-9).get(0);
final CoverageStack.Element[] elementsT0 = stackT0.getElements();
Assert.assertEquals(-5.0,elementsT0[0].getZCenter());
Assert.assertEquals(62.0,elementsT0[1].getZCenter());
Assert.assertEquals(NumberRange.create(-38.5, true, 28.5, false),elementsT0[0].getZRange()); // [ -5-((-5+62)/2) ... -5-((-5+62)/2) [
Assert.assertEquals(NumberRange.create( 28.5, true, 95.5, false),elementsT0[1].getZRange()); // [ 62-((-5+62)/2) ... 62-((-5+62)/2) [
final GridCoverageStack stackT1 = (GridCoverageStack) stackT.coveragesAt( 0).get(0);
final CoverageStack.Element[] elementsT1 = stackT0.getElements();
Assert.assertEquals(-5.0,elementsT1[0].getZCenter());
Assert.assertEquals(62.0,elementsT1[1].getZCenter());
Assert.assertEquals(NumberRange.create(-38.5, true, 28.5, false),elementsT1[0].getZRange()); // [ -5-((-5+62)/2) ... -5-((-5+62)/2) [
Assert.assertEquals(NumberRange.create( 28.5, true, 95.5, false),elementsT1[1].getZRange()); // [ 62-((-5+62)/2) ... 62-((-5+62)/2) [
final GridCoverageStack stackT2 = (GridCoverageStack) stackT.coveragesAt(21).get(0);
final CoverageStack.Element[] elementsT2 = stackT0.getElements();
Assert.assertEquals(-5.0,elementsT2[0].getZCenter());
Assert.assertEquals(62.0,elementsT2[1].getZCenter());
Assert.assertEquals(NumberRange.create(-38.5, true, 28.5, false),elementsT2[0].getZRange()); // [ -5-((-5+62)/2) ... -5-((-5+62)/2) [
Assert.assertEquals(NumberRange.create( 28.5, true, 95.5, false),elementsT2[1].getZRange()); // [ 62-((-5+62)/2) ... 62-((-5+62)/2) [
}
/**
*
* @param ref
* @param crs
* @param geovalues [0...n slices][Z coord, T coord, sample value]
*/
private static void create4DPyramid(PyramidalCoverageReference ref, CoordinateReferenceSystem crs,
int width, int height, double[][] geovalues) throws DataStoreException{
final Pyramid pyramid = ref.createPyramid(crs);
final Dimension gridSize = new Dimension(4, 3);
final Dimension tilePixelSize = new Dimension(width, height);
for(double[] slice : geovalues){
final GeneralDirectPosition upperLeft = new GeneralDirectPosition(crs);
upperLeft.setCoordinate(-50,60,slice[0],slice[1]);
final GridMosaic mosaic = ref.createMosaic(pyramid.getId(), gridSize, tilePixelSize, upperLeft, 1);
final float sample = (float)slice[2];
for(int x=0;x<gridSize.width;x++){
for(int y=0;y<gridSize.height;y++){
ref.writeTile(pyramid.getId(), mosaic.getId(), x, y, createRenderedImage(
tilePixelSize.width, tilePixelSize.height, sample, sample));
}
}
}
}
private static BufferedImage createRenderedImage(int width, int height, float fillValue1, float fillValue2){
final BufferedImage baseImage = BufferedImages.createImage(width, height, 1 , DataBuffer.TYPE_FLOAT);
final WritableRaster baseRaster1 = baseImage.getRaster();
for(int x=0;x<width;x++){
for(int y=0;y<height;y++){
baseRaster1.setSample(x, y, 0, (y<height/2) ? fillValue1 : fillValue2 );
}
}
return baseImage;
}
private static void testImageContent(RenderedImage image, int width, int height, float value1, float value2){
final Raster resultRaster = image.getData();
for(int x=0;x<width;x++){
for(int y=0;y<height;y++){
float v = resultRaster.getSampleFloat(x, y, 0);
Assert.assertEquals( (y<height/2) ? value1 : value2, v, DELTA);
}
}
}
}