All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.wikibrain.spatial.dao.postgis.PostGISSpatialNeighborDao Maven / Gradle / Ivy

There is a newer version: 0.9.1
Show newest version
package org.wikibrain.spatial.dao.postgis;

import com.google.common.collect.Lists;
import com.typesafe.config.Config;
import com.vividsolutions.jts.geom.Geometry;
import gnu.trove.set.TIntSet;
import gnu.trove.set.hash.TIntHashSet;
import org.geotools.data.FeatureSource;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.referencing.GeodeticCalculator;
import org.opengis.feature.Feature;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.filter.expression.PropertyName;
import org.wikibrain.conf.Configuration;
import org.wikibrain.conf.ConfigurationException;
import org.wikibrain.conf.Configurator;
import org.wikibrain.core.dao.DaoException;
import org.wikibrain.spatial.dao.SpatialNeighborDao;

import java.io.IOException;
import java.util.*;

/**
 * Created by toby on 4/17/14.
 */
public class PostGISSpatialNeighborDao implements SpatialNeighborDao{

    private final PostGISDB db;

    public PostGISSpatialNeighborDao (PostGISDB db){
        this.db = db;

    }

    @Override
    public TIntSet getNeighboringItemIds(Integer itemId, String layerName, String refSysName, Set subLayers, double minDist, double maxDist) throws DaoException{
        Geometry g = db.getGeometry(itemId, layerName, refSysName);
        if (g == null){
            throw new DaoException(String.format("Could not find item %d in layer %s (%s)", itemId, layerName, refSysName));
        }

        return getNeighboringItemIds(g, refSysName, subLayers, minDist, maxDist);
    }

    @Override
    public TIntSet getNeighboringItemIds(Geometry g, String refSysName, Set subLayers, double minDist, double maxDist) throws DaoException{

        if (subLayers.size() == 0) throw new DaoException("Cannot get containment without any layers");

        FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
        PropertyName geomProperty = ff.property(db.getGeometryAttributeName());


        //build ref sys clause
        PropertyName refSysProperty = ff.property(db.getRefSysAttributeName());
        Filter refSysFilter = ff.equals(refSysProperty, ff.literal(refSysName));

        // build layer-related clause
        PropertyName layerProperty = ff.property(db.getLayerAttributeName());
        List layerFilters = Lists.newArrayList();
        for (String subLayer : subLayers){
            Filter curLayerFilter = ff.equals(layerProperty, ff.literal(subLayer));
            layerFilters.add(curLayerFilter);
        }

        Filter layerFilter = ff.and(layerFilters);

        Filter withinFilter = ff.dwithin(geomProperty, ff.literal(g), maxDist , "4396");
        Filter beyondFilter = ff.beyond(geomProperty, ff.literal(g), minDist , "4396");


        List filters = Lists.newArrayList();
        filters.add(refSysFilter);
        filters.add(layerFilter);
        filters.add(withinFilter);
        filters.add(beyondFilter);

        Filter finalFilter = ff.and(filters);

        try {

            FeatureSource featureSource = db.getFeatureSource();
            FeatureCollection containedFeatures = featureSource.getFeatures(finalFilter);
            FeatureIterator featureIterator = containedFeatures.features();

            TIntSet rVal = new TIntHashSet();

            while (featureIterator.hasNext()){

                Feature f = featureIterator.next();
                Integer itemId = (Integer)f.getProperty(db.getItemIdAttributeName()).getValue();
                rVal.add(itemId);

            }
            featureIterator.close();

            return rVal;

        }catch(IOException e){
            throw new DaoException(e);
        }



    }

