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 @@ -25,6 +25,7 @@
import com.facebook.presto.spi.function.SqlType;
import com.facebook.presto.spi.type.RowType;
import com.facebook.presto.spi.type.StandardTypes;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import io.airlift.slice.Slice;

Expand Down Expand Up @@ -63,9 +64,12 @@
public class BingTileFunctions
{
private static final int TILE_PIXELS = 256;
private static final double MAX_LATITUDE = 85.05112878;

@VisibleForTesting
static final double MAX_LATITUDE = 85.05112878;
private static final double MIN_LATITUDE = -85.05112878;
private static final double MIN_LONGITUDE = -180;
@VisibleForTesting
static final double MIN_LONGITUDE = -180;
private static final double MAX_LONGITUDE = 180;
private static final double EARTH_RADIUS_KM = 6371.01;
private static final int OPTIMIZED_TILING_MIN_ZOOM_LEVEL = 10;
Expand Down Expand Up @@ -366,7 +370,22 @@ public static Block geometryToBingTiles(@SqlType(GEOMETRY_TYPE_NAME) Slice input
boolean pointOrRectangle = isPointOrRectangle(ogcGeometry, envelope);

BingTile leftUpperTile = latitudeLongitudeToTile(envelope.getYMax(), envelope.getXMin(), zoomLevel);
BingTile rightLowerTile = getTileCoveringLowerRightCorner(envelope, zoomLevel);
BingTile rightLowerTile = latitudeLongitudeToTile(envelope.getYMin(), envelope.getXMax(), zoomLevel);

// If the tile covering the lower right corner of the envelope overlaps the envelope only
// at the border then return a tile shifted to the left and/or top
int deltaX = 0;
int deltaY = 0;
Point upperLeftCorner = tileXYToLatitudeLongitude(rightLowerTile.getX(), rightLowerTile.getY(), rightLowerTile.getZoomLevel());
if (rightLowerTile.getX() > leftUpperTile.getX() && upperLeftCorner.getX() == envelope.getXMax()) {
deltaX = -1;
}
if (rightLowerTile.getY() > leftUpperTile.getY() && upperLeftCorner.getY() == envelope.getYMin()) {
deltaY = -1;
}
if (deltaX != 0 || deltaY != 0) {
rightLowerTile = BingTile.fromCoordinates(rightLowerTile.getX() + deltaX, rightLowerTile.getY() + deltaY, rightLowerTile.getZoomLevel());
}

// XY coordinates start at (0,0) in the left upper corner and increase left to right and top to bottom
long tileCount = (long) (rightLowerTile.getX() - leftUpperTile.getX() + 1) * (rightLowerTile.getY() - leftUpperTile.getY() + 1);
Expand Down Expand Up @@ -404,29 +423,6 @@ public static Block geometryToBingTiles(@SqlType(GEOMETRY_TYPE_NAME) Slice input
return blockBuilder.build();
}

private static BingTile getTileCoveringLowerRightCorner(Envelope envelope, int zoomLevel)
{
BingTile tile = latitudeLongitudeToTile(envelope.getYMin(), envelope.getXMax(), zoomLevel);

// If the tile covering the lower right corner of the envelope overlaps the envelope only
// at the border then return a tile shifted to the left and/or top
int deltaX = 0;
int deltaY = 0;
Point upperLeftCorner = tileXYToLatitudeLongitude(tile.getX(), tile.getY(), tile.getZoomLevel());
if (upperLeftCorner.getX() == envelope.getXMax()) {
deltaX = -1;
}
if (upperLeftCorner.getY() == envelope.getYMin()) {
deltaY = -1;
}

if (deltaX != 0 || deltaY != 0) {
return BingTile.fromCoordinates(tile.getX() + deltaX, tile.getY() + deltaY, tile.getZoomLevel());
}

return tile;
}

private static void checkGeometryToBingTilesLimits(OGCGeometry ogcGeometry, Envelope envelope, boolean pointOrRectangle, long tileCount, int zoomLevel)
{
if (pointOrRectangle) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
import static com.facebook.presto.operator.aggregation.AggregationTestUtils.assertAggregation;
import static com.facebook.presto.operator.scalar.ApplyFunction.APPLY_FUNCTION;
import static com.facebook.presto.plugin.geospatial.BingTile.fromCoordinates;
import static com.facebook.presto.plugin.geospatial.BingTileFunctions.MAX_LATITUDE;
import static com.facebook.presto.plugin.geospatial.BingTileFunctions.MIN_LONGITUDE;
import static com.facebook.presto.plugin.geospatial.BingTileType.BING_TILE;
import static com.facebook.presto.spi.type.BigintType.BIGINT;
import static com.facebook.presto.spi.type.BooleanType.BOOLEAN;
Expand Down Expand Up @@ -458,6 +460,12 @@ public void testGeometryToBingTiles()
assertGeometryToBingTiles("POLYGON EMPTY", 10, emptyList());
assertGeometryToBingTiles("GEOMETRYCOLLECTION EMPTY", 10, emptyList());

// Geometries at MIN_LONGITUDE/MAX_LATITUDE
assertGeometryToBingTiles("LINESTRING (-180 -79.19245, -180 -79.17133464081945)", 8, ImmutableList.of("22200000"));
assertGeometryToBingTiles(format("POINT (%s 0)", MIN_LONGITUDE), 5, ImmutableList.of("20000"));
assertGeometryToBingTiles(format("POINT (0 %s)", MAX_LATITUDE), 5, ImmutableList.of("10000"));
assertGeometryToBingTiles(format("POINT (%s %s)", MIN_LONGITUDE, MAX_LATITUDE), 5, ImmutableList.of("00000"));

// Invalid input
// Longitude out of range
assertInvalidFunction("geometry_to_bing_tiles(ST_Point(600, 30.12), 10)", "Longitude span for the geometry must be in [-180.00, 180.00] range");
Expand Down