feature-hilbert-order
Mike Barry 2023-09-25 20:51:01 -04:00
rodzic c0fa519a76
commit f77abb739f
2 zmienionych plików z 35 dodań i 8 usunięć

Wyświetl plik

@ -114,11 +114,15 @@ public class FeatureMerge {
return mergeGeometries(features, GeometryType.LINE);
}
private static final Comparator<WithIndex<?>> BY_HILBERT_INDEX =
(o1, o2) -> Integer.compare(o1.hilbert(), o2.hilbert());
private record WithIndex<T> (T feature, int hilbert) {}
private static List<VectorTile.Feature> mergeGeometries(
List<VectorTile.Feature> features,
GeometryType geometryType
) {
features = features.stream().sorted(Comparator.comparingInt(f -> f.geometry().index())).toList();
List<VectorTile.Feature> result = new ArrayList<>(features.size());
var groupedByAttrs = groupByAttrs(features, result, geometryType);
for (List<VectorTile.Feature> groupedFeatures : groupedByAttrs) {
@ -127,9 +131,11 @@ public class FeatureMerge {
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 class FeatureMerge {
}
}
if (!outputSegments.isEmpty()) {
outputSegments = sortByHilbertIndex(outputSegments);
Geometry newGeometry = GeoUtils.combineLineStrings(outputSegments);
result.add(feature1.copyWithNewGeometry(newGeometry));
}
@ -334,6 +341,7 @@ public class FeatureMerge {
extractPolygons(merged, outPolygons, minArea, minHoleArea);
}
if (!outPolygons.isEmpty()) {
outPolygons = sortByHilbertIndex(outPolygons);
Geometry combined = GeoUtils.combinePolygons(outPolygons);
result.add(feature1.copyWithNewGeometry(combined));
}
@ -341,6 +349,14 @@ public class FeatureMerge {
return result;
}
private static <G extends Geometry> List<G> sortByHilbertIndex(List<G> geometries) {
return geometries.stream()
.map(p -> new WithIndex<>(p, VectorTile.hilbertIndex(p)))
.sorted(BY_HILBERT_INDEX)
.map(d -> d.feature)
.toList();
}
public static List<VectorTile.Feature> mergeNearbyPolygons(List<VectorTile.Feature> features, double minArea,
double minHoleArea, double minDist, double buffer) throws GeometryException {
return mergeNearbyPolygons(features, minArea, minHoleArea, minDist, buffer, DefaultStats.get());

Wyświetl plik

@ -39,6 +39,7 @@ import java.util.stream.Collectors;
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 class VectorTile {
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 class VectorTile {
// 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 class VectorTile {
}
}
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);
}
}
/**