Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,17 @@ protected int setValue(GeoShapeCellValues docValues, GeoShapeValues.GeoShapeValu
return 0;
}

@Override
protected long getMaxTilesAtPrecision(int finalPrecision) {
if (crossesDateline) {
return numTilesFromPrecision(finalPrecision, boundsWestLeft, boundsWestRight, boundsBottom, boundsTop)
+ numTilesFromPrecision(finalPrecision, boundsEastLeft, boundsEastRight, boundsBottom, boundsTop);

} else {
return numTilesFromPrecision(finalPrecision, boundsEastLeft, boundsEastRight, boundsBottom, boundsTop);
}
}

@Override
protected int setValuesForFullyContainedTile(int xTile, int yTile, int zTile, GeoShapeCellValues values, int valuesIndex,
int targetPrecision) {
Expand All @@ -83,12 +94,12 @@ protected int setValuesForFullyContainedTile(int xTile, int yTile, int zTile, Ge
for (int j = 0; j < 2; j++) {
int nextX = 2 * xTile + i;
int nextY = 2 * yTile + j;
if (zTile == targetPrecision) {
if (cellIntersectsGeoBoundingBox(GeoTileUtils.toBoundingBox(nextX, nextY, zTile))) {
if (cellIntersectsGeoBoundingBox(GeoTileUtils.toBoundingBox(nextX, nextY, zTile))) {
if (zTile == targetPrecision) {
values.add(valuesIndex++, GeoTileUtils.longEncodeTiles(zTile, nextX, nextY));
} else {
valuesIndex = setValuesForFullyContainedTile(nextX, nextY, zTile, values, valuesIndex, targetPrecision);
}
} else {
valuesIndex = setValuesForFullyContainedTile(nextX, nextY, zTile, values, valuesIndex, targetPrecision);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,14 @@ public int setValues(GeoShapeCellValues values, GeoShapeValues.GeoShapeValue geo
int minYTile = GeoTileUtils.getYTile(bounds.maxY(), (long) tiles);
int maxXTile = GeoTileUtils.getXTile(bounds.maxX(), (long) tiles);
int maxYTile = GeoTileUtils.getYTile(bounds.minY(), (long) tiles);
int count = (maxXTile - minXTile + 1) * (maxYTile - minYTile + 1);
long count = (long) (maxXTile - minXTile + 1) * (maxYTile - minYTile + 1);
if (count == 1) {
return setValue(values, geoValue, minXTile, minYTile, precision);
} else if (count <= precision) {
return setValuesByBruteForceScan(values, geoValue, precision, minXTile, minYTile, maxXTile, maxYTile);
} else {
return setValuesByRasterization(0, 0, 0, values, 0, precision, geoValue);
final long maxtiles = getMaxTilesAtPrecision(precision);
return setValuesByRasterization(0, 0, 0, values, 0, precision, geoValue, maxtiles);
}
}

Expand Down Expand Up @@ -109,7 +110,7 @@ protected int setValuesByBruteForceScan(GeoShapeCellValues values, GeoShapeValue
}

protected int setValuesByRasterization(int xTile, int yTile, int zTile, GeoShapeCellValues values, int valuesIndex,
int targetPrecision, GeoShapeValues.GeoShapeValue geoValue) {
int targetPrecision, GeoShapeValues.GeoShapeValue geoValue, long maxtiles) {
zTile++;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
Expand All @@ -118,26 +119,47 @@ protected int setValuesByRasterization(int xTile, int yTile, int zTile, GeoShape
GeoRelation relation = relateTile(geoValue, nextX, nextY, zTile);
if (GeoRelation.QUERY_INSIDE == relation) {
if (zTile == targetPrecision) {
values.resizeCell(valuesIndex + 1);
values.resizeCell(getNewSize(valuesIndex, 1));
values.add(valuesIndex++, GeoTileUtils.longEncodeTiles(zTile, nextX, nextY));
} else {
final int numTilesAtPrecision = 1 << (2 * (targetPrecision - zTile));
values.resizeCell(valuesIndex + numTilesAtPrecision + 1);
int numTilesAtPrecision = getNumTilesAtPrecision(targetPrecision, zTile, maxtiles);
values.resizeCell(getNewSize(valuesIndex, numTilesAtPrecision + 1));
valuesIndex = setValuesForFullyContainedTile(nextX, nextY, zTile, values, valuesIndex, targetPrecision);
}
} else if (GeoRelation.QUERY_CROSSES == relation) {
if (zTile == targetPrecision) {
values.resizeCell(valuesIndex + 1);
values.resizeCell(getNewSize(valuesIndex, 1));
values.add(valuesIndex++, GeoTileUtils.longEncodeTiles(zTile, nextX, nextY));
} else {
valuesIndex = setValuesByRasterization(nextX, nextY, zTile, values, valuesIndex, targetPrecision, geoValue);
valuesIndex =
setValuesByRasterization(nextX, nextY, zTile, values, valuesIndex, targetPrecision, geoValue, maxtiles);
}
}
}
}
return valuesIndex;
}

private int getNewSize(int valuesIndex, int increment) {
long newSize = (long) valuesIndex + increment;
if (newSize > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Tile aggregation array overflow");
}
return (int) newSize;
}

private int getNumTilesAtPrecision(int finalPrecision, int currentPrecision, long maxtiles) {
final long numTilesAtPrecision = Math.min(1L << (2 * (finalPrecision - currentPrecision)), maxtiles);
if (numTilesAtPrecision > Integer.MAX_VALUE) {
throw new IllegalArgumentException("Tile aggregation array overflow");
}
return (int) numTilesAtPrecision;
}

protected long getMaxTilesAtPrecision(int finalPrecision) {
return Long.MAX_VALUE;
}

protected int setValuesForFullyContainedTile(int xTile, int yTile, int zTile, GeoShapeCellValues values, int valuesIndex,
int targetPrecision) {
zTile++;
Expand All @@ -154,4 +176,18 @@ protected int setValuesForFullyContainedTile(int xTile, int yTile, int zTile, Ge
}
return valuesIndex;
}

/**
* Return the number of tiles contained in the provided bounding box at the given zoom level
*/
protected static long numTilesFromPrecision(int zoom, double minX, double maxX, double minY, double maxY) {
final long tiles = 1L << zoom;
final double xDeltaPrecision = 360.0 / (10 * tiles);
final double yHalfPrecision = 180.0 / (10 * tiles);
final int minXTile = GeoTileUtils.getXTile(Math.max(-180, minX - xDeltaPrecision), tiles);
final int minYTile = GeoTileUtils.getYTile(maxY + yHalfPrecision, tiles);
final int maxXTile = GeoTileUtils.getXTile(Math.min(180, maxX + xDeltaPrecision), tiles);
final int maxYTile = GeoTileUtils.getYTile(minY - yHalfPrecision, tiles);
return (long) (maxXTile - minXTile + 1) * (maxYTile - minYTile + 1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.elasticsearch.common.breaker.CircuitBreaker;
import org.elasticsearch.common.breaker.CircuitBreakingException;
import org.elasticsearch.common.geo.GeoBoundingBox;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.geo.GeoUtils;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Settings;
Expand Down Expand Up @@ -214,6 +215,39 @@ public void testGeoHash() throws Exception {
}
}

public void testGeoTileShapeContainsBound() throws Exception {
Rectangle tile = GeoTileUtils.toBoundingBox(44140, 44140, 16);
Rectangle shapeRectangle = new Rectangle(tile.getMinX() - 15, tile.getMaxX() + 15,
tile.getMaxY() + 15, tile.getMinY() - 15);
GeoShapeValues.GeoShapeValue value = geoShapeValue(shapeRectangle);

GeoBoundingBox boundingBox = new GeoBoundingBox(
new GeoPoint(tile.getMaxLat(), tile.getMinLon()),
new GeoPoint(tile.getMinLat(), tile.getMaxLon())
);
GeoShapeCellValues values = new GeoShapeCellValues(null, 24, GEOTILE, NOOP_BREAKER);
int numTiles = new BoundedGeoTileGridTiler(boundingBox).setValues(values, value, 24);
int expectedTiles =
(int) GeoTileGridTiler.numTilesFromPrecision(24, tile.getMinX(), tile.getMaxX(), tile.getMinY(), tile.getMaxY());
assertThat(expectedTiles, equalTo(numTiles));
}

public void testGeoTileShapeContainsBoundDateLine() throws Exception {
Rectangle tile = new Rectangle(178, -178, 2, -2);
Rectangle shapeRectangle = new Rectangle(170, -170, 10, -10);
GeoShapeValues.GeoShapeValue value = geoShapeValue(shapeRectangle);

GeoBoundingBox boundingBox = new GeoBoundingBox(
new GeoPoint(tile.getMaxLat(), tile.getMinLon()),
new GeoPoint(tile.getMinLat(), tile.getMaxLon())
);
GeoShapeCellValues values = new GeoShapeCellValues(null, 13, GEOTILE, NOOP_BREAKER);
int numTiles = new BoundedGeoTileGridTiler(boundingBox).setValues(values, value, 13);
int expectedTiles = (int) (GeoTileGridTiler.numTilesFromPrecision(13, 178, 180, -2, 2)
+ GeoTileGridTiler.numTilesFromPrecision(13, -180, -178, -2, 2));
assertThat(expectedTiles, equalTo(numTiles));
}

private boolean tileIntersectsBounds(int x, int y, int precision, GeoBoundingBox bounds) {
if (bounds == null) {
return true;
Expand Down Expand Up @@ -316,7 +350,7 @@ private void checkGeoTileSetValuesBruteAndRecursive(Geometry geometry) throws Ex
GeoShapeCellValues recursiveValues = new GeoShapeCellValues(null, precision, GEOTILE, NOOP_BREAKER);
int recursiveCount;
{
recursiveCount = GEOTILE.setValuesByRasterization(0, 0, 0, recursiveValues, 0, precision, value);
recursiveCount = GEOTILE.setValuesByRasterization(0, 0, 0, recursiveValues, 0, precision, value, Long.MAX_VALUE);
}
GeoShapeCellValues bruteForceValues = new GeoShapeCellValues(null, precision, GEOTILE, NOOP_BREAKER);
int bruteForceCount;
Expand Down