Package org.geoserver.wms.featureinfo

Source Code of org.geoserver.wms.featureinfo.VectorBasicLayerIdentifier

/* (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.wms.featureinfo;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.geoserver.catalog.LayerInfo;
import org.geoserver.platform.ServiceException;
import org.geoserver.wms.FeatureInfoRequestParameters;
import org.geoserver.wms.MapLayerInfo;
import org.geoserver.wms.WMS;
import org.geotools.data.FeatureSource;
import org.geotools.data.Query;
import org.geotools.data.store.FilteringFeatureCollection;
import org.geotools.factory.Hints;
import org.geotools.feature.FeatureCollection;
import org.geotools.filter.Filters;
import org.geotools.filter.IllegalFilterException;
import org.geotools.filter.visitor.SimplifyingFilterVisitor;
import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.geotools.renderer.lite.MetaBufferEstimator;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.Rule;
import org.geotools.styling.Style;
import org.geotools.util.logging.Logging;
import org.opengis.feature.Feature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.feature.type.FeatureType;
import org.opengis.feature.type.GeometryDescriptor;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.Or;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Polygon;

/**
* An identifier for vector layers that will take into account the filters, viewparams, styles and
* build a bbox (plus extra filters) query against the database
*
* @author Andrea Aime - GeoSolutions
*/
public class VectorBasicLayerIdentifier extends AbstractVectorLayerIdentifier {
   
    static final Logger LOGGER = Logging.getLogger(VectorBasicLayerIdentifier.class);
   
    protected static final int MIN_BUFFER_SIZE = Integer.getInteger("org.geoserver.wms.featureinfo.minBuffer", 5);

    private WMS wms;

    public VectorBasicLayerIdentifier(final WMS wms) {
        this.wms = wms;
    }

    public List<FeatureCollection> identify(FeatureInfoRequestParameters params, int maxFeatures) throws Exception {
        LOGGER.log(Level.FINER, "Appliying bbox based feature info identifier");

       
        final MapLayerInfo layer = params.getLayer();
        final Filter filter = params.getFilter();
        final Style style = params.getStyle();
        // ok, internally rendered layer then, we check the style to see what's active
        final List<Rule> rules = getActiveRules(style, params.getScaleDenominator());
        if (rules.size() == 0) {
            return null;
        }

        // compute the request radius
        double radius = getSearchRadius(params, layer, rules);

        // compute the bbox for the request
        ReferencedEnvelope queryEnvelope = getEnvelopeFilter(params, radius);
        CoordinateReferenceSystem requestedCRS = params.getRequestedCRS();
        CoordinateReferenceSystem dataCRS = layer.getCoordinateReferenceSystem();
        if ((requestedCRS != null) && !CRS.equalsIgnoreMetadata(dataCRS, requestedCRS)) {
            if (dataCRS.getCoordinateSystem().getDimension() == 3
                    && requestedCRS.getCoordinateSystem().getDimension() == 2) {
                queryEnvelope = JTS.transformTo3D(queryEnvelope, dataCRS, true, 10);
            } else {
                queryEnvelope = queryEnvelope.transform(dataCRS, true);
            }
        }

        final FeatureSource<? extends FeatureType, ? extends Feature> featureSource;
        featureSource = layer.getFeatureSource(false);
        FeatureType schema = featureSource.getSchema();

        Filter getFInfoFilter = null;
        FilterFactory2 ff = params.getFilterFactory();
        try {
            GeometryDescriptor geometryDescriptor = schema.getGeometryDescriptor();
            String localName = geometryDescriptor.getLocalName();
            Polygon queryPolygon = JTS.toGeometry(queryEnvelope);
            getFInfoFilter = ff.intersects(ff.property(localName), ff.literal(queryPolygon));
        } catch (IllegalFilterException e) {
            e.printStackTrace();
            throw new ServiceException("Internal error : " + e.getMessage(), e);
        }

        // include the eventual layer definition filter
        if (filter != null) {
            getFInfoFilter = ff.and(getFInfoFilter, filter);
        }

        // see if we can include the rule filters as well, if too many we'll do them in
        // memory
        Filter postFilter = Filter.INCLUDE;
        Filter rulesFilters = buildRulesFilter(ff, rules);
        if (!(featureSource.getSchema() instanceof SimpleFeatureType)
                || !(rulesFilters instanceof Or)
                || (rulesFilters instanceof Or && ((Or) rulesFilters).getChildren().size() <= 20)) {
            getFInfoFilter = ff.and(getFInfoFilter, rulesFilters);
        } else {
            postFilter = rulesFilters;
        }

        // handle time/elevation
        Filter timeElevationFilter = wms.getTimeElevationToFilter(params.getTimes(),
                params.getElevations(), layer.getFeature());
        getFInfoFilter = Filters.and(ff, getFInfoFilter, timeElevationFilter);

        // simplify the filter
        SimplifyingFilterVisitor simplifier = new SimplifyingFilterVisitor();
        getFInfoFilter = (Filter) getFInfoFilter.accept(simplifier, null);

        // build the query
        String typeName = schema.getName().getLocalPart();
        Query q = new Query(typeName, null, getFInfoFilter, maxFeatures, params.getPropertyNames(),
                null);

        // handle sql view params
        final Map<String, String> viewParams = params.getViewParams();
        if (viewParams != null && viewParams.size() > 0) {
            q.setHints(new Hints(Hints.VIRTUAL_TABLE_PARAMETERS, viewParams));
        }

        FeatureCollection match;
        System.out.println(q);
        match = featureSource.getFeatures(q);

        // if we could not include the rules filter into the query, post process in
        // memory
        if (!Filter.INCLUDE.equals(postFilter)) {
            match = new FilteringFeatureCollection(match, postFilter);
        }

        return Collections.singletonList(match);

    }

