mirror of
https://github.com/cfpwastaken/planetiler-openmaptiles.git
synced 2026-02-04 12:31:10 +00:00
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:
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user