use of io.prestosql.geospatial.Rectangle in project hetu-core by openlookeng.
the class TestSpatialPartitioningInternalAggregation method getSpatialPartitioning.
private String getSpatialPartitioning(Rectangle extent, List<OGCGeometry> geometries, int partitionCount) {
ImmutableList.Builder<Rectangle> rectangles = ImmutableList.builder();
for (OGCGeometry geometry : geometries) {
Envelope envelope = new Envelope();
geometry.getEsriGeometry().queryEnvelope(envelope);
rectangles.add(new Rectangle(envelope.getXMin(), envelope.getYMin(), envelope.getXMax(), envelope.getYMax()));
}
return KdbTreeUtils.toJson(buildKdbTree(roundToInt(geometries.size() * 1.0 / partitionCount, CEILING), extent, rectangles.build()));
}
use of io.prestosql.geospatial.Rectangle in project hetu-core by openlookeng.
the class GeoFunctions method spatialPartitions.
private static Block spatialPartitions(KdbTree kdbTree, Rectangle envelope) {
Map<Integer, Rectangle> partitions = kdbTree.findIntersectingLeaves(envelope);
if (partitions.isEmpty()) {
return EMPTY_ARRAY_OF_INTS;
}
// For input rectangles that represent a single point, return at most one partition
// by excluding right and upper sides of partition rectangles. The logic that builds
// KDB tree needs to make sure to add some padding to the right and upper sides of the
// overall extent of the tree to avoid missing right-most and top-most points.
boolean point = (envelope.getWidth() == 0 && envelope.getHeight() == 0);
if (point) {
for (Map.Entry<Integer, Rectangle> partition : partitions.entrySet()) {
if (envelope.getXMin() < partition.getValue().getXMax() && envelope.getYMin() < partition.getValue().getYMax()) {
BlockBuilder blockBuilder = IntegerType.INTEGER.createFixedSizeBlockBuilder(1);
blockBuilder.writeInt(partition.getKey());
return blockBuilder.build();
}
}
throw new VerifyException(format("Cannot find half-open partition extent for a point: (%s, %s)", envelope.getXMin(), envelope.getYMin()));
}
BlockBuilder blockBuilder = IntegerType.INTEGER.createFixedSizeBlockBuilder(partitions.size());
for (int id : partitions.keySet()) {
blockBuilder.writeInt(id);
}
return blockBuilder.build();
}
use of io.prestosql.geospatial.Rectangle in project hetu-core by openlookeng.
the class GeoFunctions method spatialPartitions.
@ScalarFunction
@SqlNullable
@Description("Returns an array of spatial partition IDs for a geometry representing a set of points within specified distance from the input geometry")
@SqlType("array(integer)")
public static Block spatialPartitions(@SqlType(KdbTreeType.NAME) Object kdbTree, @SqlType(GEOMETRY_TYPE_NAME) Slice geometry, @SqlType(DOUBLE) double distance) {
if (isNaN(distance)) {
throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "distance is NaN");
}
if (isInfinite(distance)) {
throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "distance is infinite");
}
if (distance < 0) {
throw new PrestoException(INVALID_FUNCTION_ARGUMENT, "distance is negative");
}
Envelope envelope = deserializeEnvelope(geometry);
if (envelope == null) {
return null;
}
Rectangle expandedEnvelope2D = new Rectangle(envelope.getXMin() - distance, envelope.getYMin() - distance, envelope.getXMax() + distance, envelope.getYMax() + distance);
return spatialPartitions((KdbTree) kdbTree, expandedEnvelope2D);
}
use of io.prestosql.geospatial.Rectangle in project hetu-core by openlookeng.
the class TestSpatialPartitioningInternalAggregation method test.
@Test(dataProvider = "partitionCount")
public void test(int partitionCount) {
InternalAggregationFunction function = getFunction();
List<OGCGeometry> geometries = makeGeometries();
Block geometryBlock = makeGeometryBlock(geometries);
Block partitionCountBlock = BlockAssertions.createRLEBlock(partitionCount, geometries.size());
Rectangle expectedExtent = new Rectangle(-10, -10, Math.nextUp(10.0), Math.nextUp(10.0));
String expectedValue = getSpatialPartitioning(expectedExtent, geometries, partitionCount);
AccumulatorFactory accumulatorFactory = function.bind(Ints.asList(0, 1, 2), Optional.empty());
Page page = new Page(geometryBlock, partitionCountBlock);
Accumulator accumulator = accumulatorFactory.createAccumulator();
accumulator.addInput(page);
String aggregation = (String) BlockAssertions.getOnlyValue(accumulator.getFinalType(), getFinalBlock(accumulator));
assertEquals(aggregation, expectedValue);
GroupedAccumulator groupedAggregation = accumulatorFactory.createGroupedAccumulator();
groupedAggregation.addInput(createGroupByIdBlock(0, page.getPositionCount()), page);
String groupValue = (String) getGroupValue(groupedAggregation, 0);
assertEquals(groupValue, expectedValue);
}
use of io.prestosql.geospatial.Rectangle in project hetu-core by openlookeng.
the class SpatialPartitioningInternalAggregateFunction method output.
@OutputFunction(StandardTypes.VARCHAR)
public static void output(SpatialPartitioningState state, BlockBuilder out) {
if (state.getCount() == 0) {
out.appendNull();
return;
}
List<Rectangle> samples = state.getSamples();
int partitionCount = state.getPartitionCount();
int maxItemsPerNode = (samples.size() + partitionCount - 1) / partitionCount;
Rectangle envelope = state.getExtent();
// Add a small buffer on the right and upper sides
Rectangle paddedExtent = new Rectangle(envelope.getXMin(), envelope.getYMin(), Math.nextUp(envelope.getXMax()), Math.nextUp(envelope.getYMax()));
VARCHAR.writeString(out, KdbTreeUtils.toJson(buildKdbTree(maxItemsPerNode, paddedExtent, samples)));
}
Aggregations