Package org.neo4j.gis.spatial.pipes

Source Code of org.neo4j.gis.spatial.pipes.GeoPipeline

/**
* Copyright (c) 2010-2013 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.gis.spatial.pipes;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;

import org.geotools.data.neo4j.Neo4jFeatureBuilder;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.collection.AbstractFeatureCollection;
import org.geotools.filter.text.cql2.CQLException;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.neo4j.gis.spatial.rtree.filter.SearchAll;
import org.neo4j.gis.spatial.rtree.filter.SearchFilter;
import org.neo4j.gis.spatial.Constants;
import org.neo4j.gis.spatial.Layer;
import org.neo4j.gis.spatial.SpatialDatabaseRecord;
import org.neo4j.gis.spatial.SpatialRecord;
import org.neo4j.gis.spatial.SpatialTopologyUtils;
import org.neo4j.gis.spatial.filter.SearchIntersectWindow;
import org.neo4j.gis.spatial.filter.SearchRecords;
import org.neo4j.gis.spatial.pipes.filtering.FilterCQL;
import org.neo4j.gis.spatial.pipes.filtering.FilterContain;
import org.neo4j.gis.spatial.pipes.filtering.FilterCover;
import org.neo4j.gis.spatial.pipes.filtering.FilterCoveredBy;
import org.neo4j.gis.spatial.pipes.filtering.FilterCross;
import org.neo4j.gis.spatial.pipes.filtering.FilterDisjoint;
import org.neo4j.gis.spatial.pipes.filtering.FilterEmpty;
import org.neo4j.gis.spatial.pipes.filtering.FilterEqualExact;
import org.neo4j.gis.spatial.pipes.filtering.FilterEqualNorm;
import org.neo4j.gis.spatial.pipes.filtering.FilterEqualTopo;
import org.neo4j.gis.spatial.pipes.filtering.FilterInRelation;
import org.neo4j.gis.spatial.pipes.filtering.FilterIntersect;
import org.neo4j.gis.spatial.pipes.filtering.FilterIntersectWindow;
import org.neo4j.gis.spatial.pipes.filtering.FilterInvalid;
import org.neo4j.gis.spatial.pipes.filtering.FilterOverlap;
import org.neo4j.gis.spatial.pipes.filtering.FilterProperty;
import org.neo4j.gis.spatial.pipes.filtering.FilterPropertyNotNull;
import org.neo4j.gis.spatial.pipes.filtering.FilterPropertyNull;
import org.neo4j.gis.spatial.pipes.filtering.FilterTouch;
import org.neo4j.gis.spatial.pipes.filtering.FilterValid;
import org.neo4j.gis.spatial.pipes.filtering.FilterWithin;
import org.neo4j.gis.spatial.pipes.impl.*;
import org.neo4j.gis.spatial.pipes.processing.ApplyAffineTransformation;
import org.neo4j.gis.spatial.pipes.processing.Area;
import org.neo4j.gis.spatial.pipes.processing.Boundary;
import org.neo4j.gis.spatial.pipes.processing.Buffer;
import org.neo4j.gis.spatial.pipes.processing.Centroid;
import org.neo4j.gis.spatial.pipes.processing.ConvexHull;
import org.neo4j.gis.spatial.pipes.processing.CopyDatabaseRecordProperties;
import org.neo4j.gis.spatial.pipes.processing.Densify;
import org.neo4j.gis.spatial.pipes.processing.DensityIslands;
import org.neo4j.gis.spatial.pipes.processing.Difference;
import org.neo4j.gis.spatial.pipes.processing.Dimension;
import org.neo4j.gis.spatial.pipes.processing.Distance;
import org.neo4j.gis.spatial.pipes.processing.EndPoint;
import org.neo4j.gis.spatial.pipes.processing.ExtractGeometries;
import org.neo4j.gis.spatial.pipes.processing.ExtractPoints;
import org.neo4j.gis.spatial.pipes.processing.GML;
import org.neo4j.gis.spatial.pipes.processing.GeoJSON;
import org.neo4j.gis.spatial.pipes.processing.GeometryType;
import org.neo4j.gis.spatial.pipes.processing.InteriorPoint;
import org.neo4j.gis.spatial.pipes.processing.IntersectAll;
import org.neo4j.gis.spatial.pipes.processing.Intersection;
import org.neo4j.gis.spatial.pipes.processing.KeyholeMarkupLanguage;
import org.neo4j.gis.spatial.pipes.processing.Length;
import org.neo4j.gis.spatial.pipes.processing.Max;
import org.neo4j.gis.spatial.pipes.processing.Min;
import org.neo4j.gis.spatial.pipes.processing.NumGeometries;
import org.neo4j.gis.spatial.pipes.processing.NumPoints;
import org.neo4j.gis.spatial.pipes.processing.OrthodromicDistance;
import org.neo4j.gis.spatial.pipes.processing.OrthodromicLength;
import org.neo4j.gis.spatial.pipes.processing.SimplifyPreservingTopology;
import org.neo4j.gis.spatial.pipes.processing.SimplifyWithDouglasPeucker;
import org.neo4j.gis.spatial.pipes.processing.Sort;
import org.neo4j.gis.spatial.pipes.processing.StartPoint;
import org.neo4j.gis.spatial.pipes.processing.SymDifference;
import org.neo4j.gis.spatial.pipes.processing.Union;
import org.neo4j.gis.spatial.pipes.processing.UnionAll;
import org.neo4j.gis.spatial.pipes.processing.WellKnownText;
import org.neo4j.graphdb.Node;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.util.AffineTransformation;


public class GeoPipeline extends Pipeline<GeoPipeFlow,GeoPipeFlow> {

  protected Layer layer;
 
  protected GeoPipeline(Layer layer) {
        this.layer = layer;
  }

  protected static IdentityPipe<GeoPipeFlow> createStartPipe(List<SpatialDatabaseRecord> records) {
    return createStartPipe(records.iterator());
 
 
  protected static IdentityPipe<GeoPipeFlow> createStartPipe(final Iterator<SpatialDatabaseRecord> records) {
        Iterator<GeoPipeFlow> startIterator = new Iterator<GeoPipeFlow>() {
            @Override
            public boolean hasNext() {
                return records.hasNext();
            }

            @Override
            public GeoPipeFlow next() {
                return new GeoPipeFlow(records.next());
            }

            @Override
            public void remove() {
                records.remove();
            }
        };
        final Object start = startIterator;
        return new IdentityPipe<GeoPipeFlow>() {
            {
                super.setStarts((Iterator) start);
            }
        };
  }

  /**
   * Start a new pipeline with an iterator of SpatialDatabaseRecords
   *
   * @param layer
   * @param records
   * @return geoPipeline
   */
  public static GeoPipeline start(Layer layer, Iterator<SpatialDatabaseRecord> records) {
    GeoPipeline pipeline = new GeoPipeline(layer);
      return (GeoPipeline) pipeline.add(createStartPipe(records));       
  }
 
  /**
   * Start a new pipeline with a list of SpatialDatabaseRecords
   *
   * @param layer
   * @param records
   * @return geoPipeline
   */
  public static GeoPipeline start(Layer layer, List<SpatialDatabaseRecord> records) {
    GeoPipeline pipeline = new GeoPipeline(layer);
      return (GeoPipeline) pipeline.add(createStartPipe(records));   
  }

  /**
   * Start a new pipeline that will iterate through a SearchRecords
   *
   * @param layer
   * @param records
   * @return geoPipeline
   */
    public static GeoPipeline start(Layer layer, SearchRecords records) {
      GeoPipeline pipeline = new GeoPipeline(layer);
      return (GeoPipeline) pipeline.add(createStartPipe(records));
    }

    /**
     * Start a new pipeline that will iterate through a SearchFilter
     *
     * @param layer
     * @param searchFilter
     * @return geoPipeline
     */
    public static GeoPipeline start(Layer layer, SearchFilter searchFilter) {
      return start(layer, layer.getIndex().search(searchFilter));
    }

    /**
     * Start a new pipeline that will iterate through all items contained in a Layer
     *
     * @param layer
     * @return geoPipeline
     */
    public static GeoPipeline start(Layer layer) {
      return start(layer, new SearchAll());
    }
   
    /**
     * Extracts Layer items that intersect the given search window and start a pipeline.
     *
     * @param layer
     * @param searchWindow
     * @return geoPipeline
     */
    public static GeoPipeline startIntersectWindowSearch(Layer layer, Envelope searchWindow) {
      return start(layer, layer.getIndex().search(new SearchIntersectWindow(layer, searchWindow)));
    }
   
    /**
     * Extracts Layer items that contain the given geometry and start a pipeline.
     *
     * @param layer
     * @param geometry
     * @return geoPipeline
     */
    public static GeoPipeline startContainSearch(Layer layer, Geometry geometry) {
      return startIntersectWindowSearch(layer, geometry.getEnvelopeInternal())
        .containFilter(geometry);
    }

    /**
     * Extracts Layer items that cover the given geometry and start a pipeline.
     *
     * @param layer
     * @param geometry
     * @return geoPipeline
     */
    public static GeoPipeline startCoverSearch(Layer layer, Geometry geometry) {
      return startIntersectWindowSearch(layer, geometry.getEnvelopeInternal())
        .coverFilter(geometry);
    }   

    /**
     * Extracts Layer items that are covered by the given geometry and start a pipeline.
     *
     * @param layer
     * @param geometry
     * @return geoPipeline
     */
    public static GeoPipeline startCoveredBySearch(Layer layer, Geometry geometry) {
      return startIntersectWindowSearch(layer, geometry.getEnvelopeInternal())
        .coveredByFilter(geometry);
    }   

    /**
     * Extracts Layer items that cross by the given geometry and start a pipeline.
     *
     * @param layer
     * @param geometry
     * @return geoPipeline
     */
    public static GeoPipeline startCrossSearch(Layer layer, Geometry geometry) {
      return startIntersectWindowSearch(layer, geometry.getEnvelopeInternal())
        .crossFilter(geometry);
    }   

    /**
     * Extracts Layer items that are equal to the given geometry and start a pipeline.
     *
     * @param layer
     * @param geometry
     * @return geoPipeline
     */
    public static GeoPipeline startEqualExactSearch(Layer layer, Geometry geometry, double tolerance) {
      return startIntersectWindowSearch(layer, geometry.getEnvelopeInternal())
        .equalExactFilter(geometry, tolerance);
    }

    /**
     * Extracts Layer items that intersect the given geometry and start a pipeline.
     *
     * @param layer
     * @param geometry
     * @return geoPipeline
     */
    public static GeoPipeline startIntersectSearch(Layer layer, Geometry geometry) {
      return startIntersectWindowSearch(layer, geometry.getEnvelopeInternal())
        .intersectionFilter(geometry);
    }   

    /**
     * Extracts Layer items that overlap the given geometry and start a pipeline.
     *
     * @param layer
     * @param geometry
     * @return geoPipeline
     */
    public static GeoPipeline startOverlapSearch(Layer layer, Geometry geometry) {
      return startIntersectWindowSearch(layer, geometry.getEnvelopeInternal())
        .overlapFilter(geometry);
    }   

    /**
     * Extracts Layer items that touch the given geometry and start a pipeline.
     *
     * @param layer
     * @param geometry
     * @return geoPipeline
     */
    public static GeoPipeline startTouchSearch(Layer layer, Geometry geometry) {
      return startIntersectWindowSearch(layer, geometry.getEnvelopeInternal())
        .touchFilter(geometry);
    }   

    /**
     * Extracts Layer items that are within the given geometry and start a pipeline.
     *
     * @param layer
     * @param geometry
     * @return geoPipeline
     */
    public static GeoPipeline startWithinSearch(Layer layer, Geometry geometry) {
      return startIntersectWindowSearch(layer, geometry.getEnvelopeInternal())
        .withinFilter(geometry);
    }
   
    /**
   * Calculates the distance between Layer items nearest to the given point and the given point.
   * The search window created is based on Layer items density and it could lead to no results.
   *
     * @param layer with latitude, longitude coordinates
     * @param point
     * @param numberOfItemsToFind tries to find this number of items for comparison
     * @return geoPipeline
     */
  public static GeoPipeline startNearestNeighborLatLonSearch(Layer layer, Coordinate point, int numberOfItemsToFind) {
    Envelope searchWindow = SpatialTopologyUtils.createEnvelopeForGeometryDensityEstimate(layer, point, numberOfItemsToFind);
    return startNearestNeighborLatLonSearch(layer, point, searchWindow);
  }
   
  /**
   * Calculates the distance between Layer items inside the given search window and the given point.
   *
     * @param layer with latitude, longitude coordinates
   * @param point
   * @param searchWindow
   * @return geoPipeline
   */
  public static GeoPipeline startNearestNeighborLatLonSearch(Layer layer, Coordinate point, Envelope searchWindow) {
    return start(layer, new SearchIntersectWindow(layer, searchWindow))
      .calculateOrthodromicDistance(point);
  }

  /**
   * Extracts Layer items with a distance from the given point that is less than or equal the given distance.
   *
     * @param layer with latitude, longitude coordinates
   * @param point
   * @param maxDistanceInKm
   * @return geoPipeline
   */
  public static GeoPipeline startNearestNeighborLatLonSearch(Layer layer, Coordinate point, double maxDistanceInKm) {
    Envelope searchWindow = OrthodromicDistance.suggestSearchWindow(point, maxDistanceInKm);
    GeoPipeline pipeline = start(layer, new SearchIntersectWindow(layer, searchWindow))
      .calculateOrthodromicDistance(point);
   
    if (layer.getGeometryType() != null && layer.getGeometryType() == Constants.GTYPE_POINT) {
      pipeline = pipeline.propertyFilter("OrthodromicDistance", maxDistanceInKm, FilterPipe.Filter.LESS_THAN_EQUAL);
    }
   
    return pipeline;
  }

  /**
   * Calculates the distance between Layer items nearest to the given point and the given point.
   * The search window created is based on Layer items density and it could lead to no results.
   *
   * @param layer
   * @param point
     * @param numberOfItemsToFind tries to find this number of items for comparison
   * @return geoPipeline
   */
  public static GeoPipeline startNearestNeighborSearch(Layer layer, Coordinate point, int numberOfItemsToFind) { 
    Envelope searchWindow = SpatialTopologyUtils.createEnvelopeForGeometryDensityEstimate(layer, point, numberOfItemsToFind);
    return startNearestNeighborSearch(layer, point, searchWindow);
  }
 
  /**
   * Calculates the distance between Layer items inside the given search window and the given point.
   *
   * @param layer
   * @param point
   * @param searchWindow
   * @return geoPipeline
   */
  public static GeoPipeline startNearestNeighborSearch(Layer layer, Coordinate point, Envelope searchWindow) {
    return start(layer, new SearchIntersectWindow(layer, searchWindow))
      .calculateDistance(layer.getGeometryFactory().createPoint(point));
  }
   
  /**
   * Extracts Layer items with a distance from the given point that is less than or equal the given distance.
   *
   * @param layer
   * @param point
   * @param maxDistance
   * @return geoPipeline
   */
  public static GeoPipeline startNearestNeighborSearch(Layer layer, Coordinate point, double maxDistance) {
    Envelope extent = new Envelope(point.x - maxDistance, point.x + maxDistance,
        point.y - maxDistance, point.y + maxDistance);
   
    return start(layer, new SearchIntersectWindow(layer, extent))
      .calculateDistance(layer.getGeometryFactory().createPoint(point))
      .propertyFilter("Distance", maxDistance, FilterPipe.Filter.LESS_THAN_EQUAL);
  }
 
  /**
   * Adds a pipe at the end of this pipeline
   *
   * @param geoPipe
   * @return geoPipeline
   */
    public GeoPipeline addPipe(AbstractGeoPipe geoPipe) {
      return (GeoPipeline) add(geoPipe);
    }

    /**
   * @see CopyDatabaseRecordProperties
     */
    public GeoPipeline copyDatabaseRecordProperties() {
      return addPipe(new CopyDatabaseRecordProperties());
    }

    /**
   * @see CopyDatabaseRecordProperties
     */
    public GeoPipeline copyDatabaseRecordProperties(String[] keys) {
      return addPipe(new CopyDatabaseRecordProperties(keys));
    }   

    /**
   * @see CopyDatabaseRecordProperties
     */
    public GeoPipeline copyDatabaseRecordProperties(String key) {
      return addPipe(new CopyDatabaseRecordProperties(key));
    }       
   
    /**
     * @see Min
     */
    public GeoPipeline getMin(String property) {
      return addPipe(new Min(property));
    }

    /**
     * @see Max
     */
    public GeoPipeline getMax(String property) {
      return addPipe(new Max(property));
    }
   
    /**
     * @see Sort
     */
    public GeoPipeline sort(String property) {
      return addPipe(new Sort(property, true));
    }
   
    /**
     * @see Sort
     */
    public GeoPipeline sort(String property, boolean asc) {
      return addPipe(new Sort(property, asc));
    }
   
    /**
     * @see Sort
     */
    public GeoPipeline sort(String property, Comparator<Object> comparator) {
      return addPipe(new Sort(property, comparator));
    }   
   
    /**
     * @see Boundary
     */
    public GeoPipeline toBoundary() {
      return addPipe(new Boundary());
    }
   
    /**
     * @see Buffer
     */
    public GeoPipeline toBuffer(double distance) {
      return addPipe(new Buffer(distance));
    }
   
    /**
     * @see Centroid
     */
    public GeoPipeline toCentroid() {
      return addPipe(new Centroid());
    }

    /**
     * @see ConvexHull
     */
    public GeoPipeline toConvexHull() {
      return addPipe(new ConvexHull());
    }
   
    /**
     * @see org.neo4j.gis.spatial.pipes.processing.Envelope
     */
    public GeoPipeline toEnvelope() {
      return addPipe(new org.neo4j.gis.spatial.pipes.processing.Envelope());
    }
      
    /**
     * @see InteriorPoint
     */
    public GeoPipeline toInteriorPoint() {
      return addPipe(new InteriorPoint());
    }
   
    /**
     * @see StartPoint
     */
    public GeoPipeline toStartPoint() {
      return addPipe(new StartPoint(layer.getGeometryFactory()));
    }
   
    /**
     * @see EndPoint
     */
    public GeoPipeline toEndPoint() {
      return addPipe(new EndPoint(layer.getGeometryFactory()));
    }
   
    /**
     * @see NumPoints
     */
    public GeoPipeline countPoints() {
      return addPipe(new NumPoints());
    }
   
    /**
     * @see Union
     */
    public GeoPipeline union() {
      return addPipe(new Union());
    }

    /**
     * @see Union
     */
    public GeoPipeline union(Geometry geometry) {
      return addPipe(new Union(geometry));
    }
   
    /**
     * @see UnionAll
     */
    public GeoPipeline unionAll() {
      return addPipe(new UnionAll());
    }
   
    /**
     * @see Intersection
     */
    public GeoPipeline intersect(Geometry geometry) {
      return addPipe(new Intersection(geometry));
    }
   
    /**
     * @see IntersectAll
     */
    public GeoPipeline intersectAll() {
      return addPipe(new IntersectAll());
    }
   
    /**
     * @see Difference
     */
    public GeoPipeline difference(Geometry geometry) {
      return addPipe(new Difference(geometry));
    }
   
    /**
     * @see SymDifference
     */
    public GeoPipeline symDifference(Geometry geometry) {
      return addPipe(new SymDifference(geometry));
    }
   
    /**
     * @see SimplifyWithDouglasPeucker
     */
    public GeoPipeline simplifyWithDouglasPeucker(double distanceTolerance) {
      return addPipe(new SimplifyWithDouglasPeucker(distanceTolerance));
    }
   
    /**
     * @see SimplifyPreservingTopology
     */
    public GeoPipeline simplifyPreservingTopology(double distanceTolerance) {
      return addPipe(new SimplifyPreservingTopology(distanceTolerance));
    }
   
    /**
     * @see ApplyAffineTransformation
     */
    public GeoPipeline applyAffineTransform(AffineTransformation t) {
      return addPipe(new ApplyAffineTransformation(t));
    }
   
    /**
     * @see Densify
     */
    public GeoPipeline densify(double distanceTolerance) {
      return addPipe(new Densify(distanceTolerance));
    }
   
    /**
     * @see Area
     */
    public GeoPipeline calculateArea() {
      return addPipe(new Area());
    }
   
    /**
     * @see Length
     */
    public GeoPipeline calculateLength() {
      return addPipe(new Length());
    }
   
    /**
     * @see OrthodromicLength
     */
    public GeoPipeline calculateOrthodromicLength() {
      return addPipe(new OrthodromicLength(layer.getCoordinateReferenceSystem()));
    }   
   
    /**
     * @see Distance
     */
    public GeoPipeline calculateDistance(Geometry reference) {
      return addPipe(new Distance(reference));
    }

    /**
     * @see OrthodromicDistance
     */
    public GeoPipeline calculateOrthodromicDistance(Coordinate reference) {
      return addPipe(new OrthodromicDistance(reference));
    }
   
    /**
     * @see Dimension
     */
    public GeoPipeline getDimension() {
      return addPipe(new Dimension());
    }
   
    /**
     * @see GeometryType
     */
    public GeoPipeline getGeometryType() {
      return addPipe(new GeometryType());
    }
   
    /**
     * @see NumGeometries
     */
    public GeoPipeline getNumGeometries() {
      return addPipe(new NumGeometries());
    }
      
    /**
     * @see GeoJSON
     */
    public GeoPipeline createJson() {
      return addPipe(new GeoJSON());
    }
   
    /**
     * @see WellKnownText
     */
    public GeoPipeline createWellKnownText() {
      return addPipe(new WellKnownText());
    }
   
    /**
     * @see KeyholeMarkupLanguage
     */
    public GeoPipeline createKML() {
      return addPipe(new KeyholeMarkupLanguage());
    }

    /**
     * @see GML
     */
    public GeoPipeline createGML() {
      return addPipe(new GML());
    }

    /**
     * @see FilterProperty
     */
    public GeoPipeline propertyFilter(String key, Object value) {
      return addPipe(new FilterProperty(key, value));
    }   

    /**
     * @see FilterProperty
     */
    public GeoPipeline propertyFilter(String key, Object value, FilterPipe.Filter comparison) {
      return addPipe(new FilterProperty(key, value, comparison));     
    }

    /**
     * @see FilterPropertyNotNull
     */
    public GeoPipeline propertyNotNullFilter(String key) {
      return addPipe(new FilterPropertyNotNull(key));     
    }

    /**
     * @see FilterPropertyNull
     */
    public GeoPipeline propertyNullFilter(String key) {
      return addPipe(new FilterPropertyNull(key));     
    }   

    /**
     * @see FilterCQL
     */
    public GeoPipeline cqlFilter(String cql) throws CQLException {
      return addPipe(new FilterCQL(layer, cql));
    }

    /**
     * @see FilterIntersect
     */
    public GeoPipeline intersectionFilter(Geometry geometry) {
      return addPipe(new FilterIntersect(geometry));
    }

    /**
     * @see FilterIntersectWindow
     */
    public GeoPipeline windowIntersectionFilter(double xmin, double ymin, double xmax, double ymax) {
      return addPipe(new FilterIntersectWindow(layer.getGeometryFactory(), xmin, ymin, xmax, ymax));
    }

    /**
     * @see FilterIntersectWindow
     */
    public GeoPipeline windowIntersectionFilter(Envelope envelope) {
      return addPipe(new FilterIntersectWindow(layer.getGeometryFactory(), envelope));
    }   
   
    /**
     * @see FilterContain
     */
    public GeoPipeline containFilter(Geometry geometry) {
      return addPipe(new FilterContain(geometry));
    }

    /**
     * @see FilterCover
     */
    public GeoPipeline coverFilter(Geometry geometry) {
      return addPipe(new FilterCover(geometry));
    }

    /**
     * @see FilterCoveredBy
     */
    public GeoPipeline coveredByFilter(Geometry geometry) {
      return addPipe(new FilterCoveredBy(geometry));
    }   

    /**
     * @see FilterCross
     */
    public GeoPipeline crossFilter(Geometry geometry) {
      return addPipe(new FilterCross(geometry));
    }       

    /**
     * @see FilterDisjoint
     */
    public GeoPipeline disjointFilter(Geometry geometry) {
      return addPipe(new FilterDisjoint(geometry));
    }       

    /**
     * @see FilterEmpty
     */
    public GeoPipeline emptyFilter() {
      return addPipe(new FilterEmpty());
    }           

    /**
     * @see FilterEqualExact
     */
    public GeoPipeline equalExactFilter(Geometry geometry, double tolerance) {
      return addPipe(new FilterEqualExact(geometry, tolerance));
    }       
   
    /**
     * @see FilterEqualNorm
     */
    public GeoPipeline equalNormFilter(Geometry geometry, double tolerance) {
      return addPipe(new FilterEqualNorm(geometry, tolerance));
    }       

    /**
     * @see FilterEqualTopo
     */
    public GeoPipeline equalTopoFilter(Geometry geometry) {
      return addPipe(new FilterEqualTopo(geometry));
    }       
   
    /**
     * @see FilterInRelation
     */
    public GeoPipeline relationFilter(Geometry geometry, String intersectionPattern) {
      return addPipe(new FilterInRelation(geometry, intersectionPattern));
    }       

    /**
     * @see FilterValid
     */
    public GeoPipeline validFilter() {
      return addPipe(new FilterValid());
    }           

    /**
     * @see FilterInvalid
     */
    public GeoPipeline invalidFilter() {
      return addPipe(new FilterInvalid());
    }           
   
    /**
     * @see FilterOverlap
     */
    public GeoPipeline overlapFilter(Geometry geometry) {
      return addPipe(new FilterOverlap(geometry));
    }

    /**
     * @see FilterTouch
     */
    public GeoPipeline touchFilter(Geometry geometry) {
      return addPipe(new FilterTouch(geometry));
    }

    /**
     * @see FilterWithin
     */
    public GeoPipeline withinFilter(Geometry geometry) {
      return addPipe(new FilterWithin(geometry));
    }   
   
    /**
     * @see DensityIslands
     */
    public GeoPipeline groupByDensityIslands(double density) {
      return addPipe(new DensityIslands(density));
    }

    /**
     * @see ExtractPoints
     */
    public GeoPipeline extractPoints() {
      return addPipe(new ExtractPoints(layer.getGeometryFactory()));
    }   

    /**
     * @see ExtractGeometries
     */
    public GeoPipeline extractGeometries() {
      return addPipe(new ExtractGeometries());
    }

    public FeatureCollection<SimpleFeatureType,SimpleFeature> toStreamingFeatureCollection(final Envelope bounds) throws IOException {
      return toStreamingFeatureCollection(Neo4jFeatureBuilder.getTypeFromLayer(layer), bounds);     
    }
   
    public FeatureCollection<SimpleFeatureType,SimpleFeature> toStreamingFeatureCollection(SimpleFeatureType featureType, final Envelope bounds) throws IOException {
      final Neo4jFeatureBuilder featureBuilder = new Neo4jFeatureBuilder(layer);
      return new AbstractFeatureCollection(featureType) {
      @Override
      public int size() {
        return Integer.MAX_VALUE;
      }
     
      @Override
      protected Iterator<SimpleFeature> openIterator() {
        return new Iterator<SimpleFeature>() {
          @Override
          public boolean hasNext() {
            return GeoPipeline.this.hasNext();
          }

          @Override
          public SimpleFeature next() {
            return featureBuilder.buildFeature(GeoPipeline.this.next().getRecord());
          }

          @Override
          public void remove() {
            throw new UnsupportedOperationException();
          }         
        };
      }
     
      @Override
      public ReferencedEnvelope getBounds() {
        return new ReferencedEnvelope(bounds, layer.getCoordinateReferenceSystem());
      }
    };
    }

    public FeatureCollection<SimpleFeatureType,SimpleFeature> toFeatureCollection() throws IOException {
      return toFeatureCollection(Neo4jFeatureBuilder.getTypeFromLayer(layer));
    }
   
    public FeatureCollection<SimpleFeatureType,SimpleFeature> toFeatureCollection(SimpleFeatureType featureType) throws IOException {
    final List<GeoPipeFlow> records = toList();
     
      Envelope bounds = null;
      for (SpatialRecord record : records) {
        if (bounds == null) {
          bounds = record.getGeometry().getEnvelopeInternal();
        } else {
          bounds.expandToInclude(record.getGeometry().getEnvelopeInternal());
        }
      }
     
      final Iterator<GeoPipeFlow> recordsIterator = records.iterator();
      final ReferencedEnvelope refBounds = new ReferencedEnvelope(bounds, layer.getCoordinateReferenceSystem());
     
      final Neo4jFeatureBuilder featureBuilder = new Neo4jFeatureBuilder(featureType, Arrays.asList(layer.getExtraPropertyNames()));
      return new AbstractFeatureCollection(featureType) {
      @Override
      public int size() {
        return records.size();
      }
     
      @Override
      protected Iterator<SimpleFeature> openIterator() {
        return new Iterator<SimpleFeature>() {
         
          @Override
          public boolean hasNext() {
            return recordsIterator.hasNext();
          }

          @Override
          public SimpleFeature next() {
            return featureBuilder.buildFeature(recordsIterator.next());
          }

          @Override
          public void remove() {
            throw new UnsupportedOperationException();
          }         
        };
      }
     
      @Override
      public ReferencedEnvelope getBounds() {
        return refBounds;
      }
    };
    }
   
    /**
     * Iterates through the pipeline content and creates a list of all the SpatialDatabaseRecord found.
     * This will empty the pipeline.
     *
     * Warning: this method should not be used with pipes that extract many items from a single item
     * or with pipes that group many items into fewer items.
     *
     * Warning: GeoPipeline doesn't modify SpatialDatabaseRecords thus the geometries contained aren't those
     * transformed by the pipeline but the original ones.
     */
    public List<SpatialDatabaseRecord> toSpatialDatabaseRecordList() {

        List<SpatialDatabaseRecord> result = new ArrayList<SpatialDatabaseRecord>();
     
      try {
        while (true) {
          result.add(next().getRecord());
        }
      } catch (NoSuchElementException e) {}
      return result;
    }
   
    /**
     * Iterates through the pipeline content and creates a list of all the Nodes found.
     * This will empty the pipeline.
     *
     * Warning: this method should *not* be used with pipes that extract many items from a single item
     * or with pipes that group many items into fewer items.
     */   
    public List<Node> toNodeList() {
      List<Node> result = new ArrayList<Node>();
      try {
        while (true) {
          result.add(next().getRecord().getGeomNode());         
        }
      } catch (NoSuchElementException e) {}     
      return result;

    }

    public <T> GeoPipeline add(final Pipe<?, T> pipe) {
        this.addPipe(pipe);
        return (GeoPipeline) this;
    }

    public GeoPipeline range(final int low, final int high) {
        return this.add(new RangeFilterPipe<GeoPipeFlow>(low, high));
    }
}
TOP

Related Classes of org.neo4j.gis.spatial.pipes.GeoPipeline

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.