/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2003-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotools.coverage.grid;
import java.awt.geom.AffineTransform;
import org.geotools.geometry.DirectPosition2D;
import org.geotools.geometry.Envelope2D;
import org.opengis.referencing.datum.PixelInCell;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.metadata.spatial.PixelOrientation;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.referencing.operation.transform.IdentityTransform;
import org.junit.*;
import org.opengis.geometry.DirectPosition;
import static org.junit.Assert.*;
/**
* Test the {@link GridGeometry} implementation.
*
* @source $URL$
* @version $Id$
* @author Martin Desruisseaux (IRD)
*/
public final class GridGeometryTest extends GridCoverageTestBase {
/**
* Tests the construction with an identity transform.
*/
@Test
public void testIdentity() {
final int[] lower = new int[] {0, 0, 2};
final int[] upper = new int[] {100, 200, 4};
final MathTransform identity = IdentityTransform.create(3);
GridGeometry2D gg;
try {
gg = new GridGeometry2D(new GeneralGridEnvelope(lower, upper, false), identity, null);
fail();
} catch (IllegalArgumentException e) {
// This is the expected dimension.
}
upper[2] = 3;
gg = new GridGeometry2D(new GeneralGridEnvelope(lower, upper, false), identity, null);
assertTrue(identity.isIdentity());
assertTrue(gg.getGridToCRS().isIdentity());
assertTrue(gg.getGridToCRS2D().isIdentity());
assertEquals(3, gg.getGridToCRS().getSourceDimensions());
assertEquals(2, gg.getGridToCRS2D().getSourceDimensions());
assertTrue(gg.getGridToCRS2D() instanceof AffineTransform);
/*
* Tests with a pixel orientation.
*/
AffineTransform tr = (AffineTransform) gg.getGridToCRS2D(PixelOrientation.CENTER);
assertTrue(tr.isIdentity());
tr = (AffineTransform) gg.getGridToCRS2D(PixelOrientation.UPPER_LEFT);
assertFalse(tr.isIdentity());
assertEquals(AffineTransform.TYPE_TRANSLATION, tr.getType());
assertEquals(-0.5, tr.getTranslateX(), 0);
assertEquals(-0.5, tr.getTranslateY(), 0);
tr = (AffineTransform) gg.getGridToCRS2D(PixelOrientation.valueOf("LOWER"));
assertEquals(AffineTransform.TYPE_TRANSLATION, tr.getType());
assertEquals(0.0, tr.getTranslateX(), 0);
assertEquals(0.5, tr.getTranslateY(), 0);
}
/**
* Tests the construction from an envelope.
*/
@Test
public void testEnvelope() {
final int[] lower = new int[] { 0, 0, 4};
final int[] upper = new int[] { 90, 45, 5};
final double[] minimum = new double[] {-180, -90, 9};
final double[] maximum = new double[] {+180, +90, 10};
final GridGeometry2D gg;
gg = new GridGeometry2D(new GeneralGridEnvelope(lower, upper, false),
new GeneralEnvelope(minimum, maximum));
final AffineTransform tr = (AffineTransform) gg.getGridToCRS2D();
assertEquals(AffineTransform.TYPE_UNIFORM_SCALE |
AffineTransform.TYPE_TRANSLATION |
AffineTransform.TYPE_FLIP, tr.getType());
assertEquals( 4, tr.getScaleX(), 0);
assertEquals( -4, tr.getScaleY(), 0);
assertEquals(-178, tr.getTranslateX(), 0);
assertEquals( 88, tr.getTranslateY(), 0);
}
/**
* Tests construction with 0.5 pixel translations.
*/
@Test
public void testPixelInCell() {
final MathTransform identity = IdentityTransform.create(4);
final int[] lower = new int[] {100, 300, 3, 6};
final int[] upper = new int[] {200, 400, 4, 7};
final GeneralGridEnvelope range = new GeneralGridEnvelope(lower, upper, false);
GridGeometry2D gg = new GridGeometry2D(range, PixelInCell.CELL_CORNER, identity, null, null);
assertSame (identity, gg.getGridToCRS(PixelInCell.CELL_CORNER));
assertFalse(identity.equals(gg.getGridToCRS(PixelInCell.CELL_CENTER)));
assertFalse(identity.equals(gg.getGridToCRS(PixelOrientation.CENTER)));
assertSame (gg.getGridToCRS(PixelInCell.CELL_CENTER), gg.getGridToCRS(PixelOrientation.CENTER));
AffineTransform tr = (AffineTransform) gg.getGridToCRS2D(PixelOrientation.CENTER);
assertFalse(tr.isIdentity());
assertEquals(AffineTransform.TYPE_TRANSLATION, tr.getType());
assertEquals(0.5, tr.getTranslateX(), 0);
assertEquals(0.5, tr.getTranslateY(), 0);
tr = (AffineTransform) gg.getGridToCRS2D(PixelOrientation.UPPER_LEFT);
assertTrue(tr.isIdentity());
}
@Test
public void testWorldToGridPoint() throws Exception {
GridGeometry2D gg = getRandomCoverage().getGridGeometry();
Envelope2D worldBounds = gg.getEnvelope2D();
GridEnvelope2D gridBounds = gg.getGridRange2D();
GridCoordinates2D gridExp = new GridCoordinates2D();
DirectPosition worldPoint = worldBounds.getLowerCorner();
GridCoordinates2D gridCalc = gg.worldToGrid(worldPoint);
gridExp.setLocation(0, gridBounds.height - 1);
assertTrue(gridExp.equals(gridCalc));
worldPoint = worldBounds.getUpperCorner();
gridCalc = gg.worldToGrid(worldPoint);
gridExp.setLocation(gridBounds.width - 1, 0);
assertTrue(gridExp.equals(gridCalc));
}
@Test
public void testWorldToGridEnvelope() throws Exception {
GridGeometry2D gg = getRandomCoverage().getGridGeometry();
Envelope2D worldBounds = gg.getEnvelope2D();
GridEnvelope2D gridBounds = gg.getGridRange2D();
GridEnvelope2D gridEnv = gg.worldToGrid(worldBounds);
assertTrue(gridBounds.equals(gridEnv));
// test sub-area conversion by creating an envelope that excludes
// the first and last grid row and col centres
double cellWidthX = worldBounds.getWidth() / gridBounds.getWidth();
double cellWidthY = worldBounds.getHeight() / gridBounds.getHeight();
Envelope2D subEnv = new Envelope2D(gg.getCoordinateReferenceSystem2D(),
worldBounds.getMinX() + cellWidthX * 0.6,
worldBounds.getMinY() + cellWidthY * 0.6,
worldBounds.getWidth() - cellWidthX * 1.2,
worldBounds.getHeight() - cellWidthY * 1.2);
gridEnv = gg.worldToGrid(subEnv);
GridEnvelope2D expectedEnv = new GridEnvelope2D(
gridBounds.x + 1,
gridBounds.y + 1,
gridBounds.width - 2,
gridBounds.height - 2);
assertTrue( gridEnv.equals(expectedEnv) );
}
@Test
public void testGridToWorldPoint() throws Exception {
final double TOL = 1.0E-6;
GridGeometry2D gg = getRandomCoverage().getGridGeometry();
Envelope2D worldBounds = gg.getEnvelope2D();
GridEnvelope2D gridBounds = gg.getGridRange2D();
double cellWidthX = worldBounds.getWidth() / gridBounds.getWidth();
double cellWidthY = worldBounds.getHeight() / gridBounds.getHeight();
GridCoordinates2D low = gridBounds.getLow();
DirectPosition2D dp = (DirectPosition2D) gg.gridToWorld(low);
assertTrue(Math.abs(dp.x - (cellWidthX/2) - worldBounds.getMinX()) < TOL);
assertTrue(Math.abs(dp.y + (cellWidthY/2) - worldBounds.getMaxY()) < TOL);
GridCoordinates2D high = gridBounds.getHigh();
dp = (DirectPosition2D) gg.gridToWorld(high);
assertTrue(Math.abs(dp.x + (cellWidthX/2) - worldBounds.getMaxX()) < TOL);
assertTrue(Math.abs(dp.y - (cellWidthY/2) - worldBounds.getMinY()) < TOL);
}
@Test
public void testGridToWorldEnvelope() throws Exception {
final double TOL = 1.0E-6;
GridGeometry2D gg = getRandomCoverage().getGridGeometry();
Envelope2D worldBounds = gg.getEnvelope2D();
GridEnvelope2D gridBounds = gg.getGridRange2D();
assertTrue(worldBounds.boundsEquals(gg.gridToWorld(gridBounds), 0, 1, TOL));
// test sub-area conversion
GridEnvelope2D subGrid = new GridEnvelope2D(
gridBounds.x + 1,
gridBounds.y + 1,
gridBounds.width - 2,
gridBounds.height - 2);
Envelope2D subEnv = gg.gridToWorld(subGrid);
double cellWidthX = worldBounds.getWidth() / gridBounds.getWidth();
double cellWidthY = worldBounds.getHeight() / gridBounds.getHeight();
Envelope2D expectedEnv = new Envelope2D(gg.getCoordinateReferenceSystem2D(),
worldBounds.getMinX() + cellWidthX,
worldBounds.getMinY() + cellWidthY,
worldBounds.getWidth() - 2 * cellWidthX,
worldBounds.getHeight() - 2 * cellWidthY);
assertTrue( expectedEnv.boundsEquals(subEnv, 0, 1, TOL) );
}
}