From 0c71348d8dbfe413505966635c90de6ea86f12f4 Mon Sep 17 00:00:00 2001 From: Hilbrand Bouwkamp Date: Fri, 6 Feb 2026 14:56:21 +0100 Subject: [PATCH 1/2] AER-4255 Extended HexagonUtil to add custom rounding parameter for hexagon coordinates. Kept original method for backward compatibility. --- .../aerius/shared/domain/geo/HexagonUtil.java | 23 ++++++++--- .../shared/domain/geo/HexagonUtilTest.java | 40 ++++++++++++++----- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/source/imaer-shared/src/main/java/nl/overheid/aerius/shared/domain/geo/HexagonUtil.java b/source/imaer-shared/src/main/java/nl/overheid/aerius/shared/domain/geo/HexagonUtil.java index 75d7d115..fea825e5 100644 --- a/source/imaer-shared/src/main/java/nl/overheid/aerius/shared/domain/geo/HexagonUtil.java +++ b/source/imaer-shared/src/main/java/nl/overheid/aerius/shared/domain/geo/HexagonUtil.java @@ -16,7 +16,8 @@ */ package nl.overheid.aerius.shared.domain.geo; -import nl.overheid.aerius.shared.MathUtil; +import java.util.function.DoubleUnaryOperator; + import nl.overheid.aerius.shared.domain.v2.geojson.Point; import nl.overheid.aerius.shared.domain.v2.geojson.Polygon; @@ -27,6 +28,15 @@ public final class HexagonUtil { private HexagonUtil() {} + /** + * Returns a Geometry with a hexagon conforming to the given Point, and rounds the points of the hexagon + * + * @see #createHexagon(Point, HexagonZoomLevel, boolean) + */ + public static Polygon createHexagon(final Point point, final HexagonZoomLevel config) { + return createHexagon(point, config, Math::round); + } + /** * Returns a Geometry with a hexagon conforming to the given Point and * HexagonConfiguration. The points of the hexagon are given in the following @@ -43,9 +53,10 @@ private HexagonUtil() {} * * @param point Center of the hexagon * @param config the hexagon zoom level for level 1 + * @param roundFunction function to round the coordinates of the hexagon with * @return Returns the hexagon as an AERIUS polygon */ - public static Polygon createHexagon(final Point point, final HexagonZoomLevel config) { + public static Polygon createHexagon(final Point point, final HexagonZoomLevel config, final DoubleUnaryOperator roundFunction) { // Store hexagon values final double[] horizontal = config.getHorizontal(); final double[] vertical = config.getVertical(); @@ -54,16 +65,16 @@ public static Polygon createHexagon(final Point point, final HexagonZoomLevel co // Iterate over the number of corners in a hexagon for (int i = 0; i < HexagonZoomLevel.HEXAGON_CORNERS; i++) { final double[] coordinate = new double[] { - MathUtil.round(point.getX() + horizontal[i]), - MathUtil.round(point.getY() + vertical[i]) + roundFunction.applyAsDouble(point.getX() + horizontal[i]), + roundFunction.applyAsDouble(point.getY() + vertical[i]) }; coordinates[i] = coordinate; } // Polygon first and last point need to be the same final double[] lastCoordinate = new double[] { - MathUtil.round(point.getX() + horizontal[0]), - MathUtil.round(point.getY() + vertical[0]) + roundFunction.applyAsDouble(point.getX() + horizontal[0]), + roundFunction.applyAsDouble(point.getY() + vertical[0]) }; coordinates[HexagonZoomLevel.HEXAGON_CORNERS] = lastCoordinate; final Polygon polygon = new Polygon(); diff --git a/source/imaer-shared/src/test/java/nl/overheid/aerius/shared/domain/geo/HexagonUtilTest.java b/source/imaer-shared/src/test/java/nl/overheid/aerius/shared/domain/geo/HexagonUtilTest.java index 56d66f75..ecf07a84 100644 --- a/source/imaer-shared/src/test/java/nl/overheid/aerius/shared/domain/geo/HexagonUtilTest.java +++ b/source/imaer-shared/src/test/java/nl/overheid/aerius/shared/domain/geo/HexagonUtilTest.java @@ -16,8 +16,17 @@ */ package nl.overheid.aerius.shared.domain.geo; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.List; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import nl.overheid.aerius.shared.domain.v2.geojson.Point; import nl.overheid.aerius.shared.domain.v2.geojson.Polygon; @@ -25,22 +34,31 @@ /** * Test class for {@link HexagonUtil}. */ -public class HexagonUtilTest { +class HexagonUtilTest { private static final HexagonZoomLevel ZOOM_LEVEL_1 = new HexagonZoomLevel(1, 10000); - @Test - public void testCreateHexagon() { - assertCreateHexagon(); - // Run twice to test if cache works. - assertCreateHexagon(); + @ParameterizedTest + @MethodSource("createHexagon") + void testCreateHexagon(final boolean round, final double[][][] results) { + final Point point = new Point(ZOOM_LEVEL_1.getHexagonRadius(), ZOOM_LEVEL_1.getHexagonHeight() / 2); + // When round use the default createHexagon method to test, otherwise the version with roundingFunction + final Polygon polygon = round + ? HexagonUtil.createHexagon(point, ZOOM_LEVEL_1) + : HexagonUtil.createHexagon(point, ZOOM_LEVEL_1, d -> BigDecimal.valueOf(d).setScale(3, RoundingMode.HALF_UP).doubleValue()); + System.out.println(polygon); + Assertions.assertArrayEquals(results, polygon.getCoordinates(), "createHexagon zoom level 1"); } - private void assertCreateHexagon() { - final Point point = new Point(ZOOM_LEVEL_1.getHexagonRadius(), ZOOM_LEVEL_1.getHexagonHeight() / 2); - final Polygon polygon = HexagonUtil.createHexagon(point, ZOOM_LEVEL_1); + private static List createHexagon() { + return List.of( + Arguments.of(false, + new double[][][] {{{93.06, 107.457}, {124.081, 53.728}, {93.06, 0.0}, {31.02, 0.0}, {0.0, 53.728}, {31.02, 107.457}, {93.06, 107.457}}}), + Arguments.of(true, new double[][][] {{{93, 107}, {124, 54}, {93, 0}, {31, 0}, {0, 54}, {31, 107}, {93, 107}}})); + } - Assertions.assertArrayEquals(new double[][][] {{{93, 107}, {124, 54}, {93, 0}, {31, 0}, {0, 54}, {31, 107}, {93, 107}}}, polygon.getCoordinates(), - "createHexagon zoom level 1"); + @Test + void testGetDistanceLevelForCircle() { + assertEquals(2.0, HexagonUtil.getDistanceLevelForCircle(100, ZOOM_LEVEL_1), 1E-7, "Not the expected distance level for circle"); } } From 57f50dbedabb38cf71a8d33a60d989316603a7d4 Mon Sep 17 00:00:00 2001 From: Hilbrand Bouwkamp Date: Tue, 10 Feb 2026 14:12:23 +0100 Subject: [PATCH 2/2] Review comments --- .../nl/overheid/aerius/shared/domain/geo/HexagonUtil.java | 5 +++-- .../overheid/aerius/shared/domain/geo/HexagonUtilTest.java | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/source/imaer-shared/src/main/java/nl/overheid/aerius/shared/domain/geo/HexagonUtil.java b/source/imaer-shared/src/main/java/nl/overheid/aerius/shared/domain/geo/HexagonUtil.java index fea825e5..e3b2b382 100644 --- a/source/imaer-shared/src/main/java/nl/overheid/aerius/shared/domain/geo/HexagonUtil.java +++ b/source/imaer-shared/src/main/java/nl/overheid/aerius/shared/domain/geo/HexagonUtil.java @@ -18,6 +18,7 @@ import java.util.function.DoubleUnaryOperator; +import nl.overheid.aerius.shared.MathUtil; import nl.overheid.aerius.shared.domain.v2.geojson.Point; import nl.overheid.aerius.shared.domain.v2.geojson.Polygon; @@ -31,10 +32,10 @@ private HexagonUtil() {} /** * Returns a Geometry with a hexagon conforming to the given Point, and rounds the points of the hexagon * - * @see #createHexagon(Point, HexagonZoomLevel, boolean) + * @see #createHexagon(Point, HexagonZoomLevel, DoubleUnaryOperator) */ public static Polygon createHexagon(final Point point, final HexagonZoomLevel config) { - return createHexagon(point, config, Math::round); + return createHexagon(point, config, MathUtil::round); } /** diff --git a/source/imaer-shared/src/test/java/nl/overheid/aerius/shared/domain/geo/HexagonUtilTest.java b/source/imaer-shared/src/test/java/nl/overheid/aerius/shared/domain/geo/HexagonUtilTest.java index ecf07a84..6a382e7d 100644 --- a/source/imaer-shared/src/test/java/nl/overheid/aerius/shared/domain/geo/HexagonUtilTest.java +++ b/source/imaer-shared/src/test/java/nl/overheid/aerius/shared/domain/geo/HexagonUtilTest.java @@ -40,13 +40,13 @@ class HexagonUtilTest { @ParameterizedTest @MethodSource("createHexagon") - void testCreateHexagon(final boolean round, final double[][][] results) { + void testCreateHexagon(final boolean useDefaultMethod, final double[][][] results) { final Point point = new Point(ZOOM_LEVEL_1.getHexagonRadius(), ZOOM_LEVEL_1.getHexagonHeight() / 2); // When round use the default createHexagon method to test, otherwise the version with roundingFunction - final Polygon polygon = round + final Polygon polygon = useDefaultMethod ? HexagonUtil.createHexagon(point, ZOOM_LEVEL_1) : HexagonUtil.createHexagon(point, ZOOM_LEVEL_1, d -> BigDecimal.valueOf(d).setScale(3, RoundingMode.HALF_UP).doubleValue()); - System.out.println(polygon); + Assertions.assertArrayEquals(results, polygon.getCoordinates(), "createHexagon zoom level 1"); }