IOException, TransformException {
// see if we have a projection handler
CoordinateReferenceSystem sourceCRS = reader.getCoordinateReferenceSystem();
CoordinateReferenceSystem targetCRS = destinationEnvelope.getCoordinateReferenceSystem();
ProjectionHandler handler = null;
List<GridCoverage2D> coverages;
// read all the coverages we need, cut and whatnot
GridCoverageReaderHelper rh = new GridCoverageReaderHelper(reader, destinationSize,
ReferencedEnvelope.reference(destinationEnvelope), interpolation);
// are we dealing with a remote service wrapped in a reader, one that can handle reprojection
// by itself?
if(GridCoverageReaderHelper.isReprojectingReader(reader)) {
GridCoverage2D coverage = rh.readCoverage(readParams);
coverages = new ArrayList<>();
coverages.add(coverage);
} else {
handler = ProjectionHandlerFinder.getHandler(rh.getReadEnvelope(),
sourceCRS, wrapEnabled);
if (handler instanceof WrappingProjectionHandler) {
// raster data is monolithic and can cover the whole world, disable
// the geometry wrapping heuristic
((WrappingProjectionHandler) handler).setDatelineWrappingCheckEnabled(false);
}
coverages = rh.readCoverages(readParams, handler);
}
// reproject if needed
double[] bgValues = GridCoverageRendererUtilities.colorToArray(background);
List<GridCoverage2D> reprojectedCoverages = new ArrayList<GridCoverage2D>();
for (GridCoverage2D coverage : coverages) {
final CoordinateReferenceSystem coverageCRS = coverage.getCoordinateReferenceSystem();
if (!CRS.equalsIgnoreMetadata(coverageCRS, destinationCRS)) {
GridCoverage2D reprojected = reproject(coverage, true, bgValues);
if (reprojected != null) {
reprojectedCoverages.add(reprojected);
}
} else {
reprojectedCoverages.addAll(coverages);
}
}
// displace them if needed via a projection handler
List<GridCoverage2D> displacedCoverages = new ArrayList<GridCoverage2D>();
if (handler != null) {
Envelope testEnvelope = ReferencedEnvelope.reference(destinationEnvelope);
MathTransform mt = CRS.findMathTransform(sourceCRS, targetCRS);
PolygonExtractor polygonExtractor = new PolygonExtractor();
for (GridCoverage2D coverage : reprojectedCoverages) {
Polygon polygon = JTS.toGeometry((BoundingBox) coverage.getEnvelope2D());
Geometry postProcessed = handler.postProcess(mt, polygon);
// extract sub-polygons and displace
List<Polygon> polygons = polygonExtractor.getPolygons(postProcessed);
for (Polygon displaced : polygons) {
// check we are really inside the display area before moving one
Envelope intersection = testEnvelope.intersection(displaced