/* (c) 2014-2015 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.wms.worldwind.util; import java.util.HashMap; import javax.media.jai.Interpolation; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.coverage.grid.GridGeometry2D; import org.geotools.coverage.processing.CoverageProcessor; import org.geotools.coverage.processing.operation.Crop; import org.geotools.coverage.processing.operation.Resample; import org.geotools.factory.Hints; import org.geotools.geometry.GeneralEnvelope; import org.geotools.referencing.CRS; import org.opengis.coverage.Coverage; import org.opengis.coverage.grid.GridCoverage; import org.opengis.coverage.grid.GridEnvelope; import org.opengis.parameter.ParameterValueGroup; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.vfny.geoserver.util.WCSUtils; import org.vfny.geoserver.wcs.WcsException; /** * This class adds the missing data mangling with * geotools functions from 2.0.x WCSUtils. They were * removed for deprecation reasons, this is a placeholder * till more permanent solutions are found * @author Tishampati Dhar * @since 2.1.x */ public class BilWCSUtils extends WCSUtils { public final static Hints LENIENT_HINT = new Hints(Hints.LENIENT_DATUM_SHIFT, Boolean.TRUE); // /////////////////////////////////////////////////////////////////// // // Static Processors // // /////////////////////////////////////////////////////////////////// private static final CoverageProcessor processor = CoverageProcessor.getInstance(); private final static Hints hints = new Hints(new HashMap(5)); static { hints.add(LENIENT_HINT); } /** * <strong>Reprojecting</strong><br> * The new grid geometry can have a different coordinate reference system * than the underlying grid geometry. For example, a grid coverage can be * reprojected from a geodetic coordinate reference system to Universal * Transverse Mercator CRS. * * @param coverage * GridCoverage2D * @param sourceCRS * CoordinateReferenceSystem * @param targetCRS * CoordinateReferenceSystem * @return GridCoverage2D * @throws WcsException */ public static GridCoverage2D reproject(GridCoverage2D coverage, final CoordinateReferenceSystem sourceCRS, final CoordinateReferenceSystem targetCRS, final Interpolation interpolation) throws WcsException { // /////////////////////////////////////////////////////////////////// // // REPROJECT // // // /////////////////////////////////////////////////////////////////// if (!CRS.equalsIgnoreMetadata(sourceCRS, targetCRS)) { /* * Operations.DEFAULT.resample( coverage, targetCRS, null, * Interpolation.getInstance(Interpolation.INTERP_NEAREST)) */ final ParameterValueGroup param = (ParameterValueGroup) processor.getOperation("Resample").getParameters(); param.parameter("Source").setValue(coverage); param.parameter("CoordinateReferenceSystem").setValue(targetCRS); param.parameter("GridGeometry").setValue(null); param.parameter("InterpolationType").setValue(interpolation); coverage = (GridCoverage2D) ((Resample)processor.getOperation("Resample")).doOperation(param, hints); } return coverage; } /** * <strong>Scaling</strong><br> * Let user to scale down to the EXACT needed resolution. This step does not * prevent from having loaded an overview of the original image based on the * requested scale. * * @param coverage * GridCoverage2D * @param newGridRange * GridRange * @param sourceCoverage * GridCoverage * @param sourceCRS * CoordinateReferenceSystem * @param destinationEnvelopeInSourceCRS * @return GridCoverage2D */ public static GridCoverage2D scale(final GridCoverage2D coverage, final GridEnvelope newGridRange, final GridCoverage sourceCoverage, final CoordinateReferenceSystem sourceCRS, final GeneralEnvelope destinationEnvelopeInSourceCRS) { // /////////////////////////////////////////////////////////////////// // // SCALE to the needed resolution // Let me now scale down to the EXACT needed resolution. This step does // not prevent from having loaded an overview of the original image // based on the requested scale. // // /////////////////////////////////////////////////////////////////// GridGeometry2D scaledGridGeometry = new GridGeometry2D(newGridRange, (destinationEnvelopeInSourceCRS != null) ? destinationEnvelopeInSourceCRS : sourceCoverage.getEnvelope()); /* * Operations.DEFAULT.resample( coverage, sourceCRS, scaledGridGeometry, * Interpolation.getInstance(Interpolation.INTERP_NEAREST)); */ final ParameterValueGroup param = (ParameterValueGroup) processor.getOperation("Resample").getParameters(); param.parameter("Source").setValue(coverage); param.parameter("CoordinateReferenceSystem").setValue(sourceCRS); param.parameter("GridGeometry").setValue(scaledGridGeometry); param.parameter("InterpolationType") .setValue(Interpolation.getInstance(Interpolation.INTERP_NEAREST)); final GridCoverage2D scaledGridCoverage = (GridCoverage2D) ((Resample)processor.getOperation("Resample")).doOperation(param, hints); return scaledGridCoverage; } /** * <strong>Cropping</strong><br> * The crop operation is responsible for selecting geographic subareas of * the source coverage. * * @param coverage * Coverage * @param sourceEnvelope * GeneralEnvelope * @param sourceCRS * CoordinateReferenceSystem * @param destinationEnvelopeInSourceCRS * GeneralEnvelope * @return GridCoverage2D * @throws WcsException */ public static GridCoverage2D crop(final Coverage coverage, final GeneralEnvelope sourceEnvelope, final CoordinateReferenceSystem sourceCRS, final GeneralEnvelope destinationEnvelopeInSourceCRS, final Boolean conserveEnvelope) throws WcsException { // /////////////////////////////////////////////////////////////////// // // CROP // // // /////////////////////////////////////////////////////////////////// final GridCoverage2D croppedGridCoverage; // intersect the envelopes final GeneralEnvelope intersectionEnvelope = new GeneralEnvelope(destinationEnvelopeInSourceCRS); intersectionEnvelope.setCoordinateReferenceSystem(sourceCRS); intersectionEnvelope.intersect((GeneralEnvelope) sourceEnvelope); // dow we have something to show? if (intersectionEnvelope.isEmpty()) { throw new WcsException("The Intersection is null. Check the requested BBOX!"); } if (!intersectionEnvelope.equals((GeneralEnvelope) sourceEnvelope)) { // get the cropped grid geometry // final GridGeometry2D cropGridGeometry = getCroppedGridGeometry( // intersectionEnvelope, gridCoverage); /* Operations.DEFAULT.crop(coverage, intersectionEnvelope) */ final ParameterValueGroup param = (ParameterValueGroup) processor.getOperation("CoverageCrop").getParameters(); param.parameter("Source").setValue(coverage); param.parameter("Envelope").setValue(intersectionEnvelope); //param.parameter("ConserveEnvelope").setValue(conserveEnvelope); croppedGridCoverage = (GridCoverage2D) ((Crop)processor.getOperation("CoverageCrop")).doOperation(param, hints); } else { croppedGridCoverage = (GridCoverage2D) coverage; } // prefetch to be faster afterwards. // This step is important since at this stage we might be loading tiles // from disk croppedGridCoverage.prefetch(intersectionEnvelope.toRectangle2D()); return croppedGridCoverage; } }