Package mil.nga.giat.geowave.vector.plugin

Source Code of mil.nga.giat.geowave.vector.plugin.ExtractGeometryFilterVisitor

package mil.nga.giat.geowave.vector.plugin;

import mil.nga.giat.geowave.store.GeometryUtils;

import org.apache.log4j.Logger;
import org.geotools.filter.visitor.NullFilterVisitor;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.opengis.filter.And;
import org.opengis.filter.ExcludeFilter;
import org.opengis.filter.Filter;
import org.opengis.filter.Id;
import org.opengis.filter.IncludeFilter;
import org.opengis.filter.Not;
import org.opengis.filter.Or;
import org.opengis.filter.PropertyIsBetween;
import org.opengis.filter.PropertyIsEqualTo;
import org.opengis.filter.PropertyIsGreaterThan;
import org.opengis.filter.PropertyIsGreaterThanOrEqualTo;
import org.opengis.filter.PropertyIsLessThan;
import org.opengis.filter.PropertyIsLessThanOrEqualTo;
import org.opengis.filter.PropertyIsLike;
import org.opengis.filter.PropertyIsNotEqualTo;
import org.opengis.filter.PropertyIsNull;
import org.opengis.filter.expression.Add;
import org.opengis.filter.expression.Divide;
import org.opengis.filter.expression.Function;
import org.opengis.filter.expression.Literal;
import org.opengis.filter.expression.Multiply;
import org.opengis.filter.expression.NilExpression;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.expression.Subtract;
import org.opengis.filter.spatial.BBOX;
import org.opengis.filter.spatial.Beyond;
import org.opengis.filter.spatial.Contains;
import org.opengis.filter.spatial.Crosses;
import org.opengis.filter.spatial.DWithin;
import org.opengis.filter.spatial.Disjoint;
import org.opengis.filter.spatial.Equals;
import org.opengis.filter.spatial.Intersects;
import org.opengis.filter.spatial.Overlaps;
import org.opengis.filter.spatial.Touches;
import org.opengis.filter.spatial.Within;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.TransformException;

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

