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 @@ -187,7 +187,7 @@ public static byte[] toGeometry(byte[] bytes) {
*/
@ScalarFunction
public static long geoToH3(double longitude, double latitude, int resolution) {
return H3Utils.H3_CORE.geoToH3(latitude, longitude, resolution);
return H3Utils.H3_CORE.latLngToCell(latitude, longitude, resolution);
}

/**
Expand All @@ -201,7 +201,7 @@ public static long geoToH3(byte[] geoBytes, int resolution) {
Geometry geometry = GeometrySerializer.deserialize(geoBytes);
double latitude = geometry.getCoordinate().y;
double longitude = geometry.getCoordinate().x;
return H3Utils.H3_CORE.geoToH3(latitude, longitude, resolution);
return H3Utils.H3_CORE.latLngToCell(latitude, longitude, resolution);
}

@ScalarFunction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ public H3IndexFilterOperator(IndexSegment segment, QueryContext queryContext, Pr
}
assert _h3IndexReader != null;
int resolution = _h3IndexReader.getH3IndexResolution().getLowestResolution();
_h3Id = H3Utils.H3_CORE.geoToH3(coordinate.y, coordinate.x, resolution);
_edgeLength = H3Utils.H3_CORE.edgeLength(resolution, LengthUnit.m);
_h3Id = H3Utils.H3_CORE.latLngToCell(coordinate.y, coordinate.x, resolution);
_edgeLength = H3Utils.H3_CORE.getHexagonEdgeLengthAvg(resolution, LengthUnit.m);

RangePredicate rangePredicate = (RangePredicate) predicate;
if (!rangePredicate.getLowerBound().equals(RangePredicate.UNBOUNDED)) {
Expand Down Expand Up @@ -223,7 +223,7 @@ private List<Long> getPossibleMatchH3Ids(double distance) {
*/
private List<Long> getH3Ids(int numRings) {
Preconditions.checkState(numRings <= 100, "Expect numRings <= 100, got: %s", numRings);
return H3Utils.H3_CORE.kRing(_h3Id, numRings);
return H3Utils.H3_CORE.gridDisk(_h3Id, numRings);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public void add(Geometry geometry) {
geometry.getGeometryType());
Coordinate coordinate = geometry.getCoordinate();
// TODO: support multiple resolutions
long h3Id = H3Utils.H3_CORE.geoToH3(coordinate.y, coordinate.x, _lowestResolution);
long h3Id = H3Utils.H3_CORE.latLngToCell(coordinate.y, coordinate.x, _lowestResolution);
_bitmaps.computeIfAbsent(h3Id, k -> new ThreadSafeMutableRoaringBitmap()).add(_nextDocId);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public void add(Geometry geometry)
geometry.getGeometryType());
Coordinate coordinate = geometry.getCoordinate();
// TODO: support multiple resolutions
long h3Id = H3Utils.H3_CORE.geoToH3(coordinate.y, coordinate.x, _lowestResolution);
long h3Id = H3Utils.H3_CORE.latLngToCell(coordinate.y, coordinate.x, _lowestResolution);
RoaringBitmapWriter<RoaringBitmap> bitmapWriter = _postingListMap.get(h3Id);
if (bitmapWriter == null) {
bitmapWriter = _bitmapWriterWizard.get();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,14 @@
*/
package org.apache.pinot.segment.local.utils;

import com.uber.h3core.H3CoreV3;
import com.uber.h3core.H3Core;
import com.uber.h3core.util.LatLng;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import it.unimi.dsi.fastutil.longs.LongSets;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
Expand All @@ -41,11 +39,11 @@ public class H3Utils {
private H3Utils() {
}

public static final H3CoreV3 H3_CORE;
public static final H3Core H3_CORE;

static {
try {
H3_CORE = H3CoreV3.newInstance();
H3_CORE = H3Core.newInstance();
} catch (IOException e) {
throw new RuntimeException("Failed to instantiate H3 V3 instance", e);
}
Expand All @@ -60,14 +58,14 @@ private static LongSet coverLineInH3(LineString lineString, int resolution) {
if (numEndPoints == 0) {
return LongSets.EMPTY_SET;
}
long previousCell = H3_CORE.geoToH3(endPoints[0].y, endPoints[0].x, resolution);
long previousCell = H3_CORE.latLngToCell(endPoints[0].y, endPoints[0].x, resolution);
if (numEndPoints == 1) {
return LongSets.singleton(previousCell);
}
LongSet coveringCells = new LongOpenHashSet();
for (int i = 1; i < numEndPoints; i++) {
long currentCell = H3_CORE.geoToH3(endPoints[i].y, endPoints[i].x, resolution);
coveringCells.addAll(H3_CORE.h3Line(previousCell, currentCell));
long currentCell = H3_CORE.latLngToCell(endPoints[i].y, endPoints[i].x, resolution);
coveringCells.addAll(H3_CORE.gridPathCells(previousCell, currentCell));
previousCell = currentCell;
}
return coveringCells;
Expand All @@ -79,17 +77,20 @@ private static LongSet coverLineInH3(LineString lineString, int resolution) {
private static Pair<LongSet, LongSet> coverPolygonInH3(Polygon polygon, int resolution) {
// TODO: this can be further optimized to use native H3 implementation. They have plan to support natively.
// https://github.com/apache/pinot/issues/8547
List<Long> polyfillCells = H3_CORE.polyfill(Arrays.stream(polygon.getExteriorRing().getCoordinates())
.map(coordinate -> new LatLng(coordinate.y, coordinate.x)).collect(Collectors.toList()),
Collections.emptyList(), resolution);
Coordinate[] coordinates = polygon.getExteriorRing().getCoordinates();
List<LatLng> points = new ArrayList<>(coordinates.length);
for (Coordinate coordinate : coordinates) {
points.add(new LatLng(coordinate.y, coordinate.x));
}
List<Long> polyfillCells = H3_CORE.polygonToCells(points, List.of(), resolution);
if (polyfillCells.isEmpty()) {
// If the polyfill cells are empty, meaning the polygon might be smaller than a single cell in the H3 system.
// So just get whatever one. here choose the first one. the follow up kRing(firstCell, 1) will cover the whole
// polygon if there is potential not covered by the first point's belonging cell.
// ref: https://github.com/uber/h3/issues/456#issuecomment-827760163
Coordinate represent = polygon.getCoordinate();
return Pair.of(LongSets.EMPTY_SET,
new LongOpenHashSet(H3_CORE.kRing(H3_CORE.geoToH3(represent.y, represent.x, resolution), 1)));
new LongOpenHashSet(H3_CORE.gridDisk(H3_CORE.latLngToCell(represent.y, represent.x, resolution), 1)));
}

LongSet fullyCoveredCells = new LongOpenHashSet();
Expand All @@ -98,17 +99,22 @@ private static Pair<LongSet, LongSet> coverPolygonInH3(Polygon polygon, int reso
if (polygon.contains(createPolygonFromH3Cell(cell))) {
fullyCoveredCells.add(cell);
}
potentiallyCoveredCells.addAll(H3_CORE.kRing(cell, 1));
potentiallyCoveredCells.addAll(H3_CORE.gridDisk(cell, 1));
}
potentiallyCoveredCells.removeAll(fullyCoveredCells);
return Pair.of(fullyCoveredCells, potentiallyCoveredCells);
}

private static Polygon createPolygonFromH3Cell(long h3Cell) {
List<LatLng> boundary = H3_CORE.h3ToGeoBoundary(h3Cell);
boundary.add(boundary.get(0));
return GeometryUtils.GEOMETRY_FACTORY.createPolygon(
boundary.stream().map(geoCoord -> new Coordinate(geoCoord.lng, geoCoord.lat)).toArray(Coordinate[]::new));
List<LatLng> boundary = H3_CORE.cellToBoundary(h3Cell);
int numVertices = boundary.size();
Coordinate[] coordinates = new Coordinate[numVertices + 1];
for (int i = 0; i < numVertices; i++) {
LatLng vertex = boundary.get(i);
coordinates[i] = new Coordinate(vertex.lng, vertex.lat);
}
coordinates[numVertices] = coordinates[0];
return GeometryUtils.GEOMETRY_FACTORY.createPolygon(coordinates);
}

/**
Expand All @@ -117,7 +123,7 @@ private static Polygon createPolygonFromH3Cell(long h3Cell) {
public static Pair<LongSet, LongSet> coverGeometryInH3(Geometry geometry, int resolution) {
if (geometry instanceof Point) {
return Pair.of(LongSets.EMPTY_SET,
LongSets.singleton(H3_CORE.geoToH3(geometry.getCoordinate().y, geometry.getCoordinate().x, resolution)));
LongSets.singleton(H3_CORE.latLngToCell(geometry.getCoordinate().y, geometry.getCoordinate().x, resolution)));
} else if (geometry instanceof LineString) {
return Pair.of(LongSets.EMPTY_SET, coverLineInH3(((LineString) geometry), resolution));
} else if (geometry instanceof Polygon) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public void testH3Index()
onHeapCreator.add(point);
offHeapCreator.add(point);
mutableH3Index.add(GeometrySerializer.serialize(point), -1, docId++);
long h3Id = H3Utils.H3_CORE.geoToH3(latitude, longitude, resolution);
long h3Id = H3Utils.H3_CORE.latLngToCell(latitude, longitude, resolution);
expectedCardinalities.merge(h3Id, 1, Integer::sum);
}
onHeapCreator.seal();
Expand Down
Loading