public static GeoPoint parseGeoPoint(XContentParser parser, GeoPoint point) throws IOException, ElasticsearchParseException { return parseGeoPoint(parser, point, false); }
public static void normalizePoint(double[] lonLat, boolean normLon, boolean normLat) { assert lonLat != null && lonLat.length == 2; normLat = normLat && (lonLat[1] > 90 || lonLat[1] < -90); normLon = normLon && (lonLat[0] > 180 || lonLat[0] < -180); if (normLat) { lonLat[1] = centeredModulus(lonLat[1], 360); boolean shift = true; if (lonLat[1] < -90) { lonLat[1] = -180 - lonLat[1]; } else if (lonLat[1] > 90) { lonLat[1] = 180 - lonLat[1]; } else { // No need to shift the longitude, and the latitude is normalized shift = false; } if (shift) { if (normLon) { lonLat[0] += 180; } else { // Longitude won't be normalized, // keep it in the form x+k*360 (with x in ]-180;180]) // by only changing x, assuming k is meaningful for the user application. lonLat[0] += normalizeLon(lonLat[0]) > 0 ? -180 : 180; } } } if (normLon) { lonLat[0] = centeredModulus(lonLat[0], 360); } }
/** * Calculate the size (in meters) of geohash cells at a specific level * @param level geohash level must be greater or equal to zero * @return the size of cells at level in meters */ public static double geoHashCellSize(int level) { assert level>=0; final double w = geoHashCellWidth(level); final double h = geoHashCellHeight(level); return Math.sqrt(w*w + h*h); }
private static int getLevels(int treeLevels, double precisionInMeters, int defaultLevels, boolean geoHash) { if (treeLevels > 0 || precisionInMeters >= 0) { return Math.max(treeLevels, precisionInMeters >= 0 ? (geoHash ? GeoUtils.geoHashLevelsForPrecision(precisionInMeters) : GeoUtils.quadTreeLevelsForPrecision(precisionInMeters)) : 0); } return defaultLevels; }
/** * Set the precision use o make suggestions * * @param meters * precision as distance in meters * @return this */ public Builder precision(double meters) { int level = GeoUtils.geoHashLevelsForPrecision(meters); // Ceiling precision: we might return more results if (GeoUtils.geoHashCellSize(level) < meters) { level = Math.max(1, level - 1); } return precision(level); }
/** * Normalize the geo {@code Point} for its coordinates to lie within their * respective normalized ranges. * <p> * Note: A shift of 180° is applied in the longitude if necessary, * in order to normalize properly the latitude. * * @param point The point to normalize in-place. */ public static void normalizePoint(GeoPoint point) { normalizePoint(point, true, true); }
if (!GeoUtils.isValidLatitude(point.lat())) { throw new QueryShardException(context, "illegal latitude value [{}] for [{}]", point.lat(), GeoPolygonQueryBuilder.NAME); if (!GeoUtils.isValidLongitude(point.lon())) { throw new QueryShardException(context, "illegal longitude value [{}] for [{}]", point.lon(), GeoPolygonQueryBuilder.NAME); GeoUtils.normalizePoint(point, true, true);
/** * Normalize longitude to lie within the -180 (exclusive) to 180 (inclusive) range. * * @param lon Longitude to normalize * @return The normalized longitude. */ public static double normalizeLon(double lon) { if (lon > 180d || lon <= -180d) { lon = centeredModulus(lon, 360); } // avoid -0.0 return lon + 0d; }
boolean ignoreZValue = builder.ignoreZValue == null ? Defaults.IGNORE_Z_VALUE.value() : builder.ignoreZValue; boolean ignoreMalformed = builder.ignoreMalformed == null ? Defaults.IGNORE_MALFORMED.value() : builder.ignoreZValue; GeoPoint point = GeoUtils.parseGeoPoint(nullValue, ignoreZValue); if (ignoreMalformed == false) { if (point.lat() > 90.0 || point.lat() < -90.0) { GeoUtils.normalizePoint(point);
/** compute the distance between two points using the selected algorithm (PLANE, ARC) */ public double calculate(double srcLat, double srcLon, double dstLat, double dstLon, DistanceUnit unit) { if (this == PLANE) { return DistanceUnit.convert(GeoUtils.planeDistance(srcLat, srcLon, dstLat, dstLon), DistanceUnit.METERS, unit); } return DistanceUnit.convert(GeoUtils.arcDistance(srcLat, srcLon, dstLat, dstLon), DistanceUnit.METERS, unit); } }
/** * Calculate the number of levels needed for a specific precision. GeoHash * cells will not exceed the specified size (diagonal) of the precision. * @param distance Maximum size of cells as unit string (must greater or equal to zero) * @return levels need to achieve precision */ public static int geoHashLevelsForPrecision(String distance) { return geoHashLevelsForPrecision(DistanceUnit.METERS.parse(distance, DistanceUnit.DEFAULT)); }
protected static org.apache.lucene.geo.Polygon polygonLucene(Coordinate[][] polygon) { org.apache.lucene.geo.Polygon[] holes; Coordinate[] shell = polygon[0]; if (polygon.length > 1) { holes = new org.apache.lucene.geo.Polygon[polygon.length - 1]; for (int i = 0; i < holes.length; ++i) { Coordinate[] coords = polygon[i+1]; //We do not have holes on the dateline as they get eliminated //when breaking the polygon around it. double[] x = new double[coords.length]; double[] y = new double[coords.length]; for (int c = 0; c < coords.length; ++c) { x[c] = normalizeLon(coords[c].x); y[c] = normalizeLat(coords[c].y); } holes[i] = new org.apache.lucene.geo.Polygon(y, x); } } else { holes = new org.apache.lucene.geo.Polygon[0]; } double[] x = new double[shell.length]; double[] y = new double[shell.length]; for (int i = 0; i < shell.length; ++i) { //Lucene Tessellator treats different +180 and -180 and we should keep the sign. //normalizeLon method excludes -180. x[i] = Math.abs(shell[i].x) > 180 ? normalizeLon(shell[i].x) : shell[i].x; y[i] = normalizeLat(shell[i].y); } return new org.apache.lucene.geo.Polygon(y, x, holes); }
/** * Calculate the number of levels needed for a specific precision. QuadTree * cells will not exceed the specified size (diagonal) of the precision. * @param distance Maximum size of cells as unit string (must greater or equal to zero) * @return levels need to achieve precision */ public static int quadTreeLevelsForPrecision(String distance) { return quadTreeLevelsForPrecision(DistanceUnit.METERS.parse(distance, DistanceUnit.DEFAULT)); }
/** * Parse a precision that can be expressed as an integer or a distance measure like "1km", "10m". * * The precision is expressed as a number between 1 and 12 and indicates the length of geohash * used to represent geo points. * * @param parser {@link XContentParser} to parse the value from * @return int representing precision */ public static int parsePrecision(XContentParser parser) throws IOException, ElasticsearchParseException { XContentParser.Token token = parser.currentToken(); if (token.equals(XContentParser.Token.VALUE_NUMBER)) { return XContentMapValues.nodeIntegerValue(parser.intValue()); } else { String precision = parser.text(); try { // we want to treat simple integer strings as precision levels, not distances return XContentMapValues.nodeIntegerValue(precision); } catch (NumberFormatException e) { // try to parse as a distance value final int parsedPrecision = GeoUtils.geoHashLevelsForPrecision(precision); try { return checkPrecisionRange(parsedPrecision); } catch (IllegalArgumentException e2) { // this happens when distance too small, so precision > 12. We'd like to see the original string throw new IllegalArgumentException("precision too high [" + precision + "]", e2); } } } }
public double arcDistance(double lat, double lon) { GeoPoint point = getValue(); return GeoUtils.arcDistance(point.lat(), point.lon(), lat, lon); }
/** * Set the precision use o make suggestions * * @param meters * precision as distance in meters * @return this */ public Builder precision(double meters) { int level = GeoUtils.geoHashLevelsForPrecision(meters); // Ceiling precision: we might return more results if (GeoUtils.geoHashCellSize(level) < meters) { level = Math.max(1, level - 1); } return precision(level); }
private static int getLevels(int treeLevels, double precisionInMeters, int defaultLevels, boolean geoHash) { if (treeLevels > 0 || precisionInMeters >= 0) { return Math.max(treeLevels, precisionInMeters >= 0 ? (geoHash ? GeoUtils.geoHashLevelsForPrecision(precisionInMeters) : GeoUtils.quadTreeLevelsForPrecision(precisionInMeters)) : 0); } return defaultLevels; }
public static void normalizePoint(double[] lonLat) { normalizePoint(lonLat, true, true); }
if (GeoValidationMethod.isIgnoreMalformed(validation) == false) { for (GeoPoint point : localPoints) { if (GeoUtils.isValidLatitude(point.lat()) == false) { throw new ElasticsearchParseException( "illegal latitude value [{}] for [GeoDistanceSort] for field [{}].", fieldName); if (GeoUtils.isValidLongitude(point.lon()) == false) { throw new ElasticsearchParseException( "illegal longitude value [{}] for [GeoDistanceSort] for field [{}].", GeoUtils.normalizePoint(point, true, true);
/** * Normalize latitude to lie within the -90 to 90 (both inclusive) range. * <p> * Note: You should not normalize longitude and latitude separately, * because when normalizing latitude it may be necessary to * add a shift of 180° in the longitude. * For this purpose, you should call the * {@link #normalizePoint(GeoPoint)} function. * * @param lat Latitude to normalize * @return The normalized latitude. * @see #normalizePoint(GeoPoint) */ public static double normalizeLat(double lat) { if (lat > 90d || lat < -90d) { lat = centeredModulus(lat, 360); if (lat < -90) { lat = -180 - lat; } else if (lat > 90) { lat = 180 - lat; } } // avoid -0.0 return lat + 0d; }