/**
* This class can be used to get Geometry from an OpenGIS filter object. GeoWave
* then uses this geometry to perform a spatial intersection query.
*
*/
public class ExtractGeometryFilterVisitor extends
    NullFilterVisitor
{
  static public NullFilterVisitor GEOMETRY_VISITOR = new ExtractGeometryFilterVisitor(
      GeoWaveGTDataStore.DEFAULT_CRS);

  private static Logger LOGGER = Logger.getLogger(ExtractGeometryFilterVisitor.class);

  private final CoordinateReferenceSystem crs;

  /**
   * This FilterVisitor is stateless - use
   * ExtractGeometryFilterVisitor.BOUNDS_VISITOR. You may also subclass in
   * order to reuse this functionality in your own FilterVisitor
   * implementation.
   */
  protected ExtractGeometryFilterVisitor(
      final CoordinateReferenceSystem crs ) {
    this.crs = crs;
  }

  /**
   * Produce an ReferencedEnvelope from the provided data parameter.
   *
   * @param data
   * @return ReferencedEnvelope
   */
  private Geometry bbox(
      final Object data ) {
    try {
      if (data == null) {
        return null;
      }
      else if (data instanceof ReferencedEnvelope) {

        return new GeometryFactory().toGeometry(((ReferencedEnvelope) data).transform(
            crs,
            true));

      }
      else if (data instanceof Envelope) {
        return new GeometryFactory().toGeometry((Envelope) data);
      }
      else if (data instanceof CoordinateReferenceSystem) {
        return new GeometryFactory().toGeometry(new ReferencedEnvelope(
            (CoordinateReferenceSystem) data).transform(
            crs,
            true));
      }
    }
    catch (TransformException | FactoryException e) {
      LOGGER.warn(
          "Unable to transform geometry",
          e);
      return null;
    }
    throw new ClassCastException(
        "Could not cast data to ReferencedEnvelope");
  }

  @Override
  public Object visit(
      final ExcludeFilter filter,
      final Object data ) {
    return null;
  }

  @Override
  public Object visit(
      final IncludeFilter filter,
      final Object data ) {
    return infinity();
  }

  private Geometry infinity() {
    return GeometryUtils.infinity();
  }

  @SuppressWarnings("deprecation")
  @Override
  public Object visit(
      final BBOX filter,
      final Object data ) {
    final Geometry bbox = bbox(data);

    // consider doing reprojection here into data CRS?
    final Envelope bounds = new Envelope(
        filter.getMinX(),
        filter.getMaxX(),
        filter.getMinY(),
        filter.getMaxY());
    if (bbox != null) {
      return bbox.union(new GeometryFactory().toGeometry(bounds));
    }
    else {
      return bbox(bounds);
    }
  }

  /**
   * Please note we are only visiting literals involved in spatial operations.
   *
   * @param literal
   *            , hopefully a Geometry or Envelope
   * @param data
   *            Incoming BoundingBox (or Envelope or CRS)
   *
   * @return ReferencedEnvelope updated to reflect literal
   */
  @Override
  public Object visit(
      final Literal expression,
      final Object data ) {
    final Object value = expression.getValue();
    if (value instanceof Geometry) {
      final Geometry geometry = (Geometry) value;
      return geometry;
    }
    else {
      LOGGER.info("LiteralExpression ignored!");
    }
    return bbox(data);
  }

  @Override
  public Object visit(
      final And filter,
      final Object data ) {
    Geometry mixed = infinity();
    for (final Filter f : filter.getChildren()) {
      final Object obj = f.accept(
          this,
          data);
      if ((obj != null) && (obj instanceof Geometry)) {
        final Geometry geom = (Geometry) obj;
        final double mixedArea = mixed.getArea();
        final double geomArea = geom.getArea();
        if (Double.isInfinite(mixedArea) || Double.isNaN(mixedArea)) {
          mixed = geom;
        }
        else if (!Double.isInfinite(geomArea) && !Double.isNaN(geomArea)) {
          mixed = mixed.intersection(geom);
        }
      }
    }
    return mixed;
  }

  @Override
  public Object visit(
      final Not filter,
      final Object data ) {
    // no matter what we have to return an infinite envelope
    // rationale
    // !(finite envelope) -> an unbounded area -> infinite
    // !(non spatial filter) -> infinite (no spatial concern)
    // !(infinite) -> ... infinite, as the first infinite could be the
    // result
    // of !(finite envelope)

    return infinity();
  }

  @Override
  public Object visit(
      final Or filter,
      final Object data ) {
    Geometry mixed = new GeometryFactory().toGeometry(new Envelope());
    for (final Filter f : filter.getChildren()) {
      final Geometry geom = (Geometry) f.accept(
          this,
          data);
      final double geomArea = geom.getArea();
      if (!Double.isInfinite(geomArea) && !Double.isNaN(geomArea)) {
        mixed = mixed.union(geom);
      }
    }
    if (mixed.isEmpty()) {
      return infinity();
    }
    return mixed;
  }

  @Override
  public Object visit(
      final Beyond filter,
      final Object data ) {
    // beyond a certain distance from a finite object, no way to limit it
    return infinity();
  }

  @Override
  public Object visit(
      final Contains filter,
      Object data ) {
    data = filter.getExpression1().accept(
        this,
        data);
    data = filter.getExpression2().accept(
        this,
        data);
    return data;
  }

  @Override
  public Object visit(
      final Crosses filter,
      Object data ) {
    data = filter.getExpression1().accept(
        this,
        data);
    data = filter.getExpression2().accept(
        this,
        data);
    return data;
  }

  @Override
  public Object visit(
      final Disjoint filter,
      final Object data ) {
    // disjoint does not define a rectangle, but a hole in the
    // Cartesian plane, no way to limit it
    return infinity();
  }

  @Override
  public Object visit(
      final DWithin filter,
      final Object data ) {
    final Geometry bbox = bbox(data);

    // we have to take the reference geometry bbox and
    // expand it by the distance.
    // We ignore the unit of measure for the moment
    Literal geometry = null;
    if ((filter.getExpression1() instanceof PropertyName) && (filter.getExpression2() instanceof Literal)) {
      geometry = (Literal) filter.getExpression2();
    }
    if ((filter.getExpression2() instanceof PropertyName) && (filter.getExpression1() instanceof Literal)) {
      geometry = (Literal) filter.getExpression2();
    }

    // we cannot desume a bbox from this filter
    if (geometry == null) {
      return infinity();
    }

    Geometry geom = geometry.evaluate(
        null,
        Geometry.class);
    if (geom == null) {
      return infinity();
    }
    geom = geom.buffer(filter.getDistance());

    if (bbox != null) {
      return geom.union(bbox);
    }
    else {
      return geom;
    }
  }

  @Override
  public Object visit(
      final Equals filter,
      Object data ) {
    data = filter.getExpression1().accept(
        this,
        data);
    data = filter.getExpression2().accept(
        this,
        data);
    return data;
  }

  @Override
  public Object visit(
      final Intersects filter,
      Object data ) {
    data = filter.getExpression1().accept(
        this,
        data);
    data = filter.getExpression2().accept(
        this,
        data);

    return data;
  }

  @Override
  public Object visit(
      final Overlaps filter,
      Object data ) {
    data = filter.getExpression1().accept(
        this,
        data);
    data = filter.getExpression2().accept(
        this,
        data);

    return data;
  }

  @Override
  public Object visit(
      final Touches filter,
      Object data ) {
    data = filter.getExpression1().accept(
        this,
        data);
    data = filter.getExpression2().accept(
        this,
        data);

    return data;
  }

  @Override
  public Object visit(
      final Within filter,
      Object data ) {
    data = filter.getExpression1().accept(
        this,
        data);
    data = filter.getExpression2().accept(
        this,
        data);

    return data;
  }

  @Override
  public Object visit(
      final Add expression,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final Divide expression,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final Function expression,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final Id filter,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final Multiply expression,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final NilExpression expression,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final PropertyIsBetween filter,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final PropertyIsEqualTo filter,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final PropertyIsGreaterThan filter,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final PropertyIsGreaterThanOrEqualTo filter,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final PropertyIsLessThan filter,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final PropertyIsLessThanOrEqualTo filter,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final PropertyIsLike filter,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final PropertyIsNotEqualTo filter,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final PropertyIsNull filter,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visit(
      final PropertyName expression,
      final Object data ) {
    return null;
  }

  @Override
  public Object visit(
      final Subtract expression,
      final Object data ) {
    return infinity();
  }

  @Override
  public Object visitNullFilter(
      final Object data ) {
    return infinity();
  }

}
TOP

Related Classes of mil.nga.giat.geowave.vector.plugin.ExtractGeometryFilterVisitor

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.