/* * Licensed to STRATIO (C) under one or more contributor license agreements. * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. The STRATIO (C) licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package com.stratio.cassandra.lucene.common; import com.google.common.base.MoreObjects; import com.spatial4j.core.context.jts.JtsSpatialContext; import com.spatial4j.core.shape.jts.JtsGeometry; import com.stratio.cassandra.lucene.util.GeospatialUtilsJTS; import com.vividsolutions.jts.geom.Geometry; import org.codehaus.jackson.annotate.JsonCreator; import org.codehaus.jackson.annotate.JsonProperty; import org.codehaus.jackson.annotate.JsonSubTypes; import org.codehaus.jackson.annotate.JsonTypeInfo; /** * Class representing the transformation of a JTS geographical shape into a new shape. * * @author Andres de la Pena {@literal <adelapena@stratio.com>} */ @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") @JsonSubTypes({@JsonSubTypes.Type(value = GeoTransformation.Buffer.class, name = "buffer"), @JsonSubTypes.Type(value = GeoTransformation.Centroid.class, name = "centroid"), @JsonSubTypes.Type(value = GeoTransformation.Difference.class, name = "difference"), @JsonSubTypes.Type(value = GeoTransformation.Intersection.class, name = "intersection"), @JsonSubTypes.Type(value = GeoTransformation.Union.class, name = "union")}) public interface GeoTransformation { /** * Returns the transformed {@link JtsGeometry} resulting of applying this transformation to the specified {@link * JtsGeometry} using the specified {@link JtsSpatialContext}. * * @param shape the JTS shape to be transformed * @param context the JTS spatial context to be used * @return the transformed JTS shape */ JtsGeometry apply(JtsGeometry shape, JtsSpatialContext context); /** * {@link GeoTransformation} that returns the bounding shape of a JTS geographical shape. */ class Buffer implements GeoTransformation { /** The max allowed distance. */ @JsonProperty("max_distance") private GeoDistance maxDistance; /** The min allowed distance. */ @JsonProperty("min_distance") private GeoDistance minDistance; /** * Sets the max allowed distance. * * @param maxDistance the min distance * @return this with the specified min distance */ public Buffer maxDistance(GeoDistance maxDistance) { this.maxDistance = maxDistance; return this; } /** * Sets the min allowed distance. * * @param minDistance the min distance * @return this with the specified min distance */ public Buffer minDistance(GeoDistance minDistance) { this.minDistance = minDistance; return this; } /** * Returns the max allowed distance. * * @return the max distance */ public GeoDistance maxDistance() { return maxDistance; } /** * Returns the min allowed distance. * * @return the min distance */ public GeoDistance minDistance() { return minDistance; } /** * Returns the buffer of the specified {@link JtsGeometry}. * * @param shape the JTS shape to be transformed * @param context the JTS spatial context to be used * @return the buffer */ @Override public JtsGeometry apply(JtsGeometry shape, JtsSpatialContext context) { JtsGeometry max = maxDistance == null ? context.makeShape(shape.getGeom()) : shape.getBuffered(maxDistance.getDegrees(), context); if (minDistance != null) { JtsGeometry min = shape.getBuffered(minDistance.getDegrees(), context); Geometry difference = max.getGeom().difference(min.getGeom()); return context.makeShape(difference); } return max; } /** {@inheritDoc} */ @Override public String toString() { return MoreObjects.toStringHelper(this) .add("maxDistance", maxDistance) .add("minDistance", minDistance) .toString(); } } /** * {@link GeoTransformation} that returns the center point of a JTS geographical shape. */ class Centroid implements GeoTransformation { /** * Returns the center of the specified {@link JtsGeometry}. * * @param shape the JTS shape to be transformed * @param context the JTS spatial context to be used * @return the center */ @Override public JtsGeometry apply(JtsGeometry shape, JtsSpatialContext context) { Geometry centroid = shape.getGeom().getCentroid(); return context.makeShape(centroid); } /** {@inheritDoc} */ @Override public String toString() { return MoreObjects.toStringHelper(this).toString(); } } /** * {@link GeoTransformation} that returns the difference of two JTS geographical shapes. */ class Difference implements GeoTransformation { /** The shape to be subtracted. */ @JsonProperty("shape") public final String other; /** * Constructor receiving the geometry to be subtracted. * * @param other the geometry */ @JsonCreator public Difference(@JsonProperty("shape") String other) { this.other = other; } /** * Returns the difference of the specified {@link JtsGeometry}. * * @param shape the JTS shape to be transformed * @param context the JTS spatial context to be used * @return the difference */ @Override public JtsGeometry apply(JtsGeometry shape, JtsSpatialContext context) { Geometry geometry = GeospatialUtilsJTS.geometryFromWKT(context, other).getGeom(); Geometry difference = shape.getGeom().difference(geometry); return context.makeShape(difference); } /** {@inheritDoc} */ @Override public String toString() { return MoreObjects.toStringHelper(this).add("other", other).toString(); } } /** * {@link GeoTransformation} that returns the intersection of two JTS geographical shapes. */ class Intersection implements GeoTransformation { /** The shape to be intersected. */ @JsonProperty("shape") public final String other; /** * Constructor receiving the geometry to be added. * * @param other the geometry to be added */ @JsonCreator public Intersection(@JsonProperty("shape") String other) { this.other = other; } /** * Returns the intersection of the specified {@link JtsGeometry}. * * @param shape the JTS shape to be transformed * @param context the JTS spatial context to be used * @return the intersection */ @Override public JtsGeometry apply(JtsGeometry shape, JtsSpatialContext context) { Geometry geometry = GeospatialUtilsJTS.geometryFromWKT(context, other).getGeom(); Geometry intersection = shape.getGeom().intersection(geometry); return context.makeShape(intersection); } /** {@inheritDoc} */ @Override public String toString() { return MoreObjects.toStringHelper(this).add("other", other).toString(); } } /** * {@link GeoTransformation} that returns the union of two JTS geographical shapes. */ class Union implements GeoTransformation { /** The shape to be added. */ @JsonProperty("shape") public final String other; /** * Constructor receiving the geometry to be added. * * @param other the geometry to be added */ @JsonCreator public Union(@JsonProperty("shape") String other) { this.other = other; } /** * Returns the union of the specified {@link JtsGeometry}. * * @param shape the JTS shape to be transformed * @param context the JTS spatial context to be used * @return the union */ @Override public JtsGeometry apply(JtsGeometry shape, JtsSpatialContext context) { Geometry geometry = GeospatialUtilsJTS.geometryFromWKT(context, other).getGeom(); Geometry union = shape.getGeom().union(geometry); return context.makeShape(union); } @Override public String toString() { return MoreObjects.toStringHelper(this).add("other", other).toString(); } } }