Skip to content

Commit

Permalink
Geo clean Up
Browse files Browse the repository at this point in the history
============
The default unit for measuring distances is *MILES* in most cases. This commit moves ES
over to the *International System of Units* and make it work on a default which relates
to *METERS* . Also the current structures of the `GeoBoundingBox Filter` changed in
order to define the *Bounding* by setting abitrary corners.

Distances
---------
Since the default unit for measuring distances has changed to a default unit
`DistanceUnit.DEFAULT` relating to *meters*, the **REST API** has changed at the
following places:

  * `ScriptDocValues.factorDistance()` returns *meters* instead of *miles*
  * `ScriptDocValues.factorDistanceWithDefault()` returns *meters* instead of *miles*
  * `ScriptDocValues.arcDistance()` returns *meters* instead of *miles*
        one might use `ScriptDocValues.arcDistanceInMiles()`
  * `ScriptDocValues.arcDistanceWithDefault()` returns *meters* instead of *miles*
  * `ScriptDocValues.distance()` returns *meters* instead of *miles*
        one might use `ScriptDocValues.distanceInMiles()`
  * `ScriptDocValues.distanceWithDefault()` returns *meters* instead of *miles*
        one might use `ScriptDocValues.distanceInMilesWithDefault()`
  * `GeoDistanceFilter` default unit changes from *kilometers* to *meters*
  * `GeoDistanceRangeFilter` default unit changes from *miles* to *meters*
  * `GeoDistanceFacet` default unit changes from *miles* to *meters*

Geo Bounding Box Filter
-----------------------
The naming of the GeoBoundingBoxFilter properties allows to set arbitrary corners
(see elastic#4084) namely `top_right`, `top_left`, `bottom_right` and `bottom_left`. This
change also includes the fields `topRight` and `bottomLeft` Also it is be possible to
set the single values by using just `top`, `bottom`, `left` and `right` parameters.

Closes elastic#4515, elastic#4084
  • Loading branch information
chilling authored and brusic committed Jan 19, 2014
1 parent 110eb55 commit 7d6e2ea
Show file tree
Hide file tree
Showing 37 changed files with 514 additions and 281 deletions.
1 change: 1 addition & 0 deletions docs/reference/api-conventions.asciidoc
Expand Up @@ -152,6 +152,7 @@ The full list of units is listed below:
[horizontal]
Mile:: `mi` or `miles`
Yard:: `yd` or `yards`
Feet:: `ft` or `feet`
Inch:: `in` or `inch`
Kilometer:: `km` or `kilometers`
Meter:: `m` or `meters`
Expand Down
32 changes: 32 additions & 0 deletions docs/reference/query-dsl/filters/geo-bounding-box-filter.asciidoc
Expand Up @@ -149,6 +149,38 @@ Format in `lat,lon`.
}
--------------------------------------------------

[float]
==== Vertices

The vertices of the bounding box can either be set by `top_left` and
`bottom_right` or by `top_right` and `bottom_left` parameters. More
over the names `topLeft`, `bottomRight`, `topRight` and `bottomLeft`
are supported. Instead of setting the values pairwise, one can use
the simple names `top`, `left`, `bottom` and `right` to set the
values separately.

[source,js]
--------------------------------------------------
{
"filtered" : {
"query" : {
"match_all" : {}
},
"filter" : {
"geo_bounding_box" : {
"pin.location" : {
"top" : -74.1,
"left" : 40.73,
"bottom" : -71.12,
"right" : 40.01
}
}
}
}
}
--------------------------------------------------


[float]
==== geo_point Type

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/search/facets/geo-distance-facet.asciidoc
Expand Up @@ -169,7 +169,7 @@ itself.
|=======================================================================
|Option |Description
|`unit` |The unit the ranges are provided in. Defaults to `km`. Can also
be `mi`, `miles`, `in`, `inch`, `yd`, `yards`, `kilometers`, `mm`, `millimeters`, `cm`, `centimeters`, `m` or `meters`.
be `mi`, `miles`, `in`, `inch`, `yd`, `yards`, `ft`, `feet`, `kilometers`, `mm`, `millimeters`, `cm`, `centimeters`, `m` or `meters`.

|`distance_type` |How to compute the distance. Can either be `arc`
(better precision), `sloppy_arc` (faster) or `plane` (fastest). Defaults to `sloppy_arc`.
Expand Down
20 changes: 12 additions & 8 deletions src/main/java/org/elasticsearch/common/geo/GeoHashUtils.java
Expand Up @@ -281,22 +281,26 @@ private static final int decode(char geo) {
}
}

/**
* Decodes the given geohash
*
* @param geohash Geohash to decocde
* @return {@link GeoPoint} at the center of cell, given by the geohash
*/
public static GeoPoint decode(String geohash) {
GeoPoint point = new GeoPoint();
decode(geohash, point);
return point;
return decode(geohash, new GeoPoint());
}

