diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java index f7c3ab9099..6b3bff4533 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/FeatureMerge.java @@ -114,11 +114,15 @@ public static List mergeMultiLineString(List> BY_HILBERT_INDEX = + (o1, o2) -> Integer.compare(o1.hilbert(), o2.hilbert()); + + private record WithIndex (T feature, int hilbert) {} + private static List mergeGeometries( List features, GeometryType geometryType ) { - features = features.stream().sorted(Comparator.comparingInt(f -> f.geometry().index())).toList(); List result = new ArrayList<>(features.size()); var groupedByAttrs = groupByAttrs(features, result, geometryType); for (List groupedFeatures : groupedByAttrs) { @@ -127,9 +131,11 @@ private static List mergeGeometries( result.add(feature1); } else { VectorTile.VectorGeometryMerger combined = VectorTile.newMerger(geometryType); - for (var feature : groupedFeatures) { - combined.accept(feature.geometry()); - } + groupedFeatures.stream() + .map(f -> new WithIndex<>(f, f.geometry().hilbertIndex())) + .sorted(BY_HILBERT_INDEX) + .map(d -> d.feature.geometry()) + .forEachOrdered(combined); result.add(feature1.copyWithNewGeometry(combined.finish())); } } @@ -193,6 +199,7 @@ public static List mergeLineStrings(List } } if (!outputSegments.isEmpty()) { + outputSegments = sortByHilbertIndex(outputSegments); Geometry newGeometry = GeoUtils.combineLineStrings(outputSegments); result.add(feature1.copyWithNewGeometry(newGeometry)); } @@ -334,6 +341,7 @@ public static List mergeNearbyPolygons(List mergeNearbyPolygons(List List sortByHilbertIndex(List geometries) { + return geometries.stream() + .map(p -> new WithIndex<>(p, VectorTile.hilbertIndex(p))) + .sorted(BY_HILBERT_INDEX) + .map(d -> d.feature) + .toList(); + } + public static List mergeNearbyPolygons(List features, double minArea, double minHoleArea, double minDist, double buffer) throws GeometryException { return mergeNearbyPolygons(features, minArea, minHoleArea, minDist, buffer, DefaultStats.get()); diff --git a/planetiler-core/src/main/java/com/onthegomap/planetiler/VectorTile.java b/planetiler-core/src/main/java/com/onthegomap/planetiler/VectorTile.java index 3c3f6cbd79..50e12512b6 100644 --- a/planetiler-core/src/main/java/com/onthegomap/planetiler/VectorTile.java +++ b/planetiler-core/src/main/java/com/onthegomap/planetiler/VectorTile.java @@ -39,6 +39,7 @@ import java.util.stream.Stream; import javax.annotation.concurrent.NotThreadSafe; import org.locationtech.jts.algorithm.Orientation; +import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.CoordinateSequence; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.GeometryFactory; @@ -420,6 +421,13 @@ public static VectorGeometryMerger newMerger(GeometryType geometryType) { return new VectorGeometryMerger(geometryType); } + public static int hilbertIndex(Geometry g) { + Coordinate coord = g.getCoordinate(); + int x = zigZagEncode((int) Math.round(coord.x * 4096 / 256)); + int y = zigZagEncode((int) Math.round(coord.y * 4096 / 256)); + return Hilbert.hilbertXYToIndex(15, x, y); + } + /** * Adds features in a layer to this tile. * @@ -588,9 +596,9 @@ public static class VectorGeometryMerger implements Consumer { // the sequence private final GeometryType geometryType; + private final IntArrayList result = new IntArrayList(); private int overallX = 0; private int overallY = 0; - private final IntArrayList result = new IntArrayList(); private VectorGeometryMerger(GeometryType geometryType) { this.geometryType = geometryType; @@ -925,12 +933,15 @@ public VectorGeometry filterPointsOutsideBuffer(double buffer) { } } - public int index() { - // 0 -> 4096*2*2 + public int hilbertIndex() { + if (commands.length < 3) { + return 0; + } int x = commands[1]; int y = commands[2]; - return Hilbert.hilbertXYToIndex(14, x, y); + return Hilbert.hilbertXYToIndex(15, x >> scale, y >> scale); } + } /**