Package org.vfny.geoserver.util

Source Code of org.vfny.geoserver.util.WCSUtils

/* Copyright (c) 2001 - 2007 TOPP - www.openplans.org. All rights reserved.
* This code is licensed under the GPL 2.0 license, availible at the root
* application directory.
*/
package org.vfny.geoserver.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Logger;

import javax.media.jai.BorderExtender;
import javax.media.jai.Interpolation;
import javax.media.jai.InterpolationNearest;

import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.grid.GridGeometry2D;
import org.geotools.coverage.processing.DefaultProcessor;
import org.geotools.coverage.processing.operation.Crop;
import org.geotools.coverage.processing.operation.FilteredSubsample;
import org.geotools.coverage.processing.operation.Interpolate;
import org.geotools.coverage.processing.operation.Resample;
import org.geotools.coverage.processing.operation.Scale;
import org.geotools.coverage.processing.operation.SelectSampleDimension;
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.wcs.WcsException;


/**
*
* @author Simone Giannecchini, GeoSolutions
* @author Alessio Fabiani, GeoSolutions
*
*/
public class WCSUtils {
    private final static Hints LENIENT_HINT = new Hints(Hints.LENIENT_DATUM_SHIFT, Boolean.TRUE);
    private static final Logger LOGGER = org.geotools.util.logging.Logging.getLogger("org.vfny.geoserver.util");
    private final static SelectSampleDimension bandSelectFactory = new SelectSampleDimension();
    private final static Crop cropFactory = new Crop();
    private final static Interpolate interpolateFactory = new Interpolate();
    private final static Scale scaleFactory = new Scale();
    private final static FilteredSubsample filteredSubsampleFactory = new FilteredSubsample();
    private final static Resample resampleFactory = new Resample();

    static {
        // ///////////////////////////////////////////////////////////////////
        //
        // Static Processors
        //
        // ///////////////////////////////////////////////////////////////////
        final DefaultProcessor processor = new DefaultProcessor(LENIENT_HINT);
        bandSelectParams = processor.getOperation("SelectSampleDimension").getParameters();
        cropParams = processor.getOperation("CoverageCrop").getParameters();
        interpolateParams = processor.getOperation("Interpolate").getParameters();
        scaleParams = processor.getOperation("Scale").getParameters();
        resampleParams = processor.getOperation("Resample").getParameters();
        filteredSubsampleParams = processor.getOperation("FilteredSubsample").getParameters();
    }