    private double getSearchRadius(FeatureInfoRequestParameters params, final MapLayerInfo layer,
            final List<Rule> rules) {
        double radius;
        int buffer = params.getBuffer();
        if (buffer <= 0) {
            Integer layerBuffer = null;
            final LayerInfo layerInfo = layer.getLayerInfo();
            if (layerInfo != null) { // it is a local layer
                layerBuffer = layerInfo.getMetadata().get(LayerInfo.BUFFER, Integer.class);
            }
            if (layerBuffer != null && layerBuffer > 0) {
                radius = layerBuffer / 2.0;
            } else {
                // estimate the radius given the currently active rules
                MetaBufferEstimator estimator = new MetaBufferEstimator();
                for (Rule rule : rules) {
                    rule.accept(estimator);
                }

                int estimatedRadius = estimator.getBuffer() / 2;
                if (estimatedRadius < MIN_BUFFER_SIZE) {
                    radius = MIN_BUFFER_SIZE;
                } else {
                    radius = estimatedRadius;
                }
            }
        } else {
            radius = buffer;
        }
       
        // make sure we don't go overboard, the admin might have set a maximum
        int maxRadius = wms.getMaxBuffer();
        if (maxRadius > 0 && radius > maxRadius) {
            radius = maxRadius;
        }
       
        return radius;
    }

    private Filter buildRulesFilter(org.opengis.filter.FilterFactory ff, List<Rule> rules) {
        // build up a or of all the rule filters
        List<Filter> filters = new ArrayList<Filter>();
        for (Rule rule : rules) {
            if (rule.getFilter() == null || rule.isElseFilter())
                return Filter.INCLUDE;
            filters.add(rule.getFilter());
        }
        // not or and and simplify (if there is any include/exclude we'll get
        // a very simple result ;-)
        Filter or = ff.or(filters);
        SimplifyingFilterVisitor simplifier = new SimplifyingFilterVisitor();
        return (Filter) or.accept(simplifier, null);
    }

  
    private ReferencedEnvelope getEnvelopeFilter(FeatureInfoRequestParameters params, double radius) {
        final int x = params.getX();
        final int y = params.getY();
        final ReferencedEnvelope bbox = params.getRequestedBounds();
        final int width = params.getWidth();
        final int height = params.getHeight();
        Coordinate upperLeft = WMS.pixelToWorld(x - radius, y - radius, bbox, width, height);
        Coordinate lowerRight = WMS.pixelToWorld(x + radius, y + radius, bbox, width, height);

        return new ReferencedEnvelope(upperLeft.x, lowerRight.x, lowerRight.y, upperLeft.y,
                bbox.getCoordinateReferenceSystem());
    }

}
TOP

Related Classes of org.geoserver.wms.featureinfo.VectorBasicLayerIdentifier

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.