    @Override
    public Map getKNNeighbors (Geometry g, int k, String layerName, String refSysName, Set excludeSet) throws DaoException{


        FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
        PropertyName geomProperty = ff.property(db.getGeometryAttributeName());

        //build ref sys clause
        PropertyName refSysProperty = ff.property(db.getRefSysAttributeName());
        Filter refSysFilter = ff.equals(refSysProperty, ff.literal(refSysName));

        // build layer-related clause
        PropertyName layerProperty = ff.property(db.getLayerAttributeName());
        Filter layerFilter = ff.equals(layerProperty, ff.literal(layerName));

        double guess = 0.01;

        Filter withinFilter = ff.dwithin(geomProperty, ff.literal(g), guess * k , "4396");




        List filters = Lists.newArrayList();
        filters.add(refSysFilter);
        filters.add(layerFilter);
        filters.add(withinFilter);


        for(Integer i : excludeSet){
            Filter nonEqualFilter = ff.notEqual(ff.property(db.getItemIdAttributeName()), ff.literal(i));
            filters.add(nonEqualFilter);
        }


        Filter finalFilter = ff.and(filters);



        try {

            FeatureSource featureSource = db.getFeatureSource();
            FeatureCollection containedFeatures = featureSource.getFeatures(finalFilter);

            while(containedFeatures.size() < k && guess * k < 180){
                if(containedFeatures.size() == 0)
                    guess = guess * 2;
                else
                    guess = guess * (k / containedFeatures .size() > 2 ? 1.3 * Math.sqrt((k / containedFeatures.size())) : 2);
                withinFilter = ff.dwithin(geomProperty, ff.literal(g), guess * k , "4396");
                List newFilters = Lists.newArrayList();
                newFilters.add(refSysFilter);
                newFilters.add(layerFilter);
                newFilters.add(withinFilter);
                for(Integer i : excludeSet){
                    Filter nonEqualFilter = ff.notEqual(ff.property(db.getItemIdAttributeName()), ff.literal(i));
                    newFilters.add(nonEqualFilter);
                }
                finalFilter = ff.and(newFilters);
                containedFeatures = featureSource.getFeatures(finalFilter);
            }

            FeatureIterator featureIterator = containedFeatures.features();


            Map rVal = new HashMap();
            Map finalRVal = new LinkedHashMap();
            final Map distMap = new HashMap();
            List order = new LinkedList();

            GeodeticCalculator geoCalc = new GeodeticCalculator();


            while (featureIterator.hasNext()){
                try{

                Feature f = featureIterator.next();
                Integer itemId = (Integer)f.getProperty(db.getItemIdAttributeName()).getValue();
                Geometry geometry = (Geometry) f.getDefaultGeometryProperty().getValue();
                rVal.put(itemId, geometry);
                order.add(itemId);
                geoCalc.setStartingGeographicPoint(geometry.getCoordinate().x, geometry.getCoordinate().y);
                geoCalc.setDestinationGeographicPoint(g.getCoordinate().x, g.getCoordinate().y);
                distMap.put(itemId, geoCalc.getOrthodromicDistance());
                }
                catch (Exception e){
                    //do nothing
                }
            }
            featureIterator.close();

            Collections.sort(order, new Comparator() {
                @Override
                public int compare(Integer integer, Integer integer2){
                    try {

                        double dist1 = distMap.get(integer);

                        double dist2 = distMap.get(integer2);

                        if(dist1 < dist2) return 0;
                        else
                            return 1;
                    }
                    catch (Exception e){

                    }
                    return 0;
                }
            });
            if(k > order.size())
                k = order.size();

            for(Integer i: order.subList(0, k)){
                finalRVal.put(i, rVal.get(i));
            }
            featureIterator.close();




            return finalRVal;

        }catch(IOException e){
            throw new DaoException(e);
        }



    }
    @Override
    public Map getNeighbors(Integer itemId, String layerName, String refSysName, Set excludeSet) throws DaoException{
        return getNeighbors(db.getGeometry(itemId, layerName, refSysName), layerName, refSysName, excludeSet);
    }

    @Override
    public  Map getNeighbors(Geometry g, String layerName, String refSysName, Set excludeSet) throws DaoException{
        FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();
        PropertyName geomProperty = ff.property(db.getGeometryAttributeName());

        //build ref sys clause
        PropertyName refSysProperty = ff.property(db.getRefSysAttributeName());
        Filter refSysFilter = ff.equals(refSysProperty, ff.literal(refSysName));

        // build layer-related clause
        PropertyName layerProperty = ff.property(db.getLayerAttributeName());
        Filter layerFilter = ff.equals(layerProperty, ff.literal(layerName));

        /*

        Filter touchFilter = ff.touches(geomProperty, ff.literal(g));
        Filter intersectFilter = ff.intersects(geomProperty, ff.literal(g));

        List orFilters = Lists.newArrayList();
        orFilters.add(touchFilter);
        orFilters.add(intersectFilter);

        Filter touchOrIntersectFilter = ff.or(orFilters);

        */

        Filter intersectFilter = ff.intersects(geomProperty, ff.literal(g));
        List filters = Lists.newArrayList();
        filters.add(refSysFilter);
        filters.add(layerFilter);
        filters.add(intersectFilter);


        for(Integer i : excludeSet){
            Filter nonEqualFilter = ff.notEqual(ff.property(db.getItemIdAttributeName()), ff.literal(i));
            filters.add(nonEqualFilter);
        }


        Filter finalFilter = ff.and(filters);

        try {

            FeatureSource featureSource = db.getFeatureSource();
            FeatureCollection containedFeatures = featureSource.getFeatures(finalFilter);
            FeatureIterator featureIterator = containedFeatures.features();

            Map result = new HashMap();

            while (featureIterator.hasNext()){

                Feature f = featureIterator.next();
                result.put((Integer)f.getProperty(db.getItemIdAttributeName()).getValue(), (Geometry) f.getDefaultGeometryProperty().getValue());
            }

            featureIterator.close();

            return result;

        }catch(IOException e){
            throw new DaoException(e);
        }

    }

    public TIntSet getMaxDistanceKmItemIds(Integer itemId, String layerName, String refSysName, Set subLayers, double maxDist) throws DaoException{

        return getNeighboringItemIds(itemId, layerName, refSysName, subLayers, 0, maxDist / 112);
    }

    public TIntSet getMaxDistanceKmItemIds(Geometry g, String refSysName, Set subLayers, double maxDist) throws DaoException{

        return getNeighboringItemIds(g, refSysName, subLayers, 0, maxDist / 112);
    }

    @Override
    public Map getKNNeighbors(Integer itemId, int k, String layerName, String refSysName, Set excludeSet) throws DaoException{

        Geometry stPoint = db.getGeometry(itemId, layerName, refSysName);
        return getKNNeighbors(stPoint, k, layerName,refSysName, excludeSet);

    }

    public static class Provider extends org.wikibrain.conf.Provider {
        public Provider(Configurator configurator, Configuration config) throws ConfigurationException {
            super(configurator, config);
        }

        @Override
        public Class getType() {
            return SpatialNeighborDao.class;
        }

        @Override
        public String getPath() {
            return "spatial.dao.spatialNeighbor";
        }

        @Override
        public PostGISSpatialNeighborDao get(String name, Config config, Map runtimeParams) throws ConfigurationException {

            return new PostGISSpatialNeighborDao( getConfigurator().get(PostGISDB.class, config.getString("dataSource")));

        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy