Upgrade planetiler-basemap to be compatible with OpenMapTiles 3.13 (#49)

Applying changes to layers from [OpenMapTiles 3.13 release](https://github.com/openmaptiles/openmaptiles/releases/tag/v3.13) (https://github.com/openmaptiles/openmaptiles/compare/v3.12.2...v3.13), minus transportation network connectivity improvements - those will be a separate change.
This commit is contained in:
Michael Barry
2022-01-19 05:36:44 -05:00
committed by GitHub
parent 8e49c0831c
commit 0baaf8d886
37 changed files with 1690 additions and 464 deletions

View File

@@ -1,5 +1,5 @@
/*
Copyright (c) 2016, KlokanTech.com & OpenMapTiles contributors.
Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
All rights reserved.
Code license: BSD 3-Clause License
@@ -37,6 +37,9 @@ package com.onthegomap.planetiler.basemap.layers;
import static com.onthegomap.planetiler.basemap.util.Utils.nullIfEmpty;
import com.carrotsearch.hppc.LongObjectHashMap;
import com.google.common.util.concurrent.AtomicDouble;
import com.graphhopper.coll.GHLongObjectHashMap;
import com.onthegomap.planetiler.FeatureCollector;
import com.onthegomap.planetiler.FeatureMerge;
import com.onthegomap.planetiler.VectorTile;
@@ -46,7 +49,11 @@ import com.onthegomap.planetiler.basemap.generated.Tables;
import com.onthegomap.planetiler.basemap.util.LanguageUtils;
import com.onthegomap.planetiler.basemap.util.Utils;
import com.onthegomap.planetiler.config.PlanetilerConfig;
import com.onthegomap.planetiler.geo.GeometryException;
import com.onthegomap.planetiler.reader.SourceFeature;
import com.onthegomap.planetiler.reader.osm.OsmElement;
import com.onthegomap.planetiler.reader.osm.OsmReader;
import com.onthegomap.planetiler.reader.osm.OsmRelationInfo;
import com.onthegomap.planetiler.stats.Stats;
import com.onthegomap.planetiler.util.Translations;
import com.onthegomap.planetiler.util.ZoomFunction;
@@ -63,7 +70,9 @@ public class Waterway implements
OpenMapTilesSchema.Waterway,
Tables.OsmWaterwayLinestring.Handler,
BasemapProfile.FeaturePostProcessor,
BasemapProfile.NaturalEarthProcessor {
BasemapProfile.NaturalEarthProcessor,
BasemapProfile.OsmRelationPreprocessor,
BasemapProfile.OsmAllProcessor {
/*
* Uses Natural Earth at lower zoom-levels and OpenStreetMap at higher zoom levels.
@@ -76,14 +85,6 @@ public class Waterway implements
* short segment of it goes through this tile.
*/
private final Translations translations;
private final PlanetilerConfig config;
public Waterway(Translations translations, PlanetilerConfig config, Stats stats) {
this.config = config;
this.translations = translations;
}
private static final Map<String, Integer> CLASS_MINZOOM = Map.of(
"river", 12,
"canal", 12,
@@ -92,12 +93,29 @@ public class Waterway implements
"drain", 13,
"ditch", 13
);
private static final String TEMP_REL_ID_ADDR = "_relid";
private final Translations translations;
private final PlanetilerConfig config;
private final Stats stats;
private final LongObjectHashMap<AtomicDouble> riverRelationLengths = new GHLongObjectHashMap<>();
public Waterway(Translations translations, PlanetilerConfig config, Stats stats) {
this.config = config;
this.translations = translations;
this.stats = stats;
}
private static final ZoomFunction.MeterToPixelThresholds MIN_PIXEL_LENGTHS = ZoomFunction.meterThresholds()
.put(6, 500_000)
.put(7, 400_000)
.put(8, 300_000)
.put(9, 8_000)
.put(10, 4_000)
.put(11, 1_000);
// zoom-level 3-5 come from natural earth
@Override
public void processNaturalEarth(String table, SourceFeature feature, FeatureCollector features) {
if (feature.hasTag("featurecla", "River")) {
@@ -105,7 +123,6 @@ public class Waterway implements
ZoomRange zoom = switch (table) {
case "ne_110m_rivers_lake_centerlines" -> new ZoomRange(3, 3);
case "ne_50m_rivers_lake_centerlines" -> new ZoomRange(4, 5);
case "ne_10m_rivers_lake_centerlines" -> new ZoomRange(6, 8);
default -> null;
};
if (zoom != null) {
@@ -117,6 +134,52 @@ public class Waterway implements
}
}
// zoom-level 6-8 come from OSM river relations
private record WaterwayRelation(
long id,
Map<String, Object> names
) implements OsmRelationInfo {}
@Override
public List<OsmRelationInfo> preprocessOsmRelation(OsmElement.Relation relation) {
if (relation.hasTag("waterway", "river") && !Utils.nullOrEmpty(relation.getString("name"))) {
riverRelationLengths.put(relation.id(), new AtomicDouble());
return List.of(new WaterwayRelation(relation.id(), LanguageUtils.getNames(relation.tags(), translations)));
}
return null;
}
@Override
public void processAllOsm(SourceFeature feature, FeatureCollector features) {
List<OsmReader.RelationMember<WaterwayRelation>> waterways = feature.relationInfo(WaterwayRelation.class);
if (waterways != null && !waterways.isEmpty() && feature.canBeLine()) {
for (var waterway : waterways) {
String role = waterway.role();
if (Utils.nullOrEmpty(role) || "main_stream".equals(role)) {
long relId = waterway.relation().id();
try {
AtomicDouble counter = riverRelationLengths.get(relId);
if (counter != null) {
counter.addAndGet(feature.length());
}
} catch (GeometryException e) {
e.log(stats, "waterway_decode", "Unable to get waterway length for " + feature.id());
}
features.line(LAYER_NAME)
.setAttr(TEMP_REL_ID_ADDR, relId)
.setBufferPixels(BUFFER_SIZE)
.setAttr(Fields.CLASS, FieldValues.CLASS_RIVER)
.putAttrs(waterway.relation().names())
.setZoomRange(6, 8)
.setMinPixelSize(0);
}
}
}
}
// zoom-level 9+ come from OSM river ways
@Override
public void process(Tables.OsmWaterwayLinestring element, FeatureCollector features) {
String waterway = element.waterway();
@@ -137,7 +200,22 @@ public class Waterway implements
@Override
public List<VectorTile.Feature> postProcess(int zoom, List<VectorTile.Feature> items) {
if (zoom >= 9 && zoom <= 11) {
if (zoom >= 6 && zoom <= 8) {
// remove ways for river relations if relation is not long enough
double minSizeAtZoom = MIN_PIXEL_LENGTHS.apply(zoom).doubleValue() / Math.pow(2, zoom) / 256d;
for (int i = 0; i < items.size(); i++) {
Object relIdObj = items.get(i).attrs().remove(TEMP_REL_ID_ADDR);
if (relIdObj instanceof Long relId && riverRelationLengths.get(relId).get() < minSizeAtZoom) {
items.set(i, null);
}
}
return FeatureMerge.mergeLineStrings(
items,
config.minFeatureSize(zoom),
config.tolerance(zoom),
BUFFER_SIZE
);
} else if (zoom >= 9 && zoom <= 11) {
return FeatureMerge.mergeLineStrings(
items,
MIN_PIXEL_LENGTHS.apply(zoom).doubleValue(),