Package org.geoserver.wps.gs.download

Source Code of org.geoserver.wps.gs.download.RasterEstimator

/* (c) 2014 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.wps.gs.download;

import java.awt.geom.Rectangle2D;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geoserver.catalog.CoverageInfo;
import org.geotools.coverage.grid.GridEnvelope2D;
import org.geotools.coverage.grid.io.GridCoverage2DReader;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.operation.transform.AffineTransform2D;
import org.geotools.resources.coverage.FeatureUtilities;
import org.geotools.util.logging.Logging;
import org.opengis.filter.Filter;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.datum.PixelInCell;
import org.opengis.util.ProgressListener;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.PrecisionModel;

/**
* This class check whether or not the provided download request goes beyond the provided limits for raster data or not.
*
* @author Simone Giannecchini, GeoSolutions
*
*/
class RasterEstimator {

    private static final Logger LOGGER = Logging.getLogger(RasterEstimator.class);

    /** The downloadServiceConfiguration object containing the limits to check */
    private DownloadServiceConfiguration downloadServiceConfiguration;

    /**
     * Constructor
     *
     * @param limits the parent {@link DownloadEstimatorProcess} that contains the download limits to be enforced.
     *
     */
    public RasterEstimator(DownloadServiceConfiguration limits) {
        this.downloadServiceConfiguration = limits;
        if (limits == null) {
            throw new NullPointerException("The provided DownloadEstimatorProcess is null!");
        }
    }

    /**
     * Check the download limits for raster data.
     *
     * @param coverage the {@link CoverageInfo} to estimate the download limits
     * @param roi the {@link Geometry} for the clip/intersection
     * @param targetCRS the reproject {@link CoordinateReferenceSystem} (useless for the moment)
     * @param clip whether or not to clip the resulting data (useless for the moment)
     * @param filter the {@link Filter} to load the data
     * @return
     */
    public boolean execute(final ProgressListener progressListener, CoverageInfo coverageInfo,
            Geometry roi, CoordinateReferenceSystem targetCRS, boolean clip, Filter filter)
            throws Exception {

        //
        // Do we need to do anything?
        //
        final long rasterSizeLimits = downloadServiceConfiguration.getRasterSizeLimits();
        if (rasterSizeLimits <= 0) {
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.fine("No raster size limits, moving on....");
            }
            return true;
        }
        if (LOGGER.isLoggable(Level.FINE)) {
            LOGGER.fine("Raster size limits: " + rasterSizeLimits);
        }

        //
        // ---> READ FROM NATIVE RESOLUTION <--
        //
        if (LOGGER.isLoggable(Level.FINE)) {
            LOGGER.fine("Checking download limits for raster request");
        }
        CoordinateReferenceSystem nativeCRS = DownloadUtilities.getNativeCRS(coverageInfo);
        if (LOGGER.isLoggable(Level.FINE)) {
            LOGGER.fine("Native CRS is " + nativeCRS.toWKT());
        }

        //
        // STEP 0 - Push ROI back to native CRS (if ROI is provided)
        //
        ROIManager roiManager = null;
        if (roi != null) {
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.log(Level.FINE, "Pushing ROI to native CRS");
            }
            CoordinateReferenceSystem roiCRS = (CoordinateReferenceSystem) roi.getUserData();
            roiManager = new ROIManager(roi, roiCRS);
            // set use nativeCRS
            roiManager.useNativeCRS(nativeCRS);
        }

        // get a reader for this CoverageInfo
        final GridCoverage2DReader reader = (GridCoverage2DReader) coverageInfo
                .getGridCoverageReader(null, null);

        // Area to read in pixel
        final double areaRead;
        // If ROI is present, then the coverage BBOX is cropped with the ROI geometry
        if (roi != null) {
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.log(Level.FINE, "Reprojecting ROI");
            }
            final Geometry safeRoiInNativeCRS = roiManager.getSafeRoiInNativeCRS();
            Geometry roiInNativeCRS_ = safeRoiInNativeCRS.intersection(FeatureUtilities.getPolygon(
                    reader.getOriginalEnvelope(), new GeometryFactory(new PrecisionModel(
                            PrecisionModel.FLOATING))));
            if (roiInNativeCRS_.isEmpty()) {
                if (LOGGER.isLoggable(Level.FINE)) {
                    LOGGER.log(Level.FINE,
                            "Empty intersection, so the result does not exceed the limits");
                }
                return true; // EMPTY Intersection
            }
            // world to grid transform
            final AffineTransform2D w2G = (AffineTransform2D) reader.getOriginalGridToWorld(
                    PixelInCell.CELL_CORNER).inverse();
            final Geometry rasterGeometry = JTS.transform(roiInNativeCRS_, w2G);

            // try to make an estimate of the area we need to read
            // NOTE I use the envelope since in the end I can only pass down
            // a rectangular source region to the ImageIO-Ext reader, but in the end I am only going
            // to read the tile I will need during processing as in this case I am going to perform
            // deferred reads
            areaRead = rasterGeometry.getEnvelope().getArea();
            // TODO investigate on improved precision taking into account tiling on raster geometry

        } else {
            // No ROI, we are trying to read the entire coverage
            final Rectangle2D originalGridRange = (GridEnvelope2D) reader.getOriginalGridRange();
            areaRead = originalGridRange.getWidth() * originalGridRange.getHeight();

        }
        // checks on the area we want to download
        if (LOGGER.isLoggable(Level.FINE)) {
            LOGGER.fine("Area to read in pixels: " + areaRead);
        }
        // If the area exceeds the limits, false is returned
        if (areaRead > rasterSizeLimits) {
            if (LOGGER.isLoggable(Level.FINE)) {
                LOGGER.log(Level.FINE, "Area exceeds the limits");
            }
            return false;
        }
        if (LOGGER.isLoggable(Level.FINE)) {
            LOGGER.log(Level.FINE, "Area does not exceeds the limits");
        }
        return true;

    }
}
TOP

Related Classes of org.geoserver.wps.gs.download.RasterEstimator

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.