    private final static ParameterValueGroup bandSelectParams;
    private final static ParameterValueGroup cropParams;
    private final static ParameterValueGroup interpolateParams;
    private final static ParameterValueGroup resampleParams;
    private final static ParameterValueGroup scaleParams;
    private final static ParameterValueGroup filteredSubsampleParams;
    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) resampleParams.clone();
            param.parameter("Source").setValue(coverage);
            param.parameter("CoordinateReferenceSystem").setValue(targetCRS);
            param.parameter("GridGeometry").setValue(null);
            param.parameter("InterpolationType").setValue(interpolation);

            coverage = (GridCoverage2D) resampleFactory.doOperation(param, hints);
        }

        return coverage;
    }

    /**
     * <strong>Interpolating</strong><br>
     * Specifies the interpolation type to be used to interpolate values for
     * points which fall between grid cells. The default value is nearest
     * neighbor. The new interpolation type operates on all sample dimensions.
     * Possible values for type are: {@code "NearestNeighbor"},
     * {@code "Bilinear"} and {@code "Bicubic"} (the {@code "Optimal"}
     * interpolation type is currently not supported).
     *
     * @param coverage
     *            GridCoverage2D
     * @param interpolation
     *            Interpolation
     * @return GridCoverage2D
     * @throws WcsException
     */
    public static GridCoverage2D interpolate(GridCoverage2D coverage,
        final Interpolation interpolation) throws WcsException {
        // ///////////////////////////////////////////////////////////////////
        //
        // INTERPOLATE
        //
        //
        // ///////////////////////////////////////////////////////////////////
        if (interpolation != null) {
            /* Operations.DEFAULT.interpolate(coverage, interpolation) */
            final ParameterValueGroup param = (ParameterValueGroup) interpolateParams.clone();
            param.parameter("Source").setValue(coverage);
            param.parameter("Type").setValue(interpolation);

            coverage = (GridCoverage2D) interpolateFactory.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) resampleParams.clone();
        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) resampleFactory.doOperation(param,
                hints);

        return scaledGridCoverage;
    }
   
    /**
     * <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 destinationEnvelopeInSourceCRS
     * @return GridCoverage2D
     */
    public static GridCoverage2D scale(final GridCoverage2D coverage,
            final GridGeometry2D scaledGridGeometry) {
        final ParameterValueGroup param = (ParameterValueGroup) resampleParams.clone();
        param.parameter("Source").setValue(coverage);
        param.parameter("CoordinateReferenceSystem").setValue(coverage.getCoordinateReferenceSystem());
        param.parameter("GridGeometry").setValue(scaledGridGeometry);
        param.parameter("InterpolationType")
             .setValue(Interpolation.getInstance(Interpolation.INTERP_NEAREST));

        final GridCoverage2D scaledGridCoverage = (GridCoverage2D) resampleFactory.doOperation(param,
                hints);

        return scaledGridCoverage;
    }

    /**
     * Scaling the input coverage using the provided parameters.
     *
     * @param scaleX
     * @param scaleY
     * @param xTrans
     * @param yTrans
     * @param interpolation
     * @param be
     * @param gc
     * @return
     */
    public static GridCoverage2D scale(final double scaleX, final double scaleY, float xTrans,
        float yTrans, final Interpolation interpolation, final BorderExtender be,
        final GridCoverage2D gc) {
        final ParameterValueGroup param = (ParameterValueGroup) scaleParams.clone();
        param.parameter("source").setValue(gc);
        param.parameter("xScale").setValue(new Float(scaleX));
        param.parameter("yScale").setValue(new Float(scaleY));
        param.parameter("xTrans").setValue(new Float(xTrans));
        param.parameter("yTrans").setValue(new Float(yTrans));
        param.parameter("Interpolation").setValue(interpolation);
        param.parameter("BorderExtender").setValue(be);

        return (GridCoverage2D) scaleFactory.doOperation(param, hints);
    }

    /**
     * Reprojecting the input coverage using the provided parameters.
     *
     * @param gc
     * @param crs
     * @param interpolation
     * @return
     */
    public static GridCoverage2D resample(final GridCoverage2D gc, CoordinateReferenceSystem crs,
        final Interpolation interpolation) {
        final ParameterValueGroup param = (ParameterValueGroup) resampleParams.clone();
        param.parameter("source").setValue(gc);
        param.parameter("CoordinateReferenceSystem").setValue(crs);
        param.parameter("InterpolationType").setValue(interpolation);

        return (GridCoverage2D) resampleFactory.doOperation(param, hints);
    }

    /**
     * Subsampling the provided {@link GridCoverage2D} with the provided
     * parameters.
     *
     * @param gc
     * @param scaleXInt
     * @param scaleYInt
     * @param interpolation
     * @param be
     * @return
     */
    public static GridCoverage2D filteredSubsample(final GridCoverage2D gc, int scaleXInt,
        int scaleYInt, final Interpolation interpolation, final BorderExtender be) {
        final GridCoverage2D preScaledGridCoverage;

        if ((scaleXInt == 1) && (scaleYInt == 1)) {
            preScaledGridCoverage = gc;
        } else {
            final ParameterValueGroup param = (ParameterValueGroup) filteredSubsampleParams.clone();
            param.parameter("source").setValue(gc);
            param.parameter("scaleX").setValue(new Integer(scaleXInt));
            param.parameter("scaleY").setValue(new Integer(scaleYInt));

            if (interpolation.equals(new InterpolationNearest())) {
                param.parameter("qsFilterArray").setValue(new float[] { 1.0F });
            } else {
                param.parameter("qsFilterArray")
                     .setValue(new float[] { 0.5F, 1.0F / 3.0F, 0.0F, -1.0F / 12.0F });
            }

            param.parameter("Interpolation").setValue(interpolation);
            param.parameter("BorderExtender").setValue(be);
            preScaledGridCoverage = (GridCoverage2D) filteredSubsampleFactory.doOperation(param,
                    hints);
        }

        return preScaledGridCoverage;
    }

    /**
     * <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) cropParams.clone();
            param.parameter("Source").setValue(coverage);
            param.parameter("Envelope").setValue(intersectionEnvelope);
            param.parameter("ConserveEnvelope").setValue(conserveEnvelope);

            croppedGridCoverage = (GridCoverage2D) cropFactory.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;
    }

    /**
     * <strong>Band Selecting</strong><br>
     * Chooses <var>N</var>
     * {@linkplain org.geotools.coverage.GridSampleDimension sample dimensions}
     * from a grid coverage and copies their sample data to the destination grid
     * coverage in the order specified. The {@code "SampleDimensions"} parameter
     * specifies the source {@link org.geotools.coverage.GridSampleDimension}
     * indices, and its size ({@code SampleDimensions.length}) determines the
     * number of sample dimensions of the destination grid coverage. The
     * destination coverage may have any number of sample dimensions, and a
     * particular sample dimension of the source coverage may be repeated in the
     * destination coverage by specifying it multiple times in the
     * {@code "SampleDimensions"} parameter.
     *
     * @param params
     *            Set
     * @param coverage
     *            GridCoverage
     * @return Coverage
     * @throws WcsException
     */
    public static Coverage bandSelect(final Map params, final GridCoverage coverage)
        throws WcsException {
        // ///////////////////////////////////////////////////////////////////
        //
        // BAND SELECT
        //
        //
        // ///////////////////////////////////////////////////////////////////
        final int numDimensions = coverage.getNumSampleDimensions();
        final Map dims = new HashMap();
        final ArrayList selectedBands = new ArrayList();

        for (int d = 0; d < numDimensions; d++) {
            dims.put("band" + (d + 1), new Integer(d));
        }

        if ((params != null) && !params.isEmpty()) {
            for (Iterator p = params.keySet().iterator(); p.hasNext();) {
                final String param = (String) p.next();

                if (param.equalsIgnoreCase("BAND")) {
                    try {
                        final String values = (String) params.get(param);

                        if (values.indexOf("/") > 0) {
                            final String[] minMaxRes = values.split("/");
                            final int min = (int) Math.round(Double.parseDouble(minMaxRes[0]));
                            final int max = (int) Math.round(Double.parseDouble(minMaxRes[1]));
                            final double res = ((minMaxRes.length > 2)
                                ? Double.parseDouble(minMaxRes[2]) : 0.0);

                            for (int v = min; v <= max; v++) {
                                final String key = param.toLowerCase() + v;

                                if (dims.containsKey(key)) {
                                    selectedBands.add(dims.get(key));
                                }
                            }
                        } else {
                            final String[] bands = values.split(",");

                            for (int v = 0; v < bands.length; v++) {
                                final String key = param.toLowerCase() + bands[v];

                                if (dims.containsKey(key)) {
                                    selectedBands.add(dims.get(key));
                                }
                            }

                            if (selectedBands.size() == 0) {
                                throw new Exception("WRONG PARAM VALUES.");
                            }
                        }
                    } catch (Exception e) {
                        throw new WcsException("Band parameters incorrectly specified: "
                            + e.getLocalizedMessage());
                    }
                }
            }
        }

        final int length = selectedBands.size();
        final int[] bands = new int[length];

        for (int b = 0; b < length; b++) {
            bands[b] = ((Integer) selectedBands.get(b)).intValue();
        }

        return bandSelect(coverage, bands);
    }

    public static Coverage bandSelect(final GridCoverage coverage, final int[] bands) {
        Coverage bandSelectedCoverage;

        if ((bands != null) && (bands.length > 0)) {
            /* Operations.DEFAULT.selectSampleDimension(coverage, bands) */
            final ParameterValueGroup param = (ParameterValueGroup) bandSelectParams.clone();
            param.parameter("Source").setValue(coverage);
            param.parameter("SampleDimensions").setValue(bands);
            // param.parameter("VisibleSampleDimension").setValue(bands);
            bandSelectedCoverage = bandSelectFactory.doOperation(param, hints);
        } else {
            bandSelectedCoverage = coverage;
        }

        return bandSelectedCoverage;
    }
}
TOP

Related Classes of org.vfny.geoserver.util.WCSUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.