Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade h3 v4.2.0 #163

Merged
merged 5 commits into from
Dec 12, 2024
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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![Coverage Status](https://coveralls.io/repos/github/uber/h3-java/badge.svg?branch=master)](https://coveralls.io/github/uber/h3-java?branch=master)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.uber/h3/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.uber/h3)
[![H3 Version](https://img.shields.io/badge/h3-v4.1.0-blue.svg)](https://github.com/uber/h3/releases/tag/v4.1.0)
[![H3 Version](https://img.shields.io/badge/h3-v4.2.0-blue.svg)](https://github.com/uber/h3/releases/tag/v4.2.0)

This library provides Java bindings for the [H3 Core Library](https://github.com/uber/h3). For API reference, please see the [H3 Documentation](https://h3geo.org/).

Expand All @@ -18,14 +18,14 @@ Add it to your pom.xml:
<dependency>
<groupId>com.uber</groupId>
<artifactId>h3</artifactId>
<version>4.1.2</version>
<version>4.2.0</version>
</dependency>
```

Or, using Gradle:

```gradle
compile("com.uber:h3:4.1.2")
compile("com.uber:h3:4.2.0")
```

Encode a location into a hexagon address:
Expand Down
2 changes: 1 addition & 1 deletion h3version.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
h3.git.reference=v4.1.0
h3.git.reference=v4.2.0
2 changes: 2 additions & 0 deletions src/main/c/h3-java/build-h3-docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ BUILD_ROOT=$1
UPGRADE_CMAKE=$2
CMAKE_ROOT=$3

# TODO: This may no longer be necessary
if $UPGRADE_CMAKE; then
pushd "$CMAKE_ROOT"
if ! [ -e cmake-3.23.2-linux-x86_64.sh ]; then
Expand All @@ -51,6 +52,7 @@ mkdir -p build
pushd build

cmake -DBUILD_SHARED_LIBS=OFF \
-DENABLE_WARNINGS=OFF \
-DCMAKE_C_STANDARD_REQUIRED=ON \
-DCMAKE_C_STANDARD=99 \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
Expand Down
2 changes: 1 addition & 1 deletion src/main/c/h3-java/build-h3.sh
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ CMAKE_ROOT=target/cmake-3.23.2-linux-x86_64
mkdir -p $CMAKE_ROOT

DOCKCROSS_IMAGES="android-arm android-arm64 linux-arm64 linux-armv5 linux-armv7 linux-s390x linux-ppc64le linux-x64 linux-x86 windows-static-x64 windows-static-x86"
if ! $DOCKCROSS_ONLY; then
if ! [ -z $DOCKCROSS_ONLY ]; then
DOCKCROSS_IMAGES=$DOCKCROSS_ONLY
echo Building only: $DOCKCROSS_IMAGES
fi
Expand Down
62 changes: 61 additions & 1 deletion src/main/c/h3-java/src/jniapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,32 @@ Java_com_uber_h3core_NativeMethods_maxPolygonToCellsSize(
return numHexagons;
}

/*
* Class: com_uber_h3core_NativeMethods
* Method: maxPolygonToCellsSizeExperimental
* Signature: ([D[I[DII)J
*/
JNIEXPORT jlong JNICALL
Java_com_uber_h3core_NativeMethods_maxPolygonToCellsSizeExperimental(
JNIEnv *env, jobject thiz, jdoubleArray verts, jintArray holeSizes,
jdoubleArray holeVerts, jint res, jint flags) {
GeoPolygon polygon;
if (CreateGeoPolygon(env, verts, holeSizes, holeVerts, &polygon)) {
return -1;
}

jlong numHexagons;
H3Error err =
maxPolygonToCellsSizeExperimental(&polygon, res, flags, &numHexagons);

DestroyGeoPolygon(env, verts, holeSizes, holeVerts, &polygon);

if (err) {
ThrowH3Exception(env, err);
}
return numHexagons;
}

/*
* Class: com_uber_h3core_NativeMethods
* Method: getRes0Cells
Expand Down Expand Up @@ -657,6 +683,40 @@ JNIEXPORT void JNICALL Java_com_uber_h3core_NativeMethods_polygonToCells(
}
}

/*
* Class: com_uber_h3core_NativeMethods
* Method: polygonToCellsExperimental
* Signature: ([D[I[DII[J)V
*/
JNIEXPORT void JNICALL
Java_com_uber_h3core_NativeMethods_polygonToCellsExperimental(
JNIEnv *env, jobject thiz, jdoubleArray verts, jintArray holeSizes,
jdoubleArray holeVerts, jint res, jint flags, jlongArray results) {
GeoPolygon polygon;
if (CreateGeoPolygon(env, verts, holeSizes, holeVerts, &polygon)) {
return;
}

jlong *resultsElements = (**env).GetLongArrayElements(env, results, 0);
jsize resultsSize = (**env).GetArrayLength(env, results);

H3Error err;
if (resultsElements != NULL) {
err = polygonToCellsExperimental(&polygon, res, flags, resultsSize,
resultsElements);

(**env).ReleaseLongArrayElements(env, results, resultsElements, 0);
} else {
ThrowOutOfMemoryError(env);
}

DestroyGeoPolygon(env, verts, holeSizes, holeVerts, &polygon);

if (err) {
ThrowH3Exception(env, err);
}
}

/**
* Converts the given polygon to managed objects
* (ArrayList<ArrayList<ArrayList<LatLng>>>)
Expand Down Expand Up @@ -1337,7 +1397,7 @@ JNIEXPORT jlong JNICALL Java_com_uber_h3core_NativeMethods_cellToVertex(
JNIEXPORT void JNICALL Java_com_uber_h3core_NativeMethods_cellToVertexes(
JNIEnv *env, jobject thiz, jlong h3, jlongArray vertexes) {
jsize sz = (**env).GetArrayLength(env, vertexes);
jint *vertexesElements = (**env).GetLongArrayElements(env, vertexes, 0);
jlong *vertexesElements = (**env).GetLongArrayElements(env, vertexes, 0);

if (vertexesElements != NULL && sz >= 6) {
H3Error err = cellToVertexes(h3, vertexesElements);
Expand Down
70 changes: 64 additions & 6 deletions src/main/java/com/uber/h3core/H3Core.java
Original file line number Diff line number Diff line change
Expand Up @@ -518,10 +518,68 @@ public List<Long> gridPathCells(long start, long end) {
}

/**
* Finds indexes within the given geofence.
* Finds indexes within the given geopolygon.
*
* @param points Outline geofence
* @param holes Geofences of any internal holes
* @param points Outline geopolygon
* @param holes Geopolygons of any internal holes
* @param res Resolution of the desired indexes
*/
public List<String> polygonToCellAddressesExperimental(
List<LatLng> points, List<List<LatLng>> holes, PolygonToCellsFlags flags, int res) {
return h3ToStringList(polygonToCellsExperimental(points, holes, flags, res));
}

/**
* Finds indexes within the given geopolygon.
*
* @param points Outline geopolygon
* @param holes Geopolygon of any internal holes
* @param res Resolution of the desired indexes
* @throws IllegalArgumentException Invalid resolution
*/
public List<Long> polygonToCellsExperimental(
List<LatLng> points, List<List<LatLng>> holes, PolygonToCellsFlags flags, int res) {
checkResolution(res);

// pack the data for use by the polyfill JNI call
double[] verts = new double[points.size() * 2];
packGeofenceVertices(verts, points, 0);
int[] holeSizes = new int[0];
double[] holeVerts = new double[0];
if (holes != null) {
int holesSize = holes.size();
holeSizes = new int[holesSize];
int totalSize = 0;
for (int i = 0; i < holesSize; i++) {
int holeSize = holes.get(i).size() * 2;
totalSize += holeSize;
// Note we are storing the number of doubles
holeSizes[i] = holeSize;
}
holeVerts = new double[totalSize];
int offset = 0;
for (int i = 0; i < holesSize; i++) {
offset = packGeofenceVertices(holeVerts, holes.get(i), offset);
}
}

int flagsInt = flags.toInt();
int sz =
longToIntSize(
h3Api.maxPolygonToCellsSizeExperimental(verts, holeSizes, holeVerts, res, flagsInt));

long[] results = new long[sz];

h3Api.polygonToCellsExperimental(verts, holeSizes, holeVerts, res, flagsInt, results);

return nonZeroLongArrayToList(results);
}

/**
* Finds indexes within the given geopolygon.
*
* @param points Outline geopolygon
* @param holes Geopolygons of any internal holes
* @param res Resolution of the desired indexes
*/
public List<String> polygonToCellAddresses(
Expand All @@ -530,10 +588,10 @@ public List<String> polygonToCellAddresses(
}

/**
* Finds indexes within the given geofence.
* Finds indexes within the given geopolygon.
*
* @param points Outline geofence
* @param holes Geofences of any internal holes
* @param points Outline geopolygon
* @param holes Geopolygon of any internal holes
* @param res Resolution of the desired indexes
* @throws IllegalArgumentException Invalid resolution
*/
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/com/uber/h3core/NativeMethods.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ final class NativeMethods {

native void gridPathCells(long start, long end, long[] results);

native long maxPolygonToCellsSizeExperimental(
double[] verts, int[] holeSizes, double[] holeVerts, int res, int flags);

native void polygonToCellsExperimental(
double[] verts, int[] holeSizes, double[] holeVerts, int res, int flags, long[] results);

native long maxPolygonToCellsSize(
double[] verts, int[] holeSizes, double[] holeVerts, int res, int flags);

Expand Down
38 changes: 38 additions & 0 deletions src/main/java/com/uber/h3core/PolygonToCellsFlags.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2024 Uber Technologies, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.uber.h3core;

/** Flags for polygonToCellsExperimental */
public enum PolygonToCellsFlags {
/** Cell center is contained in the shape */
containment_center(0),
/** Cell is fully contained in the shape */
containment_full(1),
/** Cell overlaps the shape at any point */
containment_overlapping(2),
/** Cell bounding box overlaps shape */
containment_overlapping_bbox(3);

private final int value;

PolygonToCellsFlags(int value) {
this.value = value;
}

public int toInt() {
return this.value;
}
}
5 changes: 4 additions & 1 deletion src/test/java/com/uber/h3core/TestBindingCompleteness.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ class TestBindingCompleteness {
private static final Set<String> WHITELIST =
ImmutableSet.of(
// These are provided by the Java library (java.lang.Math)
"degsToRads", "radsToDegs");
"degsToRads",
"radsToDegs",
// Handled by H3Exception
"describeH3Error");

@Test
@DisabledInNativeImage
Expand Down
90 changes: 90 additions & 0 deletions src/test/java/com/uber/h3core/TestRegion.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,96 @@

/** Tests for region (polyfill, h3SetToMultiPolygon) functions. */
class TestRegion extends BaseTestH3Core {
@Test
void polyfillExperimentalCenter() {
List<Long> hexagons =
h3.polygonToCellsExperimental(
ImmutableList.of(
new LatLng(37.813318999983238, -122.4089866999972145),
new LatLng(37.7866302000007224, -122.3805436999997056),
new LatLng(37.7198061999978478, -122.3544736999993603),
new LatLng(37.7076131999975672, -122.5123436999983966),
new LatLng(37.7835871999971715, -122.5247187000021967),
new LatLng(37.8151571999998453, -122.4798767000009008)),
null,
PolygonToCellsFlags.containment_center,
9);

assertTrue(hexagons.size() > 1000);
}

@Test
void polyfillExperimentalFull() {
List<Long> hexagons =
h3.polygonToCellsExperimental(
ImmutableList.of(
new LatLng(37.813318999983238, -122.4089866999972145),
new LatLng(37.7866302000007224, -122.3805436999997056),
new LatLng(37.7198061999978478, -122.3544736999993603),
new LatLng(37.7076131999975672, -122.5123436999983966),
new LatLng(37.7835871999971715, -122.5247187000021967),
new LatLng(37.8151571999998453, -122.4798767000009008)),
null,
PolygonToCellsFlags.containment_full,
9);

assertTrue(hexagons.size() > 1000);
}

@Test
void polyfillExperimentalOverlapping() {
List<Long> hexagons =
h3.polygonToCellsExperimental(
ImmutableList.of(
new LatLng(37.813318999983238, -122.4089866999972145),
new LatLng(37.7866302000007224, -122.3805436999997056),
new LatLng(37.7198061999978478, -122.3544736999993603),
new LatLng(37.7076131999975672, -122.5123436999983966),
new LatLng(37.7835871999971715, -122.5247187000021967),
new LatLng(37.8151571999998453, -122.4798767000009008)),
null,
PolygonToCellsFlags.containment_overlapping,
9);

assertTrue(hexagons.size() > 1000);
}

@Test
void polyfillExperimentalOverlappingBbox() {
List<Long> hexagons =
h3.polygonToCellsExperimental(
ImmutableList.of(
new LatLng(37.813318999983238, -122.4089866999972145),
new LatLng(37.7866302000007224, -122.3805436999997056),
new LatLng(37.7198061999978478, -122.3544736999993603),
new LatLng(37.7076131999975672, -122.5123436999983966),
new LatLng(37.7835871999971715, -122.5247187000021967),
new LatLng(37.8151571999998453, -122.4798767000009008)),
null,
PolygonToCellsFlags.containment_overlapping_bbox,
9);

assertTrue(hexagons.size() > 1000);
}

@Test
void polyfillExperimental() {
List<Long> hexagons =
h3.polygonToCellsExperimental(
ImmutableList.of(
new LatLng(37.813318999983238, -122.4089866999972145),
new LatLng(37.7866302000007224, -122.3805436999997056),
new LatLng(37.7198061999978478, -122.3544736999993603),
new LatLng(37.7076131999975672, -122.5123436999983966),
new LatLng(37.7835871999971715, -122.5247187000021967),
new LatLng(37.8151571999998453, -122.4798767000009008)),
null,
PolygonToCellsFlags.containment_center,
9);

assertTrue(hexagons.size() > 1000);
}

@Test
void polyfill() {
List<Long> hexagons =
Expand Down
Loading