Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "[GEO] Update GeoPolygonFilter to handle ambiguous polygons" #9463

Merged
merged 1 commit into from Jan 28, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
59 changes: 27 additions & 32 deletions src/main/java/org/elasticsearch/common/geo/GeoPoint.java
Expand Up @@ -20,12 +20,13 @@
package org.elasticsearch.common.geo;


import com.vividsolutions.jts.geom.Coordinate;

/**
*
*/
public final class GeoPoint extends Coordinate {
public final class GeoPoint {

private double lat;
private double lon;

public GeoPoint() {
}
Expand All @@ -40,36 +41,32 @@ public GeoPoint(String value) {
this.resetFromString(value);
}

public GeoPoint(GeoPoint other) {
super(other);
}

public GeoPoint(double lat, double lon) {
this.y = lat;
this.x = lon;
this.lat = lat;
this.lon = lon;
}

public GeoPoint reset(double lat, double lon) {
this.y = lat;
this.x = lon;
this.lat = lat;
this.lon = lon;
return this;
}

public GeoPoint resetLat(double lat) {
this.y = lat;
this.lat = lat;
return this;
}

public GeoPoint resetLon(double lon) {
this.x = lon;
this.lon = lon;
return this;
}

public GeoPoint resetFromString(String value) {
int comma = value.indexOf(',');
if (comma != -1) {
this.y = Double.parseDouble(value.substring(0, comma).trim());
this.x = Double.parseDouble(value.substring(comma + 1).trim());
lat = Double.parseDouble(value.substring(0, comma).trim());
lon = Double.parseDouble(value.substring(comma + 1).trim());
} else {
resetFromGeoHash(value);
}
Expand All @@ -82,40 +79,38 @@ public GeoPoint resetFromGeoHash(String hash) {
}

public final double lat() {
return this.y;
return this.lat;
}

public final double getLat() {
return this.y;
return this.lat;
}

public final double lon() {
return this.x;
return this.lon;
}

public final double getLon() {
return this.x;
return this.lon;
}

public final String geohash() {
return GeoHashUtils.encode(y, x);
return GeoHashUtils.encode(lat, lon);
}

public final String getGeohash() {
return GeoHashUtils.encode(y, x);
return GeoHashUtils.encode(lat, lon);
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null) return false;
if (o instanceof Coordinate) {
Coordinate c = (Coordinate)o;
return Double.compare(c.x, this.x) == 0
&& Double.compare(c.y, this.y) == 0
&& Double.compare(c.z, this.z) == 0;
}
if (getClass() != o.getClass()) return false;
if (o == null || getClass() != o.getClass()) return false;

GeoPoint geoPoint = (GeoPoint) o;

if (Double.compare(geoPoint.lat, lat) != 0) return false;
if (Double.compare(geoPoint.lon, lon) != 0) return false;

return true;
}
Expand All @@ -124,15 +119,15 @@ public boolean equals(Object o) {
public int hashCode() {
int result;
long temp;
temp = y != +0.0d ? Double.doubleToLongBits(y) : 0L;
temp = lat != +0.0d ? Double.doubleToLongBits(lat) : 0L;
result = (int) (temp ^ (temp >>> 32));
temp = x != +0.0d ? Double.doubleToLongBits(x) : 0L;
temp = lon != +0.0d ? Double.doubleToLongBits(lon) : 0L;
result = 31 * result + (int) (temp ^ (temp >>> 32));
return result;
}

public String toString() {
return "[" + y + ", " + x + "]";
return "[" + lat + ", " + lon + "]";
}

public static GeoPoint parseFromLatLon(String latLon) {
Expand Down
112 changes: 1 addition & 111 deletions src/main/java/org/elasticsearch/common/geo/GeoUtils.java
Expand Up @@ -19,7 +19,6 @@

package org.elasticsearch.common.geo;

import org.apache.commons.lang3.tuple.Pair;
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree;
import org.apache.lucene.spatial.prefix.tree.QuadPrefixTree;
import org.apache.lucene.util.SloppyMath;
Expand All @@ -38,9 +37,7 @@ public class GeoUtils {
public static final String LATITUDE = GeoPointFieldMapper.Names.LAT;
public static final String LONGITUDE = GeoPointFieldMapper.Names.LON;
public static final String GEOHASH = GeoPointFieldMapper.Names.GEOHASH;

public static final double DATELINE = 180.0D;


/** Earth ellipsoid major axis defined by WGS 84 in meters */
public static final double EARTH_SEMI_MAJOR_AXIS = 6378137.0; // meters (WGS 84)

Expand Down Expand Up @@ -425,113 +422,6 @@ public static GeoPoint parseGeoPoint(XContentParser parser, GeoPoint point) thro
}
}

public static boolean correctPolyAmbiguity(GeoPoint[] points, boolean handedness) {
return correctPolyAmbiguity(points, handedness, computePolyOrientation(points), 0, points.length, false);
}

public static boolean correctPolyAmbiguity(GeoPoint[] points, boolean handedness, boolean orientation, int component, int length,
boolean shellCorrected) {
// OGC requires shell as ccw (Right-Handedness) and holes as cw (Left-Handedness)
// since GeoJSON doesn't specify (and doesn't need to) GEO core will assume OGC standards
// thus if orientation is computed as cw, the logic will translate points across dateline
// and convert to a right handed system

// compute the bounding box and calculate range
Pair<Pair, Pair> range = GeoUtils.computeBBox(points, length);
final double rng = (Double)range.getLeft().getRight() - (Double)range.getLeft().getLeft();
// translate the points if the following is true
// 1. shell orientation is cw and range is greater than a hemisphere (180 degrees) but not spanning 2 hemispheres
// (translation would result in a collapsed poly)
// 2. the shell of the candidate hole has been translated (to preserve the coordinate system)
boolean incorrectOrientation = component == 0 && handedness != orientation;
boolean translated = ((incorrectOrientation && (rng > DATELINE && rng != 360.0)) || (shellCorrected && component != 0));
if (translated) {
for (GeoPoint c : points) {
if (c.x < 0.0) {
c.x += 360.0;
}
}
}
return translated;
}

public static boolean computePolyOrientation(GeoPoint[] points) {
return computePolyOrientation(points, points.length);
}

public static boolean computePolyOrientation(GeoPoint[] points, int length) {
// calculate the direction of the points:
// find the point at the top of the set and check its
// neighbors orientation. So direction is equivalent
// to clockwise/counterclockwise
final int top = computePolyOrigin(points, length);
final int prev = ((top + length - 1) % length);
final int next = ((top + 1) % length);
return (points[prev].x > points[next].x);
}

private static final int computePolyOrigin(GeoPoint[] points, int length) {
int top = 0;
// we start at 1 here since top points to 0
for (int i = 1; i < length; i++) {
if (points[i].y < points[top].y) {
top = i;
} else if (points[i].y == points[top].y) {
if (points[i].x < points[top].x) {
top = i;
}
}
}
return top;
}

public static final Pair computeBBox(GeoPoint[] points) {
return computeBBox(points, 0);
}

public static final Pair computeBBox(GeoPoint[] points, int length) {
double minX = points[0].x;
double maxX = points[0].x;
double minY = points[0].y;
double maxY = points[0].y;
// compute the bounding coordinates (@todo: cleanup brute force)
for (int i = 1; i < length; ++i) {
if (points[i].x < minX) {
minX = points[i].x;
}
if (points[i].x > maxX) {
maxX = points[i].x;
}
if (points[i].y < minY) {
minY = points[i].y;
}
if (points[i].y > maxY) {
maxY = points[i].y;
}
}
// return a pair of ranges on the X and Y axis, respectively
return Pair.of(Pair.of(minX, maxX), Pair.of(minY, maxY));
}

public static GeoPoint convertToGreatCircle(GeoPoint point) {
return convertToGreatCircle(point.y, point.x);
}

public static GeoPoint convertToGreatCircle(double lat, double lon) {
GeoPoint p = new GeoPoint(lat, lon);
// convert the point to standard lat/lon bounds
normalizePoint(p);

if (p.x < 0.0D) {
p.x += 360.0D;
}

if (p.y < 0.0D) {
p.y +=180.0D;
}
return p;
}

private GeoUtils() {
}
}
Expand Up @@ -23,22 +23,22 @@
import java.util.ArrayList;
import java.util.Arrays;

import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.GeoUtils;
import com.spatial4j.core.shape.ShapeCollection;
import org.elasticsearch.common.xcontent.XContentBuilder;

import com.spatial4j.core.shape.Shape;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;

public abstract class BaseLineStringBuilder<E extends BaseLineStringBuilder<E>> extends PointCollection<E> {

protected BaseLineStringBuilder() {
this(new ArrayList<GeoPoint>());
this(new ArrayList<Coordinate>());
}

protected BaseLineStringBuilder(ArrayList<GeoPoint> points) {
protected BaseLineStringBuilder(ArrayList<Coordinate> points) {
super(points);
}

Expand All @@ -49,7 +49,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws

@Override
public Shape build() {
GeoPoint[] coordinates = points.toArray(new GeoPoint[points.size()]);
Coordinate[] coordinates = points.toArray(new Coordinate[points.size()]);
Geometry geometry;
if(wrapdateline) {
ArrayList<LineString> strings = decompose(FACTORY, coordinates, new ArrayList<LineString>());
Expand All @@ -67,9 +67,9 @@ public Shape build() {
return jtsGeometry(geometry);
}

protected static ArrayList<LineString> decompose(GeometryFactory factory, GeoPoint[] coordinates, ArrayList<LineString> strings) {
for(GeoPoint[] part : decompose(+DATELINE, coordinates)) {
for(GeoPoint[] line : decompose(-DATELINE, part)) {
protected static ArrayList<LineString> decompose(GeometryFactory factory, Coordinate[] coordinates, ArrayList<LineString> strings) {
for(Coordinate[] part : decompose(+DATELINE, coordinates)) {
for(Coordinate[] line : decompose(-DATELINE, part)) {
strings.add(factory.createLineString(line));
}
}
Expand All @@ -83,16 +83,16 @@ protected static ArrayList<LineString> decompose(GeometryFactory factory, GeoPoi
* @param coordinates coordinates forming the linestring
* @return array of linestrings given as coordinate arrays
*/
protected static GeoPoint[][] decompose(double dateline, GeoPoint[] coordinates) {
protected static Coordinate[][] decompose(double dateline, Coordinate[] coordinates) {
int offset = 0;
ArrayList<GeoPoint[]> parts = new ArrayList<>();
ArrayList<Coordinate[]> parts = new ArrayList<>();

double shift = coordinates[0].x > DATELINE ? DATELINE : (coordinates[0].x < -DATELINE ? -DATELINE : 0);

for (int i = 1; i < coordinates.length; i++) {
double t = intersection(coordinates[i-1], coordinates[i], dateline);
if(!Double.isNaN(t)) {
GeoPoint[] part;
Coordinate[] part;
if(t<1) {
part = Arrays.copyOfRange(coordinates, offset, i+1);
part[part.length-1] = Edge.position(coordinates[i-1], coordinates[i], t);
Expand All @@ -111,16 +111,16 @@ protected static GeoPoint[][] decompose(double dateline, GeoPoint[] coordinates)
if(offset == 0) {
parts.add(shift(shift, coordinates));
} else if(offset < coordinates.length-1) {
GeoPoint[] part = Arrays.copyOfRange(coordinates, offset, coordinates.length);
Coordinate[] part = Arrays.copyOfRange(coordinates, offset, coordinates.length);
parts.add(shift(shift, part));
}
return parts.toArray(new GeoPoint[parts.size()][]);
return parts.toArray(new Coordinate[parts.size()][]);
}

private static GeoPoint[] shift(double shift, GeoPoint...coordinates) {
private static Coordinate[] shift(double shift, Coordinate...coordinates) {
if(shift != 0) {
for (int j = 0; j < coordinates.length; j++) {
coordinates[j] = new GeoPoint(coordinates[j].y, coordinates[j].x - 2 * shift);
coordinates[j] = new Coordinate(coordinates[j].x - 2 * shift, coordinates[j].y);
}
}
return coordinates;
Expand Down