kopia lustrzana https://github.com/onthegomap/planetiler
608 wiersze
19 KiB
Java
608 wiersze
19 KiB
Java
package com.onthegomap.flatmap;
|
|
|
|
import static com.onthegomap.flatmap.TestUtils.*;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
|
|
import com.graphhopper.reader.ReaderRelation;
|
|
import com.onthegomap.flatmap.collections.FeatureGroup;
|
|
import com.onthegomap.flatmap.collections.FeatureSort;
|
|
import com.onthegomap.flatmap.collections.LongLongMap;
|
|
import com.onthegomap.flatmap.geo.GeoUtils;
|
|
import com.onthegomap.flatmap.geo.TileCoord;
|
|
import com.onthegomap.flatmap.monitoring.Stats;
|
|
import com.onthegomap.flatmap.profiles.OpenMapTilesProfile;
|
|
import com.onthegomap.flatmap.read.OpenStreetMapReader;
|
|
import com.onthegomap.flatmap.read.Reader;
|
|
import com.onthegomap.flatmap.read.ReaderFeature;
|
|
import com.onthegomap.flatmap.worker.Topology;
|
|
import com.onthegomap.flatmap.write.Mbtiles;
|
|
import com.onthegomap.flatmap.write.MbtilesWriter;
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.sql.SQLException;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.function.BiConsumer;
|
|
import java.util.function.Function;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.junit.jupiter.params.ParameterizedTest;
|
|
import org.junit.jupiter.params.provider.CsvSource;
|
|
import org.locationtech.jts.geom.Coordinate;
|
|
import org.locationtech.jts.geom.MultiPolygon;
|
|
import org.locationtech.jts.io.InputStreamInStream;
|
|
import org.locationtech.jts.io.ParseException;
|
|
import org.locationtech.jts.io.WKBReader;
|
|
|
|
/**
|
|
* In-memory tests with fake data and profiles to ensure all features work end-to-end.
|
|
*/
|
|
public class FlatMapTest {
|
|
|
|
private static final String TEST_PROFILE_NAME = "test name";
|
|
private static final String TEST_PROFILE_DESCRIPTION = "test description";
|
|
private static final String TEST_PROFILE_ATTRIBUTION = "test attribution";
|
|
private static final String TEST_PROFILE_VERSION = "test version";
|
|
private static final int Z14_TILES = 1 << 14;
|
|
private static final double Z14_WIDTH = 1d / Z14_TILES;
|
|
private static final int Z13_TILES = 1 << 13;
|
|
private static final double Z13_WIDTH = 1d / Z13_TILES;
|
|
private static final int Z12_TILES = 1 << 12;
|
|
private static final double Z12_WIDTH = 1d / Z12_TILES;
|
|
private static final int Z4_TILES = 1 << 4;
|
|
private final Stats stats = new Stats.InMemory();
|
|
|
|
private void processReaderFeatures(FeatureGroup featureGroup, Profile profile, CommonParams config,
|
|
List<? extends SourceFeature> features) {
|
|
new Reader(profile, stats, "test") {
|
|
|
|
@Override
|
|
public long getCount() {
|
|
return features.size();
|
|
}
|
|
|
|
@Override
|
|
public Topology.SourceStep<SourceFeature> read() {
|
|
return features::forEach;
|
|
}
|
|
|
|
@Override
|
|
public void close() {
|
|
}
|
|
}.process(featureGroup, config);
|
|
}
|
|
|
|
private FlatMapResults runWithReaderFeatures(
|
|
Map<String, String> args,
|
|
List<ReaderFeature> features,
|
|
BiConsumer<SourceFeature, FeatureCollector> profileFunction
|
|
) throws IOException, SQLException {
|
|
CommonParams config = CommonParams.from(Arguments.of(args));
|
|
var translations = Translations.defaultProvider(List.of());
|
|
var profile1 = new OpenMapTilesProfile();
|
|
LongLongMap nodeLocations = LongLongMap.newInMemorySortedTable();
|
|
FeatureSort featureDb = FeatureSort.newInMemory();
|
|
FeatureGroup featureGroup = new FeatureGroup(featureDb, profile1, stats);
|
|
var profile = TestProfile.processSourceFeatures(profileFunction);
|
|
processReaderFeatures(featureGroup, profile, config, features);
|
|
featureGroup.sorter().sort();
|
|
try (Mbtiles db = Mbtiles.newInMemoryDatabase()) {
|
|
MbtilesWriter.writeOutput(featureGroup, db, () -> 0L, profile, config, stats);
|
|
var tileMap = TestUtils.getTileMap(db);
|
|
tileMap.values().forEach(fs -> {
|
|
fs.forEach(f -> f.geometry().validate());
|
|
});
|
|
return new FlatMapResults(tileMap, db.metadata().getAll());
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testMetadataButNoPoints() throws IOException, SQLException {
|
|
var results = runWithReaderFeatures(
|
|
Map.of("threads", "1"),
|
|
List.of(),
|
|
(sourceFeature, features) -> {
|
|
}
|
|
);
|
|
assertEquals(Map.of(), results.tiles);
|
|
assertSubmap(Map.of(
|
|
"name", TEST_PROFILE_NAME,
|
|
"description", TEST_PROFILE_DESCRIPTION,
|
|
"attribution", TEST_PROFILE_ATTRIBUTION,
|
|
"version", TEST_PROFILE_VERSION,
|
|
"type", "baselayer",
|
|
"format", "pbf",
|
|
"minzoom", "0",
|
|
"maxzoom", "14",
|
|
"center", "0,0,0",
|
|
"bounds", "-180,-85.05113,180,85.05113"
|
|
), results.metadata);
|
|
assertSameJson(
|
|
"""
|
|
{
|
|
"vector_layers": [
|
|
]
|
|
}
|
|
""",
|
|
results.metadata.get("json")
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testSinglePoint() throws IOException, SQLException {
|
|
double x = 0.5 + Z14_WIDTH / 2;
|
|
double y = 0.5 + Z14_WIDTH / 2;
|
|
double lat = GeoUtils.getWorldLat(y);
|
|
double lng = GeoUtils.getWorldLon(x);
|
|
|
|
var results = runWithReaderFeatures(
|
|
Map.of("threads", "1"),
|
|
List.of(
|
|
new ReaderFeature(newPoint(lng, lat), Map.of(
|
|
"attr", "value"
|
|
))
|
|
),
|
|
(in, features) -> {
|
|
features.point("layer")
|
|
.setZoomRange(13, 14)
|
|
.setAttr("name", "name value")
|
|
.inheritFromSource("attr");
|
|
}
|
|
);
|
|
|
|
assertSubmap(Map.of(
|
|
TileCoord.ofXYZ(Z14_TILES / 2, Z14_TILES / 2, 14), List.of(
|
|
feature(newPoint(128, 128), Map.of(
|
|
"attr", "value",
|
|
"name", "name value"
|
|
))
|
|
),
|
|
TileCoord.ofXYZ(Z13_TILES / 2, Z13_TILES / 2, 13), List.of(
|
|
feature(newPoint(64, 64), Map.of(
|
|
"attr", "value",
|
|
"name", "name value"
|
|
))
|
|
)
|
|
), results.tiles);
|
|
assertSameJson(
|
|
"""
|
|
{
|
|
"vector_layers": [
|
|
{"id": "layer", "fields": {"name": "String", "attr": "String"}, "minzoom": 13, "maxzoom": 14}
|
|
]
|
|
}
|
|
""",
|
|
results.metadata.get("json")
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testMultiPoint() throws IOException, SQLException {
|
|
double x1 = 0.5 + Z14_WIDTH / 2;
|
|
double y1 = 0.5 + Z14_WIDTH / 2;
|
|
double x2 = x1 + Z13_WIDTH / 256d;
|
|
double y2 = y1 + Z13_WIDTH / 256d;
|
|
double lat1 = GeoUtils.getWorldLat(y1);
|
|
double lng1 = GeoUtils.getWorldLon(x1);
|
|
double lat2 = GeoUtils.getWorldLat(y2);
|
|
double lng2 = GeoUtils.getWorldLon(x2);
|
|
|
|
var results = runWithReaderFeatures(
|
|
Map.of("threads", "1"),
|
|
List.of(
|
|
new ReaderFeature(newMultiPoint(
|
|
newPoint(lng1, lat1),
|
|
newPoint(lng2, lat2)
|
|
), Map.of(
|
|
"attr", "value"
|
|
))
|
|
),
|
|
(in, features) -> {
|
|
features.point("layer")
|
|
.setZoomRange(13, 14)
|
|
.setAttr("name", "name value")
|
|
.inheritFromSource("attr");
|
|
}
|
|
);
|
|
|
|
assertSubmap(Map.of(
|
|
TileCoord.ofXYZ(Z14_TILES / 2, Z14_TILES / 2, 14), List.of(
|
|
feature(newMultiPoint(
|
|
newPoint(128, 128),
|
|
newPoint(130, 130)
|
|
), Map.of(
|
|
"attr", "value",
|
|
"name", "name value"
|
|
))
|
|
),
|
|
TileCoord.ofXYZ(Z13_TILES / 2, Z13_TILES / 2, 13), List.of(
|
|
feature(newMultiPoint(
|
|
newPoint(64, 64),
|
|
newPoint(65, 65)
|
|
), Map.of(
|
|
"attr", "value",
|
|
"name", "name value"
|
|
))
|
|
)
|
|
), results.tiles);
|
|
}
|
|
|
|
@Test
|
|
public void testLabelGridLimit() throws IOException, SQLException {
|
|
double y = 0.5 + Z14_WIDTH / 2;
|
|
double lat = GeoUtils.getWorldLat(y);
|
|
|
|
double x1 = 0.5 + Z14_WIDTH / 4;
|
|
double lng1 = GeoUtils.getWorldLon(x1);
|
|
double lng2 = GeoUtils.getWorldLon(x1 + Z14_WIDTH * 10d / 256);
|
|
double lng3 = GeoUtils.getWorldLon(x1 + Z14_WIDTH * 20d / 256);
|
|
|
|
var results = runWithReaderFeatures(
|
|
Map.of("threads", "1"),
|
|
List.of(
|
|
new ReaderFeature(newPoint(lng1, lat), Map.of("rank", "1")),
|
|
new ReaderFeature(newPoint(lng2, lat), Map.of("rank", "2")),
|
|
new ReaderFeature(newPoint(lng3, lat), Map.of("rank", "3"))
|
|
),
|
|
(in, features) -> {
|
|
features.point("layer")
|
|
.setZoomRange(13, 14)
|
|
.inheritFromSource("rank")
|
|
.setZorder(Integer.parseInt(in.getTag("rank").toString()))
|
|
.setLabelGridSizeAndLimit(13, 128, 2);
|
|
}
|
|
);
|
|
|
|
assertSubmap(Map.of(
|
|
TileCoord.ofXYZ(Z14_TILES / 2, Z14_TILES / 2, 14), List.of(
|
|
feature(newPoint(64, 128), Map.of("rank", "1")),
|
|
feature(newPoint(74, 128), Map.of("rank", "2")),
|
|
feature(newPoint(84, 128), Map.of("rank", "3"))
|
|
),
|
|
TileCoord.ofXYZ(Z13_TILES / 2, Z13_TILES / 2, 13), List.of(
|
|
// omit rank=1 due to label grid size
|
|
feature(newPoint(37, 64), Map.of("rank", "2")),
|
|
feature(newPoint(42, 64), Map.of("rank", "3"))
|
|
)
|
|
), results.tiles);
|
|
}
|
|
|
|
@Test
|
|
public void testLineString() throws IOException, SQLException {
|
|
double x1 = 0.5 + Z14_WIDTH / 2;
|
|
double y1 = 0.5 + Z14_WIDTH / 2;
|
|
double x2 = x1 + Z14_WIDTH;
|
|
double y2 = y1 + Z14_WIDTH;
|
|
double lat1 = GeoUtils.getWorldLat(y1);
|
|
double lng1 = GeoUtils.getWorldLon(x1);
|
|
double lat2 = GeoUtils.getWorldLat(y2);
|
|
double lng2 = GeoUtils.getWorldLon(x2);
|
|
|
|
var results = runWithReaderFeatures(
|
|
Map.of("threads", "1"),
|
|
List.of(
|
|
new ReaderFeature(newLineString(lng1, lat1, lng2, lat2), Map.of(
|
|
"attr", "value"
|
|
))
|
|
),
|
|
(in, features) -> {
|
|
features.line("layer")
|
|
.setZoomRange(13, 14)
|
|
.setBufferPixels(4);
|
|
}
|
|
);
|
|
|
|
assertSubmap(Map.of(
|
|
TileCoord.ofXYZ(Z14_TILES / 2, Z14_TILES / 2, 14), List.of(
|
|
feature(newLineString(128, 128, 260, 260), Map.of())
|
|
),
|
|
TileCoord.ofXYZ(Z14_TILES / 2 + 1, Z14_TILES / 2 + 1, 14), List.of(
|
|
feature(newLineString(-4, -4, 128, 128), Map.of())
|
|
),
|
|
TileCoord.ofXYZ(Z13_TILES / 2, Z13_TILES / 2, 13), List.of(
|
|
feature(newLineString(64, 64, 192, 192), Map.of())
|
|
)
|
|
), results.tiles);
|
|
}
|
|
|
|
@Test
|
|
public void testMultiLineString() throws IOException, SQLException {
|
|
double x1 = 0.5 + Z14_WIDTH / 2;
|
|
double y1 = 0.5 + Z14_WIDTH / 2;
|
|
double x2 = x1 + Z14_WIDTH;
|
|
double y2 = y1 + Z14_WIDTH;
|
|
double lat1 = GeoUtils.getWorldLat(y1);
|
|
double lng1 = GeoUtils.getWorldLon(x1);
|
|
double lat2 = GeoUtils.getWorldLat(y2);
|
|
double lng2 = GeoUtils.getWorldLon(x2);
|
|
|
|
var results = runWithReaderFeatures(
|
|
Map.of("threads", "1"),
|
|
List.of(
|
|
new ReaderFeature(newMultiLineString(
|
|
newLineString(lng1, lat1, lng2, lat2),
|
|
newLineString(lng2, lat2, lng1, lat1)
|
|
), Map.of(
|
|
"attr", "value"
|
|
))
|
|
),
|
|
(in, features) -> {
|
|
features.line("layer")
|
|
.setZoomRange(13, 14)
|
|
.setBufferPixels(4);
|
|
}
|
|
);
|
|
|
|
assertSubmap(Map.of(
|
|
TileCoord.ofXYZ(Z14_TILES / 2, Z14_TILES / 2, 14), List.of(
|
|
feature(newMultiLineString(
|
|
newLineString(128, 128, 260, 260),
|
|
newLineString(260, 260, 128, 128)
|
|
), Map.of())
|
|
),
|
|
TileCoord.ofXYZ(Z14_TILES / 2 + 1, Z14_TILES / 2 + 1, 14), List.of(
|
|
feature(newMultiLineString(
|
|
newLineString(-4, -4, 128, 128),
|
|
newLineString(128, 128, -4, -4)
|
|
), Map.of())
|
|
),
|
|
TileCoord.ofXYZ(Z13_TILES / 2, Z13_TILES / 2, 13), List.of(
|
|
feature(newMultiLineString(
|
|
newLineString(64, 64, 192, 192),
|
|
newLineString(192, 192, 64, 64)
|
|
), Map.of())
|
|
)
|
|
), results.tiles);
|
|
}
|
|
|
|
private List<Coordinate> worldCoordinateList(double... coords) {
|
|
List<Coordinate> points = newCoordinateList(coords);
|
|
points.forEach(c -> {
|
|
c.x = GeoUtils.getWorldLon(c.x);
|
|
c.y = GeoUtils.getWorldLat(c.y);
|
|
});
|
|
return points;
|
|
}
|
|
|
|
private List<Coordinate> z14CoordinateList(double... coords) {
|
|
List<Coordinate> points = newCoordinateList(coords);
|
|
points.forEach(c -> {
|
|
c.x = GeoUtils.getWorldLon(0.5 + c.x * Z14_WIDTH);
|
|
c.y = GeoUtils.getWorldLat(0.5 + c.y * Z14_WIDTH);
|
|
});
|
|
return points;
|
|
}
|
|
|
|
@Test
|
|
public void testPolygonWithHoleSpanningMultipleTiles() throws IOException, SQLException {
|
|
List<Coordinate> outerPoints = z14CoordinateList(
|
|
0.5, 0.5,
|
|
3.5, 0.5,
|
|
3.5, 2.5,
|
|
0.5, 2.5,
|
|
0.5, 0.5
|
|
);
|
|
List<Coordinate> innerPoints = z14CoordinateList(
|
|
1.25, 1.25,
|
|
1.75, 1.25,
|
|
1.75, 1.75,
|
|
1.25, 1.75,
|
|
1.25, 1.25
|
|
);
|
|
|
|
var results = runWithReaderFeatures(
|
|
Map.of("threads", "1"),
|
|
List.of(
|
|
new ReaderFeature(newPolygon(
|
|
outerPoints,
|
|
List.of(innerPoints)
|
|
), Map.of())
|
|
),
|
|
(in, features) -> {
|
|
features.polygon("layer")
|
|
.setZoomRange(12, 14)
|
|
.setBufferPixels(4);
|
|
}
|
|
);
|
|
|
|
assertEquals(Map.ofEntries(
|
|
// Z12
|
|
newTileEntry(Z12_TILES / 2, Z12_TILES / 2, 12, List.of(
|
|
feature(newPolygon(
|
|
rectangleCoordList(32, 32, 256 - 32, 128 + 32),
|
|
List.of(
|
|
rectangleCoordList(64 + 16, 128 - 16) // hole
|
|
)
|
|
), Map.of())
|
|
)),
|
|
|
|
// Z13
|
|
newTileEntry(Z13_TILES / 2, Z13_TILES / 2, 13, List.of(
|
|
feature(newPolygon(
|
|
rectangleCoordList(64, 256 + 4),
|
|
List.of(rectangleCoordList(128 + 32, 256 - 32)) // hole
|
|
), Map.of())
|
|
)),
|
|
newTileEntry(Z13_TILES / 2 + 1, Z13_TILES / 2, 13, List.of(
|
|
feature(rectangle(-4, 64, 256 - 64, 256 + 4), Map.of())
|
|
)),
|
|
newTileEntry(Z13_TILES / 2, Z13_TILES / 2 + 1, 13, List.of(
|
|
feature(rectangle(64, -4, 256 + 4, 64), Map.of())
|
|
)),
|
|
newTileEntry(Z13_TILES / 2 + 1, Z13_TILES / 2 + 1, 13, List.of(
|
|
feature(rectangle(-4, -4, 256 - 64, 64), Map.of())
|
|
)),
|
|
|
|
// Z14 - row 1
|
|
newTileEntry(Z14_TILES / 2, Z14_TILES / 2, 14, List.of(
|
|
feature(tileBottomRight(4), Map.of())
|
|
)),
|
|
newTileEntry(Z14_TILES / 2 + 1, Z14_TILES / 2, 14, List.of(
|
|
feature(tileBottom(4), Map.of())
|
|
)),
|
|
newTileEntry(Z14_TILES / 2 + 2, Z14_TILES / 2, 14, List.of(
|
|
feature(tileBottom(4), Map.of())
|
|
)),
|
|
newTileEntry(Z14_TILES / 2 + 3, Z14_TILES / 2, 14, List.of(
|
|
feature(tileBottomLeft(4), Map.of())
|
|
)),
|
|
// Z14 - row 2
|
|
newTileEntry(Z14_TILES / 2, Z14_TILES / 2 + 1, 14, List.of(
|
|
feature(tileRight(4), Map.of())
|
|
)),
|
|
newTileEntry(Z14_TILES / 2 + 1, Z14_TILES / 2 + 1, 14, List.of(
|
|
feature(newPolygon(
|
|
tileFill(4 + 256d / 4096),
|
|
List.of(newCoordinateList(
|
|
64, 64,
|
|
192, 64,
|
|
192, 192,
|
|
64, 192,
|
|
64, 64
|
|
))
|
|
), Map.of())
|
|
)),
|
|
newTileEntry(Z14_TILES / 2 + 2, Z14_TILES / 2 + 1, 14, List.of(
|
|
feature(newPolygon(tileFill(5), List.of()), Map.of())
|
|
)),
|
|
newTileEntry(Z14_TILES / 2 + 3, Z14_TILES / 2 + 1, 14, List.of(
|
|
feature(tileLeft(4), Map.of())
|
|
)),
|
|
// Z14 - row 3
|
|
newTileEntry(Z14_TILES / 2, Z14_TILES / 2 + 2, 14, List.of(
|
|
feature(tileTopRight(4), Map.of())
|
|
)),
|
|
newTileEntry(Z14_TILES / 2 + 1, Z14_TILES / 2 + 2, 14, List.of(
|
|
feature(tileTop(4), Map.of())
|
|
)),
|
|
newTileEntry(Z14_TILES / 2 + 2, Z14_TILES / 2 + 2, 14, List.of(
|
|
feature(tileTop(4), Map.of())
|
|
)),
|
|
newTileEntry(Z14_TILES / 2 + 3, Z14_TILES / 2 + 2, 14, List.of(
|
|
feature(tileTopLeft(4), Map.of())
|
|
))
|
|
), results.tiles);
|
|
}
|
|
|
|
@Test
|
|
public void testOceanPolygon() throws IOException, SQLException {
|
|
List<Coordinate> outerPoints = worldCoordinateList(
|
|
Z14_WIDTH / 2, Z14_WIDTH / 2,
|
|
1 - Z14_WIDTH / 2, Z14_WIDTH / 2,
|
|
1 - Z14_WIDTH / 2, 1 - Z14_WIDTH / 2,
|
|
Z14_WIDTH / 2, 1 - Z14_WIDTH / 2,
|
|
Z14_WIDTH / 2, Z14_WIDTH / 2
|
|
);
|
|
|
|
var results = runWithReaderFeatures(
|
|
Map.of("threads", "1"),
|
|
List.of(
|
|
new ReaderFeature(newPolygon(
|
|
outerPoints,
|
|
List.of()
|
|
), Map.of())
|
|
),
|
|
(in, features) -> {
|
|
features.polygon("layer")
|
|
.setZoomRange(0, 6)
|
|
.setBufferPixels(4);
|
|
}
|
|
);
|
|
|
|
assertEquals(5461, results.tiles.size());
|
|
// spot-check one filled tile
|
|
assertEquals(List.of(rectangle(-5, 256 + 5).norm()), results.tiles.get(TileCoord.ofXYZ(
|
|
Z4_TILES / 2, Z4_TILES / 2, 4
|
|
)).stream().map(d -> d.geometry().geom().norm()).toList());
|
|
}
|
|
|
|
@ParameterizedTest
|
|
@CsvSource({
|
|
"chesapeake.wkb, 4076",
|
|
"mdshore.wkb, 19904",
|
|
"njshore.wkb, 10571"
|
|
})
|
|
public void testComplexShorelinePolygons__TAKES_A_MINUTE_OR_TWO(String fileName, int expected)
|
|
throws IOException, SQLException, ParseException {
|
|
MultiPolygon geometry = (MultiPolygon) new WKBReader()
|
|
.read(new InputStreamInStream(Files.newInputStream(Path.of("src", "test", "resources", fileName))));
|
|
assertNotNull(geometry);
|
|
|
|
// automatically checks for self-intersections
|
|
var results = runWithReaderFeatures(
|
|
Map.of("threads", "1"),
|
|
List.of(
|
|
new ReaderFeature(geometry, Map.of())
|
|
),
|
|
(in, features) -> {
|
|
features.polygon("layer")
|
|
.setZoomRange(0, 14)
|
|
.setBufferPixels(4);
|
|
}
|
|
);
|
|
|
|
assertEquals(expected, results.tiles.size());
|
|
}
|
|
|
|
private Map.Entry<TileCoord, List<TestUtils.ComparableFeature>> newTileEntry(int x, int y, int z,
|
|
List<TestUtils.ComparableFeature> features) {
|
|
return Map.entry(TileCoord.ofXYZ(x, y, z), features);
|
|
}
|
|
|
|
private interface LayerPostprocessFunction {
|
|
|
|
List<VectorTileEncoder.Feature> process(String layer, int zoom, List<VectorTileEncoder.Feature> items);
|
|
}
|
|
|
|
private static record FlatMapResults(
|
|
Map<TileCoord, List<TestUtils.ComparableFeature>> tiles, Map<String, String> metadata
|
|
) {}
|
|
|
|
private static record TestProfile(
|
|
@Override String name,
|
|
@Override String description,
|
|
@Override String attribution,
|
|
@Override String version,
|
|
BiConsumer<SourceFeature, FeatureCollector> processFeature,
|
|
Function<ReaderRelation, List<OpenStreetMapReader.RelationInfo>> preprocessOsmRelation,
|
|
LayerPostprocessFunction postprocessLayerFeatures
|
|
) implements Profile {
|
|
|
|
TestProfile(
|
|
BiConsumer<SourceFeature, FeatureCollector> processFeature,
|
|
Function<ReaderRelation, List<OpenStreetMapReader.RelationInfo>> preprocessOsmRelation,
|
|
LayerPostprocessFunction postprocessLayerFeatures
|
|
) {
|
|
this(TEST_PROFILE_NAME, TEST_PROFILE_DESCRIPTION, TEST_PROFILE_ATTRIBUTION, TEST_PROFILE_VERSION, processFeature,
|
|
preprocessOsmRelation,
|
|
postprocessLayerFeatures);
|
|
}
|
|
|
|
static TestProfile processSourceFeatures(BiConsumer<SourceFeature, FeatureCollector> processFeature) {
|
|
return new TestProfile(processFeature, (a) -> null, (a, b, c) -> null);
|
|
}
|
|
|
|
@Override
|
|
public List<OpenStreetMapReader.RelationInfo> preprocessOsmRelation(
|
|
ReaderRelation relation) {
|
|
return preprocessOsmRelation.apply(relation);
|
|
}
|
|
|
|
@Override
|
|
public void processFeature(SourceFeature sourceFeature, FeatureCollector features) {
|
|
processFeature.accept(sourceFeature, features);
|
|
}
|
|
|
|
@Override
|
|
public void release() {
|
|
}
|
|
|
|
@Override
|
|
public List<VectorTileEncoder.Feature> postProcessLayerFeatures(String layer, int zoom,
|
|
List<VectorTileEncoder.Feature> items) {
|
|
return postprocessLayerFeatures.process(layer, zoom, items);
|
|
}
|
|
}
|
|
}
|