/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2014, 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.renderer.lite.gridcoverage2d;
import static org.junit.Assert.*;
import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.media.jai.Interpolation;
import org.geotools.TestData;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridCoverageFactory;
import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader;
import org.geotools.coverage.grid.io.GridCoverage2DReader;
import org.geotools.data.DataUtilities;
import org.geotools.factory.Hints;
import org.geotools.gce.geotiff.GeoTiffReader;
import org.geotools.geometry.Envelope2D;
import org.geotools.geometry.GeneralEnvelope;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultEngineeringCRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.referencing.operation.projection.MapProjection;
import org.geotools.renderer.crs.ProjectionHandler;
import org.geotools.renderer.crs.ProjectionHandlerFinder;
import org.geotools.renderer.lite.GridCoverageRendererTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.opengis.coverage.grid.Format;
import org.opengis.geometry.BoundingBox;
import org.opengis.geometry.Envelope;
import org.opengis.parameter.GeneralParameterValue;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
public class GridCoverageReaderHelperTest {
static final double EPS = 1e-9;
private GeoTiffReader reader;
File coverageFile;
@Before
public void getData() throws IOException {
MapProjection.SKIP_SANITY_CHECKS = true;
coverageFile = TestData.copy(this, "geotiff/world.tiff");
assertTrue(coverageFile.exists());
reader = new GeoTiffReader(coverageFile);
}
@After
public void close() {
MapProjection.SKIP_SANITY_CHECKS = false;
reader.dispose();
}
@Test
public void testGeographicLarge() throws Exception {
ReferencedEnvelope mapExtent = new ReferencedEnvelope(-360, 360, -90, 90,
DefaultGeographicCRS.WGS84);
GridCoverageReaderHelper helper = new GridCoverageReaderHelper(reader, new Rectangle(720,
180), mapExtent, Interpolation.getInstance(Interpolation.INTERP_NEAREST));
// read single coverage with no projection handling
GridCoverage2D coverage = helper.readCoverage(null);
Envelope2D envelope = coverage.getEnvelope2D();
assertEquals(-180, envelope.getMinX(), EPS);
assertEquals(180, envelope.getMaxX(), EPS);
assertEquals(-90, envelope.getMinY(), EPS);
assertEquals(90, envelope.getMaxY(), EPS);
// try multiple coverage with projection handling, should not make a difference
// since we are already reading everything in a single shot, just in need of coverage
// replication
// (which has to be performed after the eventual reprojection, so not here in the reader)
ProjectionHandler handler = ProjectionHandlerFinder.getHandler(mapExtent,
reader.getCoordinateReferenceSystem(), true);
List<GridCoverage2D> coverages = helper.readCoverages(null, handler);
// System.out.println(coverages);
assertEquals(1, coverages.size());
assertEquals(envelope, coverages.get(0).getEnvelope2D());
}
@Test
public void testGeographicDatelineCross() throws Exception {
ReferencedEnvelope mapExtent = new ReferencedEnvelope(170, 190, 70, 80,
DefaultGeographicCRS.WGS84);
GridCoverageReaderHelper helper = new GridCoverageReaderHelper(reader, new Rectangle(100,
100), mapExtent, Interpolation.getInstance(Interpolation.INTERP_NEAREST));
// read single coverage with no projection handling, the geotiff reader gives us all
GridCoverage2D coverage = helper.readCoverage(null);
Envelope2D envelope = coverage.getEnvelope2D();
assertEquals(-180, envelope.getMinX(), EPS);
assertEquals(180, envelope.getMaxX(), EPS);
assertEquals(-90, envelope.getMinY(), EPS);
assertEquals(90, envelope.getMaxY(), EPS);
// now read with projection handling instead, we must get two at the
// two ends of the dateline
ProjectionHandler handler = ProjectionHandlerFinder.getHandler(mapExtent,
reader.getCoordinateReferenceSystem(), true);
List<GridCoverage2D> coverages = helper.readCoverages(null, handler);
// System.out.println(coverages);
assertEquals(2, coverages.size());
Envelope2D firstEnvelope = coverages.get(0).getEnvelope2D();
assertEquals(169.2, firstEnvelope.getMinX(), EPS);
assertEquals(180, firstEnvelope.getMaxX(), EPS);
assertEquals(69.3, firstEnvelope.getMinY(), EPS);
assertEquals(80.1, firstEnvelope.getMaxY(), EPS);
Envelope2D secondEnvelope = coverages.get(1).getEnvelope2D();
assertEquals(-180, secondEnvelope.getMinX(), EPS);
assertEquals(-169.2, secondEnvelope.getMaxX(), EPS);
assertEquals(69.3, secondEnvelope.getMinY(), EPS);
assertEquals(80.1, secondEnvelope.getMaxY(), EPS);
}
@Test
public void testUTM() throws Exception {
// setup a request large enough to cause severe reprojection deformation
CoordinateReferenceSystem crs = CRS.decode("EPSG:32632", true);
ReferencedEnvelope mapExtent = new ReferencedEnvelope(-1.5e7, 1.5e7, 0, 1e6, crs);
// System.out.println(mapExtent.transform(DefaultGeographicCRS.WGS84, true));
GridCoverageReaderHelper helper = new GridCoverageReaderHelper(reader, new Rectangle(400,
200), mapExtent, Interpolation.getInstance(Interpolation.INTERP_NEAREST));
// read single coverage with no projection handling, we should get the full requested area
GridCoverage2D coverage = helper.readCoverage(null);
Envelope2D envelope = coverage.getEnvelope2D();
// System.out.println(envelope);
assertTrue(envelope.getMinX() < -100);
assertTrue(envelope.getMaxX() > 100);
// now read via the projection handlers
ProjectionHandler handler = ProjectionHandlerFinder.getHandler(mapExtent,
reader.getCoordinateReferenceSystem(), true);
List<GridCoverage2D> coverages = helper.readCoverages(null, handler);
// System.out.println(coverages);
assertEquals(1, coverages.size());
envelope = coverages.get(0).getEnvelope2D();
// west/east limited to 45 degrees from the central meridian, plus reading gutter
assertEquals(-36, envelope.getMinX(), EPS);
assertEquals(54, envelope.getMaxX(), EPS);
}
@Test
public void testConic() throws Exception {
// setup a request large enough to cause severe reprojection deformation
CoordinateReferenceSystem crs = CRS.decode("EPSG:32632", true);
ReferencedEnvelope mapExtent = new ReferencedEnvelope(-1.5e7, 1.5e7, 0, 1e6, crs);
// System.out.println(mapExtent.transform(DefaultGeographicCRS.WGS84, true));
GridCoverageReaderHelper helper = new GridCoverageReaderHelper(reader, new Rectangle(400,
200), mapExtent, Interpolation.getInstance(Interpolation.INTERP_NEAREST));
// read single coverage with no projection handling, we should get the full requested area
GridCoverage2D coverage = helper.readCoverage(null);
Envelope2D envelope = coverage.getEnvelope2D();
// System.out.println(envelope);
assertTrue(envelope.getMinX() < -100);
assertTrue(envelope.getMaxX() > 100);
// now read via the projection handlers
ProjectionHandler handler = ProjectionHandlerFinder.getHandler(mapExtent,
reader.getCoordinateReferenceSystem(), true);
List<GridCoverage2D> coverages = helper.readCoverages(null, handler);
// System.out.println(coverages);
assertEquals(1, coverages.size());
envelope = coverages.get(0).getEnvelope2D();
// west/east limited to 45 degrees from the central meridian
assertEquals(-36, envelope.getMinX(), EPS);
assertEquals(54, envelope.getMaxX(), EPS);
}
@Test
public void testOutsideDefinitionArea() throws Exception {
// setup a request that is outside of the coverage
CoordinateReferenceSystem crs = CRS.decode("EPSG:3031", true);
ReferencedEnvelope mapExtent = new ReferencedEnvelope(-1250000, 0, -13750000, -12500000,
crs);
// System.out.println(mapExtent.transform(DefaultGeographicCRS.WGS84, true));
GridCoverageReaderHelper helper = new GridCoverageReaderHelper(reader, new Rectangle(400,
200), mapExtent, Interpolation.getInstance(Interpolation.INTERP_NEAREST));
// read, nothing should come out
ProjectionHandler handler = ProjectionHandlerFinder.getHandler(mapExtent,
reader.getCoordinateReferenceSystem(), true);
List<GridCoverage2D> coverages = helper.readCoverages(null, handler);
assertTrue(coverages.isEmpty());
}
@Test
public void testFullResolutionNull() throws Exception {
// this one has null native resolutions
final GridCoverage2D coverage = new GridCoverageFactory().create("test",
new float[200][100], new ReferencedEnvelope(-180, 180, -90, 90,
DefaultGeographicCRS.WGS84));
GridCoverage2DReader reader = new AbstractGridCoverage2DReader() {
{
this.crs = DefaultGeographicCRS.WGS84;
this.originalEnvelope = new GeneralEnvelope((BoundingBox) coverage.getEnvelope2D());
this.originalGridRange = coverage.getGridGeometry().getGridRange();
}
@Override
public Format getFormat() {
return null;
}
@Override
public GridCoverage2D read(GeneralParameterValue[] parameters) throws IllegalArgumentException,
IOException {
// return fake coveage
return coverage;
}
};
CoordinateReferenceSystem crs = CRS.decode("EPSG:3031", true);
ReferencedEnvelope mapExtent = new ReferencedEnvelope(-20000000, 20000000, -20000000,
20000000, crs);
GridCoverageReaderHelper helper = new GridCoverageReaderHelper(reader, new Rectangle(400,
200), mapExtent, Interpolation.getInstance(Interpolation.INTERP_NEAREST));
// read, we should get back a coverage, not a exception
ProjectionHandler handler = ProjectionHandlerFinder.getHandler(mapExtent,
reader.getCoordinateReferenceSystem(), true);
List<GridCoverage2D> coverages = helper.readCoverages(null, handler);
assertEquals(1, coverages.size());
}
@Test
public void testCutUnreferenced() throws Exception {
// force a CRS that does not have a projection handler (and most likely never will)
Hints hints = new Hints(Hints.DEFAULT_COORDINATE_REFERENCE_SYSTEM, DefaultEngineeringCRS.GENERIC_2D);
GridCoverage2DReader reader = null;
try {
reader = new GeoTiffReader(coverageFile, hints);
// setup the read
ReferencedEnvelope mapExtent = new ReferencedEnvelope(-90, 0, -45, 45, DefaultEngineeringCRS.GENERIC_2D);
GridCoverageReaderHelper helper = new GridCoverageReaderHelper(reader, new Rectangle(200,
200), mapExtent, Interpolation.getInstance(Interpolation.INTERP_NEAREST));
List<GridCoverage2D> coverages = helper.readCoverages(null, null);
assertEquals(1, coverages.size());
// check it has been cut
GridCoverage2D gc = coverages.get(0);
Envelope envelope = gc.getEnvelope();
assertEquals(-90, envelope.getMinimum(0), EPS);
assertEquals(0, envelope.getMaximum(0), EPS);
assertEquals(-45, envelope.getMinimum(1), EPS);
assertEquals(45, envelope.getMaximum(1), EPS);
} finally {
if(reader != null) {
reader.dispose();
}
}
}
@Test
public void testReadResolution3003InvalidArea() throws Exception {
coverageFile = DataUtilities
.urlToFile(GridCoverageRendererTest.class.getResource("test-data/test3003.tif"));
assertTrue(coverageFile.exists());
GeoTiffReader reader = new GeoTiffReader(coverageFile);
try {
reader = new GeoTiffReader(coverageFile);
ReferencedEnvelope mapExtent = new ReferencedEnvelope(-130, -120, -40, 30, DefaultGeographicCRS.WGS84);
GridCoverageReaderHelper helper = new GridCoverageReaderHelper(reader, new Rectangle(200,
200), mapExtent, Interpolation.getInstance(Interpolation.INTERP_NEAREST));
// make sure the accurate resolution does not happen, it cannot work in this context
ReferencedEnvelope readExtent = mapExtent.transform(reader.getCoordinateReferenceSystem(), true);
assertFalse(helper.isAccurateResolutionComputationSafe(readExtent));
// nothing is really getting read
ProjectionHandler handler = ProjectionHandlerFinder.getHandler(new ReferencedEnvelope(DefaultGeographicCRS.WGS84), reader.getCoordinateReferenceSystem(), false);
List<GridCoverage2D> coverages = helper.readCoverageInEnvelope(mapExtent, null, handler, true);
assertNull(coverages);
} finally {
if(reader != null) {
reader.dispose();
}
}
}
}