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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,14 @@ file [H3Core.java](./src/main/java/com/uber/h3core/H3Core.java), and support
for the Linux x64 and Darwin x64 platforms.

## Unreleased Changes

## [4.4.0] - 2025-12-12
### Added
- `constructCell`, `isValidIndex`, and `getIndexDigit` functions.

### Changed
- Restored benchmark target to the build script. (#188)
- Upgraded the core library to v4.4.1. (#192)

## [4.3.2] - 2025-10-10
### Changed
Expand Down
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.3.0-blue.svg)](https://github.com/uber/h3/releases/tag/v4.3.0)
[![H3 Version](https://img.shields.io/badge/h3-v4.4.1-blue.svg)](https://github.com/uber/h3/releases/tag/v4.4.1)

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.3.2</version>
<version>4.4.0</version>
</dependency>
```

Or, using Gradle:

```gradle
compile("com.uber:h3:4.3.2")
compile("com.uber:h3:4.4.0")
```

Encode a location into a hexagon address:
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ spotless {
}

jacoco {
toolVersion = '0.8.12'
toolVersion = '0.8.14'
}

jacocoTestReport {
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
org.gradle.configuration-cache=false

# No spaces on the following line, needed by release.yml:
version=4.3.3-SNAPSHOT
version=4.4.0
2 changes: 1 addition & 1 deletion h3version.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
h3.git.reference=v4.3.0
h3.git.reference=v4.4.1
37 changes: 37 additions & 0 deletions src/main/c/h3-java/src/jniapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,33 @@ void DestroyGeoPolygon(JNIEnv *env, jdoubleArray verts,
}
}

/*
* Class: com_uber_h3core_NativeMethods
* Method: constructCell
* Signature: (II[I)J
*/
JNIEXPORT jlong JNICALL Java_com_uber_h3core_NativeMethods_constructCell(
JNIEnv *env, jobject thiz, jint res, jint baseCell, jintArray digits) {
H3Index result = 0;
jint *digitsElements = (**env).GetIntArrayElements(env, digits, 0);

if (digitsElements != NULL) {
// if sz is too small, bad things will happen
// note: We assume int can at least contain `jint` on the current
// platform. This may not be true if sizeof(int) < 32, but we don't
// support any platforms where this would be the case.
H3Error err = constructCell(res, baseCell, digitsElements, &result);

(**env).ReleaseIntArrayElements(env, digits, digitsElements, 0);
if (err) {
ThrowH3Exception(env, err);
}
} else {
ThrowOutOfMemoryError(env);
}
return result;
}

/*
* Class: com_uber_h3core_NativeMethods
* Method: isValidCell
Expand All @@ -228,6 +255,16 @@ JNIEXPORT jboolean JNICALL Java_com_uber_h3core_NativeMethods_isValidCell(
return isValidCell(h3);
}

/*
* Class: com_uber_h3core_NativeMethods
* Method: isValidIndex
* Signature: (J)Z
*/
JNIEXPORT jboolean JNICALL Java_com_uber_h3core_NativeMethods_isValidIndex(
JNIEnv *env, jobject thiz, jlong h3) {
return isValidIndex(h3);
}

/*
* Class: com_uber_h3core_NativeMethods
* Method: getBaseCellNumber
Expand Down
75 changes: 72 additions & 3 deletions src/main/java/com/uber/h3core/H3Core.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,59 @@ private H3Core(NativeMethods h3Api) {
this.h3Api = h3Api;
}

/** Returns true if this is a valid H3 index. */
/** Returns true if this is a valid H3 cell index. */
public boolean isValidCell(long h3) {
return h3Api.isValidCell(h3);
}

/** Returns true if this is a valid H3 index. */
/** Returns true if this is a valid H3 cell index. */
public boolean isValidCell(String h3Address) {
return isValidCell(stringToH3(h3Address));
}

/** Returns true if this is a valid H3 index. */
public boolean isValidIndex(long h3) {
return h3Api.isValidIndex(h3);
}

/** Returns true if this is a valid H3 index. */
public boolean isValidIndex(String h3Address) {
return isValidIndex(stringToH3(h3Address));
}

/** Construct a cell index from component parts */
public long constructCell(int baseCellNumber, List<Integer> digits, int res) {
int[] digitsArray = digits.stream().mapToInt(Integer::intValue).toArray();
if (digitsArray.length != res) {
throw new IllegalArgumentException(
String.format(
"Number of provided digits is incorrect, must be %d, was %d",
res, digitsArray.length));
}
if (digitsArray.length > 15) {
throw new IllegalArgumentException(
String.format(
"Additional unused digits provided, must be at most 15 but was %d",
digitsArray.length));
}
return h3Api.constructCell(res, baseCellNumber, digitsArray);
}

/** Construct a cell index from component parts */
public long constructCell(int baseCellNumber, List<Integer> digits) {
return constructCell(baseCellNumber, digits, digits.size());
}

/** Construct a cell index from component parts */
public String constructCellAddress(int baseCellNumber, List<Integer> digits) {
return h3ToString(constructCell(baseCellNumber, digits, digits.size()));
}

/** Construct a cell index from component parts */
public String constructCellAddress(int baseCellNumber, List<Integer> digits, int res) {
return h3ToString(constructCell(baseCellNumber, digits, res));
}

/** Returns the base cell number for this index. */
public int getBaseCellNumber(long h3) {
return h3Api.getBaseCellNumber(h3);
Expand Down Expand Up @@ -727,11 +770,37 @@ public int getResolution(String h3Address) {
return getResolution(stringToH3(h3Address));
}

/** Returns the resolution of the provided index */
/** Returns the resolution of the provided index. */
public int getResolution(long h3) {
return (int) ((h3 & H3_RES_MASK) >> H3_RES_OFFSET);
}

/**
* Returns the indexing digit of the index at `res`
*
* @param h3 H3 index.
* @param res Resolution of the digit, <code>1 &lt;= res &lt;= 15</code>
* @throws IllegalArgumentException <code>res</code> is not between 0 and 15, inclusive.
*/
public int getIndexDigit(String h3Address, int res) {
return getIndexDigit(stringToH3(h3Address), res);
}

/**
* Returns the indexing digit of the index at `res`
*
* @param h3 H3 index.
* @param res Resolution of the digit, <code>1 &lt;= res &lt;= 15</code>
* @throws IllegalArgumentException <code>res</code> is not between 0 and 15, inclusive.
*/
public int getIndexDigit(long h3, int res) {
if (res < 1 || res > 15) {
throw new IllegalArgumentException(
String.format("resolution %d is out of range (must be 1 <= res <= 15)", res));
}
return (int) ((h3 >> ((15 - res) * 3)) & 7);
}

/**
* Returns the parent of the index at the given resolution.
*
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/uber/h3core/NativeMethods.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ final class NativeMethods {

native long cellToCenterChild(long h3, int childRes);

native long constructCell(int res, int baseCell, int[] digits);

native boolean isValidCell(long h3);

native boolean isValidIndex(long h3);

native int getBaseCellNumber(long h3);

native boolean isPentagon(long h3);
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/uber/h3core/exceptions/H3Exception.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,14 @@ public static String codeToMessage(int code) {
return "Bounds of provided memory were insufficient";
case 15:
return "Mode or flags argument was not valid";
case 16:
return "Index argument was not valid";
case 17:
return "Base cell number was outside of acceptable range";
case 18:
return "Child indexing digits invalid";
case 19:
return "Child indexing digits refer to a deleted subsequence";
default:
return "Unknown error";
}
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/com/uber/h3core/TestDirectedEdges.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ void unidirectionalEdges() {

assertTrue(h3.isValidDirectedEdge(edge));
assertFalse(h3.isValidDirectedEdge(start));
assertTrue(h3.isValidIndex(edge));
assertFalse(h3.isValidCell(edge));

assertEquals(start, h3.getDirectedEdgeOrigin(edge));
assertEquals(adjacent, h3.getDirectedEdgeDestination(edge));
Expand Down
Loading
Loading