/**
* Decodes the given geohash into a latitude and longitude
*
* @param geohash Geohash to deocde
* @return Array with the latitude at index 0, and longitude at index 1
* @param geohash Geohash to decocde
* @return the given {@link GeoPoint} reseted to the center of
* cell, given by the geohash
*/
public static void decode(String geohash, GeoPoint ret) {
public static GeoPoint decode(String geohash, GeoPoint ret) {
double[] interval = decodeCell(geohash);
ret.reset((interval[0] + interval[1]) / 2D, (interval[2] + interval[3]) / 2D);

return ret.reset((interval[0] + interval[1]) / 2D, (interval[2] + interval[3]) / 2D);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/elasticsearch/common/geo/GeoPoint.java
Expand Up @@ -19,13 +19,13 @@

package org.elasticsearch.common.geo;

import java.io.IOException;

import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentParser.Token;
import org.elasticsearch.index.mapper.geo.GeoPointFieldMapper;

import java.io.IOException;

/**
*
*/
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/elasticsearch/common/geo/GeoUtils.java
Expand Up @@ -137,7 +137,7 @@ public static int quadTreeLevelsForPrecision(double meters) {
* @return levels need to achieve precision
*/
public static int quadTreeLevelsForPrecision(String distance) {
return quadTreeLevelsForPrecision(DistanceUnit.parse(distance, DistanceUnit.METERS, DistanceUnit.METERS));
return quadTreeLevelsForPrecision(DistanceUnit.METERS.parse(distance, DistanceUnit.DEFAULT));
}

/**
Expand Down Expand Up @@ -173,7 +173,7 @@ public static int geoHashLevelsForPrecision(double meters) {
* @return levels need to achieve precision
*/
public static int geoHashLevelsForPrecision(String distance) {
return geoHashLevelsForPrecision(DistanceUnit.parse(distance, DistanceUnit.METERS, DistanceUnit.METERS));
return geoHashLevelsForPrecision(DistanceUnit.METERS.parse(distance, DistanceUnit.DEFAULT));
}

/**
Expand Down
Expand Up @@ -19,14 +19,13 @@

package org.elasticsearch.common.geo.builders;

import java.io.IOException;

import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.unit.DistanceUnit.Distance;
import org.elasticsearch.common.xcontent.XContentBuilder;

import com.spatial4j.core.shape.Circle;
import com.vividsolutions.jts.geom.Coordinate;
import java.io.IOException;

public class CircleBuilder extends ShapeBuilder {

Expand Down Expand Up @@ -64,7 +63,7 @@ public CircleBuilder center(double lon, double lat) {
* @return this
*/
public CircleBuilder radius(String radius) {
return radius(DistanceUnit.Distance.parseDistance(radius, DistanceUnit.METERS));
return radius(DistanceUnit.Distance.parseDistance(radius));
}

/**
Expand Down
Expand Up @@ -19,31 +19,30 @@

package org.elasticsearch.common.geo.builders;

import java.io.IOException;

import org.elasticsearch.common.xcontent.XContentBuilder;

import com.spatial4j.core.shape.Rectangle;
import com.vividsolutions.jts.geom.Coordinate;
import org.elasticsearch.common.xcontent.XContentBuilder;

import java.io.IOException;

public class EnvelopeBuilder extends ShapeBuilder {

public static final GeoShapeType TYPE = GeoShapeType.ENVELOPE;

protected Coordinate northEast;
protected Coordinate southWest;
public EnvelopeBuilder topLeft(Coordinate northEast) {
this.northEast = northEast;
protected Coordinate topLeft;
protected Coordinate bottomRight;

public EnvelopeBuilder topLeft(Coordinate topLeft) {
this.topLeft = topLeft;
return this;
}

public EnvelopeBuilder topLeft(double longitude, double latitude) {
return topLeft(coordinate(longitude, latitude));
}

public EnvelopeBuilder bottomRight(Coordinate southWest) {
this.southWest = southWest;
public EnvelopeBuilder bottomRight(Coordinate bottomRight) {
this.bottomRight = bottomRight;
return this;
}

Expand All @@ -56,17 +55,15 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
builder.startObject();
builder.field(FIELD_TYPE, TYPE.shapename);
builder.startArray(FIELD_COORDINATES);
toXContent(builder, northEast);
toXContent(builder, southWest);
toXContent(builder, topLeft);
toXContent(builder, bottomRight);
builder.endArray();
return builder.endObject();
}

@Override
public Rectangle build() {
return SPATIAL_CONTEXT.makeRectangle(
northEast.x, southWest.x,
southWest.y, northEast.y);
return SPATIAL_CONTEXT.makeRectangle(topLeft.x, bottomRight.x, bottomRight.y, topLeft.y);
}

@Override
Expand Down
Expand Up @@ -19,14 +19,10 @@

package org.elasticsearch.common.geo.builders;

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

import org.elasticsearch.ElasticsearchIllegalArgumentException;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.ESLoggerFactory;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.unit.DistanceUnit.Distance;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContent;
Expand All @@ -38,7 +34,12 @@
import com.spatial4j.core.shape.Shape;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import java.io.IOException;
import java.util.*;

/**
* Basic class for building GeoJSON shapes like Polygons, Linestrings, etc
*/
public abstract class ShapeBuilder implements ToXContent {

protected static final ESLogger LOGGER = ESLoggerFactory.getLogger(ShapeBuilder.class.getName());
Expand Down Expand Up @@ -541,7 +542,7 @@ public static ShapeBuilder parse(XContentParser parser) throws IOException {
node = parseCoordinates(parser);
} else if (CircleBuilder.FIELD_RADIUS.equals(fieldName)) {
parser.nextToken();
radius = Distance.parseDistance(parser.text(), DistanceUnit.METERS);
radius = Distance.parseDistance(parser.text());
} else {
parser.nextToken();
parser.skipChildren();
Expand Down
64 changes: 35 additions & 29 deletions src/main/java/org/elasticsearch/common/unit/DistanceUnit.java
Expand Up @@ -30,25 +30,29 @@
* The DistanceUnit enumerates several units for measuring distances. These units
* provide methods for converting strings and methods to convert units among each
* others. Some methods like {@link DistanceUnit#getEarthCircumference} refer to
* the earth ellipsoid defined in {@link GeoUtils}.
* the earth ellipsoid defined in {@link GeoUtils}. The default unit used within
* this project is <code>METERS</code> which is defined by <code>DEFAULT</code>
*/
public enum DistanceUnit {
INCH(0.0254, "in", "inch"),
YARD(0.9144, "yd", "yards"),
FEET(0.3048, "ft", "feet"),
MILES(1609.344, "mi", "miles"),
KILOMETERS(1000.0, "km", "kilometers"),
MILLIMETERS(0.001, "mm", "millimeters"),
CENTIMETERS(0.01, "cm", "centimeters"),

// since 'm' is suffix of other unit
// it must be the last entry of unit
// names ending with 'm'. otherwise
// parsing would fail
METERS(1, "m", "meters");
METERS(1, "m", "meters");

public static DistanceUnit DEFAULT = METERS;

private double meters;
private final String[] names;

DistanceUnit(double meters, String...names) {
this.meters = meters;
this.names = names;
Expand Down Expand Up @@ -81,26 +85,6 @@ public double getDistancePerDegree() {
return GeoUtils.EARTH_EQUATOR / (360.0 * meters);
}

/**
* Convert a value into miles
*
* @param distance distance in this unit
* @return value in miles
*/
public double toMiles(double distance) {
return convert(distance, this, DistanceUnit.MILES);
}

/**
* Convert a value into kilometers
*
* @param distance distance in this unit
* @return value in kilometers
*/
public double toKilometers(double distance) {
return convert(distance, this, DistanceUnit.KILOMETERS);
}

/**
* Convert a value into meters
*
Expand All @@ -125,11 +109,11 @@ public double fromMeters(double distance) {
* Convert a given value into another unit
*
* @param distance value in this unit
* @param unit target unit
* @return value of the target unit
* @param unit source unit
* @return value in this unit
*/
public double convert(double distance, DistanceUnit unit) {
return convert(distance, this, unit);
return convert(distance, unit, this);
}

/**
Expand All @@ -141,7 +125,7 @@ public double convert(double distance, DistanceUnit unit) {
public String toString(double distance) {
return distance + toString();
}

@Override
public String toString() {
return names[0];
Expand Down Expand Up @@ -176,6 +160,17 @@ public static double parse(String distance, DistanceUnit defaultUnit, DistanceUn
return convert(dist.value, dist.unit, to);
}

/**
* Parses a given distance and converts it to this unit.
*
* @param distance String defining a distance (value and unit)
* @param defaultUnit unit to expect if none if provided
* @return parsed distance
*/
public double parse(String distance, DistanceUnit defaultUnit) {
return parse(distance, defaultUnit, this);
}

/**
* Convert a String to a {@link DistanceUnit}
*
Expand Down Expand Up @@ -296,6 +291,17 @@ public String toString() {
return unit.toString(value);
}

/**
* Parse a {@link Distance} from a given String. If no unit is given
* <code>DistanceUnit.DEFAULT</code> will be used
*
* @param distance String defining a {@link Distance}
* @return parsed {@link Distance}
*/
public static Distance parseDistance(String distance) {
return parseDistance(distance, DEFAULT);
}

/**
* Parse a {@link Distance} from a given String
*
Expand All @@ -304,7 +310,7 @@ public String toString() {
* if not unit is provided in the first argument
* @return parsed {@link Distance}
*/
public static Distance parseDistance(String distance, DistanceUnit defaultUnit) {
private static Distance parseDistance(String distance, DistanceUnit defaultUnit) {
for (DistanceUnit unit : values()) {
for (String name : unit.names) {
if(distance.endsWith(name)) {
Expand Down

0 comments on commit 7d6e2ea

Please sign in to comment.