kopia lustrzana https://github.com/onthegomap/planetiler
waterway
rodzic
cd9122c5ad
commit
8a630796ad
|
@ -204,6 +204,11 @@ public class FeatureCollector implements Iterable<FeatureCollector.Feature> {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Feature setMinPixelSizeThresholds(ZoomFunction<Number> levels) {
|
||||
this.minPixelSize = levels;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Feature setMinPixelSizeBelowZoom(int zoom, double minPixelSize) {
|
||||
this.minPixelSize = ZoomFunction.maxZoom(zoom, minPixelSize);
|
||||
return this;
|
||||
|
|
|
@ -45,6 +45,25 @@ public interface ZoomFunction<T> extends IntFunction<T> {
|
|||
return zoom -> orderedMap.ceilingEntry(zoom).getValue();
|
||||
}
|
||||
|
||||
class MeterThresholds implements ZoomFunction<Number> {
|
||||
|
||||
private static TreeMap<Integer, Number> levels = new TreeMap<>();
|
||||
|
||||
public MeterThresholds put(int zoom, double meters) {
|
||||
levels.put(zoom, GeoUtils.metersToPixelAtEquator(zoom, meters));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number apply(int value) {
|
||||
return levels.get(value);
|
||||
}
|
||||
}
|
||||
|
||||
static MeterThresholds meterThresholds() {
|
||||
return new MeterThresholds();
|
||||
}
|
||||
|
||||
static <T> ZoomFunction<T> constant(T value) {
|
||||
return zoom -> value;
|
||||
}
|
||||
|
|
|
@ -151,6 +151,10 @@ public class GeoUtils {
|
|||
return WORLD_CIRCUMFERENCE_METERS / Math.pow(2, zoom + 8);
|
||||
}
|
||||
|
||||
public static double metersToPixelAtEquator(int zoom, double meters) {
|
||||
return meters / metersPerPixelAtEquator(zoom);
|
||||
}
|
||||
|
||||
public static long longPair(int a, int b) {
|
||||
return (((long) a) << 32L) | (((long) b) & LOWER_32_BIT_MASK);
|
||||
}
|
||||
|
|
|
@ -330,8 +330,8 @@ public class Generate {
|
|||
private static void emitLayerDefinitions(OpenmaptilesTileSet info, List<LayerConfig> layers, String packageName,
|
||||
Path output)
|
||||
throws IOException {
|
||||
StringBuilder layersClass = new StringBuilder();
|
||||
layersClass.append("""
|
||||
StringBuilder schemaClass = new StringBuilder();
|
||||
schemaClass.append("""
|
||||
// AUTOGENERATED BY Generate.java -- DO NOT MODIFY
|
||||
package %s;
|
||||
|
||||
|
@ -344,7 +344,7 @@ public class Generate {
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Layers {
|
||||
public class OpenMapTilesSchema {
|
||||
public static final String NAME = %s;
|
||||
public static final String DESCRIPTION = %s;
|
||||
public static final String VERSION = %s;
|
||||
|
@ -430,7 +430,7 @@ public class Generate {
|
|||
}
|
||||
});
|
||||
|
||||
layersClass.append("""
|
||||
schemaClass.append("""
|
||||
/** %s */
|
||||
public interface %s extends Layer {
|
||||
double BUFFER_SIZE = %s;
|
||||
|
@ -460,8 +460,8 @@ public class Generate {
|
|||
).indent(2));
|
||||
}
|
||||
|
||||
layersClass.append("}");
|
||||
Files.writeString(output.resolve("Layers.java"), layersClass);
|
||||
schemaClass.append("}");
|
||||
Files.writeString(output.resolve("OpenMapTilesSchema.java"), schemaClass);
|
||||
}
|
||||
|
||||
static MultiExpression<String> generateFieldMapping(JsonNode valuesNode) {
|
||||
|
|
|
@ -80,7 +80,7 @@ public class LanguageUtils {
|
|||
return name.trim();
|
||||
}
|
||||
|
||||
public static Map<String, Object> getNames(Map<String, Object> properties) {
|
||||
public static Map<String, Object> getNamesWithoutTranslations(Map<String, Object> properties) {
|
||||
return getNames(properties, null);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,16 +6,16 @@ import com.onthegomap.flatmap.FlatMapRunner;
|
|||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.Wikidata;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
import com.onthegomap.flatmap.read.OsmInputFile;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class OpenMaptilesMain {
|
||||
public class OpenMapTilesMain {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(OpenMaptilesMain.class);
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(OpenMapTilesMain.class);
|
||||
private static final String fallbackOsmFile = "north-america_us_massachusetts.pbf";
|
||||
private static final Path sourcesDir = Path.of("data", "sources");
|
||||
|
||||
|
@ -25,12 +25,12 @@ public class OpenMaptilesMain {
|
|||
|
||||
runner
|
||||
.setProfile(createProfileWithWikidataTranslations(runner))
|
||||
// .addShapefileSource("EPSG:3857", OpenMapTilesProfile.LAKE_CENTERLINE_SOURCE,
|
||||
// sourcesDir.resolve("lake_centerline.shp.zip"))
|
||||
// .addShapefileSource(OpenMapTilesProfile.WATER_POLYGON_SOURCE,
|
||||
// sourcesDir.resolve("water-polygons-split-3857.zip"))
|
||||
// .addNaturalEarthSource(OpenMapTilesProfile.NATURAL_EARTH_SOURCE,
|
||||
// sourcesDir.resolve("natural_earth_vector.sqlite.zip"))
|
||||
.addShapefileSource("EPSG:3857", OpenMapTilesProfile.LAKE_CENTERLINE_SOURCE,
|
||||
sourcesDir.resolve("lake_centerline.shp.zip"))
|
||||
.addShapefileSource(OpenMapTilesProfile.WATER_POLYGON_SOURCE,
|
||||
sourcesDir.resolve("water-polygons-split-3857.zip"))
|
||||
.addNaturalEarthSource(OpenMapTilesProfile.NATURAL_EARTH_SOURCE,
|
||||
sourcesDir.resolve("natural_earth_vector.sqlite.zip"))
|
||||
.addOsmSource(OpenMapTilesProfile.OSM_SOURCE, sourcesDir.resolve(fallbackOsmFile))
|
||||
.setOutput("mbtiles", Path.of("data", "massachusetts.mbtiles"))
|
||||
.run();
|
||||
|
@ -46,7 +46,7 @@ public class OpenMaptilesMain {
|
|||
Path.of("data", "sources", "wikidata_names.json"));
|
||||
// most common languages: "en,ru,ar,zh,ja,ko,fr,de,fi,pl,es,be,br,he"
|
||||
List<String> languages = arguments
|
||||
.get("name_languages", "languages to use", Layers.LANGUAGES.toArray(String[]::new));
|
||||
.get("name_languages", "languages to use", OpenMapTilesSchema.LANGUAGES.toArray(String[]::new));
|
||||
var translations = Translations.defaultProvider(languages).setShouldTransliterate(transliterate);
|
||||
var profile = new OpenMapTilesProfile(translations, arguments, runner.stats());
|
||||
|
|
@ -15,10 +15,11 @@ import com.onthegomap.flatmap.Translations;
|
|||
import com.onthegomap.flatmap.VectorTileEncoder;
|
||||
import com.onthegomap.flatmap.geo.GeometryException;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Tables;
|
||||
import com.onthegomap.flatmap.read.OpenStreetMapReader;
|
||||
import com.onthegomap.flatmap.read.ReaderFeature;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -41,6 +42,7 @@ public class OpenMapTilesProfile implements Profile {
|
|||
private final List<Layer> layers;
|
||||
private final Map<Class<? extends Tables.Row>, List<Tables.RowHandler<Tables.Row>>> osmDispatchMap;
|
||||
private final Map<String, FeaturePostProcessor> postProcessors;
|
||||
private final List<FeatureProcessor> rawProcessors;
|
||||
|
||||
private MultiExpression.MultiExpressionIndex<Tables.Constructor> indexForType(String type) {
|
||||
return Tables.MAPPINGS
|
||||
|
@ -56,7 +58,7 @@ public class OpenMapTilesProfile implements Profile {
|
|||
}
|
||||
|
||||
public OpenMapTilesProfile(Translations translations, Arguments arguments, Stats stats) {
|
||||
this.layers = Layers.createInstances(translations, arguments, stats);
|
||||
this.layers = OpenMapTilesSchema.createInstances(translations, arguments, stats);
|
||||
osmDispatchMap = new HashMap<>();
|
||||
Tables.generateDispatchMap(layers).forEach((clazz, handlers) -> {
|
||||
osmDispatchMap.put(clazz, handlers.stream().map(handler -> {
|
||||
|
@ -69,10 +71,14 @@ public class OpenMapTilesProfile implements Profile {
|
|||
this.osmPolygonMappings = indexForType("polygon");
|
||||
this.osmRelationMemberMappings = indexForType("relation_member");
|
||||
postProcessors = new HashMap<>();
|
||||
rawProcessors = new ArrayList<>();
|
||||
for (Layer layer : layers) {
|
||||
if (layer instanceof FeaturePostProcessor postProcessor) {
|
||||
postProcessors.put(layer.name(), postProcessor);
|
||||
}
|
||||
if (layer instanceof FeatureProcessor processor) {
|
||||
rawProcessors.add(processor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -113,6 +119,10 @@ public class OpenMapTilesProfile implements Profile {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < rawProcessors.size(); i++) {
|
||||
rawProcessors.get(i).process(sourceFeature, features);
|
||||
}
|
||||
//
|
||||
// if (sourceFeature.isPoint()) {
|
||||
// if (sourceFeature.hasTag("natural", "peak", "volcano")) {
|
||||
|
@ -169,7 +179,7 @@ public class OpenMapTilesProfile implements Profile {
|
|||
return result == null ? List.of() : result;
|
||||
}
|
||||
|
||||
public interface SourceFeatureProcessors {
|
||||
public interface FeatureProcessor {
|
||||
|
||||
void process(SourceFeature feature, FeatureCollector features);
|
||||
}
|
||||
|
@ -193,21 +203,21 @@ public class OpenMapTilesProfile implements Profile {
|
|||
|
||||
@Override
|
||||
public String name() {
|
||||
return Layers.NAME;
|
||||
return OpenMapTilesSchema.NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String description() {
|
||||
return Layers.DESCRIPTION;
|
||||
return OpenMapTilesSchema.DESCRIPTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String attribution() {
|
||||
return Layers.ATTRIBUTION;
|
||||
return OpenMapTilesSchema.ATTRIBUTION;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String version() {
|
||||
return Layers.VERSION;
|
||||
return OpenMapTilesSchema.VERSION;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import com.onthegomap.flatmap.openmaptiles.MultiExpression;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Layers {
|
||||
public class OpenMapTilesSchema {
|
||||
|
||||
public static final String NAME = "OpenMapTiles";
|
||||
public static final String DESCRIPTION = "A tileset showcasing all layers in OpenMapTiles. https://openmaptiles.org";
|
|
@ -9,10 +9,10 @@ import com.onthegomap.flatmap.monitoring.Stats;
|
|||
import com.onthegomap.flatmap.openmaptiles.LanguageUtils;
|
||||
import com.onthegomap.flatmap.openmaptiles.MultiExpression;
|
||||
import com.onthegomap.flatmap.openmaptiles.Utils;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Tables;
|
||||
|
||||
public class AerodromeLabel implements Layers.AerodromeLabel, Tables.OsmAerodromeLabelPoint.Handler {
|
||||
public class AerodromeLabel implements OpenMapTilesSchema.AerodromeLabel, Tables.OsmAerodromeLabelPoint.Handler {
|
||||
|
||||
private final MultiExpression.MultiExpressionIndex<String> classLookup;
|
||||
private final Translations translations;
|
||||
|
|
|
@ -4,10 +4,11 @@ import com.onthegomap.flatmap.Arguments;
|
|||
import com.onthegomap.flatmap.FeatureCollector;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Tables;
|
||||
|
||||
public class Aeroway implements Layers.Aeroway, Tables.OsmAerowayLinestring.Handler, Tables.OsmAerowayPolygon.Handler,
|
||||
public class Aeroway implements OpenMapTilesSchema.Aeroway, Tables.OsmAerowayLinestring.Handler,
|
||||
Tables.OsmAerowayPolygon.Handler,
|
||||
Tables.OsmAerowayPoint.Handler {
|
||||
|
||||
public Aeroway(Translations translations, Arguments args, Stats stats) {
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.onthegomap.flatmap.openmaptiles.layers;
|
|||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
|
||||
public class Boundary implements Layers.Boundary {
|
||||
public class Boundary implements OpenMapTilesSchema.Boundary {
|
||||
|
||||
public Boundary(Translations translations, Arguments args, Stats stats) {
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.onthegomap.flatmap.openmaptiles.layers;
|
|||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
|
||||
public class Building implements Layers.Building {
|
||||
public class Building implements OpenMapTilesSchema.Building {
|
||||
|
||||
public Building(Translations translations, Arguments args, Stats stats) {
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.onthegomap.flatmap.openmaptiles.layers;
|
|||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
|
||||
public class Housenumber implements Layers.Housenumber {
|
||||
public class Housenumber implements OpenMapTilesSchema.Housenumber {
|
||||
|
||||
public Housenumber(Translations translations, Arguments args, Stats stats) {
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.onthegomap.flatmap.openmaptiles.layers;
|
|||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
|
||||
public class Landcover implements Layers.Landcover {
|
||||
public class Landcover implements OpenMapTilesSchema.Landcover {
|
||||
|
||||
public Landcover(Translations translations, Arguments args, Stats stats) {
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.onthegomap.flatmap.openmaptiles.layers;
|
|||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
|
||||
public class Landuse implements Layers.Landuse {
|
||||
public class Landuse implements OpenMapTilesSchema.Landuse {
|
||||
|
||||
public Landuse(Translations translations, Arguments args, Stats stats) {
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.onthegomap.flatmap.openmaptiles.layers;
|
||||
|
||||
import static com.onthegomap.flatmap.openmaptiles.LanguageUtils.getNames;
|
||||
import static com.onthegomap.flatmap.openmaptiles.Utils.elevationTags;
|
||||
import static com.onthegomap.flatmap.openmaptiles.Utils.nullIfEmpty;
|
||||
|
||||
|
@ -12,13 +11,14 @@ import com.onthegomap.flatmap.Parse;
|
|||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.VectorTileEncoder;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.LanguageUtils;
|
||||
import com.onthegomap.flatmap.openmaptiles.OpenMapTilesProfile;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Tables;
|
||||
import java.util.List;
|
||||
|
||||
public class MountainPeak implements
|
||||
Layers.MountainPeak,
|
||||
OpenMapTilesSchema.MountainPeak,
|
||||
Tables.OsmPeakPoint.Handler,
|
||||
OpenMapTilesProfile.FeaturePostProcessor {
|
||||
|
||||
|
@ -34,7 +34,7 @@ public class MountainPeak implements
|
|||
if (meters != null && Math.abs(meters) < 10_000) {
|
||||
features.point(LAYER_NAME)
|
||||
.setAttr(Fields.CLASS, element.source().getTag("natural"))
|
||||
.setAttrs(getNames(element.source().properties(), translations))
|
||||
.setAttrs(LanguageUtils.getNames(element.source().properties(), translations))
|
||||
.setAttrs(elevationTags(meters))
|
||||
.setBufferPixels(BUFFER_SIZE)
|
||||
.setZorder(
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.onthegomap.flatmap.openmaptiles.layers;
|
|||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
|
||||
public class Park implements Layers.Park {
|
||||
public class Park implements OpenMapTilesSchema.Park {
|
||||
|
||||
public Park(Translations translations, Arguments args, Stats stats) {
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.onthegomap.flatmap.openmaptiles.layers;
|
|||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
|
||||
public class Place implements Layers.Place {
|
||||
public class Place implements OpenMapTilesSchema.Place {
|
||||
|
||||
public Place(Translations translations, Arguments args, Stats stats) {
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.onthegomap.flatmap.openmaptiles.layers;
|
|||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
|
||||
public class Poi implements Layers.Poi {
|
||||
public class Poi implements OpenMapTilesSchema.Poi {
|
||||
|
||||
public Poi(Translations translations, Arguments args, Stats stats) {
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.onthegomap.flatmap.openmaptiles.layers;
|
|||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
|
||||
public class Transportation implements Layers.Transportation {
|
||||
public class Transportation implements OpenMapTilesSchema.Transportation {
|
||||
|
||||
public Transportation(Translations translations, Arguments args, Stats stats) {
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.onthegomap.flatmap.openmaptiles.layers;
|
|||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
|
||||
public class TransportationName implements Layers.TransportationName {
|
||||
public class TransportationName implements OpenMapTilesSchema.TransportationName {
|
||||
|
||||
public TransportationName(Translations translations, Arguments args, Stats stats) {
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.onthegomap.flatmap.openmaptiles.layers;
|
|||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
|
||||
public class Water implements Layers.Water {
|
||||
public class Water implements OpenMapTilesSchema.Water {
|
||||
|
||||
public Water(Translations translations, Arguments args, Stats stats) {
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ package com.onthegomap.flatmap.openmaptiles.layers;
|
|||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
|
||||
public class WaterName implements Layers.WaterName {
|
||||
public class WaterName implements OpenMapTilesSchema.WaterName {
|
||||
|
||||
public WaterName(Translations translations, Arguments args, Stats stats) {
|
||||
}
|
||||
|
|
|
@ -1,12 +1,90 @@
|
|||
package com.onthegomap.flatmap.openmaptiles.layers;
|
||||
|
||||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Layers;
|
||||
import static com.onthegomap.flatmap.openmaptiles.Utils.nullIfEmpty;
|
||||
|
||||
public class Waterway implements Layers.Waterway {
|
||||
import com.onthegomap.flatmap.Arguments;
|
||||
import com.onthegomap.flatmap.FeatureCollector;
|
||||
import com.onthegomap.flatmap.FeatureMerge;
|
||||
import com.onthegomap.flatmap.SourceFeature;
|
||||
import com.onthegomap.flatmap.Translations;
|
||||
import com.onthegomap.flatmap.VectorTileEncoder;
|
||||
import com.onthegomap.flatmap.ZoomFunction;
|
||||
import com.onthegomap.flatmap.geo.GeometryException;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.LanguageUtils;
|
||||
import com.onthegomap.flatmap.openmaptiles.OpenMapTilesProfile;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.OpenMapTilesSchema;
|
||||
import com.onthegomap.flatmap.openmaptiles.generated.Tables;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Waterway implements OpenMapTilesSchema.Waterway, Tables.OsmWaterwayLinestring.Handler,
|
||||
OpenMapTilesProfile.FeaturePostProcessor, OpenMapTilesProfile.FeatureProcessor {
|
||||
|
||||
private final Translations translations;
|
||||
|
||||
public Waterway(Translations translations, Arguments args, Stats stats) {
|
||||
this.translations = translations;
|
||||
}
|
||||
|
||||
private static final Map<String, Integer> minzooms = Map.of(
|
||||
"river", 12,
|
||||
"canal", 12,
|
||||
|
||||
"stream", 13,
|
||||
"drain", 13,
|
||||
"ditch", 13
|
||||
);
|
||||
|
||||
private static final ZoomFunction.MeterThresholds minPixelSizeThresholds = ZoomFunction.meterThresholds()
|
||||
.put(9, 8_000)
|
||||
.put(10, 4_000)
|
||||
.put(11, 1_000);
|
||||
|
||||
@Override
|
||||
public void process(Tables.OsmWaterwayLinestring element, FeatureCollector features) {
|
||||
String waterway = element.waterway();
|
||||
String name = nullIfEmpty(element.name());
|
||||
boolean important = "river".equals(waterway) && name != null;
|
||||
int minzoom = important ? 9 : minzooms.getOrDefault(element.waterway(), 14);
|
||||
features.line(LAYER_NAME)
|
||||
.setBufferPixels(BUFFER_SIZE)
|
||||
.setAttr(Fields.CLASS, element.waterway())
|
||||
.setAttrs(LanguageUtils.getNames(element.source().properties(), translations))
|
||||
.setZoomRange(minzoom, 14)
|
||||
// details only at higher zoom levels
|
||||
.setAttrWithMinzoom(Fields.BRUNNEL, element.isBridge() ? "bridge" : element.isTunnel() ? "tunnel" : null, 12)
|
||||
.setAttrWithMinzoom(Fields.INTERMITTENT, element.isIntermittent() ? 1 : 0, 12)
|
||||
// at lower zoom levels, we'll merge linestrings and limit length/clip afterwards
|
||||
.setBufferPixelOverrides(minPixelSizeThresholds).setMinPixelSizeBelowZoom(11, 0);
|
||||
}
|
||||
|
||||
private static record ZoomRange(int min, int max) {}
|
||||
|
||||
@Override
|
||||
public void process(SourceFeature feature, FeatureCollector features) {
|
||||
if (OpenMapTilesProfile.NATURAL_EARTH_SOURCE.equals(feature.getSource()) && feature.hasTag("featurecla", "River")) {
|
||||
ZoomRange zoom = switch (feature.getSourceLayer()) {
|
||||
case "ne_10m_rivers_lake_centerlines" -> new ZoomRange(6, 8);
|
||||
case "ne_50m_rivers_lake_centerlines" -> new ZoomRange(4, 5);
|
||||
case "ne_110m_rivers_lake_centerlines" -> new ZoomRange(3, 3);
|
||||
default -> null;
|
||||
};
|
||||
if (zoom != null) {
|
||||
features.line(LAYER_NAME)
|
||||
.setBufferPixels(BUFFER_SIZE)
|
||||
.setAttr(Fields.CLASS, "river")
|
||||
.setZoomRange(zoom.min, zoom.max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VectorTileEncoder.Feature> postProcess(int zoom, List<VectorTileEncoder.Feature> items)
|
||||
throws GeometryException {
|
||||
if (zoom >= 9 && zoom <= 11) {
|
||||
return FeatureMerge.mergeLineStrings(items, minPixelSizeThresholds.apply(zoom).doubleValue(), 0.1d, BUFFER_SIZE);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.onthegomap.flatmap.openmaptiles;
|
||||
|
||||
import static com.onthegomap.flatmap.TestUtils.assertSubmap;
|
||||
import static com.onthegomap.flatmap.openmaptiles.LanguageUtils.getNames;
|
||||
import static com.onthegomap.flatmap.openmaptiles.LanguageUtils.isLatin;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
@ -27,7 +26,7 @@ public class LanguageUtilsTest {
|
|||
"name", "name",
|
||||
"name_en", "english name",
|
||||
"name_de", "german name"
|
||||
), getNames(Map.of(
|
||||
), LanguageUtils.getNames(Map.of(
|
||||
"name", "name",
|
||||
"name:en", "english name",
|
||||
"name:de", "german name"
|
||||
|
@ -37,7 +36,7 @@ public class LanguageUtilsTest {
|
|||
"name", "name",
|
||||
"name_en", "name",
|
||||
"name_de", "german name"
|
||||
), getNames(Map.of(
|
||||
), LanguageUtils.getNames(Map.of(
|
||||
"name", "name",
|
||||
"name:de", "german name"
|
||||
), translations));
|
||||
|
@ -46,7 +45,7 @@ public class LanguageUtilsTest {
|
|||
"name", "name",
|
||||
"name_en", "english name",
|
||||
"name_de", "name"
|
||||
), getNames(Map.of(
|
||||
), LanguageUtils.getNames(Map.of(
|
||||
"name", "name",
|
||||
"name:en", "english name"
|
||||
), translations));
|
||||
|
@ -72,7 +71,7 @@ public class LanguageUtilsTest {
|
|||
if (!isLatin) {
|
||||
assertFalse(isLatin(in));
|
||||
} else {
|
||||
assertEquals(isLatin ? in : null, getNames(Map.of(
|
||||
assertEquals(isLatin ? in : null, LanguageUtils.getNames(Map.of(
|
||||
"name", in
|
||||
), translations).get("name:latin"));
|
||||
}
|
||||
|
@ -90,7 +89,7 @@ public class LanguageUtilsTest {
|
|||
"Japan / 日本 / Japan , 日本",
|
||||
}, nullValues = "null")
|
||||
public void testRemoveNonLatin(String in, String out) {
|
||||
assertEquals(out, getNames(Map.of(
|
||||
assertEquals(out, LanguageUtils.getNames(Map.of(
|
||||
"name", in
|
||||
), translations).get("name:nonlatin"));
|
||||
}
|
||||
|
@ -111,7 +110,7 @@ public class LanguageUtilsTest {
|
|||
"name:jp_rm, a, true",
|
||||
})
|
||||
public void testLatinFallbacks(String key, String value, boolean use) {
|
||||
assertEquals(use ? value : null, getNames(Map.of(
|
||||
assertEquals(use ? value : null, LanguageUtils.getNames(Map.of(
|
||||
key, value
|
||||
), translations).get("name:latin"));
|
||||
}
|
||||
|
@ -123,11 +122,11 @@ public class LanguageUtilsTest {
|
|||
"биологическом, biologičeskom",
|
||||
})
|
||||
public void testTransliterate(String in, String out) {
|
||||
assertEquals(out, getNames(Map.of(
|
||||
assertEquals(out, LanguageUtils.getNames(Map.of(
|
||||
"name", in
|
||||
), translations).get("name:latin"));
|
||||
translations.setShouldTransliterate(false);
|
||||
assertNull(getNames(Map.of(
|
||||
assertNull(LanguageUtils.getNames(Map.of(
|
||||
"name", in
|
||||
), translations).get("name:latin"));
|
||||
}
|
||||
|
@ -137,7 +136,7 @@ public class LanguageUtilsTest {
|
|||
wikidataTranslations.put(123, "es", "es name");
|
||||
assertSubmap(Map.of(
|
||||
"name:es", "es name"
|
||||
), getNames(Map.of(
|
||||
), LanguageUtils.getNames(Map.of(
|
||||
"name", "name",
|
||||
"wikidata", "Q123"
|
||||
), translations));
|
||||
|
@ -147,7 +146,7 @@ public class LanguageUtilsTest {
|
|||
public void testUseOsm() {
|
||||
assertSubmap(Map.of(
|
||||
"name:es", "es name osm"
|
||||
), getNames(Map.of(
|
||||
), LanguageUtils.getNames(Map.of(
|
||||
"name", "name",
|
||||
"wikidata", "Q123",
|
||||
"name:es", "es name osm"
|
||||
|
@ -160,7 +159,7 @@ public class LanguageUtilsTest {
|
|||
assertSubmap(Map.of(
|
||||
"name:es", "wd es name",
|
||||
"name:de", "de name osm"
|
||||
), getNames(Map.of(
|
||||
), LanguageUtils.getNames(Map.of(
|
||||
"name", "name",
|
||||
"wikidata", "Q123",
|
||||
"name:es", "es name osm",
|
||||
|
@ -170,7 +169,7 @@ public class LanguageUtilsTest {
|
|||
|
||||
@Test
|
||||
public void testDontUseTranslationsWhenNotSpecified() {
|
||||
var result = getNames(Map.of(
|
||||
var result = LanguageUtils.getNamesWithoutTranslations(Map.of(
|
||||
"name", "name",
|
||||
"wikidata", "Q123",
|
||||
"name:es", "es name osm",
|
||||
|
@ -184,7 +183,7 @@ public class LanguageUtilsTest {
|
|||
@Test
|
||||
public void testIgnoreLanguages() {
|
||||
wikidataTranslations.put(123, "ja", "ja name wd");
|
||||
var result = getNames(Map.of(
|
||||
var result = LanguageUtils.getNamesWithoutTranslations(Map.of(
|
||||
"name", "name",
|
||||
"wikidata", "Q123",
|
||||
"name:ja", "ja name osm"
|
||||
|
|
|
@ -4,6 +4,7 @@ import static com.onthegomap.flatmap.TestUtils.assertSubmap;
|
|||
import static com.onthegomap.flatmap.TestUtils.newLineString;
|
||||
import static com.onthegomap.flatmap.TestUtils.newPoint;
|
||||
import static com.onthegomap.flatmap.TestUtils.newPolygon;
|
||||
import static com.onthegomap.flatmap.openmaptiles.OpenMapTilesProfile.NATURAL_EARTH_SOURCE;
|
||||
import static com.onthegomap.flatmap.openmaptiles.OpenMapTilesProfile.OSM_SOURCE;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
|
@ -22,6 +23,7 @@ import com.onthegomap.flatmap.Wikidata;
|
|||
import com.onthegomap.flatmap.geo.GeometryException;
|
||||
import com.onthegomap.flatmap.monitoring.Stats;
|
||||
import com.onthegomap.flatmap.openmaptiles.layers.MountainPeak;
|
||||
import com.onthegomap.flatmap.openmaptiles.layers.Waterway;
|
||||
import com.onthegomap.flatmap.read.ReaderFeature;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
@ -147,7 +149,7 @@ public class OpenMaptilesProfileTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testMountainPeakPostProcessingEmpty() throws GeometryException {
|
||||
public void testMountainPeakPostProcessing() throws GeometryException {
|
||||
assertEquals(List.of(), profile.postProcessLayerFeatures(MountainPeak.LAYER_NAME, 13, List.of()));
|
||||
|
||||
assertEquals(List.of(pointFeature(
|
||||
|
@ -383,6 +385,177 @@ public class OpenMaptilesProfileTest {
|
|||
))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWaterwayImportantRiverProcess() {
|
||||
var charlesRiver = process(lineFeature(Map.of(
|
||||
"waterway", "river",
|
||||
"name", "charles river",
|
||||
"name:es", "es name"
|
||||
)));
|
||||
assertFeatures(14, List.of(Map.of(
|
||||
"class", "river",
|
||||
"name", "charles river",
|
||||
"name:es", "es name",
|
||||
"intermittent", 0,
|
||||
|
||||
"_layer", "waterway",
|
||||
"_type", "line",
|
||||
"_minzoom", 9,
|
||||
"_maxzoom", 14,
|
||||
"_buffer", 4d
|
||||
)), charlesRiver);
|
||||
assertFeatures(11, List.of(Map.of(
|
||||
"class", "river",
|
||||
"name", "charles river",
|
||||
"name:es", "es name",
|
||||
"intermittent", "<null>",
|
||||
"_buffer", 13.082664546679323
|
||||
)), charlesRiver);
|
||||
assertFeatures(10, List.of(Map.of(
|
||||
"class", "river",
|
||||
"_buffer", 26.165329093358647
|
||||
)), charlesRiver);
|
||||
assertFeatures(9, List.of(Map.of(
|
||||
"class", "river",
|
||||
"_buffer", 26.165329093358647
|
||||
)), charlesRiver);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWaterwayImportantRiverPostProcess() throws GeometryException {
|
||||
var line1 = new VectorTileEncoder.Feature(
|
||||
Waterway.LAYER_NAME,
|
||||
1,
|
||||
VectorTileEncoder.encodeGeometry(newLineString(0, 0, 10, 0)),
|
||||
Map.of("name", "river"),
|
||||
0
|
||||
);
|
||||
var line2 = new VectorTileEncoder.Feature(
|
||||
Waterway.LAYER_NAME,
|
||||
1,
|
||||
VectorTileEncoder.encodeGeometry(newLineString(10, 0, 20, 0)),
|
||||
Map.of("name", "river"),
|
||||
0
|
||||
);
|
||||
var connected = new VectorTileEncoder.Feature(
|
||||
Waterway.LAYER_NAME,
|
||||
1,
|
||||
VectorTileEncoder.encodeGeometry(newLineString(00, 0, 20, 0)),
|
||||
Map.of("name", "river"),
|
||||
0
|
||||
);
|
||||
|
||||
assertEquals(
|
||||
List.of(),
|
||||
profile.postProcessLayerFeatures(Waterway.LAYER_NAME, 11, List.of())
|
||||
);
|
||||
assertEquals(
|
||||
List.of(line1, line2),
|
||||
profile.postProcessLayerFeatures(Waterway.LAYER_NAME, 12, List.of(line1, line2))
|
||||
);
|
||||
assertEquals(
|
||||
List.of(connected),
|
||||
profile.postProcessLayerFeatures(Waterway.LAYER_NAME, 11, List.of(line1, line2))
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWaterwaySmaller() {
|
||||
// river with no name is not important
|
||||
assertFeatures(14, List.of(Map.of(
|
||||
"class", "river",
|
||||
"brunnel", "bridge",
|
||||
|
||||
"_layer", "waterway",
|
||||
"_type", "line",
|
||||
"_minzoom", 12
|
||||
)), process(lineFeature(Map.of(
|
||||
"waterway", "river",
|
||||
"bridge", "1"
|
||||
))));
|
||||
|
||||
assertFeatures(14, List.of(Map.of(
|
||||
"class", "canal",
|
||||
"_layer", "waterway",
|
||||
"_type", "line",
|
||||
"_minzoom", 12
|
||||
)), process(lineFeature(Map.of(
|
||||
"waterway", "canal",
|
||||
"name", "name"
|
||||
))));
|
||||
|
||||
assertFeatures(14, List.of(Map.of(
|
||||
"class", "stream",
|
||||
"_layer", "waterway",
|
||||
"_type", "line",
|
||||
"_minzoom", 13
|
||||
)), process(lineFeature(Map.of(
|
||||
"waterway", "stream",
|
||||
"name", "name"
|
||||
))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWaterwayNaturalEarth() {
|
||||
assertFeatures(3, List.of(Map.of(
|
||||
"class", "river",
|
||||
"name", "<null>",
|
||||
"intermittent", "<null>",
|
||||
|
||||
"_layer", "waterway",
|
||||
"_type", "line",
|
||||
"_minzoom", 3,
|
||||
"_maxzoom", 3
|
||||
)), process(new ReaderFeature(
|
||||
newLineString(0, 0, 1, 1),
|
||||
Map.of(
|
||||
"featurecla", "River",
|
||||
"name", "name"
|
||||
),
|
||||
NATURAL_EARTH_SOURCE,
|
||||
"ne_110m_rivers_lake_centerlines",
|
||||
0
|
||||
)));
|
||||
|
||||
assertFeatures(6, List.of(Map.of(
|
||||
"class", "river",
|
||||
"intermittent", "<null>",
|
||||
|
||||
"_layer", "waterway",
|
||||
"_type", "line",
|
||||
"_minzoom", 4,
|
||||
"_maxzoom", 5
|
||||
)), process(new ReaderFeature(
|
||||
newLineString(0, 0, 1, 1),
|
||||
Map.of(
|
||||
"featurecla", "River",
|
||||
"name", "name"
|
||||
),
|
||||
NATURAL_EARTH_SOURCE,
|
||||
"ne_50m_rivers_lake_centerlines",
|
||||
0
|
||||
)));
|
||||
|
||||
assertFeatures(6, List.of(Map.of(
|
||||
"class", "river",
|
||||
"intermittent", "<null>",
|
||||
|
||||
"_layer", "waterway",
|
||||
"_type", "line",
|
||||
"_minzoom", 6,
|
||||
"_maxzoom", 8
|
||||
)), process(new ReaderFeature(
|
||||
newLineString(0, 0, 1, 1),
|
||||
Map.of(
|
||||
"featurecla", "River",
|
||||
"name", "name"
|
||||
),
|
||||
NATURAL_EARTH_SOURCE,
|
||||
"ne_10m_rivers_lake_centerlines",
|
||||
0
|
||||
)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCaresAboutWikidata() {
|
||||
var node = new ReaderNode(1, 1, 1);
|
||||
|
|
Ładowanie…
Reference in New Issue