pull/1/head
Mike Barry 2021-05-18 07:30:46 -04:00
rodzic c12ffbf337
commit 7e06af0b1d
2 zmienionych plików z 54 dodań i 7 usunięć

Wyświetl plik

@ -4,12 +4,14 @@ import com.onthegomap.flatmap.geo.GeoUtils;
import com.onthegomap.flatmap.geo.TileCoord;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.CoordinateSequence;
import org.locationtech.jts.geom.CoordinateXY;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryCollection;
@ -19,6 +21,9 @@ import org.locationtech.jts.geom.MultiPoint;
import org.locationtech.jts.geom.MultiPolygon;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.geom.Polygonal;
import org.locationtech.jts.geom.util.AffineTransformation;
import org.locationtech.jts.simplify.DouglasPeuckerSimplifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -144,12 +149,53 @@ public class FeatureRenderer {
}
}
private void addLinearFeature(FeatureCollector.Feature feature, Geometry geom) {
private void addLinearFeature(FeatureCollector.Feature feature, Geometry input) {
// TODO move to feature?
double minSizeAtMaxZoom = 1d / 4096;
double normalTolerance = 0.1 / 256;
double toleranceAtMaxZoom = 1d / 4096;
boolean area = input instanceof Polygonal;
double worldLength = (area || input.getNumGeometries() > 1) ? 0 : input.getLength();
for (int z = feature.getMaxZoom(); z >= feature.getMinZoom(); z--) {
boolean isMaxZoom = feature.getMaxZoom() == 14;
double scale = 1 << z;
double tolerance = isMaxZoom ? toleranceAtMaxZoom : normalTolerance;
double minSize = isMaxZoom ? minSizeAtMaxZoom : (feature.getMinPixelSize(z) / 256);
if (area) {
minSize *= minSize;
} else if (worldLength > 0 && worldLength * scale < minSize) {
// skip linestring, too short
continue;
}
Geometry geom = AffineTransformation.scaleInstance(scale, scale).transform(input);
DouglasPeuckerSimplifier simplifier = new DouglasPeuckerSimplifier(geom);
simplifier.setEnsureValid(false);
simplifier.setDistanceTolerance(tolerance);
geom = simplifier.getResultGeometry();
List<List<CoordinateSequence>> groups = extractGroups(geom);
double buffer = feature.getBufferPixelsAtZoom(z);
TileExtents.ForZoom extents = config.extents().getForZoom(z);
TiledGeometry sliced = TiledGeometry.sliceIntoTiles(groups, buffer, area, z, extents);
writeTileFeatures(feature, sliced);
}
}
private void writeTileFeatures(FeatureCollector.Feature feature, TiledGeometry sliced) {
build polygons, enforce correctness
build linestrings
reduce precision
handle errors
fix orientation
write filled tiles
log stats
}
private List<List<CoordinateSequence>> extractGroups(Geometry geom) {
limit length
limit area
enforce orientation
}
}

Wyświetl plik

@ -34,11 +34,11 @@ import org.slf4j.LoggerFactory;
/**
* This class is adapted from the stripe clipping algorithm in https://github.com/mapbox/geojson-vt/ and modified so
* that it eagerly produces all sliced tiles at every zoom level for each input geometry.
* that it eagerly produces all sliced tiles at a zoom level for each input geometry.
*/
public class SlicedGeometry {
public class TiledGeometry {
private static final Logger LOGGER = LoggerFactory.getLogger(SlicedGeometry.class);
private static final Logger LOGGER = LoggerFactory.getLogger(TiledGeometry.class);
private final Map<TileCoord, List<List<CoordinateSequence>>> tileContents = new HashMap<>();
private final Map<Column, IntRange> filledRanges = new HashMap<>();
@ -48,7 +48,7 @@ public class SlicedGeometry {
private final boolean area;
private final int max;
private SlicedGeometry(TileExtents.ForZoom extents, double buffer, int z, boolean area) {
private TiledGeometry(TileExtents.ForZoom extents, double buffer, int z, boolean area) {
this.extents = extents;
this.buffer = buffer;
this.z = z;
@ -56,9 +56,10 @@ public class SlicedGeometry {
this.max = 1 << z;
}
public static SlicedGeometry slice(List<List<CoordinateSequence>> groups, double buffer, boolean area, int z,
public static TiledGeometry sliceIntoTiles(List<List<CoordinateSequence>> groups, double buffer, boolean area, int z,
TileExtents.ForZoom extents) {
SlicedGeometry result = new SlicedGeometry(extents, buffer, z, area);
TiledGeometry result = new TiledGeometry(extents, buffer, z, area);
EnumSet<Direction> wrapResult = result.sliceWorldCopy(groups, 0);
if (wrapResult.contains(Direction.RIGHT)) {
result.sliceWorldCopy(groups, 1);