> handlers
- ) {}
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/Generate.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/Generate.java
deleted file mode 100644
index f6f7fbb4fa..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/Generate.java
+++ /dev/null
@@ -1,764 +0,0 @@
-package com.onthegomap.planetiler.basemap;
-
-import static com.onthegomap.planetiler.expression.Expression.*;
-import static java.util.stream.Collectors.joining;
-
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.base.CaseFormat;
-import com.onthegomap.planetiler.config.Arguments;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.expression.Expression;
-import com.onthegomap.planetiler.expression.MultiExpression;
-import com.onthegomap.planetiler.util.Downloader;
-import com.onthegomap.planetiler.util.FileUtils;
-import com.onthegomap.planetiler.util.Format;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.stream.Stream;
-import org.commonmark.parser.Parser;
-import org.commonmark.renderer.html.HtmlRenderer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.yaml.snakeyaml.LoaderOptions;
-import org.yaml.snakeyaml.Yaml;
-
-/**
- * Generates code in the {@code generated} package from the OpenMapTiles schema crawled from a tag or branch in the
- * OpenMapTiles GitHub repo.
- *
- * {@code OpenMapTilesSchema.java} contains the output layer definitions (i.e. attributes and allowed values) so that
- * layer implementations in {@code layers} package can reference them instead of hard-coding.
- *
- * {@code Tables.java} contains the imposm3 table definitions from
- * mapping.yaml files in the OpenMapTiles repo. Layers in the {@code layer} package can extend the {@code Handler}
- * nested class for a table definition to "subscribe" to OSM elements that imposm3 would put in that table.
- *
- * To run use {@code ./scripts/regenerate-openmaptiles.sh}
- */
-public class Generate {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(Generate.class);
- private static final ObjectMapper mapper = new ObjectMapper();
- private static final Yaml yaml;
- private static final String LINE_SEPARATOR = System.lineSeparator();
- private static final String GENERATED_FILE_HEADER = """
- /*
- Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
- All rights reserved.
-
- Code license: BSD 3-Clause License
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- * Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
- Design license: CC-BY 4.0
-
- See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
- */
- // AUTOGENERATED BY Generate.java -- DO NOT MODIFY
- """;
- private static final Parser parser = Parser.builder().build();
- private static final HtmlRenderer renderer = HtmlRenderer.builder().build();
-
- static {
- // bump the default limit of 50
- var options = new LoaderOptions();
- options.setMaxAliasesForCollections(1_000);
- yaml = new Yaml(options);
- }
-
- private static T loadAndParseYaml(String url, PlanetilerConfig config, Class clazz) throws IOException {
- LOGGER.info("reading {}", url);
- try (var stream = Downloader.openStream(url, config)) {
- // Jackson yaml parsing does not handle anchors and references, so first parse the input
- // using SnakeYAML, then parse SnakeYAML's output using Jackson to get it into our records.
- Map parsed = yaml.load(stream);
- return mapper.convertValue(parsed, clazz);
- }
- }
-
- static T parseYaml(String string, Class clazz) {
- // Jackson yaml parsing does not handle anchors and references, so first parse the input
- // using SnakeYAML, then parse SnakeYAML's output using Jackson to get it into our records.
- Map parsed = yaml.load(string);
- return mapper.convertValue(parsed, clazz);
- }
-
- static JsonNode parseYaml(String string) {
- return string == null ? null : parseYaml(string, JsonNode.class);
- }
-
- public static void main(String[] args) throws IOException {
- Arguments arguments = Arguments.fromArgsOrConfigFile(args);
- PlanetilerConfig planetilerConfig = PlanetilerConfig.from(arguments);
- String tag = arguments.getString("tag", "openmaptiles tag to use", "v3.13.1");
- String baseUrl = arguments.getString("base-url", "the url used to download the openmaptiles.yml",
- "https://raw.githubusercontent.com/openmaptiles/openmaptiles/");
- String base = baseUrl + tag + "/";
-
- // start crawling from openmaptiles.yaml
- // then crawl schema from each layers//.yaml file that it references
- // then crawl table definitions from each layers//mapping.yaml file that the layer references
- String rootUrl = base + "openmaptiles.yaml";
- OpenmaptilesConfig config = loadAndParseYaml(rootUrl, planetilerConfig, OpenmaptilesConfig.class);
-
- List layers = new ArrayList<>();
- Set imposm3MappingFiles = new LinkedHashSet<>();
- for (String layerFile : config.tileset.layers) {
- String layerURL = base + layerFile;
- LayerConfig layer = loadAndParseYaml(layerURL, planetilerConfig, LayerConfig.class);
- layers.add(layer);
- for (Datasource datasource : layer.datasources) {
- if ("imposm3".equals(datasource.type)) {
- String mappingPath = Path.of(layerFile).resolveSibling(datasource.mapping_file).normalize().toString();
- imposm3MappingFiles.add(base + mappingPath);
- } else {
- LOGGER.warn("Unknown datasource type: {}", datasource.type);
- }
- }
- }
-
- Map tables = new LinkedHashMap<>();
- for (String uri : imposm3MappingFiles) {
- Imposm3Mapping layer = loadAndParseYaml(uri, planetilerConfig, Imposm3Mapping.class);
- tables.putAll(layer.tables);
- }
-
- String packageName = "com.onthegomap.planetiler.basemap.generated";
- String[] packageParts = packageName.split("\\.");
- Path output = Path.of("planetiler-basemap", "src", "main", "java")
- .resolve(Path.of(packageParts[0], Arrays.copyOfRange(packageParts, 1, packageParts.length)));
-
- FileUtils.deleteDirectory(output);
- Files.createDirectories(output);
-
- emitLayerSchemaDefinitions(config.tileset, layers, packageName, output, tag);
- emitTableDefinitions(tables, packageName, output, tag);
- LOGGER.info("Done!");
- }
-
- /** Generates {@code OpenMapTilesSchema.java} */
- private static void emitLayerSchemaDefinitions(OpenmaptilesTileSet info, List layers, String packageName,
- Path output, String tag)
- throws IOException {
- StringBuilder schemaClass = new StringBuilder();
- schemaClass.append(
- """
- %s
- package %s;
-
- import static com.onthegomap.planetiler.expression.Expression.*;
- import com.onthegomap.planetiler.config.PlanetilerConfig;
- import com.onthegomap.planetiler.stats.Stats;
- import com.onthegomap.planetiler.expression.MultiExpression;
- import com.onthegomap.planetiler.basemap.Layer;
- import com.onthegomap.planetiler.util.Translations;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
-
- /**
- * All vector tile layer definitions, attributes, and allowed values generated from the
- * OpenMapTiles vector tile schema %s.
- */
- @SuppressWarnings("unused")
- public class OpenMapTilesSchema {
- public static final String NAME = %s;
- public static final String DESCRIPTION = %s;
- public static final String VERSION = %s;
- public static final String ATTRIBUTION = %s;
- public static final List LANGUAGES = List.of(%s);
-
- /** Returns a list of expected layer implementation instances from the {@code layers} package. */
- public static List createInstances(Translations translations, PlanetilerConfig config, Stats stats) {
- return List.of(
- %s
- );
- }
- """
- .formatted(
- GENERATED_FILE_HEADER,
- packageName,
- escapeJavadoc(tag),
- escapeJavadoc(tag),
- Format.quote(info.name),
- Format.quote(info.description),
- Format.quote(info.version),
- Format.quote(info.attribution),
- info.languages.stream().map(Format::quote).collect(joining(", ")),
- layers.stream()
- .map(
- l -> "new com.onthegomap.planetiler.basemap.layers.%s(translations, config, stats)"
- .formatted(lowerUnderscoreToUpperCamel(l.layer.id)))
- .collect(joining("," + LINE_SEPARATOR))
- .indent(6).trim()
- ));
- for (var layer : layers) {
- String layerCode = generateCodeForLayer(tag, layer);
- schemaClass.append(layerCode);
- }
-
- schemaClass.append("}");
- Files.writeString(output.resolve("OpenMapTilesSchema.java"), schemaClass);
- }
-
- private static String generateCodeForLayer(String tag, LayerConfig layer) {
- String layerName = layer.layer.id;
- String className = lowerUnderscoreToUpperCamel(layerName);
-
- StringBuilder fields = new StringBuilder();
- StringBuilder fieldValues = new StringBuilder();
- StringBuilder fieldMappings = new StringBuilder();
-
- layer.layer.fields.forEach((name, value) -> {
- JsonNode valuesNode = value.get("values");
- List valuesForComment = valuesNode == null ? List.of() : valuesNode.isArray() ?
- iterToList(valuesNode.elements()).stream().map(Objects::toString).toList() :
- iterToList(valuesNode.fieldNames());
- String javadocDescription = markdownToJavadoc(getFieldDescription(value));
- fields.append("""
- %s
- public static final String %s = %s;
- """.formatted(
- valuesForComment.isEmpty() ? "/** %s */".formatted(javadocDescription) : """
-
- /**
- * %s
- *
- * allowed values:
- *
- */
- """.stripTrailing().formatted(javadocDescription,
- valuesForComment.stream().map(v -> "" + v).collect(joining(LINE_SEPARATOR + " * "))),
- name.toUpperCase(Locale.ROOT),
- Format.quote(name)
- ).indent(4));
-
- List values = valuesNode == null ? List.of() : valuesNode.isArray() ?
- iterToList(valuesNode.elements()).stream().filter(JsonNode::isTextual).map(JsonNode::textValue)
- .map(t -> t.replaceAll(" .*", "")).toList() :
- iterToList(valuesNode.fieldNames());
- if (values.size() > 0) {
- fieldValues.append(values.stream()
- .map(v -> "public static final String %s = %s;"
- .formatted(name.toUpperCase(Locale.ROOT) + "_" + v.toUpperCase(Locale.ROOT).replace('-', '_'),
- Format.quote(v)))
- .collect(joining(LINE_SEPARATOR)).indent(2).strip()
- .indent(4));
- fieldValues.append("public static final Set %s = Set.of(%s);".formatted(
- name.toUpperCase(Locale.ROOT) + "_VALUES",
- values.stream().map(Format::quote).collect(joining(", "))
- ).indent(4));
- }
-
- if (valuesNode != null && valuesNode.isObject()) {
- MultiExpression mapping = generateFieldMapping(valuesNode);
- fieldMappings.append(" public static final MultiExpression %s = %s;%n"
- .formatted(lowerUnderscoreToUpperCamel(name), generateJavaCode(mapping)));
- }
- });
-
- return """
- /**
- * %s
- *
- * Generated from %s.yaml
- */
- public interface %s extends Layer {
- double BUFFER_SIZE = %s;
- String LAYER_NAME = %s;
- @Override
- default String name() {
- return LAYER_NAME;
- }
- /** Attribute names for map elements in the %s layer. */
- final class Fields {
- %s
- }
- /** Attribute values for map elements in the %s layer. */
- final class FieldValues {
- %s
- }
- /** Complex mappings to generate attribute values from OSM element tags in the %s layer. */
- final class FieldMappings {
- %s
- }
- }
- """.formatted(
- markdownToJavadoc(layer.layer.description),
- escapeJavadoc(tag),
- escapeJavadoc(layerName),
- escapeJavadoc(layerName),
- escapeJavadoc(layerName),
- className,
- layer.layer.buffer_size,
- Format.quote(layerName),
- escapeJavadoc(layerName),
- fields.toString().strip(),
- escapeJavadoc(layerName),
- fieldValues.toString().strip(),
- escapeJavadoc(layerName),
- fieldMappings.toString().strip()
- ).indent(2);
- }
-
- /** Generates {@code Tables.java} */
- private static void emitTableDefinitions(Map tables, String packageName, Path output,
- String tag)
- throws IOException {
- StringBuilder tablesClass = new StringBuilder();
- tablesClass.append(
- """
- %s
- package %s;
-
- import static com.onthegomap.planetiler.expression.Expression.*;
-
- import com.onthegomap.planetiler.expression.Expression;
- import com.onthegomap.planetiler.expression.MultiExpression;
- import com.onthegomap.planetiler.FeatureCollector;
- import com.onthegomap.planetiler.reader.SourceFeature;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.List;
- import java.util.Map;
- import java.util.Set;
-
- /**
- * OSM element parsers generated from the imposm3 table definitions
- * in the OpenMapTiles vector tile schema.
- *
- * These filter and parse the raw OSM key/value attribute pairs on tags into records with fields that match the
- * columns in the tables that imposm3 would generate. Layer implementations can "subscribe" to elements from each
- * "table" but implementing the table's {@code Handler} interface and use the element's typed API to access
- * attributes.
- */
- @SuppressWarnings("unused")
- public class Tables {
- /** A parsed OSM element that would appear in a "row" of the imposm3 table. */
- public interface Row {
-
- /** Returns the original OSM element. */
- SourceFeature source();
- }
-
- /** A functional interface that the constructor of a new table row can be coerced to. */
- @FunctionalInterface
- public interface Constructor {
-
- Row create(SourceFeature source, String mappingKey);
- }
-
- /** The {@code rowClass} of an imposm3 table row and its constructor coerced to a {@link Constructor}. */
- public record RowClassAndConstructor(
- Class extends Row> rowClass,
- Constructor create
- ) {}
-
- /** A functional interface that the typed handler method that a layer implementation can be coerced to. */
- @FunctionalInterface
- public interface RowHandler {
-
- /** Process a typed element according to the profile. */
- void process(T element, FeatureCollector features);
- }
-
- /** The {@code handlerClass} of a layer handler and it's {@code process} method coerced to a {@link RowHandler}. */
- public record RowHandlerAndClass(
- Class> handlerClass,
- RowHandler handler
- ) {}
- """
- .formatted(GENERATED_FILE_HEADER, packageName, escapeJavadoc(tag)));
-
- List classNames = new ArrayList<>();
- Map fieldNameToType = new TreeMap<>();
- for (var entry : tables.entrySet()) {
- String key = entry.getKey();
- Imposm3Table table = entry.getValue();
- List fields = parseTableFields(table);
- for (var field : fields) {
- String existing = fieldNameToType.get(field.name);
- if (existing == null) {
- fieldNameToType.put(field.name, field.clazz);
- } else if (!existing.equals(field.clazz)) {
- throw new IllegalArgumentException(
- "Field " + field.name + " has both " + existing + " and " + field.clazz + " types");
- }
- }
- Expression mappingExpression = parseImposm3MappingExpression(table);
- String mapping = """
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = %s;
- """.formatted(
- mappingExpression.generateJavaCode()
- );
- String tableName = "osm_" + key;
- String className = lowerUnderscoreToUpperCamel(tableName);
- if (!"relation_member".equals(table.type)) {
- classNames.add(className);
-
- tablesClass.append("""
- /** An OSM element that would appear in the {@code %s} table generated by imposm3. */
- public record %s(%s) implements Row, %s {
- public %s(SourceFeature source, String mappingKey) {
- this(%s);
- }
- %s
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link %s}.
- */
- public interface Handler {
- void process(%s element, FeatureCollector features);
- }
- }
- """.formatted(
- tableName,
- escapeJavadoc(className),
- fields.stream().map(c -> "@Override " + c.clazz + " " + lowerUnderscoreToLowerCamel(c.name))
- .collect(joining(", ")),
- fields.stream().map(c -> lowerUnderscoreToUpperCamel("with_" + c.name))
- .collect(joining(", ")),
- className,
- fields.stream().map(c -> c.extractCode).collect(joining(", ")),
- mapping,
- escapeJavadoc(className),
- className
- ).indent(2));
- }
- }
-
- tablesClass.append(fieldNameToType.entrySet().stream().map(e -> {
- String attrName = lowerUnderscoreToLowerCamel(e.getKey());
- String type = e.getValue();
- String interfaceName = lowerUnderscoreToUpperCamel("with_" + e.getKey());
- return """
- /** Rows with a %s %s attribute. */
- public interface %s {
- %s %s();
- }
- """.formatted(
- escapeJavadoc(type),
- escapeJavadoc(attrName),
- interfaceName,
- type,
- attrName);
- }).collect(joining(LINE_SEPARATOR)).indent(2));
-
- tablesClass.append("""
- /** Index to efficiently choose which imposm3 "tables" an element should appear in based on its attributes. */
- public static final MultiExpression MAPPINGS = MultiExpression.of(List.of(
- %s
- ));
- """.formatted(
- classNames.stream().map(
- className -> "MultiExpression.entry(new RowClassAndConstructor(%s.class, %s::new), %s.MAPPING)".formatted(
- className, className, className))
- .collect(joining("," + LINE_SEPARATOR)).indent(2).strip()
- ).indent(2));
-
- String handlerCondition = classNames.stream()
- .map(
- className -> """
- if (handler instanceof %s.Handler typedHandler) {
- result.computeIfAbsent(%s.class, cls -> new ArrayList<>()).add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }"""
- .formatted(className, className)
- ).collect(joining(LINE_SEPARATOR));
- tablesClass.append("""
- /**
- * Returns a map from imposm3 "table row" class to the layers that have a handler for it from a list of layer
- * implementations.
- */
- public static Map, List>> generateDispatchMap(List> handlers) {
- Map, List>> result = new HashMap<>();
- for (var handler : handlers) {
- %s
- }
- return result;
- }
- }
- """.formatted(handlerCondition.indent(6).trim()));
- Files.writeString(output.resolve("Tables.java"), tablesClass);
- }
-
- /**
- * Returns an {@link Expression} that implements the same logic as the
- * Imposm3 Data Mapping definition for a table.
- */
- static Expression parseImposm3MappingExpression(Imposm3Table table) {
- if (table.type_mappings != null) {
- return or(
- table.type_mappings.entrySet().stream()
- .map(entry -> parseImposm3MappingExpression(entry.getKey(), entry.getValue(), table.filters)
- ).toList()
- ).simplify();
- } else {
- return parseImposm3MappingExpression(table.type, table.mapping, table.filters);
- }
- }
-
- /**
- * Returns an {@link Expression} that implements the same logic as the
- * Imposm3 Data Mapping filters for a table.
- */
- static Expression parseImposm3MappingExpression(String type, JsonNode mapping, Imposm3Filters filters) {
- return and(
- or(parseFieldMappingExpression(mapping).toList()),
- and(
- filters == null || filters.require == null ? List.of() : parseFieldMappingExpression(filters.require).toList()),
- not(or(
- filters == null || filters.reject == null ? List.of() : parseFieldMappingExpression(filters.reject).toList())),
- matchType(type.replaceAll("s$", ""))
- ).simplify();
- }
-
- private static List parseTableFields(Imposm3Table tableDefinition) {
- List result = new ArrayList<>();
- boolean relationMember = "relation_member".equals(tableDefinition.type);
- for (Imposm3Column col : tableDefinition.columns) {
- if (relationMember && col.from_member) {
- // layers process relation info that they need manually
- continue;
- }
- switch (col.type) {
- case "id", "validated_geometry", "area", "hstore_tags", "geometry" -> {
- // do nothing - already on source feature
- }
- case "member_id", "member_role", "member_type", "member_index" -> {
- // do nothing
- }
- case "mapping_key" -> result
- .add(new OsmTableField("String", col.name, "mappingKey"));
- case "mapping_value" -> result
- .add(new OsmTableField("String", col.name, "source.getString(mappingKey)"));
- case "string" -> result
- .add(new OsmTableField("String", col.name,
- "source.getString(\"%s\")".formatted(Objects.requireNonNull(col.key, col.toString()))));
- case "bool" -> result
- .add(new OsmTableField("boolean", col.name,
- "source.getBoolean(\"%s\")".formatted(Objects.requireNonNull(col.key, col.toString()))));
- case "integer" -> result
- .add(new OsmTableField("long", col.name,
- "source.getLong(\"%s\")".formatted(Objects.requireNonNull(col.key, col.toString()))));
- case "wayzorder" -> result.add(new OsmTableField("int", col.name, "source.getWayZorder()"));
- case "direction" -> result.add(new OsmTableField("int", col.name,
- "source.getDirection(\"%s\")".formatted(Objects.requireNonNull(col.key, col.toString()))));
- default -> throw new IllegalArgumentException("Unhandled column: " + col.type);
- }
- }
- result.add(new OsmTableField("SourceFeature", "source", "source"));
- return result;
- }
-
- /**
- * Returns a {@link MultiExpression} to efficiently determine the value for an output vector tile feature (i.e.
- * "class") based on the "field mapping" defined in the layer schema definition.
- */
- static MultiExpression generateFieldMapping(JsonNode valuesNode) {
- MultiExpression mapping = MultiExpression.of(new ArrayList<>());
- valuesNode.fields().forEachRemaining(entry -> {
- String field = entry.getKey();
- JsonNode node = entry.getValue();
- Expression expression = or(parseFieldMappingExpression(node).toList()).simplify();
- if (!expression.equals(or()) && !expression.equals(and())) {
- mapping.expressions().add(MultiExpression.entry(field, expression));
- }
- });
- return mapping;
- }
-
- private static Stream parseFieldMappingExpression(JsonNode node) {
- if (node.isObject()) {
- List keys = iterToList(node.fieldNames());
- if (keys.contains("__AND__")) {
- if (keys.size() > 1) {
- throw new IllegalArgumentException("Cannot combine __AND__ with others");
- }
- return Stream.of(and(parseFieldMappingExpression(node.get("__AND__")).toList()));
- } else if (keys.contains("__OR__")) {
- if (keys.size() > 1) {
- throw new IllegalArgumentException("Cannot combine __OR__ with others");
- }
- return Stream.of(or(parseFieldMappingExpression(node.get("__OR__")).toList()));
- } else {
- return iterToList(node.fields()).stream().map(entry -> {
- String field = entry.getKey();
- List value = toFlatList(entry.getValue()).map(JsonNode::textValue).filter(Objects::nonNull).toList();
- return value.isEmpty() || value.contains("__any__") ? matchField(field) : matchAny(field, value);
- });
- }
- } else if (node.isArray()) {
- return iterToList(node.elements()).stream().flatMap(Generate::parseFieldMappingExpression);
- } else if (node.isNull()) {
- return Stream.empty();
- } else {
- throw new IllegalArgumentException("parseExpression input not handled: " + node);
- }
- }
-
- /**
- * Returns a flattened list of all the elements in nested arrays from {@code node}.
- *
- * For example: {@code [[[a, b], c], [d]} becomes {@code [a, b, c, d]}
- *
- * And {@code a} becomes {@code [a]}
- */
- private static Stream toFlatList(JsonNode node) {
- return node.isArray() ? iterToList(node.elements()).stream().flatMap(Generate::toFlatList) : Stream.of(node);
- }
-
- /** Returns java code that will recreate an {@link MultiExpression} identical to {@code mapping}. */
- private static String generateJavaCode(MultiExpression mapping) {
- return "MultiExpression.of(List.of(" + mapping.expressions().stream()
- .map(s -> "MultiExpression.entry(%s, %s)".formatted(Format.quote(s.result()), s.expression().generateJavaCode()))
- .collect(joining(", ")) + "))";
- }
-
- private static String lowerUnderscoreToLowerCamel(String name) {
- return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name);
- }
-
- private static String lowerUnderscoreToUpperCamel(String name) {
- return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name);
- }
-
- private static List iterToList(Iterator iter) {
- List result = new ArrayList<>();
- iter.forEachRemaining(result::add);
- return result;
- }
-
- /** Renders {@code markdown} as HTML and returns comment text safe to insert in generated javadoc. */
- private static String markdownToJavadoc(String markdown) {
- return Stream.of(markdown.strip().split("[\r\n][\r\n]+"))
- .map(p -> parser.parse(p.strip()))
- .map(node -> escapeJavadoc(renderer.render(node)))
- .map(p -> p.replaceAll("((^)|(
$))", "").strip())
- .collect(joining(LINE_SEPARATOR + "" + LINE_SEPARATOR));
- }
-
- /** Returns {@code comment} text safe to insert in generated javadoc. */
- private static String escapeJavadoc(String comment) {
- return comment.strip().replaceAll("[\n\r*\\s]+", " ");
- }
-
- private static String getFieldDescription(JsonNode value) {
- if (value.isTextual()) {
- return value.textValue();
- } else {
- return value.get("description").textValue();
- }
- }
-
- /*
- * Models for deserializing yaml into:
- */
-
- private record OpenmaptilesConfig(
- OpenmaptilesTileSet tileset
- ) {}
-
- @JsonIgnoreProperties(ignoreUnknown = true)
- private record OpenmaptilesTileSet(
- List layers,
- String version,
- String attribution,
- String name,
- String description,
- List languages
- ) {}
-
- @JsonIgnoreProperties(ignoreUnknown = true)
- private record LayerDetails(
- String id,
- String description,
- Map fields,
- double buffer_size
- ) {}
-
- private record Datasource(
- String type,
- String mapping_file
- ) {}
-
- @JsonIgnoreProperties(ignoreUnknown = true)
- private record LayerConfig(
- LayerDetails layer,
- List datasources
- ) {}
-
- private record Imposm3Column(
- String type,
- String name,
- String key,
- boolean from_member
- ) {}
-
- record Imposm3Filters(
- JsonNode reject,
- JsonNode require
- ) {}
-
- record Imposm3Table(
- String type,
- @JsonProperty("_resolve_wikidata") boolean resolveWikidata,
- List columns,
- Imposm3Filters filters,
- JsonNode mapping,
- Map type_mappings,
- @JsonProperty("relation_types") List relationTypes
- ) {}
-
- @JsonIgnoreProperties(ignoreUnknown = true)
- private record Imposm3Mapping(
- Map tables
- ) {}
-
- private record OsmTableField(
- String clazz,
- String name,
- String extractCode
- ) {}
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/Layer.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/Layer.java
deleted file mode 100644
index 20446594fa..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/Layer.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.onthegomap.planetiler.basemap;
-
-import com.onthegomap.planetiler.ForwardingProfile;
-
-/** Interface for all vector tile layer implementations that {@link BasemapProfile} delegates to. */
-public interface Layer extends
- ForwardingProfile.Handler,
- ForwardingProfile.HandlerForLayer {}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/OpenMapTilesSchema.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/OpenMapTilesSchema.java
deleted file mode 100644
index dc20317fb0..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/OpenMapTilesSchema.java
+++ /dev/null
@@ -1,1906 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-// AUTOGENERATED BY Generate.java -- DO NOT MODIFY
-
-package com.onthegomap.planetiler.basemap.generated;
-
-import static com.onthegomap.planetiler.expression.Expression.*;
-
-import com.onthegomap.planetiler.basemap.Layer;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.expression.MultiExpression;
-import com.onthegomap.planetiler.stats.Stats;
-import com.onthegomap.planetiler.util.Translations;
-import java.util.List;
-import java.util.Set;
-
-/**
- * All vector tile layer definitions, attributes, and allowed values generated from the
- * OpenMapTiles vector tile schema
- * v3.13.1.
- */
-@SuppressWarnings("unused")
-public class OpenMapTilesSchema {
- public static final String NAME = "OpenMapTiles";
- public static final String DESCRIPTION = "A tileset showcasing all layers in OpenMapTiles. https://openmaptiles.org";
- public static final String VERSION = "3.13.1";
- public static final String ATTRIBUTION =
- "© OpenMapTiles © OpenStreetMap contributors";
- public static final List LANGUAGES = List.of("am", "ar", "az", "be", "bg", "br", "bs", "ca", "co", "cs", "cy",
- "da", "de", "el", "en", "eo", "es", "et", "eu", "fi", "fr", "fy", "ga", "gd", "he", "hi", "hr", "hu", "hy", "id",
- "is", "it", "ja", "ja_kana", "ja_rm", "ja-Latn", "ja-Hira", "ka", "kk", "kn", "ko", "ko-Latn", "ku", "la", "lb",
- "lt", "lv", "mk", "mt", "ml", "nl", "no", "oc", "pl", "pt", "rm", "ro", "ru", "sk", "sl", "sq", "sr", "sr-Latn",
- "sv", "ta", "te", "th", "tr", "uk", "zh");
-
- /** Returns a list of expected layer implementation instances from the {@code layers} package. */
- public static List createInstances(Translations translations, PlanetilerConfig config, Stats stats) {
- return List.of(
- new com.onthegomap.planetiler.basemap.layers.Water(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.Waterway(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.Landcover(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.Landuse(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.MountainPeak(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.Park(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.Boundary(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.Aeroway(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.Transportation(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.Building(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.WaterName(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.TransportationName(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.Place(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.Housenumber(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.Poi(translations, config, stats),
- new com.onthegomap.planetiler.basemap.layers.AerodromeLabel(translations, config, stats)
- );
- }
-
- /**
- * Water polygons representing oceans and lakes. Covered watered areas are excluded (covered=yes
). On low
- * zoom levels all water originates from Natural Earth. To get a more correct display of the south pole you should
- * also style the covering ice shelves over the water. On higher zoom levels water polygons from
- * OpenStreetMapData are used. The polygons are split into many smaller
- * polygons to improve rendering performance. This however can lead to less rendering options in clients since these
- * boundaries show up. So you might not be able to use border styling for ocean water features.
- *
- * Generated from
- * water.yaml
- */
- public interface Water extends Layer {
- double BUFFER_SIZE = 4.0;
- String LAYER_NAME = "water";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the water layer. */
- final class Fields {
- /**
- * From zoom 6 are taken OSM IDs. Up to zoom 5 there are used Natural Earth lakes, where are propagated the OSM
- * IDs insted of Natural Earth IDs. For smaller area then planet, NE lakes keep their Natural Earth IDs.
- */
- public static final String ID = "id";
-
- /**
- * All water polygons from OpenStreetMapData have the class
- * ocean
. Water bodies with the
- * waterway=riverbank
or
- * water=river
tag are classified as
- * river. Wet and dry docks tagged
- * waterway=dock
are classified as
- * a dock
. Swimming pools tagged
- * leisure=swimming_pool
- * are classified as a swimming_pool
All other water bodies are classified as lake
.
- *
- * allowed values:
- *
- * - dock
- *
- river
- *
- lake
- *
- ocean
- *
- swimming_pool
- *
- */
- public static final String CLASS = "class";
-
- /**
- * Mark with 1
if it is an
- * intermittent water polygon.
- *
- * allowed values:
- *
- */
- public static final String INTERMITTENT = "intermittent";
-
- /**
- * Identifies the type of crossing as either a bridge or a tunnel.
- *
- * allowed values:
- *
- * - "bridge"
- *
- "tunnel"
- *
- */
- public static final String BRUNNEL = "brunnel";
- }
- /** Attribute values for map elements in the water layer. */
- final class FieldValues {
- public static final String CLASS_DOCK = "dock";
- public static final String CLASS_RIVER = "river";
- public static final String CLASS_LAKE = "lake";
- public static final String CLASS_OCEAN = "ocean";
- public static final String CLASS_SWIMMING_POOL = "swimming_pool";
- public static final Set CLASS_VALUES = Set.of("dock", "river", "lake", "ocean", "swimming_pool");
- public static final String BRUNNEL_BRIDGE = "bridge";
- public static final String BRUNNEL_TUNNEL = "tunnel";
- public static final Set BRUNNEL_VALUES = Set.of("bridge", "tunnel");
- }
- /** Complex mappings to generate attribute values from OSM element tags in the water layer. */
- final class FieldMappings {
- public static final MultiExpression Class =
- MultiExpression.of(List.of(MultiExpression.entry("dock", matchAny("waterway", "dock")),
- MultiExpression.entry("river", or(matchAny("water", "river"), matchAny("waterway", "riverbank"))),
- MultiExpression.entry("lake", FALSE), MultiExpression.entry("ocean", FALSE),
- MultiExpression.entry("swimming_pool", matchAny("leisure", "swimming_pool"))));
- }
- }
- /**
- * OpenStreetMap waterways for higher zoom levels (z9 and
- * more) and Natural Earth rivers and lake centerlines for low zoom levels (z3 - z8). Linestrings without a name or
- * which are too short are filtered out at low zoom levels. Till z11 there is river
class only, in z12
- * there is also canal
generated, starting z13 there is no generalization according to class
- * field applied. Waterways do not have a subclass
field.
- *
- * Generated from
- * waterway.yaml
- */
- public interface Waterway extends Layer {
- double BUFFER_SIZE = 4.0;
- String LAYER_NAME = "waterway";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the waterway layer. */
- final class Fields {
- /**
- * The OSM name
value of the waterway. The
- * name
field may be empty for NaturalEarth data or at lower zoom levels.
- */
- public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
- public static final String NAME_EN = "name_en";
- /** German name name:de
if available, otherwise name
or name:en
. */
- public static final String NAME_DE = "name_de";
-
- /**
- * The original value of the waterway
- * tag.
- *
- * allowed values:
- *
- * - "stream"
- *
- "river"
- *
- "canal"
- *
- "drain"
- *
- "ditch"
- *
- */
- public static final String CLASS = "class";
-
- /**
- * Mark whether way is a tunnel or bridge.
- *
- * allowed values:
- *
- * - "bridge"
- *
- "tunnel"
- *
- */
- public static final String BRUNNEL = "brunnel";
-
- /**
- * Mark with 1
if it is an
- * intermittent waterway.
- *
- * allowed values:
- *
- */
- public static final String INTERMITTENT = "intermittent";
- }
- /** Attribute values for map elements in the waterway layer. */
- final class FieldValues {
- public static final String CLASS_STREAM = "stream";
- public static final String CLASS_RIVER = "river";
- public static final String CLASS_CANAL = "canal";
- public static final String CLASS_DRAIN = "drain";
- public static final String CLASS_DITCH = "ditch";
- public static final Set CLASS_VALUES = Set.of("stream", "river", "canal", "drain", "ditch");
- public static final String BRUNNEL_BRIDGE = "bridge";
- public static final String BRUNNEL_TUNNEL = "tunnel";
- public static final Set BRUNNEL_VALUES = Set.of("bridge", "tunnel");
- }
- /** Complex mappings to generate attribute values from OSM element tags in the waterway layer. */
- final class FieldMappings {
-
- }
- }
- /**
- * Landcover is used to describe the physical material at the surface of the earth. At lower zoom levels this is from
- * Natural Earth data for glaciers and ice shelves and at higher zoom levels the landcover is
- * implied by OSM tags. The most common use case for this
- * layer is to style wood (class=wood
) and grass (class=grass
) areas.
- *
- * Generated from landcover.yaml
- */
- public interface Landcover extends Layer {
- double BUFFER_SIZE = 4.0;
- String LAYER_NAME = "landcover";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the landcover layer. */
- final class Fields {
- /**
- * Use the class to assign natural colors for landcover.
- *
- * allowed values:
- *
- * - farmland
- *
- ice
- *
- wood
- *
- rock
- *
- grass
- *
- wetland
- *
- sand
- *
- */
- public static final String CLASS = "class";
-
- /**
- * Use subclass to do more precise styling. Original value of either the
- * natural
,
- * landuse
,
- * leisure
, or
- * wetland
tag.
- *
- * allowed values:
- *
- * - "allotments"
- *
- "bare_rock"
- *
- "beach"
- *
- "bog"
- *
- "dune"
- *
- "scrub"
- *
- "farm"
- *
- "farmland"
- *
- "fell"
- *
- "forest"
- *
- "garden"
- *
- "glacier"
- *
- "grass"
- *
- "grassland"
- *
- "golf_course"
- *
- "heath"
- *
- "mangrove"
- *
- "marsh"
- *
- "meadow"
- *
- "orchard"
- *
- "park"
- *
- "plant_nursery"
- *
- "recreation_ground"
- *
- "reedbed"
- *
- "saltern"
- *
- "saltmarsh"
- *
- "sand"
- *
- "scree"
- *
- "swamp"
- *
- "tidalflat"
- *
- "tundra"
- *
- "village_green"
- *
- "vineyard"
- *
- "wet_meadow"
- *
- "wetland"
- *
- "wood"
- *
- */
- public static final String SUBCLASS = "subclass";
- }
- /** Attribute values for map elements in the landcover layer. */
- final class FieldValues {
- public static final String CLASS_FARMLAND = "farmland";
- public static final String CLASS_ICE = "ice";
- public static final String CLASS_WOOD = "wood";
- public static final String CLASS_ROCK = "rock";
- public static final String CLASS_GRASS = "grass";
- public static final String CLASS_WETLAND = "wetland";
- public static final String CLASS_SAND = "sand";
- public static final Set CLASS_VALUES =
- Set.of("farmland", "ice", "wood", "rock", "grass", "wetland", "sand");
- public static final String SUBCLASS_ALLOTMENTS = "allotments";
- public static final String SUBCLASS_BARE_ROCK = "bare_rock";
- public static final String SUBCLASS_BEACH = "beach";
- public static final String SUBCLASS_BOG = "bog";
- public static final String SUBCLASS_DUNE = "dune";
- public static final String SUBCLASS_SCRUB = "scrub";
- public static final String SUBCLASS_FARM = "farm";
- public static final String SUBCLASS_FARMLAND = "farmland";
- public static final String SUBCLASS_FELL = "fell";
- public static final String SUBCLASS_FOREST = "forest";
- public static final String SUBCLASS_GARDEN = "garden";
- public static final String SUBCLASS_GLACIER = "glacier";
- public static final String SUBCLASS_GRASS = "grass";
- public static final String SUBCLASS_GRASSLAND = "grassland";
- public static final String SUBCLASS_GOLF_COURSE = "golf_course";
- public static final String SUBCLASS_HEATH = "heath";
- public static final String SUBCLASS_MANGROVE = "mangrove";
- public static final String SUBCLASS_MARSH = "marsh";
- public static final String SUBCLASS_MEADOW = "meadow";
- public static final String SUBCLASS_ORCHARD = "orchard";
- public static final String SUBCLASS_PARK = "park";
- public static final String SUBCLASS_PLANT_NURSERY = "plant_nursery";
- public static final String SUBCLASS_RECREATION_GROUND = "recreation_ground";
- public static final String SUBCLASS_REEDBED = "reedbed";
- public static final String SUBCLASS_SALTERN = "saltern";
- public static final String SUBCLASS_SALTMARSH = "saltmarsh";
- public static final String SUBCLASS_SAND = "sand";
- public static final String SUBCLASS_SCREE = "scree";
- public static final String SUBCLASS_SWAMP = "swamp";
- public static final String SUBCLASS_TIDALFLAT = "tidalflat";
- public static final String SUBCLASS_TUNDRA = "tundra";
- public static final String SUBCLASS_VILLAGE_GREEN = "village_green";
- public static final String SUBCLASS_VINEYARD = "vineyard";
- public static final String SUBCLASS_WET_MEADOW = "wet_meadow";
- public static final String SUBCLASS_WETLAND = "wetland";
- public static final String SUBCLASS_WOOD = "wood";
- public static final Set SUBCLASS_VALUES =
- Set.of("allotments", "bare_rock", "beach", "bog", "dune", "scrub", "farm", "farmland", "fell", "forest",
- "garden", "glacier", "grass", "grassland", "golf_course", "heath", "mangrove", "marsh", "meadow", "orchard",
- "park", "plant_nursery", "recreation_ground", "reedbed", "saltern", "saltmarsh", "sand", "scree", "swamp",
- "tidalflat", "tundra", "village_green", "vineyard", "wet_meadow", "wetland", "wood");
- }
- /** Complex mappings to generate attribute values from OSM element tags in the landcover layer. */
- final class FieldMappings {
- public static final MultiExpression Class =
- MultiExpression
- .of(List.of(
- MultiExpression.entry("farmland",
- matchAny("subclass", "farmland", "farm", "orchard", "vineyard", "plant_nursery")),
- MultiExpression.entry("ice", matchAny("subclass", "glacier", "ice_shelf")),
- MultiExpression.entry("wood", matchAny("subclass", "wood", "forest")),
- MultiExpression.entry("rock", matchAny("subclass", "bare_rock", "scree")),
- MultiExpression.entry("grass",
- matchAny("subclass", "fell", "grassland", "heath", "scrub", "tundra", "grass", "meadow", "allotments",
- "park", "village_green", "recreation_ground", "garden", "golf_course")),
- MultiExpression.entry("wetland",
- matchAny("subclass", "wetland", "bog", "swamp", "wet_meadow", "marsh", "reedbed", "saltern", "tidalflat",
- "saltmarsh", "mangrove")),
- MultiExpression.entry("sand", matchAny("subclass", "beach", "sand", "dune"))));
- }
- }
- /**
- * Landuse is used to describe use of land by humans. At lower zoom levels this is from Natural Earth data for
- * residential (urban) areas and at higher zoom levels mostly OSM landuse
tags.
- *
- * Generated from
- * landuse.yaml
- */
- public interface Landuse extends Layer {
- double BUFFER_SIZE = 4.0;
- String LAYER_NAME = "landuse";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the landuse layer. */
- final class Fields {
- /**
- * Use the class to assign special colors to areas. Original value of either the
- * landuse
,
- * amenity
,
- * leisure
,
- * tourism
,
- * place
or
- * waterway
tag.
- *
- * allowed values:
- *
- * - "railway"
- *
- "cemetery"
- *
- "military"
- *
- "residential"
- *
- "commercial"
- *
- "industrial"
- *
- "garages"
- *
- "retail"
- *
- "bus_station"
- *
- "school"
- *
- "university"
- *
- "kindergarten"
- *
- "college"
- *
- "library"
- *
- "hospital"
- *
- "stadium"
- *
- "pitch"
- *
- "playground"
- *
- "track"
- *
- "theme_park"
- *
- "zoo"
- *
- "suburb"
- *
- "quarter"
- *
- "neighbourhood"
- *
- "dam"
- *
- */
- public static final String CLASS = "class";
- }
- /** Attribute values for map elements in the landuse layer. */
- final class FieldValues {
- public static final String CLASS_RAILWAY = "railway";
- public static final String CLASS_CEMETERY = "cemetery";
- public static final String CLASS_MILITARY = "military";
- public static final String CLASS_RESIDENTIAL = "residential";
- public static final String CLASS_COMMERCIAL = "commercial";
- public static final String CLASS_INDUSTRIAL = "industrial";
- public static final String CLASS_GARAGES = "garages";
- public static final String CLASS_RETAIL = "retail";
- public static final String CLASS_BUS_STATION = "bus_station";
- public static final String CLASS_SCHOOL = "school";
- public static final String CLASS_UNIVERSITY = "university";
- public static final String CLASS_KINDERGARTEN = "kindergarten";
- public static final String CLASS_COLLEGE = "college";
- public static final String CLASS_LIBRARY = "library";
- public static final String CLASS_HOSPITAL = "hospital";
- public static final String CLASS_STADIUM = "stadium";
- public static final String CLASS_PITCH = "pitch";
- public static final String CLASS_PLAYGROUND = "playground";
- public static final String CLASS_TRACK = "track";
- public static final String CLASS_THEME_PARK = "theme_park";
- public static final String CLASS_ZOO = "zoo";
- public static final String CLASS_SUBURB = "suburb";
- public static final String CLASS_QUARTER = "quarter";
- public static final String CLASS_NEIGHBOURHOOD = "neighbourhood";
- public static final String CLASS_DAM = "dam";
- public static final Set CLASS_VALUES =
- Set.of("railway", "cemetery", "military", "residential", "commercial", "industrial", "garages", "retail",
- "bus_station", "school", "university", "kindergarten", "college", "library", "hospital", "stadium", "pitch",
- "playground", "track", "theme_park", "zoo", "suburb", "quarter", "neighbourhood", "dam");
- }
- /** Complex mappings to generate attribute values from OSM element tags in the landuse layer. */
- final class FieldMappings {
-
- }
- }
- /**
- * Natural peaks
- *
- * Generated from mountain_peak.yaml
- */
- public interface MountainPeak extends Layer {
- double BUFFER_SIZE = 64.0;
- String LAYER_NAME = "mountain_peak";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the mountain_peak layer. */
- final class Fields {
- /** The OSM name
value of the peak. */
- public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
- public static final String NAME_EN = "name_en";
- /** German name name:de
if available, otherwise name
or name:en
. */
- public static final String NAME_DE = "name_de";
-
- /**
- * Use the class to differentiate between natural objects.
- *
- * allowed values:
- *
- * - "peak"
- *
- "volcano"
- *
- "saddle"
- *
- "ridge"
- *
- "cliff"
- *
- "arete"
- *
- */
- public static final String CLASS = "class";
- /** Elevation (ele
) in meters. */
- public static final String ELE = "ele";
- /** Elevation (ele
) in feet. */
- public static final String ELE_FT = "ele_ft";
-
- /**
- * Value 1 for peaks in location where feet is used as customary unit (USA).
- *
- * allowed values:
- *
- */
- public static final String CUSTOMARY_FT = "customary_ft";
- /** Rank of the peak within one tile (starting at 1 that is the most important peak). */
- public static final String RANK = "rank";
- }
- /** Attribute values for map elements in the mountain_peak layer. */
- final class FieldValues {
- public static final String CLASS_PEAK = "peak";
- public static final String CLASS_VOLCANO = "volcano";
- public static final String CLASS_SADDLE = "saddle";
- public static final String CLASS_RIDGE = "ridge";
- public static final String CLASS_CLIFF = "cliff";
- public static final String CLASS_ARETE = "arete";
- public static final Set CLASS_VALUES = Set.of("peak", "volcano", "saddle", "ridge", "cliff", "arete");
- }
- /** Complex mappings to generate attribute values from OSM element tags in the mountain_peak layer. */
- final class FieldMappings {
-
- }
- }
- /**
- * The park layer contains parks from OpenStreetMap tagged with
- * boundary=national_park
,
- * boundary=protected_area
, or
- * leisure=nature_reserve
.
- *
- * Generated from
- * park.yaml
- */
- public interface Park extends Layer {
- double BUFFER_SIZE = 4.0;
- String LAYER_NAME = "park";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the park layer. */
- final class Fields {
- /**
- * Use the class to differentiate between different parks. The class for
- * boundary=protected_area
parks is the lower-case of the
- * protection_title
value with
- * blanks replaced by _
. national_park
is the class of
- * protection_title=National Park
and boundary=national_park
.
- * nature_reserve
is the class of protection_title=Nature Reserve
and
- * leisure=nature_reserve
. The class for other
- * protection_title
values is
- * similarly assigned.
- */
- public static final String CLASS = "class";
- /**
- * The OSM name
value of the park (point
- * features only).
- */
- public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
(point features only). */
- public static final String NAME_EN = "name_en";
- /**
- * German name name:de
if available, otherwise name
or name:en
(point
- * features only).
- */
- public static final String NAME_DE = "name_de";
- /** Rank of the park within one tile, starting at 1 that is the most important park (point features only). */
- public static final String RANK = "rank";
- }
- /** Attribute values for map elements in the park layer. */
- final class FieldValues {
-
- }
- /** Complex mappings to generate attribute values from OSM element tags in the park layer. */
- final class FieldMappings {
-
- }
- }
- /**
- * Contains administrative boundaries as linestrings. Until z4
- * Natural Earth data is used after which OSM boundaries
- * (boundary=administrative
) are
- * present from z5 to z14 (also for maritime boundaries with admin_level <= 2
at z4). OSM data
- * contains several
- * admin_level
- * but for most styles it makes sense to just style admin_level=2
and admin_level=4
.
- *
- * Generated from
- * boundary.yaml
- */
- public interface Boundary extends Layer {
- double BUFFER_SIZE = 4.0;
- String LAYER_NAME = "boundary";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the boundary layer. */
- final class Fields {
- /**
- * OSM admin_level
- * indicating the level of importance of this boundary. The admin_level
corresponds to the lowest
- * admin_level
the line participates in. At low zoom levels the Natural Earth boundaries are mapped
- * to the equivalent admin levels.
- */
- public static final String ADMIN_LEVEL = "admin_level";
- /** State name on the left of the border. For country boundaries only (admin_level = 2
). */
- public static final String ADM0_L = "adm0_l";
- /** State name on the right of the border. For country boundaries only (admin_level = 2
). */
- public static final String ADM0_R = "adm0_r";
-
- /**
- * Mark with 1
if the border is disputed.
- *
- * allowed values:
- *
- */
- public static final String DISPUTED = "disputed";
-
- /**
- * Field containing name of the disputed area (extracted from border relation in OSM, without spaces). For country
- * boundaries only (admin_level = 2
). Value examples from Asian OSM pbf extract
- *
- * allowed values:
- *
- * - "AbuMusaIsland"
- *
- "BaraHotiiValleys"
- *
- "ChineseClaim"
- *
- "Crimea"
- *
- "Demchok"
- *
- "Dokdo"
- *
- "IndianClaim-North"
- *
- "IndianClaimwesternKashmir"
- *
- "PakistaniClaim"
- *
- "SamduValleys"
- *
- "TirpaniValleys"
- *
- */
- public static final String DISPUTED_NAME = "disputed_name";
- /**
- * ISO2 code of country, which wants to see the boundary line. For country boundaries only
- * (admin_level = 2
).
- */
- public static final String CLAIMED_BY = "claimed_by";
-
- /**
- * Mark with 1
if it is a maritime border.
- *
- * allowed values:
- *
- */
- public static final String MARITIME = "maritime";
- }
- /** Attribute values for map elements in the boundary layer. */
- final class FieldValues {
- public static final String DISPUTED_NAME_ABUMUSAISLAND = "AbuMusaIsland";
- public static final String DISPUTED_NAME_BARAHOTIIVALLEYS = "BaraHotiiValleys";
- public static final String DISPUTED_NAME_CHINESECLAIM = "ChineseClaim";
- public static final String DISPUTED_NAME_CRIMEA = "Crimea";
- public static final String DISPUTED_NAME_DEMCHOK = "Demchok";
- public static final String DISPUTED_NAME_DOKDO = "Dokdo";
- public static final String DISPUTED_NAME_INDIANCLAIM_NORTH = "IndianClaim-North";
- public static final String DISPUTED_NAME_INDIANCLAIMWESTERNKASHMIR = "IndianClaimwesternKashmir";
- public static final String DISPUTED_NAME_PAKISTANICLAIM = "PakistaniClaim";
- public static final String DISPUTED_NAME_SAMDUVALLEYS = "SamduValleys";
- public static final String DISPUTED_NAME_TIRPANIVALLEYS = "TirpaniValleys";
- public static final Set DISPUTED_NAME_VALUES =
- Set.of("AbuMusaIsland", "BaraHotiiValleys", "ChineseClaim", "Crimea", "Demchok", "Dokdo", "IndianClaim-North",
- "IndianClaimwesternKashmir", "PakistaniClaim", "SamduValleys", "TirpaniValleys");
- }
- /** Complex mappings to generate attribute values from OSM element tags in the boundary layer. */
- final class FieldMappings {
-
- }
- }
- /**
- * Aeroway polygons based of OpenStreetMap aeroways. Airport
- * buildings are contained in the building layer but all other airport related polygons can be found
- * in the aeroway layer.
- *
- * Generated from
- * aeroway.yaml
- */
- public interface Aeroway extends Layer {
- double BUFFER_SIZE = 4.0;
- String LAYER_NAME = "aeroway";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the aeroway layer. */
- final class Fields {
- /**
- * The OSM ref
tag of the runway/taxiway.
- */
- public static final String REF = "ref";
-
- /**
- * The original value of aeroway
or
- * area:aeroway
tag.
- *
- * allowed values:
- *
- * - "aerodrome"
- *
- "heliport"
- *
- "runway"
- *
- "helipad"
- *
- "taxiway"
- *
- "apron"
- *
- "gate"
- *
- */
- public static final String CLASS = "class";
- }
- /** Attribute values for map elements in the aeroway layer. */
- final class FieldValues {
- public static final String CLASS_AERODROME = "aerodrome";
- public static final String CLASS_HELIPORT = "heliport";
- public static final String CLASS_RUNWAY = "runway";
- public static final String CLASS_HELIPAD = "helipad";
- public static final String CLASS_TAXIWAY = "taxiway";
- public static final String CLASS_APRON = "apron";
- public static final String CLASS_GATE = "gate";
- public static final Set CLASS_VALUES =
- Set.of("aerodrome", "heliport", "runway", "helipad", "taxiway", "apron", "gate");
- }
- /** Complex mappings to generate attribute values from OSM element tags in the aeroway layer. */
- final class FieldMappings {
-
- }
- }
- /**
- * transportation contains roads, railways, aerial ways, and shipping lines. This layer is directly
- * derived from the OSM road hierarchy. At lower zoom levels major highways from Natural Earth are used. It contains
- * all roads from motorways to primary, secondary and tertiary roads to residential roads and foot paths. Styling the
- * roads is the most essential part of the map. The transportation
layer also contains polygons for
- * features like plazas.
- *
- * Generated from transportation.yaml
- */
- public interface Transportation extends Layer {
- double BUFFER_SIZE = 4.0;
- String LAYER_NAME = "transportation";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the transportation layer. */
- final class Fields {
- /**
- * Distinguish between more and less important roads or railways and roads under construction. Class is derived
- * from the value of the highway
,
- * construction
,
- * railway
,
- * aerialway
,
- * route
tag (for shipping ways),
- * busway
, or
- * man_made
.
- *
- * allowed values:
- *
- * - motorway
- *
- trunk
- *
- primary
- *
- secondary
- *
- tertiary
- *
- minor
- *
- path
- *
- service
- *
- track
- *
- raceway
- *
- busway
- *
- motorway_construction
- *
- trunk_construction
- *
- primary_construction
- *
- secondary_construction
- *
- tertiary_construction
- *
- minor_construction
- *
- path_construction
- *
- service_construction
- *
- track_construction
- *
- raceway_construction
- *
- */
- public static final String CLASS = "class";
-
- /**
- * Distinguish more specific classes of railway and path: Subclass is value of the
- * railway
,
- * highway
(for paths), or
- * public_transport
(for
- * platforms) tag.
- *
- * allowed values:
- *
- * - "rail"
- *
- "narrow_gauge"
- *
- "preserved"
- *
- "funicular"
- *
- "subway"
- *
- "light_rail"
- *
- "monorail"
- *
- "tram"
- *
- "pedestrian"
- *
- "path"
- *
- "footway"
- *
- "cycleway"
- *
- "steps"
- *
- "bridleway"
- *
- "corridor"
- *
- "platform"
- *
- */
- public static final String SUBCLASS = "subclass";
- /**
- * The network type derived mainly from
- * network
tag of the road. See more
- * info about us-
,
- * ca-transcanada
, or
- * gb-
.
- */
- public static final String NETWORK = "network";
-
- /**
- * Mark whether way is a tunnel or bridge.
- *
- * allowed values:
- *
- * - "bridge"
- *
- "tunnel"
- *
- "ford"
- *
- */
- public static final String BRUNNEL = "brunnel";
-
- /**
- * Mark with 1
whether way is a oneway in the direction of the way, with -1
whether way
- * is a oneway in the opposite direction of the way or not a oneway with 0
.
- *
- * allowed values:
- *
- */
- public static final String ONEWAY = "oneway";
-
- /**
- * Mark with 1
whether way is a ramp (link or steps) or not with 0
.
- *
- * allowed values:
- *
- */
- public static final String RAMP = "ramp";
-
- /**
- * Original value of the service
tag.
- *
- * allowed values:
- *
- * - "spur"
- *
- "yard"
- *
- "siding"
- *
- "crossover"
- *
- "driveway"
- *
- "alley"
- *
- "parking_aisle"
- *
- */
- public static final String SERVICE = "service";
-
- /**
- * Access restrictions on this road. Supported values of the
- * access
tag are no
and
- * private
, which resolve to no
.
- *
- * allowed values:
- *
- */
- public static final String ACCESS = "access";
-
- /**
- * Whether this is a toll road, based on the
- * toll
tag.
- *
- * allowed values:
- *
- */
- public static final String TOLL = "toll";
-
- /**
- * Whether this is an expressway, based on the
- * expressway
tag.
- *
- * allowed values:
- *
- */
- public static final String EXPRESSWAY = "expressway";
- /** Original value of the layer
tag. */
- public static final String LAYER = "layer";
- /**
- * Experimental feature! Filled only for steps and footways. Original value of the
- * level
tag.
- */
- public static final String LEVEL = "level";
-
- /**
- * Experimental feature! Filled only for steps and footways. Original value of the
- * indoor
tag.
- *
- * allowed values:
- *
- */
- public static final String INDOOR = "indoor";
- /**
- * Original value of the bicycle
tag
- * (highways only).
- */
- public static final String BICYCLE = "bicycle";
- /**
- * Original value of the foot
tag (highways
- * only).
- */
- public static final String FOOT = "foot";
- /**
- * Original value of the horse
tag
- * (highways only).
- */
- public static final String HORSE = "horse";
- /**
- * Original value of the mtb:scale
tag
- * (highways only).
- */
- public static final String MTB_SCALE = "mtb_scale";
-
- /**
- * Values of surface
tag devided into 2
- * groups paved
(paved, asphalt, cobblestone, concrete, concrete:lanes, concrete:plates, metal,
- * paving_stones, sett, unhewn_cobblestone, wood) and unpaved
(unpaved, compacted, dirt, earth,
- * fine_gravel, grass, grass_paver, gravel, gravel_turf, ground, ice, mud, pebblestone, salt, sand, snow,
- * woodchips).
- *
- * allowed values:
- *
- * - "paved"
- *
- "unpaved"
- *
- */
- public static final String SURFACE = "surface";
- }
- /** Attribute values for map elements in the transportation layer. */
- final class FieldValues {
- public static final String CLASS_MOTORWAY = "motorway";
- public static final String CLASS_TRUNK = "trunk";
- public static final String CLASS_PRIMARY = "primary";
- public static final String CLASS_SECONDARY = "secondary";
- public static final String CLASS_TERTIARY = "tertiary";
- public static final String CLASS_MINOR = "minor";
- public static final String CLASS_PATH = "path";
- public static final String CLASS_SERVICE = "service";
- public static final String CLASS_TRACK = "track";
- public static final String CLASS_RACEWAY = "raceway";
- public static final String CLASS_BUSWAY = "busway";
- public static final String CLASS_MOTORWAY_CONSTRUCTION = "motorway_construction";
- public static final String CLASS_TRUNK_CONSTRUCTION = "trunk_construction";
- public static final String CLASS_PRIMARY_CONSTRUCTION = "primary_construction";
- public static final String CLASS_SECONDARY_CONSTRUCTION = "secondary_construction";
- public static final String CLASS_TERTIARY_CONSTRUCTION = "tertiary_construction";
- public static final String CLASS_MINOR_CONSTRUCTION = "minor_construction";
- public static final String CLASS_PATH_CONSTRUCTION = "path_construction";
- public static final String CLASS_SERVICE_CONSTRUCTION = "service_construction";
- public static final String CLASS_TRACK_CONSTRUCTION = "track_construction";
- public static final String CLASS_RACEWAY_CONSTRUCTION = "raceway_construction";
- public static final Set CLASS_VALUES = Set.of("motorway", "trunk", "primary", "secondary", "tertiary",
- "minor", "path", "service", "track", "raceway", "busway", "motorway_construction", "trunk_construction",
- "primary_construction", "secondary_construction", "tertiary_construction", "minor_construction",
- "path_construction", "service_construction", "track_construction", "raceway_construction");
- public static final String SUBCLASS_RAIL = "rail";
- public static final String SUBCLASS_NARROW_GAUGE = "narrow_gauge";
- public static final String SUBCLASS_PRESERVED = "preserved";
- public static final String SUBCLASS_FUNICULAR = "funicular";
- public static final String SUBCLASS_SUBWAY = "subway";
- public static final String SUBCLASS_LIGHT_RAIL = "light_rail";
- public static final String SUBCLASS_MONORAIL = "monorail";
- public static final String SUBCLASS_TRAM = "tram";
- public static final String SUBCLASS_PEDESTRIAN = "pedestrian";
- public static final String SUBCLASS_PATH = "path";
- public static final String SUBCLASS_FOOTWAY = "footway";
- public static final String SUBCLASS_CYCLEWAY = "cycleway";
- public static final String SUBCLASS_STEPS = "steps";
- public static final String SUBCLASS_BRIDLEWAY = "bridleway";
- public static final String SUBCLASS_CORRIDOR = "corridor";
- public static final String SUBCLASS_PLATFORM = "platform";
- public static final Set SUBCLASS_VALUES =
- Set.of("rail", "narrow_gauge", "preserved", "funicular", "subway", "light_rail", "monorail", "tram",
- "pedestrian", "path", "footway", "cycleway", "steps", "bridleway", "corridor", "platform");
- public static final String BRUNNEL_BRIDGE = "bridge";
- public static final String BRUNNEL_TUNNEL = "tunnel";
- public static final String BRUNNEL_FORD = "ford";
- public static final Set BRUNNEL_VALUES = Set.of("bridge", "tunnel", "ford");
- public static final String SERVICE_SPUR = "spur";
- public static final String SERVICE_YARD = "yard";
- public static final String SERVICE_SIDING = "siding";
- public static final String SERVICE_CROSSOVER = "crossover";
- public static final String SERVICE_DRIVEWAY = "driveway";
- public static final String SERVICE_ALLEY = "alley";
- public static final String SERVICE_PARKING_AISLE = "parking_aisle";
- public static final Set SERVICE_VALUES =
- Set.of("spur", "yard", "siding", "crossover", "driveway", "alley", "parking_aisle");
- public static final String SURFACE_PAVED = "paved";
- public static final String SURFACE_UNPAVED = "unpaved";
- public static final Set SURFACE_VALUES = Set.of("paved", "unpaved");
- }
- /** Complex mappings to generate attribute values from OSM element tags in the transportation layer. */
- final class FieldMappings {
- public static final MultiExpression Class =
- MultiExpression.of(List.of(MultiExpression.entry("motorway", matchAny("highway", "motorway", "motorway_link")),
- MultiExpression.entry("trunk", matchAny("highway", "trunk", "trunk_link")),
- MultiExpression.entry("primary", matchAny("highway", "primary", "primary_link")),
- MultiExpression.entry("secondary", matchAny("highway", "secondary", "secondary_link")),
- MultiExpression.entry("tertiary", matchAny("highway", "tertiary", "tertiary_link")),
- MultiExpression.entry("minor", matchAny("highway", "unclassified", "residential", "living_street", "road")),
- MultiExpression.entry("path",
- or(matchAny("highway", "pedestrian", "path", "footway", "cycleway", "steps", "bridleway", "corridor"),
- matchAny("public_transport", "platform"))),
- MultiExpression.entry("service", matchAny("highway", "service")),
- MultiExpression.entry("track", matchAny("highway", "track")),
- MultiExpression.entry("raceway", matchAny("highway", "raceway")),
- MultiExpression.entry("busway", matchAny("highway", "busway")),
- MultiExpression.entry("motorway_construction",
- and(matchAny("highway", "construction"), matchAny("construction", "motorway", "motorway_link"))),
- MultiExpression.entry("trunk_construction",
- and(matchAny("highway", "construction"), matchAny("construction", "trunk", "trunk_link"))),
- MultiExpression.entry("primary_construction",
- and(matchAny("highway", "construction"), matchAny("construction", "primary", "primary_link"))),
- MultiExpression.entry("secondary_construction",
- and(matchAny("highway", "construction"), matchAny("construction", "secondary", "secondary_link"))),
- MultiExpression.entry("tertiary_construction",
- and(matchAny("highway", "construction"), matchAny("construction", "tertiary", "tertiary_link"))),
- MultiExpression.entry(
- "minor_construction",
- and(matchAny("highway", "construction"),
- matchAny("construction", "", "unclassified", "residential", "living_street", "road"))),
- MultiExpression.entry("path_construction", and(matchAny("highway", "construction"),
- or(matchAny("construction", "pedestrian", "path", "footway", "cycleway", "steps", "bridleway", "corridor"),
- matchAny("public_transport", "platform")))),
- MultiExpression.entry("service_construction",
- and(matchAny("highway", "construction"), matchAny("construction", "service"))),
- MultiExpression.entry("track_construction",
- and(matchAny("highway", "construction"), matchAny("construction", "track"))),
- MultiExpression.entry("raceway_construction",
- and(matchAny("highway", "construction"), matchAny("construction", "raceway")))));
- }
- }
- /**
- * All OSM Buildings. All building tags are imported
- * (building=
). Only buildings with tag
- * location:underground are excluded.
- *
- * Generated from
- * building.yaml
- */
- public interface Building extends Layer {
- double BUFFER_SIZE = 4.0;
- String LAYER_NAME = "building";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the building layer. */
- final class Fields {
- /** An approximated height from levels and height of the building or building:part. */
- public static final String RENDER_HEIGHT = "render_height";
- /**
- * An approximated height from minimum levels or minimum height of the bottom of the building or building:part.
- */
- public static final String RENDER_MIN_HEIGHT = "render_min_height";
- /** Colour */
- public static final String COLOUR = "colour";
- /**
- * If True, building (part) should not be rendered in 3D. Currently,
- * building outlines are marked as hide_3d.
- */
- public static final String HIDE_3D = "hide_3d";
- }
- /** Attribute values for map elements in the building layer. */
- final class FieldValues {
-
- }
- /** Complex mappings to generate attribute values from OSM element tags in the building layer. */
- final class FieldMappings {
-
- }
- }
- /**
- * Lake center lines for labelling lake bodies. This is based of the
- * osm-lakelines project which derives nice centerlines
- * from OSM water bodies. Only the most important lakes contain labels.
- *
- * Generated from water_name.yaml
- */
- public interface WaterName extends Layer {
- double BUFFER_SIZE = 256.0;
- String LAYER_NAME = "water_name";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the water_name layer. */
- final class Fields {
- /**
- * The OSM name
value of the water body.
- */
- public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
- public static final String NAME_EN = "name_en";
- /** German name name:de
if available, otherwise name
or name:en
. */
- public static final String NAME_DE = "name_de";
-
- /**
- * Distinguish between lake
, ocean
and sea
.
- *
- * allowed values:
- *
- * - "lake"
- *
- "sea"
- *
- "ocean"
- *
- */
- public static final String CLASS = "class";
-
- /**
- * Mark with 1
if it is an
- * intermittent lake.
- *
- * allowed values:
- *
- */
- public static final String INTERMITTENT = "intermittent";
- }
- /** Attribute values for map elements in the water_name layer. */
- final class FieldValues {
- public static final String CLASS_LAKE = "lake";
- public static final String CLASS_SEA = "sea";
- public static final String CLASS_OCEAN = "ocean";
- public static final Set CLASS_VALUES = Set.of("lake", "sea", "ocean");
- }
- /** Complex mappings to generate attribute values from OSM element tags in the water_name layer. */
- final class FieldMappings {
-
- }
- }
- /**
- * This is the layer for labelling the highways. Only highways that are named name=
and are long enough
- * to place text upon appear. The OSM roads are stitched together if they contain the same name to have better label
- * placement than having many small linestrings. For motorways you should use the ref
field to label them
- * while for other roads you should use name
.
- *
- * Generated from transportation_name.yaml
- */
- public interface TransportationName extends Layer {
- double BUFFER_SIZE = 8.0;
- String LAYER_NAME = "transportation_name";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the transportation_name layer. */
- final class Fields {
- /**
- * The OSM name
value
- * of the highway.
- */
- public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
- public static final String NAME_EN = "name_en";
- /** German name name:de
if available, otherwise name
or name:en
. */
- public static final String NAME_DE = "name_de";
- /**
- * The OSM ref
tag of the motorway or its
- * network.
- */
- public static final String REF = "ref";
- /** Length of the ref
field. Useful for having a shield icon as background for labeling motorways. */
- public static final String REF_LENGTH = "ref_length";
-
- /**
- * The network type derived mainly from
- * network
tag of the road. See more
- * info about us-
,
- * ca-transcanada
, or
- * gb-
.
- *
- * allowed values:
- *
- * - "us-interstate"
- *
- "us-highway"
- *
- "us-state"
- *
- "ca-transcanada"
- *
- "gb-motorway"
- *
- "gb-trunk"
- *
- "road (default)"
- *
- */
- public static final String NETWORK = "network";
-
- /**
- * Distinguish between more and less important roads and roads under construction.
- *
- * allowed values:
- *
- * - "motorway"
- *
- "trunk"
- *
- "primary"
- *
- "secondary"
- *
- "tertiary"
- *
- "minor"
- *
- "service"
- *
- "track"
- *
- "path"
- *
- "raceway"
- *
- "motorway_construction"
- *
- "trunk_construction"
- *
- "primary_construction"
- *
- "secondary_construction"
- *
- "tertiary_construction"
- *
- "minor_construction"
- *
- "service_construction"
- *
- "track_construction"
- *
- "path_construction"
- *
- "raceway_construction"
- *
- "rail"
- *
- "transit"
- *
- "motorway_junction"
- *
- */
- public static final String CLASS = "class";
-
- /**
- * Distinguish more specific classes of path: Subclass is value of the
- * highway
(for paths), and
- * "junction" for
- * motorway junctions
.
- *
- * allowed values:
- *
- * - "pedestrian"
- *
- "path"
- *
- "footway"
- *
- "cycleway"
- *
- "steps"
- *
- "bridleway"
- *
- "corridor"
- *
- "platform"
- *
- "junction"
- *
- */
- public static final String SUBCLASS = "subclass";
-
- /**
- * Mark whether way is a bridge, a tunnel or a ford.
- *
- * allowed values:
- *
- * - "bridge"
- *
- "tunnel"
- *
- "ford"
- *
- */
- public static final String BRUNNEL = "brunnel";
- /**
- * Experimental feature! Filled only for steps and footways. Original value of
- * level
tag.
- */
- public static final String LEVEL = "level";
- /**
- * Experimental feature! Filled only for steps and footways. Original value of
- * layer
tag.
- */
- public static final String LAYER = "layer";
-
- /**
- * Experimental feature! Filled only for steps and footways. Original value of
- * indoor
tag.
- *
- * allowed values:
- *
- */
- public static final String INDOOR = "indoor";
- /** 1st route concurrency. */
- public static final String ROUTE_1 = "route_1";
- /** 2nd route concurrency. */
- public static final String ROUTE_2 = "route_2";
- /** 3rd route concurrency. */
- public static final String ROUTE_3 = "route_3";
- /** 4th route concurrency. */
- public static final String ROUTE_4 = "route_4";
- /** 5th route concurrency. */
- public static final String ROUTE_5 = "route_5";
- /** 6th route concurrency. */
- public static final String ROUTE_6 = "route_6";
- }
- /** Attribute values for map elements in the transportation_name layer. */
- final class FieldValues {
- public static final String NETWORK_US_INTERSTATE = "us-interstate";
- public static final String NETWORK_US_HIGHWAY = "us-highway";
- public static final String NETWORK_US_STATE = "us-state";
- public static final String NETWORK_CA_TRANSCANADA = "ca-transcanada";
- public static final String NETWORK_GB_MOTORWAY = "gb-motorway";
- public static final String NETWORK_GB_TRUNK = "gb-trunk";
- public static final String NETWORK_ROAD = "road";
- public static final Set NETWORK_VALUES =
- Set.of("us-interstate", "us-highway", "us-state", "ca-transcanada", "gb-motorway", "gb-trunk", "road");
- public static final String CLASS_MOTORWAY = "motorway";
- public static final String CLASS_TRUNK = "trunk";
- public static final String CLASS_PRIMARY = "primary";
- public static final String CLASS_SECONDARY = "secondary";
- public static final String CLASS_TERTIARY = "tertiary";
- public static final String CLASS_MINOR = "minor";
- public static final String CLASS_SERVICE = "service";
- public static final String CLASS_TRACK = "track";
- public static final String CLASS_PATH = "path";
- public static final String CLASS_RACEWAY = "raceway";
- public static final String CLASS_MOTORWAY_CONSTRUCTION = "motorway_construction";
- public static final String CLASS_TRUNK_CONSTRUCTION = "trunk_construction";
- public static final String CLASS_PRIMARY_CONSTRUCTION = "primary_construction";
- public static final String CLASS_SECONDARY_CONSTRUCTION = "secondary_construction";
- public static final String CLASS_TERTIARY_CONSTRUCTION = "tertiary_construction";
- public static final String CLASS_MINOR_CONSTRUCTION = "minor_construction";
- public static final String CLASS_SERVICE_CONSTRUCTION = "service_construction";
- public static final String CLASS_TRACK_CONSTRUCTION = "track_construction";
- public static final String CLASS_PATH_CONSTRUCTION = "path_construction";
- public static final String CLASS_RACEWAY_CONSTRUCTION = "raceway_construction";
- public static final String CLASS_RAIL = "rail";
- public static final String CLASS_TRANSIT = "transit";
- public static final String CLASS_MOTORWAY_JUNCTION = "motorway_junction";
- public static final Set CLASS_VALUES =
- Set.of("motorway", "trunk", "primary", "secondary", "tertiary", "minor", "service", "track", "path", "raceway",
- "motorway_construction", "trunk_construction", "primary_construction", "secondary_construction",
- "tertiary_construction", "minor_construction", "service_construction", "track_construction",
- "path_construction", "raceway_construction", "rail", "transit", "motorway_junction");
- public static final String SUBCLASS_PEDESTRIAN = "pedestrian";
- public static final String SUBCLASS_PATH = "path";
- public static final String SUBCLASS_FOOTWAY = "footway";
- public static final String SUBCLASS_CYCLEWAY = "cycleway";
- public static final String SUBCLASS_STEPS = "steps";
- public static final String SUBCLASS_BRIDLEWAY = "bridleway";
- public static final String SUBCLASS_CORRIDOR = "corridor";
- public static final String SUBCLASS_PLATFORM = "platform";
- public static final String SUBCLASS_JUNCTION = "junction";
- public static final Set SUBCLASS_VALUES =
- Set.of("pedestrian", "path", "footway", "cycleway", "steps", "bridleway", "corridor", "platform", "junction");
- public static final String BRUNNEL_BRIDGE = "bridge";
- public static final String BRUNNEL_TUNNEL = "tunnel";
- public static final String BRUNNEL_FORD = "ford";
- public static final Set BRUNNEL_VALUES = Set.of("bridge", "tunnel", "ford");
- }
- /** Complex mappings to generate attribute values from OSM element tags in the transportation_name layer. */
- final class FieldMappings {
-
- }
- }
- /**
- * The place layer consists out of countries,
- * states,
- * cities and
- * islands. Apart from the roads this is also one
- * of the more important layers to create a beautiful map. We suggest you use different font styles and sizes to
- * create a text hierarchy.
- *
- * Generated from
- * place.yaml
- */
- public interface Place extends Layer {
- double BUFFER_SIZE = 256.0;
- String LAYER_NAME = "place";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the place layer. */
- final class Fields {
- /** The OSM name
value of the POI. */
- public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
- public static final String NAME_EN = "name_en";
- /** German name name:de
if available, otherwise name
or name:en
. */
- public static final String NAME_DE = "name_de";
-
- /**
- * The capital field marks the admin_level
of
- * the boundary the place is a capital of.
- *
- * allowed values:
- *
- */
- public static final String CAPITAL = "capital";
-
- /**
- * Original value of the place
tag.
- * Distinguish between continents, countries, states, islands and places like settlements or smaller entities. Use
- * class to separately style the different places and build a text hierarchy according to their
- * importance.
- *
- * allowed values:
- *
- * - "continent"
- *
- "country"
- *
- "state"
- *
- "province"
- *
- "city"
- *
- "town"
- *
- "village"
- *
- "hamlet"
- *
- "suburb"
- *
- "quarter"
- *
- "neighbourhood"
- *
- "isolated_dwelling"
- *
- "island"
- *
- */
- public static final String CLASS = "class";
- /**
- * Two-letter country code ISO 3166-1 alpha-2.
- * Available only for class=country
. Original value of the country_code_iso3166_1_alpha_2
tag.
- */
- public static final String ISO_A2 = "iso_a2";
- /**
- * Countries, states and the most important cities all have a rank to boost their importance on
- * the map. The rank field for countries and states ranges from 1
to 6
- * while the rank field for cities ranges from 1
to 10
for the most
- * important cities and continues from 10
serially based on the local importance of the city (derived
- * from population and city class). You can use the rank to limit density of labels or improve
- * the text hierarchy. The rank value is a combination of the Natural Earth scalerank
,
- * labelrank
and datarank
values for countries and states and for cities consists out of
- * a shifted Natural Earth scalerank
combined with a local rank within a grid for cities that do not
- * have a Natural Earth scalerank
.
- */
- public static final String RANK = "rank";
- }
- /** Attribute values for map elements in the place layer. */
- final class FieldValues {
- public static final String CLASS_CONTINENT = "continent";
- public static final String CLASS_COUNTRY = "country";
- public static final String CLASS_STATE = "state";
- public static final String CLASS_PROVINCE = "province";
- public static final String CLASS_CITY = "city";
- public static final String CLASS_TOWN = "town";
- public static final String CLASS_VILLAGE = "village";
- public static final String CLASS_HAMLET = "hamlet";
- public static final String CLASS_SUBURB = "suburb";
- public static final String CLASS_QUARTER = "quarter";
- public static final String CLASS_NEIGHBOURHOOD = "neighbourhood";
- public static final String CLASS_ISOLATED_DWELLING = "isolated_dwelling";
- public static final String CLASS_ISLAND = "island";
- public static final Set CLASS_VALUES = Set.of("continent", "country", "state", "province", "city", "town",
- "village", "hamlet", "suburb", "quarter", "neighbourhood", "isolated_dwelling", "island");
- }
- /** Complex mappings to generate attribute values from OSM element tags in the place layer. */
- final class FieldMappings {
-
- }
- }
- /**
- * Everything in OpenStreetMap which contains a addr:housenumber
tag useful for labelling housenumbers on
- * a map. This adds significant size to z14. For buildings the centroid of the building is used as
- * housenumber.
- *
- * Generated from housenumber.yaml
- */
- public interface Housenumber extends Layer {
- double BUFFER_SIZE = 8.0;
- String LAYER_NAME = "housenumber";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the housenumber layer. */
- final class Fields {
- /** Value of the addr:housenumber
tag. */
- public static final String HOUSENUMBER = "housenumber";
- }
- /** Attribute values for map elements in the housenumber layer. */
- final class FieldValues {
-
- }
- /** Complex mappings to generate attribute values from OSM element tags in the housenumber layer. */
- final class FieldMappings {
-
- }
- }
- /**
- * Points of interests containing a of a variety
- * of OpenStreetMap tags. Mostly contains amenities, sport, shop and tourist POIs.
- *
- * Generated from poi.yaml
- */
- public interface Poi extends Layer {
- double BUFFER_SIZE = 64.0;
- String LAYER_NAME = "poi";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the poi layer. */
- final class Fields {
- /** The OSM name
value of the POI. */
- public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
- public static final String NAME_EN = "name_en";
- /** German name name:de
if available, otherwise name
or name:en
. */
- public static final String NAME_DE = "name_de";
-
- /**
- * More general classes of POIs. If there is no more general class
for the subclass
this
- * field will contain the same value as subclass
. But for example for schools you only need to style
- * the class school
to filter the subclasses school
and kindergarten
. Or
- * use the class shop
to style all shops.
- *
- * allowed values:
- *
- * - shop
- *
- town_hall
- *
- golf
- *
- fast_food
- *
- park
- *
- bus
- *
- railway
- *
- aerialway
- *
- entrance
- *
- campsite
- *
- laundry
- *
- grocery
- *
- library
- *
- college
- *
- lodging
- *
- ice_cream
- *
- post
- *
- cafe
- *
- school
- *
- alcohol_shop
- *
- bar
- *
- harbor
- *
- car
- *
- hospital
- *
- cemetery
- *
- attraction
- *
- beer
- *
- music
- *
- stadium
- *
- art_gallery
- *
- clothing_store
- *
- swimming
- *
- castle
- *
- atm
- *
- */
- public static final String CLASS = "class";
- /**
- * Original value of either the amenity
,
- * barrier
,
- * historic
,
- * information
,
- * landuse
,
- * leisure
,
- * railway
,
- * shop
,
- * sport
,
- * station
,
- * religion
,
- * tourism
,
- * aerialway
,
- * building
,
- * highway
,
- * office
or
- * waterway
tag. Use this to do more
- * precise styling.
- */
- public static final String SUBCLASS = "subclass";
- /**
- * The POIs are ranked ascending according to their importance within a grid. The rank
value shows
- * the local relative importance of a POI within it's cell in the grid. This can be used to reduce label density
- * at z14. Since all POIs already need to be contained at z14 you can use
- * less than rank=10
epxression to limit POIs. At some point like z17 you can show all POIs.
- */
- public static final String RANK = "rank";
-
- /**
- * Experimental feature! Indicates main platform of public transport stops (buses, trams, and subways). Grouping
- * of platforms is implemented using
- * uic_ref
tag that is not used
- * worldwide.
- *
- * allowed values:
- *
- */
- public static final String AGG_STOP = "agg_stop";
- /** Original value of level
tag. */
- public static final String LEVEL = "level";
- /** Original value of layer
tag. */
- public static final String LAYER = "layer";
-
- /**
- * Original value of indoor
tag.
- *
- * allowed values:
- *
- */
- public static final String INDOOR = "indoor";
- }
- /** Attribute values for map elements in the poi layer. */
- final class FieldValues {
- public static final String CLASS_SHOP = "shop";
- public static final String CLASS_TOWN_HALL = "town_hall";
- public static final String CLASS_GOLF = "golf";
- public static final String CLASS_FAST_FOOD = "fast_food";
- public static final String CLASS_PARK = "park";
- public static final String CLASS_BUS = "bus";
- public static final String CLASS_RAILWAY = "railway";
- public static final String CLASS_AERIALWAY = "aerialway";
- public static final String CLASS_ENTRANCE = "entrance";
- public static final String CLASS_CAMPSITE = "campsite";
- public static final String CLASS_LAUNDRY = "laundry";
- public static final String CLASS_GROCERY = "grocery";
- public static final String CLASS_LIBRARY = "library";
- public static final String CLASS_COLLEGE = "college";
- public static final String CLASS_LODGING = "lodging";
- public static final String CLASS_ICE_CREAM = "ice_cream";
- public static final String CLASS_POST = "post";
- public static final String CLASS_CAFE = "cafe";
- public static final String CLASS_SCHOOL = "school";
- public static final String CLASS_ALCOHOL_SHOP = "alcohol_shop";
- public static final String CLASS_BAR = "bar";
- public static final String CLASS_HARBOR = "harbor";
- public static final String CLASS_CAR = "car";
- public static final String CLASS_HOSPITAL = "hospital";
- public static final String CLASS_CEMETERY = "cemetery";
- public static final String CLASS_ATTRACTION = "attraction";
- public static final String CLASS_BEER = "beer";
- public static final String CLASS_MUSIC = "music";
- public static final String CLASS_STADIUM = "stadium";
- public static final String CLASS_ART_GALLERY = "art_gallery";
- public static final String CLASS_CLOTHING_STORE = "clothing_store";
- public static final String CLASS_SWIMMING = "swimming";
- public static final String CLASS_CASTLE = "castle";
- public static final String CLASS_ATM = "atm";
- public static final Set CLASS_VALUES = Set.of("shop", "town_hall", "golf", "fast_food", "park", "bus",
- "railway", "aerialway", "entrance", "campsite", "laundry", "grocery", "library", "college", "lodging",
- "ice_cream", "post", "cafe", "school", "alcohol_shop", "bar", "harbor", "car", "hospital", "cemetery",
- "attraction", "beer", "music", "stadium", "art_gallery", "clothing_store", "swimming", "castle", "atm");
- }
- /** Complex mappings to generate attribute values from OSM element tags in the poi layer. */
- final class FieldMappings {
- public static final MultiExpression Class = MultiExpression.of(List.of(
- MultiExpression.entry("shop",
- matchAny("subclass", "accessories", "antiques", "beauty", "bed", "boutique", "camera", "carpet", "charity",
- "chemist", "coffee", "computer", "convenience", "copyshop", "cosmetics", "garden_centre", "doityourself",
- "erotic", "electronics", "fabric", "florist", "frozen_food", "furniture", "video_games", "video", "general",
- "gift", "hardware", "hearing_aids", "hifi", "ice_cream", "interior_decoration", "jewelry", "kiosk",
- "locksmith", "lamps", "mall", "massage", "motorcycle", "mobile_phone", "newsagent", "optician", "outdoor",
- "perfumery", "perfume", "pet", "photo", "second_hand", "shoes", "sports", "stationery", "tailor", "tattoo",
- "ticket", "tobacco", "toys", "travel_agency", "watches", "weapons", "wholesale")),
- MultiExpression.entry("town_hall",
- matchAny("subclass", "townhall", "public_building", "courthouse", "community_centre")),
- MultiExpression.entry("golf", matchAny("subclass", "golf", "golf_course", "miniature_golf")),
- MultiExpression.entry("fast_food", matchAny("subclass", "fast_food", "food_court")),
- MultiExpression.entry("park", matchAny("subclass", "park", "bbq")),
- MultiExpression.entry("bus", matchAny("subclass", "bus_stop", "bus_station")),
- MultiExpression.entry("railway",
- or(and(matchAny("subclass", "station"), matchAny("mapping_key", "railway")),
- matchAny("subclass", "halt", "tram_stop", "subway"))),
- MultiExpression.entry("aerialway", and(matchAny("subclass", "station"), matchAny("mapping_key", "aerialway"))),
- MultiExpression.entry("entrance", matchAny("subclass", "subway_entrance", "train_station_entrance")),
- MultiExpression.entry("campsite", matchAny("subclass", "camp_site", "caravan_site")),
- MultiExpression.entry("laundry", matchAny("subclass", "laundry", "dry_cleaning")),
- MultiExpression.entry("grocery",
- matchAny("subclass", "supermarket", "deli", "delicatessen", "department_store", "greengrocer",
- "marketplace")),
- MultiExpression.entry("library", matchAny("subclass", "books", "library")),
- MultiExpression.entry("college", matchAny("subclass", "university", "college")),
- MultiExpression.entry("lodging",
- matchAny("subclass", "hotel", "motel", "bed_and_breakfast", "guest_house", "hostel", "chalet", "alpine_hut",
- "dormitory")),
- MultiExpression.entry("ice_cream", matchAny("subclass", "chocolate", "confectionery")),
- MultiExpression.entry("post", matchAny("subclass", "post_box", "post_office")),
- MultiExpression.entry("cafe", matchAny("subclass", "cafe")),
- MultiExpression.entry("school", matchAny("subclass", "school", "kindergarten")),
- MultiExpression.entry("alcohol_shop", matchAny("subclass", "alcohol", "beverages", "wine")),
- MultiExpression.entry("bar", matchAny("subclass", "bar", "nightclub")),
- MultiExpression.entry("harbor", matchAny("subclass", "marina", "dock")),
- MultiExpression.entry("car", matchAny("subclass", "car", "car_repair", "car_parts", "taxi")),
- MultiExpression.entry("hospital", matchAny("subclass", "hospital", "nursing_home", "clinic")),
- MultiExpression.entry("cemetery", matchAny("subclass", "grave_yard", "cemetery")),
- MultiExpression.entry("attraction", matchAny("subclass", "attraction", "viewpoint")),
- MultiExpression.entry("beer", matchAny("subclass", "biergarten", "pub")),
- MultiExpression.entry("music", matchAny("subclass", "music", "musical_instrument")),
- MultiExpression.entry("stadium", matchAny("subclass", "american_football", "stadium", "soccer")),
- MultiExpression.entry("art_gallery", matchAny("subclass", "art", "artwork", "gallery", "arts_centre")),
- MultiExpression.entry("clothing_store", matchAny("subclass", "bag", "clothes")),
- MultiExpression.entry("swimming", matchAny("subclass", "swimming_area", "swimming")),
- MultiExpression.entry("castle", matchAny("subclass", "castle", "ruins")),
- MultiExpression.entry("atm", matchAny("subclass", "atm"))));
- }
- }
- /**
- * Aerodrome labels
- *
- * Generated from aerodrome_label.yaml
- */
- public interface AerodromeLabel extends Layer {
- double BUFFER_SIZE = 64.0;
- String LAYER_NAME = "aerodrome_label";
-
- @Override
- default String name() {
- return LAYER_NAME;
- }
-
- /** Attribute names for map elements in the aerodrome_label layer. */
- final class Fields {
- /** The OSM name
value of the aerodrome. */
- public static final String NAME = "name";
- /** English name name:en
if available, otherwise name
. */
- public static final String NAME_EN = "name_en";
- /** German name name:de
if available, otherwise name
or name:en
. */
- public static final String NAME_DE = "name_de";
-
- /**
- * Distinguish between more and less important aerodromes. Class is derived from the value of
- * aerodrome
and
- * aerodrome:type
tags.
- *
- * allowed values:
- *
- * - international
- *
- public
- *
- regional
- *
- military
- *
- private
- *
- other
- *
- */
- public static final String CLASS = "class";
- /** 3-character code issued by the IATA. */
- public static final String IATA = "iata";
- /** 4-letter code issued by the ICAO. */
- public static final String ICAO = "icao";
- /** Elevation (ele
) in meters. */
- public static final String ELE = "ele";
- /** Elevation (ele
) in feets. */
- public static final String ELE_FT = "ele_ft";
- }
- /** Attribute values for map elements in the aerodrome_label layer. */
- final class FieldValues {
- public static final String CLASS_INTERNATIONAL = "international";
- public static final String CLASS_PUBLIC = "public";
- public static final String CLASS_REGIONAL = "regional";
- public static final String CLASS_MILITARY = "military";
- public static final String CLASS_PRIVATE = "private";
- public static final String CLASS_OTHER = "other";
- public static final Set CLASS_VALUES =
- Set.of("international", "public", "regional", "military", "private", "other");
- }
- /** Complex mappings to generate attribute values from OSM element tags in the aerodrome_label layer. */
- final class FieldMappings {
- public static final MultiExpression Class = MultiExpression.of(List.of(
- MultiExpression.entry("international",
- or(matchAny("aerodrome", "international"), matchAny("aerodrome_type", "international"))),
- MultiExpression.entry("public",
- or(matchAny("aerodrome", "public"), matchAny("aerodrome_type", "%public%", "civil"))),
- MultiExpression.entry("regional",
- or(matchAny("aerodrome", "regional"), matchAny("aerodrome_type", "regional"))),
- MultiExpression.entry("military",
- or(matchAny("aerodrome", "military"), matchAny("aerodrome_type", "%military%"),
- matchAny("military", "airfield"))),
- MultiExpression.entry("private", or(matchAny("aerodrome", "private"), matchAny("aerodrome_type", "private"))),
- MultiExpression.entry("other", FALSE)));
- }
- }
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/Tables.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/Tables.java
deleted file mode 100644
index f60caff40a..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/generated/Tables.java
+++ /dev/null
@@ -1,1501 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-// AUTOGENERATED BY Generate.java -- DO NOT MODIFY
-
-package com.onthegomap.planetiler.basemap.generated;
-
-import static com.onthegomap.planetiler.expression.Expression.*;
-
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.expression.Expression;
-import com.onthegomap.planetiler.expression.MultiExpression;
-import com.onthegomap.planetiler.reader.SourceFeature;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * OSM element parsers generated from the imposm3 table definitions
- * in the OpenMapTiles vector tile
- * schema.
- *
- * These filter and parse the raw OSM key/value attribute pairs on tags into records with fields that match the columns
- * in the tables that imposm3 would generate. Layer implementations can "subscribe" to elements from each "table" but
- * implementing the table's {@code Handler} interface and use the element's typed API to access attributes.
- */
-@SuppressWarnings("unused")
-public class Tables {
- /** A parsed OSM element that would appear in a "row" of the imposm3 table. */
- public interface Row {
-
- /** Returns the original OSM element. */
- SourceFeature source();
- }
-
- /** A functional interface that the constructor of a new table row can be coerced to. */
- @FunctionalInterface
- public interface Constructor {
-
- Row create(SourceFeature source, String mappingKey);
- }
-
- /** The {@code rowClass} of an imposm3 table row and its constructor coerced to a {@link Constructor}. */
- public record RowClassAndConstructor(
- Class extends Row> rowClass,
- Constructor create
- ) {}
-
- /** A functional interface that the typed handler method that a layer implementation can be coerced to. */
- @FunctionalInterface
- public interface RowHandler {
-
- /** Process a typed element according to the profile. */
- void process(T element, FeatureCollector features);
- }
-
- /** The {@code handlerClass} of a layer handler and it's {@code process} method coerced to a {@link RowHandler}. */
- public record RowHandlerAndClass (
- Class> handlerClass,
- RowHandler handler
- ) {}
- /** An OSM element that would appear in the {@code osm_water_polygon} table generated by imposm3. */
- public record OsmWaterPolygon(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override String natural, @Override String landuse, @Override String waterway, @Override String leisure,
- @Override String water, @Override boolean isIntermittent, @Override boolean isTunnel, @Override boolean isBridge,
- @Override SourceFeature source) implements Row, WithName, WithNameEn, WithNameDe, WithNatural, WithLanduse,
- WithWaterway, WithLeisure, WithWater, WithIsIntermittent, WithIsTunnel, WithIsBridge, WithSource {
- public OsmWaterPolygon(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"),
- source.getString("natural"), source.getString("landuse"), source.getString("waterway"),
- source.getString("leisure"), source.getString("water"), source.getBoolean("intermittent"),
- source.getBoolean("tunnel"), source.getBoolean("bridge"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING =
- and(or(matchAny("landuse", "reservoir", "basin", "salt_pond"), matchAny("leisure", "swimming_pool"),
- matchAny("natural", "water", "bay", "spring"), matchAny("waterway", "riverbank", "dock"),
- matchAny("water", "river")), not(matchAny("covered", "yes")), matchType("polygon"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmWaterPolygon}.
- */
- public interface Handler {
- void process(OsmWaterPolygon element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_waterway_linestring} table generated by imposm3. */
- public record OsmWaterwayLinestring(@Override String waterway, @Override String name, @Override String nameEn,
- @Override String nameDe, @Override boolean isTunnel, @Override boolean isBridge, @Override boolean isIntermittent,
- @Override SourceFeature source) implements Row, WithWaterway, WithName, WithNameEn, WithNameDe, WithIsTunnel,
- WithIsBridge, WithIsIntermittent, WithSource {
- public OsmWaterwayLinestring(SourceFeature source, String mappingKey) {
- this(source.getString("waterway"), source.getString("name"), source.getString("name:en"),
- source.getString("name:de"), source.getBoolean("tunnel"), source.getBoolean("bridge"),
- source.getBoolean("intermittent"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING =
- and(matchAny("waterway", "stream", "river", "canal", "drain", "ditch"), matchType("linestring"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmWaterwayLinestring}.
- */
- public interface Handler {
- void process(OsmWaterwayLinestring element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_landcover_polygon} table generated by imposm3. */
- public record OsmLandcoverPolygon(@Override String subclass, @Override String mappingKey,
- @Override SourceFeature source) implements Row, WithSubclass, WithMappingKey, WithSource {
- public OsmLandcoverPolygon(SourceFeature source, String mappingKey) {
- this(source.getString(mappingKey), mappingKey, source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(or(
- matchAny("landuse", "allotments", "farm", "farmland", "orchard", "plant_nursery", "vineyard", "grass",
- "grassland", "meadow", "forest", "village_green", "recreation_ground"),
- matchAny("natural", "wood", "wetland", "fell", "grassland", "heath", "scrub", "tundra", "glacier", "bare_rock",
- "scree", "beach", "sand", "dune"),
- matchAny("leisure", "park", "garden", "golf_course"), matchAny("wetland", "bog", "swamp", "wet_meadow", "marsh",
- "reedbed", "saltern", "tidalflat", "saltmarsh", "mangrove")),
- matchType("polygon"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmLandcoverPolygon}.
- */
- public interface Handler {
- void process(OsmLandcoverPolygon element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_landuse_polygon} table generated by imposm3. */
- public record OsmLandusePolygon(@Override String landuse, @Override String amenity, @Override String leisure,
- @Override String tourism, @Override String place, @Override String waterway, @Override SourceFeature source)
- implements Row, WithLanduse, WithAmenity, WithLeisure, WithTourism, WithPlace, WithWaterway, WithSource {
- public OsmLandusePolygon(SourceFeature source, String mappingKey) {
- this(source.getString("landuse"), source.getString("amenity"), source.getString("leisure"),
- source.getString("tourism"), source.getString("place"), source.getString("waterway"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(or(
- matchAny("landuse", "railway", "cemetery", "military", "residential", "commercial", "industrial", "garages",
- "retail"),
- matchAny("amenity", "bus_station", "school", "university", "kindergarten", "college", "library", "hospital",
- "grave_yard"),
- matchAny("leisure", "stadium", "pitch", "playground", "track"), matchAny("tourism", "theme_park", "zoo"),
- matchAny("place", "suburb", "quarter", "neighbourhood"), matchAny("waterway", "dam")), matchType("polygon"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmLandusePolygon}.
- */
- public interface Handler {
- void process(OsmLandusePolygon element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_peak_point} table generated by imposm3. */
- public record OsmPeakPoint(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override String ele, @Override String wikipedia, @Override SourceFeature source)
- implements Row, WithName, WithNameEn, WithNameDe, WithEle, WithWikipedia, WithSource {
- public OsmPeakPoint(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("ele"),
- source.getString("wikipedia"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(matchAny("natural", "peak", "volcano", "saddle"), matchType("point"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmPeakPoint}.
- */
- public interface Handler {
- void process(OsmPeakPoint element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_mountain_linestring} table generated by imposm3. */
- public record OsmMountainLinestring(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override String wikipedia, @Override SourceFeature source)
- implements Row, WithName, WithNameEn, WithNameDe, WithWikipedia, WithSource {
- public OsmMountainLinestring(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"),
- source.getString("wikipedia"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING =
- and(matchAny("natural", "ridge", "cliff", "arete"), matchType("linestring"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmMountainLinestring}.
- */
- public interface Handler {
- void process(OsmMountainLinestring element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_park_polygon} table generated by imposm3. */
- public record OsmParkPolygon(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override String landuse, @Override String leisure, @Override String boundary, @Override String protectionTitle,
- @Override SourceFeature source) implements Row, WithName, WithNameEn, WithNameDe, WithLanduse, WithLeisure,
- WithBoundary, WithProtectionTitle, WithSource {
- public OsmParkPolygon(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"),
- source.getString("landuse"), source.getString("leisure"), source.getString("boundary"),
- source.getString("protection_title"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING =
- and(or(matchAny("leisure", "nature_reserve"), matchAny("boundary", "national_park", "protected_area")),
- matchType("polygon"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmParkPolygon}.
- */
- public interface Handler {
- void process(OsmParkPolygon element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_aeroway_polygon} table generated by imposm3. */
- public record OsmAerowayPolygon(@Override String ref, @Override String aeroway, @Override SourceFeature source)
- implements Row, WithRef, WithAeroway, WithSource {
- public OsmAerowayPolygon(SourceFeature source, String mappingKey) {
- this(source.getString("ref"), source.getString(mappingKey), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(
- or(matchAny("aeroway", "aerodrome", "heliport", "runway", "helipad", "taxiway", "apron"),
- matchAny("area:aeroway", "aerodrome", "heliport", "runway", "helipad", "taxiway", "apron")),
- matchType("polygon"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmAerowayPolygon}.
- */
- public interface Handler {
- void process(OsmAerowayPolygon element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_aeroway_linestring} table generated by imposm3. */
- public record OsmAerowayLinestring(@Override String ref, @Override String aeroway, @Override SourceFeature source)
- implements Row, WithRef, WithAeroway, WithSource {
- public OsmAerowayLinestring(SourceFeature source, String mappingKey) {
- this(source.getString("ref"), source.getString("aeroway"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(matchAny("aeroway", "runway", "taxiway"), matchType("linestring"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmAerowayLinestring}.
- */
- public interface Handler {
- void process(OsmAerowayLinestring element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_aeroway_point} table generated by imposm3. */
- public record OsmAerowayPoint(@Override String ref, @Override String aeroway, @Override SourceFeature source)
- implements Row, WithRef, WithAeroway, WithSource {
- public OsmAerowayPoint(SourceFeature source, String mappingKey) {
- this(source.getString("ref"), source.getString("aeroway"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(matchAny("aeroway", "gate"), matchType("point"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmAerowayPoint}.
- */
- public interface Handler {
- void process(OsmAerowayPoint element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_highway_linestring} table generated by imposm3. */
- public record OsmHighwayLinestring(@Override String highway, @Override String construction, @Override String ref,
- @Override String network, @Override int zOrder, @Override long layer, @Override long level,
- @Override boolean indoor, @Override String name, @Override String nameEn, @Override String nameDe,
- @Override String shortName, @Override boolean isTunnel, @Override boolean isBridge, @Override boolean isRamp,
- @Override boolean isFord, @Override int isOneway, @Override boolean isArea, @Override String service,
- @Override String access, @Override boolean toll, @Override String usage, @Override String publicTransport,
- @Override String manMade, @Override String bicycle, @Override String foot, @Override String horse,
- @Override String mtbScale, @Override String sacScale, @Override String surface, @Override boolean expressway,
- @Override SourceFeature source) implements Row, WithHighway, WithConstruction, WithRef, WithNetwork, WithZOrder,
- WithLayer, WithLevel, WithIndoor, WithName, WithNameEn, WithNameDe, WithShortName, WithIsTunnel, WithIsBridge,
- WithIsRamp, WithIsFord, WithIsOneway, WithIsArea, WithService, WithAccess, WithToll, WithUsage, WithPublicTransport,
- WithManMade, WithBicycle, WithFoot, WithHorse, WithMtbScale, WithSacScale, WithSurface, WithExpressway, WithSource {
- public OsmHighwayLinestring(SourceFeature source, String mappingKey) {
- this(source.getString("highway"), source.getString("construction"), source.getString("ref"),
- source.getString("network"), source.getWayZorder(), source.getLong("layer"), source.getLong("level"),
- source.getBoolean("indoor"), source.getString("name"), source.getString("name:en"), source.getString("name:de"),
- source.getString("short_name"), source.getBoolean("tunnel"), source.getBoolean("bridge"),
- source.getBoolean("ramp"), source.getBoolean("ford"), source.getDirection("oneway"), source.getBoolean("area"),
- source.getString("service"), source.getString("access"), source.getBoolean("toll"), source.getString("usage"),
- source.getString("public_transport"), source.getString("man_made"), source.getString("bicycle"),
- source.getString("foot"), source.getString("horse"), source.getString("mtb:scale"),
- source.getString("sac_scale"), source.getString("surface"), source.getBoolean("expressway"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(or(
- matchAny("highway", "motorway", "motorway_link", "trunk", "trunk_link", "primary", "primary_link", "secondary",
- "secondary_link", "tertiary", "tertiary_link", "unclassified", "residential", "living_street", "road",
- "pedestrian", "path", "footway", "cycleway", "steps", "bridleway", "corridor", "service", "track", "raceway",
- "busway", "construction"),
- matchAny("public_transport", "platform"), matchAny("man_made", "pier"),
- matchAny("service", "driveway", "parking_aisle")), matchType("linestring"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmHighwayLinestring}.
- */
- public interface Handler {
- void process(OsmHighwayLinestring element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_railway_linestring} table generated by imposm3. */
- public record OsmRailwayLinestring(@Override String railway, @Override String ref, @Override String network,
- @Override int zOrder, @Override long layer, @Override long level, @Override boolean indoor, @Override String name,
- @Override String nameEn, @Override String nameDe, @Override String shortName, @Override boolean isTunnel,
- @Override boolean isBridge, @Override boolean isRamp, @Override boolean isFord, @Override int isOneway,
- @Override boolean isArea, @Override String service, @Override String usage, @Override SourceFeature source)
- implements Row, WithRailway, WithRef, WithNetwork, WithZOrder, WithLayer, WithLevel, WithIndoor, WithName,
- WithNameEn, WithNameDe, WithShortName, WithIsTunnel, WithIsBridge, WithIsRamp, WithIsFord, WithIsOneway, WithIsArea,
- WithService, WithUsage, WithSource {
- public OsmRailwayLinestring(SourceFeature source, String mappingKey) {
- this(source.getString("railway"), source.getString("ref"), source.getString("network"), source.getWayZorder(),
- source.getLong("layer"), source.getLong("level"), source.getBoolean("indoor"), source.getString("name"),
- source.getString("name:en"), source.getString("name:de"), source.getString("short_name"),
- source.getBoolean("tunnel"), source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"),
- source.getDirection("oneway"), source.getBoolean("area"), source.getString("service"),
- source.getString("usage"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(
- matchAny("railway", "rail", "narrow_gauge", "preserved", "funicular", "subway", "light_rail", "monorail", "tram"),
- matchType("linestring"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmRailwayLinestring}.
- */
- public interface Handler {
- void process(OsmRailwayLinestring element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_aerialway_linestring} table generated by imposm3. */
- public record OsmAerialwayLinestring(@Override String aerialway, @Override int zOrder, @Override long layer,
- @Override String name, @Override String nameEn, @Override String nameDe, @Override String shortName,
- @Override boolean isTunnel, @Override boolean isBridge, @Override boolean isRamp, @Override boolean isFord,
- @Override int isOneway, @Override boolean isArea, @Override String service, @Override String usage,
- @Override SourceFeature source)
- implements Row, WithAerialway, WithZOrder, WithLayer, WithName, WithNameEn, WithNameDe, WithShortName, WithIsTunnel,
- WithIsBridge, WithIsRamp, WithIsFord, WithIsOneway, WithIsArea, WithService, WithUsage, WithSource {
- public OsmAerialwayLinestring(SourceFeature source, String mappingKey) {
- this(source.getString("aerialway"), source.getWayZorder(), source.getLong("layer"), source.getString("name"),
- source.getString("name:en"), source.getString("name:de"), source.getString("short_name"),
- source.getBoolean("tunnel"), source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"),
- source.getDirection("oneway"), source.getBoolean("area"), source.getString("service"),
- source.getString("usage"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(matchAny("aerialway", "chair_lift", "drag_lift", "platter", "t-bar",
- "gondola", "cable_car", "j-bar", "mixed_lift"), matchType("linestring"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmAerialwayLinestring}.
- */
- public interface Handler {
- void process(OsmAerialwayLinestring element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_shipway_linestring} table generated by imposm3. */
- public record OsmShipwayLinestring(@Override String shipway, @Override int zOrder, @Override long layer,
- @Override String name, @Override String nameEn, @Override String nameDe, @Override String shortName,
- @Override boolean isTunnel, @Override boolean isBridge, @Override boolean isRamp, @Override boolean isFord,
- @Override int isOneway, @Override boolean isArea, @Override String service, @Override String usage,
- @Override SourceFeature source)
- implements Row, WithShipway, WithZOrder, WithLayer, WithName, WithNameEn, WithNameDe, WithShortName, WithIsTunnel,
- WithIsBridge, WithIsRamp, WithIsFord, WithIsOneway, WithIsArea, WithService, WithUsage, WithSource {
- public OsmShipwayLinestring(SourceFeature source, String mappingKey) {
- this(source.getString("route"), source.getWayZorder(), source.getLong("layer"), source.getString("name"),
- source.getString("name:en"), source.getString("name:de"), source.getString("short_name"),
- source.getBoolean("tunnel"), source.getBoolean("bridge"), source.getBoolean("ramp"), source.getBoolean("ford"),
- source.getDirection("oneway"), source.getBoolean("area"), source.getString("service"),
- source.getString("usage"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(matchAny("route", "ferry"), matchType("linestring"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmShipwayLinestring}.
- */
- public interface Handler {
- void process(OsmShipwayLinestring element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_highway_polygon} table generated by imposm3. */
- public record OsmHighwayPolygon(@Override String highway, @Override int zOrder, @Override long layer,
- @Override long level, @Override boolean indoor, @Override boolean isArea, @Override String publicTransport,
- @Override String manMade, @Override String service, @Override SourceFeature source)
- implements Row, WithHighway, WithZOrder, WithLayer, WithLevel, WithIndoor, WithIsArea, WithPublicTransport,
- WithManMade, WithService, WithSource {
- public OsmHighwayPolygon(SourceFeature source, String mappingKey) {
- this(source.getString("highway"), source.getWayZorder(), source.getLong("layer"), source.getLong("level"),
- source.getBoolean("indoor"), source.getBoolean("area"), source.getString("public_transport"),
- source.getString("man_made"), source.getString("service"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING =
- and(or(matchAny("highway", "path", "cycleway", "bridleway", "footway", "corridor", "pedestrian", "steps"),
- matchAny("public_transport", "platform"), matchAny("man_made", "bridge", "pier")), matchType("polygon"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmHighwayPolygon}.
- */
- public interface Handler {
- void process(OsmHighwayPolygon element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_highway_point} table generated by imposm3. */
- public record OsmHighwayPoint(@Override String highway, @Override int zOrder, @Override long layer,
- @Override long level, @Override String name, @Override String nameEn, @Override String nameDe, @Override String ref,
- @Override SourceFeature source) implements Row, WithHighway, WithZOrder, WithLayer, WithLevel, WithName, WithNameEn,
- WithNameDe, WithRef, WithSource {
- public OsmHighwayPoint(SourceFeature source, String mappingKey) {
- this(source.getString("highway"), source.getWayZorder(), source.getLong("layer"), source.getLong("level"),
- source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getString("ref"),
- source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(matchAny("highway", "motorway_junction"), matchType("point"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmHighwayPoint}.
- */
- public interface Handler {
- void process(OsmHighwayPoint element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_building_polygon} table generated by imposm3. */
- public record OsmBuildingPolygon(@Override String material, @Override String colour, @Override String building,
- @Override String buildingpart, @Override String buildingheight, @Override String buildingminHeight,
- @Override String buildinglevels, @Override String buildingminLevel, @Override String height,
- @Override String minHeight, @Override String levels, @Override String minLevel, @Override SourceFeature source)
- implements Row, WithMaterial, WithColour, WithBuilding, WithBuildingpart, WithBuildingheight, WithBuildingminHeight,
- WithBuildinglevels, WithBuildingminLevel, WithHeight, WithMinHeight, WithLevels, WithMinLevel, WithSource {
- public OsmBuildingPolygon(SourceFeature source, String mappingKey) {
- this(source.getString("building:material"), source.getString("building:colour"), source.getString("building"),
- source.getString("building:part"), source.getString("building:height"), source.getString("building:min_height"),
- source.getString("building:levels"), source.getString("building:min_level"), source.getString("height"),
- source.getString("min_height"), source.getString("levels"), source.getString("min_level"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(
- or(matchField("building:part"), matchField("building"), matchAny("aeroway", "terminal", "hangar"),
- matchAny("location", "underground")),
- not(matchAny("building", "no", "none", "No")), not(matchAny("building:part", "no", "none", "No")),
- not(matchAny("man_made", "bridge")), not(matchAny("location", "underground")), matchType("polygon"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmBuildingPolygon}.
- */
- public interface Handler {
- void process(OsmBuildingPolygon element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_marine_point} table generated by imposm3. */
- public record OsmMarinePoint(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override String place, @Override long rank, @Override boolean isIntermittent, @Override SourceFeature source)
- implements Row, WithName, WithNameEn, WithNameDe, WithPlace, WithRank, WithIsIntermittent, WithSource {
- public OsmMarinePoint(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"),
- source.getString("place"), source.getLong("rank"), source.getBoolean("intermittent"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING =
- and(matchAny("place", "ocean", "sea"), matchField("name"), matchType("point"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmMarinePoint}.
- */
- public interface Handler {
- void process(OsmMarinePoint element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_continent_point} table generated by imposm3. */
- public record OsmContinentPoint(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override SourceFeature source) implements Row, WithName, WithNameEn, WithNameDe, WithSource {
- public OsmContinentPoint(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING =
- and(matchAny("place", "continent"), matchField("name"), matchType("point"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmContinentPoint}.
- */
- public interface Handler {
- void process(OsmContinentPoint element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_country_point} table generated by imposm3. */
- public record OsmCountryPoint(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override long rank, @Override String countryCodeIso31661Alpha2, @Override String iso31661Alpha2,
- @Override String iso31661, @Override SourceFeature source) implements Row, WithName, WithNameEn, WithNameDe,
- WithRank, WithCountryCodeIso31661Alpha2, WithIso31661Alpha2, WithIso31661, WithSource {
- public OsmCountryPoint(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getLong("rank"),
- source.getString("country_code_iso3166_1_alpha_2"), source.getString("ISO3166-1:alpha2"),
- source.getString("ISO3166-1"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(matchAny("place", "country"), matchField("name"), matchType("point"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmCountryPoint}.
- */
- public interface Handler {
- void process(OsmCountryPoint element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_island_polygon} table generated by imposm3. */
- public record OsmIslandPolygon(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override long rank, @Override SourceFeature source)
- implements Row, WithName, WithNameEn, WithNameDe, WithRank, WithSource {
- public OsmIslandPolygon(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getLong("rank"),
- source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(matchAny("place", "island"), matchField("name"), matchType("polygon"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmIslandPolygon}.
- */
- public interface Handler {
- void process(OsmIslandPolygon element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_island_point} table generated by imposm3. */
- public record OsmIslandPoint(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override long rank, @Override SourceFeature source)
- implements Row, WithName, WithNameEn, WithNameDe, WithRank, WithSource {
- public OsmIslandPoint(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"), source.getLong("rank"),
- source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(matchAny("place", "island"), matchField("name"), matchType("point"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmIslandPoint}.
- */
- public interface Handler {
- void process(OsmIslandPoint element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_state_point} table generated by imposm3. */
- public record OsmStatePoint(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override String place, @Override String isInCountry, @Override String isInCountryCode, @Override String ref,
- @Override long rank, @Override SourceFeature source) implements Row, WithName, WithNameEn, WithNameDe, WithPlace,
- WithIsInCountry, WithIsInCountryCode, WithRef, WithRank, WithSource {
- public OsmStatePoint(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"),
- source.getString("place"), source.getString("is_in:country"), source.getString("is_in:country_code"),
- source.getString("ref"), source.getLong("rank"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING =
- and(matchAny("place", "state", "province"), matchField("name"), matchType("point"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmStatePoint}.
- */
- public interface Handler {
- void process(OsmStatePoint element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_city_point} table generated by imposm3. */
- public record OsmCityPoint(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override String place, @Override long population, @Override String capital, @Override long rank,
- @Override SourceFeature source)
- implements Row, WithName, WithNameEn, WithNameDe, WithPlace, WithPopulation, WithCapital, WithRank, WithSource {
- public OsmCityPoint(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"),
- source.getString("place"), source.getLong("population"), source.getString("capital"), source.getLong("rank"),
- source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(
- matchAny("place", "city", "town", "village", "hamlet", "suburb", "quarter", "neighbourhood", "isolated_dwelling"),
- matchField("name"), matchType("point"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmCityPoint}.
- */
- public interface Handler {
- void process(OsmCityPoint element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_housenumber_point} table generated by imposm3. */
- public record OsmHousenumberPoint(@Override String housenumber, @Override SourceFeature source)
- implements Row, WithHousenumber, WithSource {
- public OsmHousenumberPoint(SourceFeature source, String mappingKey) {
- this(source.getString("addr:housenumber"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = or(and(matchField("addr:housenumber"), matchType("point")),
- and(matchField("addr:housenumber"), matchType("polygon")));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmHousenumberPoint}.
- */
- public interface Handler {
- void process(OsmHousenumberPoint element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_poi_point} table generated by imposm3. */
- public record OsmPoiPoint(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override String subclass, @Override String mappingKey, @Override String station, @Override String funicular,
- @Override String information, @Override String uicRef, @Override String religion, @Override long level,
- @Override boolean indoor, @Override long layer, @Override String sport, @Override String operator,
- @Override String network, @Override SourceFeature source) implements Row, WithName, WithNameEn, WithNameDe,
- WithSubclass, WithMappingKey, WithStation, WithFunicular, WithInformation, WithUicRef, WithReligion, WithLevel,
- WithIndoor, WithLayer, WithSport, WithOperator, WithNetwork, WithSource {
- public OsmPoiPoint(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"),
- source.getString(mappingKey), mappingKey, source.getString("station"), source.getString("funicular"),
- source.getString("information"), source.getString("uic_ref"), source.getString("religion"),
- source.getLong("level"), source.getBoolean("indoor"), source.getLong("layer"), source.getString("sport"),
- source.getString("operator"), source.getString("network"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(or(matchAny("aerialway", "station"),
- matchAny("amenity", "arts_centre", "atm", "bank", "bar", "bbq", "bicycle_parking", "bicycle_rental", "biergarten",
- "bus_station", "cafe", "cinema", "clinic", "college", "community_centre", "courthouse", "dentist", "doctors",
- "drinking_water", "fast_food", "ferry_terminal", "fire_station", "food_court", "fuel", "grave_yard", "hospital",
- "ice_cream", "kindergarten", "library", "marketplace", "motorcycle_parking", "nightclub", "nursing_home",
- "parking", "pharmacy", "place_of_worship", "police", "post_box", "post_office", "prison", "pub",
- "public_building", "recycling", "restaurant", "school", "shelter", "swimming_pool", "taxi", "telephone",
- "theatre", "toilets", "townhall", "university", "veterinary", "waste_basket"),
- matchAny("barrier", "bollard", "border_control", "cycle_barrier", "gate", "lift_gate", "sally_port", "stile",
- "toll_booth"),
- matchAny("building", "dormitory"), matchAny("highway", "bus_stop"),
- matchAny("historic", "monument", "castle", "ruins"),
- matchAny("landuse", "basin", "brownfield", "cemetery", "reservoir", "winter_sports"),
- matchAny("leisure", "dog_park", "escape_game", "garden", "golf_course", "ice_rink", "hackerspace", "marina",
- "miniature_golf", "park", "pitch", "playground", "sports_centre", "stadium", "swimming_area", "swimming_pool",
- "water_park"),
- matchAny("office", "diplomatic"),
- matchAny("railway", "halt", "station", "subway_entrance", "train_station_entrance", "tram_stop"),
- matchAny("shop", "accessories", "alcohol", "antiques", "art", "bag", "bakery", "beauty", "bed", "beverages",
- "bicycle", "books", "boutique", "butcher", "camera", "car", "car_repair", "car_parts", "carpet", "charity",
- "chemist", "chocolate", "clothes", "coffee", "computer", "confectionery", "convenience", "copyshop",
- "cosmetics", "deli", "delicatessen", "department_store", "doityourself", "dry_cleaning", "electronics",
- "erotic", "fabric", "florist", "frozen_food", "furniture", "garden_centre", "general", "gift", "greengrocer",
- "hairdresser", "hardware", "hearing_aids", "hifi", "ice_cream", "interior_decoration", "jewelry", "kiosk",
- "lamps", "laundry", "locksmith", "mall", "massage", "mobile_phone", "motorcycle", "music", "musical_instrument",
- "newsagent", "optician", "outdoor", "perfume", "perfumery", "pet", "photo", "second_hand", "shoes", "sports",
- "stationery", "supermarket", "tailor", "tattoo", "ticket", "tobacco", "toys", "travel_agency", "video",
- "video_games", "watches", "weapons", "wholesale", "wine"),
- matchAny("sport", "american_football", "archery", "athletics", "australian_football", "badminton", "baseball",
- "basketball", "beachvolleyball", "billiards", "bmx", "boules", "bowls", "boxing", "canadian_football", "canoe",
- "chess", "climbing", "climbing_adventure", "cricket", "cricket_nets", "croquet", "curling", "cycling",
- "disc_golf", "diving", "dog_racing", "equestrian", "fatsal", "field_hockey", "free_flying", "gaelic_games",
- "golf", "gymnastics", "handball", "hockey", "horse_racing", "horseshoes", "ice_hockey", "ice_stock", "judo",
- "karting", "korfball", "long_jump", "model_aerodrome", "motocross", "motor", "multi", "netball", "orienteering",
- "paddle_tennis", "paintball", "paragliding", "pelota", "racquet", "rc_car", "rowing", "rugby", "rugby_league",
- "rugby_union", "running", "sailing", "scuba_diving", "shooting", "shooting_range", "skateboard", "skating",
- "skiing", "soccer", "surfing", "swimming", "table_soccer", "table_tennis", "team_handball", "tennis",
- "toboggan", "volleyball", "water_ski", "yoga"),
- matchAny("tourism", "alpine_hut", "aquarium", "artwork", "attraction", "bed_and_breakfast", "camp_site",
- "caravan_site", "chalet", "gallery", "guest_house", "hostel", "hotel", "information", "motel", "museum",
- "picnic_site", "theme_park", "viewpoint", "zoo"),
- matchAny("waterway", "dock")), matchType("point"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmPoiPoint}.
- */
- public interface Handler {
- void process(OsmPoiPoint element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_poi_polygon} table generated by imposm3. */
- public record OsmPoiPolygon(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override String subclass, @Override String mappingKey, @Override String station, @Override String funicular,
- @Override String information, @Override String uicRef, @Override String religion, @Override long level,
- @Override boolean indoor, @Override long layer, @Override String sport, @Override String operator,
- @Override String network, @Override SourceFeature source) implements Row, WithName, WithNameEn, WithNameDe,
- WithSubclass, WithMappingKey, WithStation, WithFunicular, WithInformation, WithUicRef, WithReligion, WithLevel,
- WithIndoor, WithLayer, WithSport, WithOperator, WithNetwork, WithSource {
- public OsmPoiPolygon(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"),
- source.getString(mappingKey), mappingKey, source.getString("station"), source.getString("funicular"),
- source.getString("information"), source.getString("uic_ref"), source.getString("religion"),
- source.getLong("level"), source.getBoolean("indoor"), source.getLong("layer"), source.getString("sport"),
- source.getString("operator"), source.getString("network"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = and(or(matchAny("aerialway", "station"),
- matchAny("amenity", "arts_centre", "atm", "bank", "bar", "bbq", "bicycle_parking", "bicycle_rental", "biergarten",
- "bus_station", "cafe", "cinema", "clinic", "college", "community_centre", "courthouse", "dentist", "doctors",
- "drinking_water", "fast_food", "ferry_terminal", "fire_station", "food_court", "fuel", "grave_yard", "hospital",
- "ice_cream", "kindergarten", "library", "marketplace", "motorcycle_parking", "nightclub", "nursing_home",
- "parking", "pharmacy", "place_of_worship", "police", "post_box", "post_office", "prison", "pub",
- "public_building", "recycling", "restaurant", "school", "shelter", "swimming_pool", "taxi", "telephone",
- "theatre", "toilets", "townhall", "university", "veterinary", "waste_basket"),
- matchAny("barrier", "bollard", "border_control", "cycle_barrier", "gate", "lift_gate", "sally_port", "stile",
- "toll_booth"),
- matchAny("building", "dormitory"), matchAny("highway", "bus_stop"),
- matchAny("historic", "monument", "castle", "ruins"),
- matchAny("landuse", "basin", "brownfield", "cemetery", "reservoir", "winter_sports"),
- matchAny("leisure", "dog_park", "escape_game", "garden", "golf_course", "ice_rink", "hackerspace", "marina",
- "miniature_golf", "park", "pitch", "playground", "sports_centre", "stadium", "swimming_area", "swimming_pool",
- "water_park"),
- matchAny("office", "diplomatic"),
- matchAny("railway", "halt", "station", "subway_entrance", "train_station_entrance", "tram_stop"),
- matchAny("shop", "accessories", "alcohol", "antiques", "art", "bag", "bakery", "beauty", "bed", "beverages",
- "bicycle", "books", "boutique", "butcher", "camera", "car", "car_repair", "car_parts", "carpet", "charity",
- "chemist", "chocolate", "clothes", "coffee", "computer", "confectionery", "convenience", "copyshop",
- "cosmetics", "deli", "delicatessen", "department_store", "doityourself", "dry_cleaning", "electronics",
- "erotic", "fabric", "florist", "frozen_food", "furniture", "garden_centre", "general", "gift", "greengrocer",
- "hairdresser", "hardware", "hearing_aids", "hifi", "ice_cream", "interior_decoration", "jewelry", "kiosk",
- "lamps", "laundry", "locksmith", "mall", "massage", "mobile_phone", "motorcycle", "music", "musical_instrument",
- "newsagent", "optician", "outdoor", "perfume", "perfumery", "pet", "photo", "second_hand", "shoes", "sports",
- "stationery", "supermarket", "tailor", "tattoo", "ticket", "tobacco", "toys", "travel_agency", "video",
- "video_games", "watches", "weapons", "wholesale", "wine"),
- matchAny("sport", "american_football", "archery", "athletics", "australian_football", "badminton", "baseball",
- "basketball", "beachvolleyball", "billiards", "bmx", "boules", "bowls", "boxing", "canadian_football", "canoe",
- "chess", "climbing", "climbing_adventure", "cricket", "cricket_nets", "croquet", "curling", "cycling",
- "disc_golf", "diving", "dog_racing", "equestrian", "fatsal", "field_hockey", "free_flying", "gaelic_games",
- "golf", "gymnastics", "handball", "hockey", "horse_racing", "horseshoes", "ice_hockey", "ice_stock", "judo",
- "karting", "korfball", "long_jump", "model_aerodrome", "motocross", "motor", "multi", "netball", "orienteering",
- "paddle_tennis", "paintball", "paragliding", "pelota", "racquet", "rc_car", "rowing", "rugby", "rugby_league",
- "rugby_union", "running", "sailing", "scuba_diving", "shooting", "shooting_range", "skateboard", "skating",
- "skiing", "soccer", "surfing", "swimming", "table_soccer", "table_tennis", "team_handball", "tennis",
- "toboggan", "volleyball", "water_ski", "yoga"),
- matchAny("tourism", "alpine_hut", "aquarium", "artwork", "attraction", "bed_and_breakfast", "camp_site",
- "caravan_site", "chalet", "gallery", "guest_house", "hostel", "hotel", "information", "motel", "museum",
- "picnic_site", "theme_park", "viewpoint", "zoo"),
- matchAny("waterway", "dock")), matchType("polygon"));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmPoiPolygon}.
- */
- public interface Handler {
- void process(OsmPoiPolygon element, FeatureCollector features);
- }
- }
- /** An OSM element that would appear in the {@code osm_aerodrome_label_point} table generated by imposm3. */
- public record OsmAerodromeLabelPoint(@Override String name, @Override String nameEn, @Override String nameDe,
- @Override String aerodromeType, @Override String aerodrome, @Override String military, @Override String iata,
- @Override String icao, @Override String ele, @Override SourceFeature source) implements Row, WithName, WithNameEn,
- WithNameDe, WithAerodromeType, WithAerodrome, WithMilitary, WithIata, WithIcao, WithEle, WithSource {
- public OsmAerodromeLabelPoint(SourceFeature source, String mappingKey) {
- this(source.getString("name"), source.getString("name:en"), source.getString("name:de"),
- source.getString("aerodrome:type"), source.getString("aerodrome"), source.getString("military"),
- source.getString("iata"), source.getString("icao"), source.getString("ele"), source);
- }
-
- /** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
- public static final Expression MAPPING = or(and(matchAny("aeroway", "aerodrome"), matchType("point")),
- and(matchAny("aeroway", "aerodrome"), matchType("polygon")));
-
- /**
- * Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
- * {@link OsmAerodromeLabelPoint}.
- */
- public interface Handler {
- void process(OsmAerodromeLabelPoint element, FeatureCollector features);
- }
- }
- /** Rows with a String access attribute. */
- public interface WithAccess {
- String access();
- }
-
- /** Rows with a long adminLevel attribute. */
- public interface WithAdminLevel {
- long adminLevel();
- }
-
- /** Rows with a String aerialway attribute. */
- public interface WithAerialway {
- String aerialway();
- }
-
- /** Rows with a String aerodrome attribute. */
- public interface WithAerodrome {
- String aerodrome();
- }
-
- /** Rows with a String aerodromeType attribute. */
- public interface WithAerodromeType {
- String aerodromeType();
- }
-
- /** Rows with a String aeroway attribute. */
- public interface WithAeroway {
- String aeroway();
- }
-
- /** Rows with a String amenity attribute. */
- public interface WithAmenity {
- String amenity();
- }
-
- /** Rows with a String bicycle attribute. */
- public interface WithBicycle {
- String bicycle();
- }
-
- /** Rows with a String boundary attribute. */
- public interface WithBoundary {
- String boundary();
- }
-
- /** Rows with a String building attribute. */
- public interface WithBuilding {
- String building();
- }
-
- /** Rows with a String buildingheight attribute. */
- public interface WithBuildingheight {
- String buildingheight();
- }
-
- /** Rows with a String buildinglevels attribute. */
- public interface WithBuildinglevels {
- String buildinglevels();
- }
-
- /** Rows with a String buildingminHeight attribute. */
- public interface WithBuildingminHeight {
- String buildingminHeight();
- }
-
- /** Rows with a String buildingminLevel attribute. */
- public interface WithBuildingminLevel {
- String buildingminLevel();
- }
-
- /** Rows with a String buildingpart attribute. */
- public interface WithBuildingpart {
- String buildingpart();
- }
-
- /** Rows with a String capital attribute. */
- public interface WithCapital {
- String capital();
- }
-
- /** Rows with a String claimedBy attribute. */
- public interface WithClaimedBy {
- String claimedBy();
- }
-
- /** Rows with a String colour attribute. */
- public interface WithColour {
- String colour();
- }
-
- /** Rows with a String construction attribute. */
- public interface WithConstruction {
- String construction();
- }
-
- /** Rows with a String countryCodeIso31661Alpha2 attribute. */
- public interface WithCountryCodeIso31661Alpha2 {
- String countryCodeIso31661Alpha2();
- }
-
- /** Rows with a String ele attribute. */
- public interface WithEle {
- String ele();
- }
-
- /** Rows with a boolean expressway attribute. */
- public interface WithExpressway {
- boolean expressway();
- }
-
- /** Rows with a String foot attribute. */
- public interface WithFoot {
- String foot();
- }
-
- /** Rows with a String funicular attribute. */
- public interface WithFunicular {
- String funicular();
- }
-
- /** Rows with a String height attribute. */
- public interface WithHeight {
- String height();
- }
-
- /** Rows with a String highway attribute. */
- public interface WithHighway {
- String highway();
- }
-
- /** Rows with a String horse attribute. */
- public interface WithHorse {
- String horse();
- }
-
- /** Rows with a String housenumber attribute. */
- public interface WithHousenumber {
- String housenumber();
- }
-
- /** Rows with a String iata attribute. */
- public interface WithIata {
- String iata();
- }
-
- /** Rows with a String icao attribute. */
- public interface WithIcao {
- String icao();
- }
-
- /** Rows with a boolean indoor attribute. */
- public interface WithIndoor {
- boolean indoor();
- }
-
- /** Rows with a String information attribute. */
- public interface WithInformation {
- String information();
- }
-
- /** Rows with a boolean isArea attribute. */
- public interface WithIsArea {
- boolean isArea();
- }
-
- /** Rows with a boolean isBridge attribute. */
- public interface WithIsBridge {
- boolean isBridge();
- }
-
- /** Rows with a boolean isFord attribute. */
- public interface WithIsFord {
- boolean isFord();
- }
-
- /** Rows with a String isInCountry attribute. */
- public interface WithIsInCountry {
- String isInCountry();
- }
-
- /** Rows with a String isInCountryCode attribute. */
- public interface WithIsInCountryCode {
- String isInCountryCode();
- }
-
- /** Rows with a boolean isIntermittent attribute. */
- public interface WithIsIntermittent {
- boolean isIntermittent();
- }
-
- /** Rows with a int isOneway attribute. */
- public interface WithIsOneway {
- int isOneway();
- }
-
- /** Rows with a boolean isRamp attribute. */
- public interface WithIsRamp {
- boolean isRamp();
- }
-
- /** Rows with a boolean isTunnel attribute. */
- public interface WithIsTunnel {
- boolean isTunnel();
- }
-
- /** Rows with a String iso31661 attribute. */
- public interface WithIso31661 {
- String iso31661();
- }
-
- /** Rows with a String iso31661Alpha2 attribute. */
- public interface WithIso31661Alpha2 {
- String iso31661Alpha2();
- }
-
- /** Rows with a String landuse attribute. */
- public interface WithLanduse {
- String landuse();
- }
-
- /** Rows with a long layer attribute. */
- public interface WithLayer {
- long layer();
- }
-
- /** Rows with a String leisure attribute. */
- public interface WithLeisure {
- String leisure();
- }
-
- /** Rows with a long level attribute. */
- public interface WithLevel {
- long level();
- }
-
- /** Rows with a String levels attribute. */
- public interface WithLevels {
- String levels();
- }
-
- /** Rows with a String manMade attribute. */
- public interface WithManMade {
- String manMade();
- }
-
- /** Rows with a String mappingKey attribute. */
- public interface WithMappingKey {
- String mappingKey();
- }
-
- /** Rows with a String material attribute. */
- public interface WithMaterial {
- String material();
- }
-
- /** Rows with a String military attribute. */
- public interface WithMilitary {
- String military();
- }
-
- /** Rows with a String minHeight attribute. */
- public interface WithMinHeight {
- String minHeight();
- }
-
- /** Rows with a String minLevel attribute. */
- public interface WithMinLevel {
- String minLevel();
- }
-
- /** Rows with a String mtbScale attribute. */
- public interface WithMtbScale {
- String mtbScale();
- }
-
- /** Rows with a String name attribute. */
- public interface WithName {
- String name();
- }
-
- /** Rows with a String nameDe attribute. */
- public interface WithNameDe {
- String nameDe();
- }
-
- /** Rows with a String nameEn attribute. */
- public interface WithNameEn {
- String nameEn();
- }
-
- /** Rows with a String natural attribute. */
- public interface WithNatural {
- String natural();
- }
-
- /** Rows with a String network attribute. */
- public interface WithNetwork {
- String network();
- }
-
- /** Rows with a String operator attribute. */
- public interface WithOperator {
- String operator();
- }
-
- /** Rows with a String osmcSymbol attribute. */
- public interface WithOsmcSymbol {
- String osmcSymbol();
- }
-
- /** Rows with a String place attribute. */
- public interface WithPlace {
- String place();
- }
-
- /** Rows with a long population attribute. */
- public interface WithPopulation {
- long population();
- }
-
- /** Rows with a String protectionTitle attribute. */
- public interface WithProtectionTitle {
- String protectionTitle();
- }
-
- /** Rows with a String publicTransport attribute. */
- public interface WithPublicTransport {
- String publicTransport();
- }
-
- /** Rows with a String railway attribute. */
- public interface WithRailway {
- String railway();
- }
-
- /** Rows with a long rank attribute. */
- public interface WithRank {
- long rank();
- }
-
- /** Rows with a String ref attribute. */
- public interface WithRef {
- String ref();
- }
-
- /** Rows with a String relbuildingheight attribute. */
- public interface WithRelbuildingheight {
- String relbuildingheight();
- }
-
- /** Rows with a String relbuildinglevels attribute. */
- public interface WithRelbuildinglevels {
- String relbuildinglevels();
- }
-
- /** Rows with a String relbuildingminHeight attribute. */
- public interface WithRelbuildingminHeight {
- String relbuildingminHeight();
- }
-
- /** Rows with a String relbuildingminLevel attribute. */
- public interface WithRelbuildingminLevel {
- String relbuildingminLevel();
- }
-
- /** Rows with a String relheight attribute. */
- public interface WithRelheight {
- String relheight();
- }
-
- /** Rows with a String religion attribute. */
- public interface WithReligion {
- String religion();
- }
-
- /** Rows with a String rellevels attribute. */
- public interface WithRellevels {
- String rellevels();
- }
-
- /** Rows with a String relminHeight attribute. */
- public interface WithRelminHeight {
- String relminHeight();
- }
-
- /** Rows with a String relminLevel attribute. */
- public interface WithRelminLevel {
- String relminLevel();
- }
-
- /** Rows with a String sacScale attribute. */
- public interface WithSacScale {
- String sacScale();
- }
-
- /** Rows with a String service attribute. */
- public interface WithService {
- String service();
- }
-
- /** Rows with a String shipway attribute. */
- public interface WithShipway {
- String shipway();
- }
-
- /** Rows with a String shortName attribute. */
- public interface WithShortName {
- String shortName();
- }
-
- /** Rows with a SourceFeature source attribute. */
- public interface WithSource {
- SourceFeature source();
- }
-
- /** Rows with a String sport attribute. */
- public interface WithSport {
- String sport();
- }
-
- /** Rows with a String station attribute. */
- public interface WithStation {
- String station();
- }
-
- /** Rows with a String subclass attribute. */
- public interface WithSubclass {
- String subclass();
- }
-
- /** Rows with a String surface attribute. */
- public interface WithSurface {
- String surface();
- }
-
- /** Rows with a boolean toll attribute. */
- public interface WithToll {
- boolean toll();
- }
-
- /** Rows with a String tourism attribute. */
- public interface WithTourism {
- String tourism();
- }
-
- /** Rows with a String uicRef attribute. */
- public interface WithUicRef {
- String uicRef();
- }
-
- /** Rows with a String usage attribute. */
- public interface WithUsage {
- String usage();
- }
-
- /** Rows with a String water attribute. */
- public interface WithWater {
- String water();
- }
-
- /** Rows with a String waterway attribute. */
- public interface WithWaterway {
- String waterway();
- }
-
- /** Rows with a String wikipedia attribute. */
- public interface WithWikipedia {
- String wikipedia();
- }
-
- /** Rows with a int zOrder attribute. */
- public interface WithZOrder {
- int zOrder();
- }
-
- /** Index to efficiently choose which imposm3 "tables" an element should appear in based on its attributes. */
- public static final MultiExpression MAPPINGS = MultiExpression.of(List.of(
- MultiExpression.entry(new RowClassAndConstructor(OsmWaterPolygon.class, OsmWaterPolygon::new),
- OsmWaterPolygon.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmWaterwayLinestring.class, OsmWaterwayLinestring::new),
- OsmWaterwayLinestring.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmLandcoverPolygon.class, OsmLandcoverPolygon::new),
- OsmLandcoverPolygon.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmLandusePolygon.class, OsmLandusePolygon::new),
- OsmLandusePolygon.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmPeakPoint.class, OsmPeakPoint::new), OsmPeakPoint.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmMountainLinestring.class, OsmMountainLinestring::new),
- OsmMountainLinestring.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmParkPolygon.class, OsmParkPolygon::new),
- OsmParkPolygon.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmAerowayPolygon.class, OsmAerowayPolygon::new),
- OsmAerowayPolygon.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmAerowayLinestring.class, OsmAerowayLinestring::new),
- OsmAerowayLinestring.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmAerowayPoint.class, OsmAerowayPoint::new),
- OsmAerowayPoint.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmHighwayLinestring.class, OsmHighwayLinestring::new),
- OsmHighwayLinestring.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmRailwayLinestring.class, OsmRailwayLinestring::new),
- OsmRailwayLinestring.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmAerialwayLinestring.class, OsmAerialwayLinestring::new),
- OsmAerialwayLinestring.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmShipwayLinestring.class, OsmShipwayLinestring::new),
- OsmShipwayLinestring.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmHighwayPolygon.class, OsmHighwayPolygon::new),
- OsmHighwayPolygon.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmHighwayPoint.class, OsmHighwayPoint::new),
- OsmHighwayPoint.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmBuildingPolygon.class, OsmBuildingPolygon::new),
- OsmBuildingPolygon.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmMarinePoint.class, OsmMarinePoint::new),
- OsmMarinePoint.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmContinentPoint.class, OsmContinentPoint::new),
- OsmContinentPoint.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmCountryPoint.class, OsmCountryPoint::new),
- OsmCountryPoint.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmIslandPolygon.class, OsmIslandPolygon::new),
- OsmIslandPolygon.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmIslandPoint.class, OsmIslandPoint::new),
- OsmIslandPoint.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmStatePoint.class, OsmStatePoint::new), OsmStatePoint.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmCityPoint.class, OsmCityPoint::new), OsmCityPoint.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmHousenumberPoint.class, OsmHousenumberPoint::new),
- OsmHousenumberPoint.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmPoiPoint.class, OsmPoiPoint::new), OsmPoiPoint.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmPoiPolygon.class, OsmPoiPolygon::new), OsmPoiPolygon.MAPPING),
- MultiExpression.entry(new RowClassAndConstructor(OsmAerodromeLabelPoint.class, OsmAerodromeLabelPoint::new),
- OsmAerodromeLabelPoint.MAPPING)
- ));
-
- /**
- * Returns a map from imposm3 "table row" class to the layers that have a handler for it from a list of layer
- * implementations.
- */
- public static Map, List>> generateDispatchMap(List> handlers) {
- Map, List>> result = new HashMap<>();
- for (var handler : handlers) {
- if (handler instanceof OsmWaterPolygon.Handler typedHandler) {
- result.computeIfAbsent(OsmWaterPolygon.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmWaterwayLinestring.Handler typedHandler) {
- result.computeIfAbsent(OsmWaterwayLinestring.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmLandcoverPolygon.Handler typedHandler) {
- result.computeIfAbsent(OsmLandcoverPolygon.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmLandusePolygon.Handler typedHandler) {
- result.computeIfAbsent(OsmLandusePolygon.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmPeakPoint.Handler typedHandler) {
- result.computeIfAbsent(OsmPeakPoint.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmMountainLinestring.Handler typedHandler) {
- result.computeIfAbsent(OsmMountainLinestring.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmParkPolygon.Handler typedHandler) {
- result.computeIfAbsent(OsmParkPolygon.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmAerowayPolygon.Handler typedHandler) {
- result.computeIfAbsent(OsmAerowayPolygon.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmAerowayLinestring.Handler typedHandler) {
- result.computeIfAbsent(OsmAerowayLinestring.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmAerowayPoint.Handler typedHandler) {
- result.computeIfAbsent(OsmAerowayPoint.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmHighwayLinestring.Handler typedHandler) {
- result.computeIfAbsent(OsmHighwayLinestring.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmRailwayLinestring.Handler typedHandler) {
- result.computeIfAbsent(OsmRailwayLinestring.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmAerialwayLinestring.Handler typedHandler) {
- result.computeIfAbsent(OsmAerialwayLinestring.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmShipwayLinestring.Handler typedHandler) {
- result.computeIfAbsent(OsmShipwayLinestring.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmHighwayPolygon.Handler typedHandler) {
- result.computeIfAbsent(OsmHighwayPolygon.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmHighwayPoint.Handler typedHandler) {
- result.computeIfAbsent(OsmHighwayPoint.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmBuildingPolygon.Handler typedHandler) {
- result.computeIfAbsent(OsmBuildingPolygon.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmMarinePoint.Handler typedHandler) {
- result.computeIfAbsent(OsmMarinePoint.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmContinentPoint.Handler typedHandler) {
- result.computeIfAbsent(OsmContinentPoint.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmCountryPoint.Handler typedHandler) {
- result.computeIfAbsent(OsmCountryPoint.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmIslandPolygon.Handler typedHandler) {
- result.computeIfAbsent(OsmIslandPolygon.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmIslandPoint.Handler typedHandler) {
- result.computeIfAbsent(OsmIslandPoint.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmStatePoint.Handler typedHandler) {
- result.computeIfAbsent(OsmStatePoint.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmCityPoint.Handler typedHandler) {
- result.computeIfAbsent(OsmCityPoint.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmHousenumberPoint.Handler typedHandler) {
- result.computeIfAbsent(OsmHousenumberPoint.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmPoiPoint.Handler typedHandler) {
- result.computeIfAbsent(OsmPoiPoint.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmPoiPolygon.Handler typedHandler) {
- result.computeIfAbsent(OsmPoiPolygon.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- if (handler instanceof OsmAerodromeLabelPoint.Handler typedHandler) {
- result.computeIfAbsent(OsmAerodromeLabelPoint.class, cls -> new ArrayList<>())
- .add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
- }
- }
- return result;
- }
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/AerodromeLabel.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/AerodromeLabel.java
deleted file mode 100644
index 09038b4a4a..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/AerodromeLabel.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
- */
-package com.onthegomap.planetiler.basemap.layers;
-
-import static com.onthegomap.planetiler.basemap.util.Utils.nullIfEmpty;
-import static com.onthegomap.planetiler.basemap.util.Utils.nullOrEmpty;
-
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema;
-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.expression.MultiExpression;
-import com.onthegomap.planetiler.stats.Stats;
-import com.onthegomap.planetiler.util.Translations;
-
-/**
- * Defines the logic for generating map elements in the {@code aerodrome_label} layer from source features.
- *
- * This class is ported to Java from
- * OpenMapTiles
- * aerodrome_layer sql files.
- */
-public class AerodromeLabel implements
- OpenMapTilesSchema.AerodromeLabel,
- Tables.OsmAerodromeLabelPoint.Handler {
-
- private final MultiExpression.Index classLookup;
- private final Translations translations;
-
- public AerodromeLabel(Translations translations, PlanetilerConfig config, Stats stats) {
- this.classLookup = FieldMappings.Class.index();
- this.translations = translations;
- }
-
- @Override
- public void process(Tables.OsmAerodromeLabelPoint element, FeatureCollector features) {
- String clazz = classLookup.getOrElse(element.source(), FieldValues.CLASS_OTHER);
- boolean important = !nullOrEmpty(element.iata()) && FieldValues.CLASS_INTERNATIONAL.equals(clazz);
- features.centroid(LAYER_NAME)
- .setBufferPixels(BUFFER_SIZE)
- .setMinZoom(important ? 8 : 10)
- .putAttrs(LanguageUtils.getNames(element.source().tags(), translations))
- .putAttrs(Utils.elevationTags(element.ele()))
- .setAttr(Fields.IATA, nullIfEmpty(element.iata()))
- .setAttr(Fields.ICAO, nullIfEmpty(element.icao()))
- .setAttr(Fields.CLASS, clazz);
- }
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Aeroway.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Aeroway.java
deleted file mode 100644
index 230a965ca8..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Aeroway.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-package com.onthegomap.planetiler.basemap.layers;
-
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema;
-import com.onthegomap.planetiler.basemap.generated.Tables;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.stats.Stats;
-import com.onthegomap.planetiler.util.Translations;
-
-/**
- * Defines the logic for generating map elements in the {@code aeroway} layer from source features.
- *
- * This class is ported to Java from
- * OpenMapTiles aeroway sql files.
- */
-public class Aeroway implements
- OpenMapTilesSchema.Aeroway,
- Tables.OsmAerowayLinestring.Handler,
- Tables.OsmAerowayPolygon.Handler,
- Tables.OsmAerowayPoint.Handler {
-
- public Aeroway(Translations translations, PlanetilerConfig config, Stats stats) {}
-
- @Override
- public void process(Tables.OsmAerowayPolygon element, FeatureCollector features) {
- features.polygon(LAYER_NAME)
- .setMinZoom(10)
- .setMinPixelSize(2)
- .setAttr(Fields.CLASS, element.aeroway())
- .setAttr(Fields.REF, element.ref());
- }
-
- @Override
- public void process(Tables.OsmAerowayLinestring element, FeatureCollector features) {
- features.line(LAYER_NAME)
- .setMinZoom(10)
- .setAttr(Fields.CLASS, element.aeroway())
- .setAttr(Fields.REF, element.ref());
- }
-
- @Override
- public void process(Tables.OsmAerowayPoint element, FeatureCollector features) {
- features.point(LAYER_NAME)
- .setMinZoom(14)
- .setAttr(Fields.CLASS, element.aeroway())
- .setAttr(Fields.REF, element.ref());
- }
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Boundary.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Boundary.java
deleted file mode 100644
index 310c019b68..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Boundary.java
+++ /dev/null
@@ -1,469 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-package com.onthegomap.planetiler.basemap.layers;
-
-import static com.onthegomap.planetiler.util.MemoryEstimator.CLASS_HEADER_BYTES;
-import static com.onthegomap.planetiler.util.MemoryEstimator.POINTER_BYTES;
-import static com.onthegomap.planetiler.util.MemoryEstimator.estimateSize;
-import static java.util.stream.Collectors.counting;
-import static java.util.stream.Collectors.groupingBy;
-
-import com.carrotsearch.hppc.LongObjectMap;
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.FeatureMerge;
-import com.onthegomap.planetiler.VectorTile;
-import com.onthegomap.planetiler.basemap.BasemapProfile;
-import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema;
-import com.onthegomap.planetiler.collection.Hppc;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.geo.GeoUtils;
-import com.onthegomap.planetiler.geo.GeometryException;
-import com.onthegomap.planetiler.reader.SimpleFeature;
-import com.onthegomap.planetiler.reader.SourceFeature;
-import com.onthegomap.planetiler.reader.osm.OsmElement;
-import com.onthegomap.planetiler.reader.osm.OsmRelationInfo;
-import com.onthegomap.planetiler.stats.Stats;
-import com.onthegomap.planetiler.util.Format;
-import com.onthegomap.planetiler.util.MemoryEstimator;
-import com.onthegomap.planetiler.util.Parse;
-import com.onthegomap.planetiler.util.Translations;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-import org.locationtech.jts.geom.Coordinate;
-import org.locationtech.jts.geom.Geometry;
-import org.locationtech.jts.geom.LineString;
-import org.locationtech.jts.geom.Point;
-import org.locationtech.jts.geom.TopologyException;
-import org.locationtech.jts.geom.prep.PreparedGeometry;
-import org.locationtech.jts.geom.prep.PreparedGeometryFactory;
-import org.locationtech.jts.operation.linemerge.LineMerger;
-import org.locationtech.jts.operation.polygonize.Polygonizer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Defines the logic for generating map elements for country, state, and town boundaries in the {@code boundary} layer
- * from source features.
- *
- * This class is ported to Java from
- * OpenMapTiles boundary sql
- * files.
- */
-public class Boundary implements
- OpenMapTilesSchema.Boundary,
- BasemapProfile.NaturalEarthProcessor,
- BasemapProfile.OsmRelationPreprocessor,
- BasemapProfile.OsmAllProcessor,
- BasemapProfile.FeaturePostProcessor,
- BasemapProfile.FinishHandler {
-
- /*
- * Uses natural earth at lower zoom levels and OpenStreetMap at higher zoom levels.
- *
- * For OpenStreetMap data at higher zoom levels:
- * 1) Preprocess relations on the first pass to extract info for relations where
- * type=boundary and boundary=administrative and store the admin_level for
- * later.
- * 2) When processing individual ways, take the minimum (most important) admin
- * level of every relation they are a part of and use that as the admin level
- * for the way.
- * 3) If boundary_country_names argument is true and the way is part of a country
- * (admin_level=2) boundary, then hold onto it for later
- * 4) When we finish processing the OSM source, build country polygons from the
- * saved ways and use that to determine which country is on the left and right
- * side of each way, then emit the way with ADM0_L and ADM0_R keys set.
- * 5) Before emitting boundary lines, merge linestrings with the same tags.
- */
-
- private static final Logger LOGGER = LoggerFactory.getLogger(Boundary.class);
- private static final double COUNTRY_TEST_OFFSET = GeoUtils.metersToPixelAtEquator(0, 10) / 256d;
- private final Stats stats;
- private final boolean addCountryNames;
- // may be updated concurrently by multiple threads
- private final Map regionNames = new ConcurrentHashMap<>();
- // need to synchronize updates to these shared data structures:
- private final Map> regionGeometries = new HashMap<>();
- private final Map> boundariesToMerge = new HashMap<>();
- private final PlanetilerConfig config;
-
- public Boundary(Translations translations, PlanetilerConfig config, Stats stats) {
- this.config = config;
- this.addCountryNames = config.arguments().getBoolean(
- "boundary_country_names",
- "boundary layer: add left/right codes of neighboring countries",
- true
- );
- this.stats = stats;
- }
-
- private static boolean isDisputed(Map tags) {
- return Parse.bool(tags.get("disputed")) ||
- Parse.bool(tags.get("dispute")) ||
- "dispute".equals(tags.get("border_status")) ||
- tags.containsKey("disputed_by") ||
- tags.containsKey("claimed_by");
- }
-
- private static String editName(String name) {
- return name == null ? null : name.replace(" at ", "")
- .replaceAll("\\s+", "")
- .replace("Extentof", "");
- }
-
- @Override
- public void release() {
- regionGeometries.clear();
- boundariesToMerge.clear();
- regionNames.clear();
- }
-
- @Override
- public void processNaturalEarth(String table, SourceFeature feature, FeatureCollector features) {
- boolean disputed = feature.getString("featurecla", "").startsWith("Disputed");
- record BoundaryInfo(int adminLevel, int minzoom, int maxzoom) {}
- BoundaryInfo info = switch (table) {
- case "ne_110m_admin_0_boundary_lines_land" -> new BoundaryInfo(2, 0, 0);
- case "ne_50m_admin_0_boundary_lines_land" -> new BoundaryInfo(2, 1, 3);
- case "ne_10m_admin_0_boundary_lines_land" -> feature.hasTag("featurecla", "Lease Limit") ? null :
- new BoundaryInfo(2, 4, 4);
- case "ne_10m_admin_1_states_provinces_lines" -> {
- Double minZoom = Parse.parseDoubleOrNull(feature.getTag("min_zoom"));
- yield minZoom != null && minZoom <= 7 ? new BoundaryInfo(4, 1, 4) :
- minZoom != null && minZoom <= 7.7 ? new BoundaryInfo(4, 4, 4) :
- null;
- }
- default -> null;
- };
- if (info != null) {
- features.line(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .setZoomRange(info.minzoom, info.maxzoom)
- .setMinPixelSizeAtAllZooms(0)
- .setAttr(Fields.ADMIN_LEVEL, info.adminLevel)
- .setAttr(Fields.MARITIME, 0)
- .setAttr(Fields.DISPUTED, disputed ? 1 : 0);
- }
- }
-
- @Override
- public List preprocessOsmRelation(OsmElement.Relation relation) {
- if (relation.hasTag("type", "boundary") &&
- relation.hasTag("admin_level") &&
- relation.hasTag("boundary", "administrative")) {
- Integer adminLevelValue = Parse.parseRoundInt(relation.getTag("admin_level"));
- String code = relation.getString("ISO3166-1:alpha3");
- if (adminLevelValue != null && adminLevelValue >= 2 && adminLevelValue <= 10) {
- boolean disputed = isDisputed(relation.tags());
- if (code != null) {
- regionNames.put(relation.id(), code);
- }
- return List.of(new BoundaryRelation(
- relation.id(),
- adminLevelValue,
- disputed,
- relation.getString("name"),
- disputed ? relation.getString("claimed_by") : null,
- code
- ));
- }
- }
- return null;
- }
-
- @Override
- public void processAllOsm(SourceFeature feature, FeatureCollector features) {
- if (!feature.canBeLine()) {
- return;
- }
- var relationInfos = feature.relationInfo(BoundaryRelation.class);
- if (!relationInfos.isEmpty()) {
- int minAdminLevel = Integer.MAX_VALUE;
- String disputedName = null, claimedBy = null;
- Set regionIds = new HashSet<>();
- boolean disputed = false;
- // aggregate all borders this way is a part of - take the lowest
- // admin level, and assume it is disputed if any relation is disputed.
- for (var info : relationInfos) {
- BoundaryRelation rel = info.relation();
- disputed |= rel.disputed;
- if (rel.adminLevel < minAdminLevel) {
- minAdminLevel = rel.adminLevel;
- }
- if (rel.disputed) {
- disputedName = disputedName == null ? rel.name : disputedName;
- claimedBy = claimedBy == null ? rel.claimedBy : claimedBy;
- }
- if (minAdminLevel == 2 && regionNames.containsKey(info.relation().id)) {
- regionIds.add(info.relation().id);
- }
- }
-
- if (minAdminLevel <= 10) {
- boolean wayIsDisputed = isDisputed(feature.tags());
- disputed |= wayIsDisputed;
- if (wayIsDisputed) {
- disputedName = disputedName == null ? feature.getString("name") : disputedName;
- claimedBy = claimedBy == null ? feature.getString("claimed_by") : claimedBy;
- }
- boolean maritime = feature.getBoolean("maritime") ||
- feature.hasTag("natural", "coastline") ||
- feature.hasTag("boundary_type", "maritime");
- int minzoom =
- (maritime && minAdminLevel == 2) ? 4 :
- minAdminLevel <= 4 ? 5 :
- minAdminLevel <= 6 ? 9 :
- minAdminLevel <= 8 ? 11 : 12;
- if (addCountryNames && !regionIds.isEmpty()) {
- // save for later
- try {
- CountryBoundaryComponent component = new CountryBoundaryComponent(
- minAdminLevel,
- disputed,
- maritime,
- minzoom,
- feature.line(),
- regionIds,
- claimedBy,
- disputedName
- );
- // multiple threads may update this concurrently
- synchronized (this) {
- boundariesToMerge.computeIfAbsent(component.groupingKey(), key -> new ArrayList<>()).add(component.line);
- for (var info : relationInfos) {
- var rel = info.relation();
- if (rel.adminLevel <= 2) {
- regionGeometries.computeIfAbsent(rel.id, id -> new ArrayList<>()).add(component.line);
- }
- }
- }
- } catch (GeometryException e) {
- LOGGER.warn("Cannot extract boundary line from " + feature);
- }
- } else {
- features.line(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .setAttr(Fields.ADMIN_LEVEL, minAdminLevel)
- .setAttr(Fields.DISPUTED, disputed ? 1 : 0)
- .setAttr(Fields.MARITIME, maritime ? 1 : 0)
- .setMinPixelSizeAtAllZooms(0)
- .setMinZoom(minzoom)
- .setAttr(Fields.CLAIMED_BY, claimedBy)
- .setAttr(Fields.DISPUTED_NAME, editName(disputedName));
- }
- }
- }
- }
-
- @Override
- public void finish(String sourceName, FeatureCollector.Factory featureCollectors,
- Consumer emit) {
- if (BasemapProfile.OSM_SOURCE.equals(sourceName)) {
- var timer = stats.startStage("boundaries");
- LongObjectMap countryBoundaries = prepareRegionPolygons();
-
- for (var entry : boundariesToMerge.entrySet()) {
- CountryBoundaryComponent key = entry.getKey();
- LineMerger merger = new LineMerger();
- for (Geometry geom : entry.getValue()) {
- merger.add(geom);
- }
- entry.getValue().clear();
- for (Object merged : merger.getMergedLineStrings()) {
- if (merged instanceof LineString lineString) {
- BorderingRegions borderingRegions = getBorderingRegions(countryBoundaries, key.regions, lineString);
-
- var features = featureCollectors.get(SimpleFeature.fromWorldGeometry(lineString));
- features.line(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .setAttr(Fields.ADMIN_LEVEL, key.adminLevel)
- .setAttr(Fields.DISPUTED, key.disputed ? 1 : 0)
- .setAttr(Fields.MARITIME, key.maritime ? 1 : 0)
- .setAttr(Fields.CLAIMED_BY, key.claimedBy)
- .setAttr(Fields.DISPUTED_NAME, key.disputed ? editName(key.name) : null)
- .setAttr(Fields.ADM0_L, borderingRegions.left == null ? null : regionNames.get(borderingRegions.left))
- .setAttr(Fields.ADM0_R, borderingRegions.right == null ? null : regionNames.get(borderingRegions.right))
- .setMinPixelSizeAtAllZooms(0)
- .setMinZoom(key.minzoom);
- for (var feature : features) {
- emit.accept(feature);
- }
- }
- }
- }
- timer.stop();
- }
- }
-
- @Override
- public List postProcess(int zoom, List items) {
- double minLength = config.minFeatureSize(zoom);
- double tolerance = config.tolerance(zoom);
- return FeatureMerge.mergeLineStrings(items, attrs -> minLength, tolerance, BUFFER_SIZE);
- }
-
- /** Returns the left and right country for {@code lineString}. */
- private BorderingRegions getBorderingRegions(
- LongObjectMap countryBoundaries,
- Set allRegions,
- LineString lineString
- ) {
- Set validRegions = allRegions.stream()
- .filter(countryBoundaries::containsKey)
- .collect(Collectors.toSet());
- if (validRegions.isEmpty()) {
- return BorderingRegions.empty();
- }
- List rights = new ArrayList<>();
- List lefts = new ArrayList<>();
- int steps = 10;
- for (int i = 0; i < steps; i++) {
- double ratio = (double) (i + 1) / (steps + 2);
- Point right = GeoUtils.pointAlongOffset(lineString, ratio, COUNTRY_TEST_OFFSET);
- Point left = GeoUtils.pointAlongOffset(lineString, ratio, -COUNTRY_TEST_OFFSET);
- for (Long regionId : validRegions) {
- PreparedGeometry geom = countryBoundaries.get(regionId);
- if (geom != null) {
- if (geom.contains(right)) {
- rights.add(regionId);
- } else if (geom.contains(left)) {
- lefts.add(regionId);
- }
- }
- }
- }
-
- var right = mode(rights);
- if (right != null) {
- lefts.removeAll(List.of(right));
- }
- var left = mode(lefts);
-
- if (left == null && right == null) {
- Coordinate point = GeoUtils.worldToLatLonCoords(GeoUtils.pointAlongOffset(lineString, 0.5, 0)).getCoordinate();
- LOGGER.warn("no left or right country for border between OSM country relations: %s around %s"
- .formatted(
- validRegions,
- Format.osmDebugUrl(10, point)
- ));
- }
-
- return new BorderingRegions(left, right);
- }
-
- /** Returns a map from region ID to prepared geometry optimized for {@code contains} queries. */
- private LongObjectMap prepareRegionPolygons() {
- LOGGER.info("Creating polygons for " + regionGeometries.size() + " boundaries");
- LongObjectMap countryBoundaries = Hppc.newLongObjectHashMap();
- for (var entry : regionGeometries.entrySet()) {
- Long regionId = entry.getKey();
- Polygonizer polygonizer = new Polygonizer();
- polygonizer.add(entry.getValue());
- try {
- Geometry combined = polygonizer.getGeometry().union();
- if (combined.isEmpty()) {
- LOGGER.warn("Unable to form closed polygon for OSM relation " + regionId + " (likely missing edges)");
- } else {
- countryBoundaries.put(regionId, PreparedGeometryFactory.prepare(combined));
- }
- } catch (TopologyException e) {
- LOGGER
- .warn("Unable to build boundary polygon for OSM relation " + regionId + ": " + e.getMessage());
- }
- }
- LOGGER.info("Finished creating " + countryBoundaries.size() + " country polygons");
- return countryBoundaries;
- }
-
- /** Returns most frequently-occurring element in {@code list}. */
- private static Long mode(List list) {
- return list.stream()
- .collect(groupingBy(Function.identity(), counting())).entrySet().stream()
- .max(Map.Entry.comparingByValue())
- .map(Map.Entry::getKey)
- .orElse(null);
- }
-
- private record BorderingRegions(Long left, Long right) {
-
- public static BorderingRegions empty() {
- return new BorderingRegions(null, null);
- }
- }
-
- /**
- * Minimal set of information extracted from a boundary relation to be used when processing each way in that relation.
- */
- private record BoundaryRelation(
- long id,
- int adminLevel,
- boolean disputed,
- String name,
- String claimedBy,
- String iso3166alpha3
- ) implements OsmRelationInfo {
-
- @Override
- public long estimateMemoryUsageBytes() {
- return CLASS_HEADER_BYTES + MemoryEstimator.estimateSizeLong(id) + MemoryEstimator.estimateSizeInt(adminLevel) +
- estimateSize(disputed) + POINTER_BYTES + estimateSize(name) + POINTER_BYTES + estimateSize(claimedBy) +
- POINTER_BYTES + estimateSize(iso3166alpha3);
- }
- }
-
- /**
- * Information to hold onto from processing a way in a boundary relation to determine the left/right region ID later.
- */
- private record CountryBoundaryComponent(
- int adminLevel,
- boolean disputed,
- boolean maritime,
- int minzoom,
- Geometry line,
- Set regions,
- String claimedBy,
- String name
- ) {
-
- CountryBoundaryComponent groupingKey() {
- return new CountryBoundaryComponent(adminLevel, disputed, maritime, minzoom, null, regions, claimedBy, name);
- }
- }
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Building.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Building.java
deleted file mode 100644
index ccab4f2616..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Building.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-package com.onthegomap.planetiler.basemap.layers;
-
-import static com.onthegomap.planetiler.basemap.util.Utils.coalesce;
-import static com.onthegomap.planetiler.util.MemoryEstimator.CLASS_HEADER_BYTES;
-import static com.onthegomap.planetiler.util.Parse.parseDoubleOrNull;
-import static java.util.Map.entry;
-
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.FeatureMerge;
-import com.onthegomap.planetiler.VectorTile;
-import com.onthegomap.planetiler.basemap.BasemapProfile;
-import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema;
-import com.onthegomap.planetiler.basemap.generated.Tables;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.geo.GeometryException;
-import com.onthegomap.planetiler.reader.osm.OsmElement;
-import com.onthegomap.planetiler.reader.osm.OsmRelationInfo;
-import com.onthegomap.planetiler.stats.Stats;
-import com.onthegomap.planetiler.util.MemoryEstimator;
-import com.onthegomap.planetiler.util.Translations;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-/**
- * Defines the logic for generating map elements for buildings in the {@code building} layer from source features.
- *
- * This class is ported to Java from
- * OpenMapTiles building sql
- * files.
- */
-public class Building implements
- OpenMapTilesSchema.Building,
- Tables.OsmBuildingPolygon.Handler,
- BasemapProfile.FeaturePostProcessor,
- BasemapProfile.OsmRelationPreprocessor {
-
- /*
- * Emit all buildings from OSM data at z14.
- *
- * At z13, emit all buildings at process-time, but then at tile render-time,
- * merge buildings that are overlapping or almost touching into combined
- * buildings so that entire city blocks show up as a single building polygon.
- *
- * THIS IS VERY EXPENSIVE! Merging buildings at z13 adds about 50% to the
- * total map generation time. To disable it, set building_merge_z13 argument
- * to false.
- */
-
- private static final Map MATERIAL_COLORS = Map.ofEntries(
- entry("cement_block", "#6a7880"),
- entry("brick", "#bd8161"),
- entry("plaster", "#dadbdb"),
- entry("wood", "#d48741"),
- entry("concrete", "#d3c2b0"),
- entry("metal", "#b7b1a6"),
- entry("stone", "#b4a995"),
- entry("mud", "#9d8b75"),
- entry("steel", "#b7b1a6"), // same as metal
- entry("glass", "#5a81a0"),
- entry("traditional", "#bd8161"), // same as brick
- entry("masonry", "#bd8161"), // same as brick
- entry("Brick", "#bd8161"), // same as brick
- entry("tin", "#b7b1a6"), // same as metal
- entry("timber_framing", "#b3b0a9"),
- entry("sandstone", "#b4a995"), // same as stone
- entry("clay", "#9d8b75") // same as mud
- );
- private final boolean mergeZ13Buildings;
-
- public Building(Translations translations, PlanetilerConfig config, Stats stats) {
- this.mergeZ13Buildings = config.arguments().getBoolean(
- "building_merge_z13",
- "building layer: merge nearby buildings at z13",
- true
- );
- }
-
- @Override
- public List preprocessOsmRelation(OsmElement.Relation relation) {
- if (relation.hasTag("type", "building")) {
- return List.of(new BuildingRelationInfo(relation.id()));
- }
- return null;
- }
-
- @Override
- public void process(Tables.OsmBuildingPolygon element, FeatureCollector features) {
- Boolean hide3d = null;
- var relations = element.source().relationInfo(BuildingRelationInfo.class);
- for (var relation : relations) {
- if ("outline".equals(relation.role())) {
- hide3d = true;
- break;
- }
- }
-
- String color = element.colour();
- if (color == null && element.material() != null) {
- color = MATERIAL_COLORS.get(element.material());
- }
- if (color != null) {
- color = color.toLowerCase(Locale.ROOT);
- }
-
- Double height = coalesce(
- parseDoubleOrNull(element.height()),
- parseDoubleOrNull(element.buildingheight())
- );
- Double minHeight = coalesce(
- parseDoubleOrNull(element.minHeight()),
- parseDoubleOrNull(element.buildingminHeight())
- );
- Double levels = coalesce(
- parseDoubleOrNull(element.levels()),
- parseDoubleOrNull(element.buildinglevels())
- );
- Double minLevels = coalesce(
- parseDoubleOrNull(element.minLevel()),
- parseDoubleOrNull(element.buildingminLevel())
- );
-
- int renderHeight = (int) Math.ceil(height != null ? height : levels != null ? (levels * 3.66) : 5);
- int renderMinHeight = (int) Math.floor(minHeight != null ? minHeight : minLevels != null ? (minLevels * 3.66) : 0);
-
- if (renderHeight < 3660 && renderMinHeight < 3660) {
- var feature = features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .setMinZoom(13)
- .setMinPixelSize(2)
- .setAttrWithMinzoom(Fields.RENDER_HEIGHT, renderHeight, 14)
- .setAttrWithMinzoom(Fields.RENDER_MIN_HEIGHT, renderMinHeight, 14)
- .setAttrWithMinzoom(Fields.COLOUR, color, 14)
- .setAttrWithMinzoom(Fields.HIDE_3D, hide3d, 14)
- .setSortKey(renderHeight);
- if (mergeZ13Buildings) {
- feature
- .setMinPixelSize(0.1)
- .setPixelTolerance(0.25);
- }
- }
- }
-
- @Override
- public List postProcess(int zoom,
- List items) throws GeometryException {
- return (mergeZ13Buildings && zoom == 13) ? FeatureMerge.mergeNearbyPolygons(items, 4, 4, 0.5, 0.5) : items;
- }
-
- private record BuildingRelationInfo(long id) implements OsmRelationInfo {
-
- @Override
- public long estimateMemoryUsageBytes() {
- return CLASS_HEADER_BYTES + MemoryEstimator.estimateSizeLong(id);
- }
- }
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Housenumber.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Housenumber.java
deleted file mode 100644
index 1526459cca..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Housenumber.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-package com.onthegomap.planetiler.basemap.layers;
-
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema;
-import com.onthegomap.planetiler.basemap.generated.Tables;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.stats.Stats;
-import com.onthegomap.planetiler.util.Translations;
-
-/**
- * Defines the logic for generating map elements in the {@code housenumber} layer from source features.
- *
- * This class is ported to Java from
- * OpenMapTiles housenumber sql
- * files.
- */
-public class Housenumber implements
- OpenMapTilesSchema.Housenumber,
- Tables.OsmHousenumberPoint.Handler {
-
- public Housenumber(Translations translations, PlanetilerConfig config, Stats stats) {}
-
- @Override
- public void process(Tables.OsmHousenumberPoint element, FeatureCollector features) {
- features.centroidIfConvex(LAYER_NAME)
- .setBufferPixels(BUFFER_SIZE)
- .setAttr(Fields.HOUSENUMBER, element.housenumber())
- .setMinZoom(14);
- }
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Landcover.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Landcover.java
deleted file mode 100644
index 2efc207f8e..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Landcover.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-package com.onthegomap.planetiler.basemap.layers;
-
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.FeatureMerge;
-import com.onthegomap.planetiler.VectorTile;
-import com.onthegomap.planetiler.basemap.BasemapProfile;
-import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema;
-import com.onthegomap.planetiler.basemap.generated.Tables;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.expression.MultiExpression;
-import com.onthegomap.planetiler.geo.GeometryException;
-import com.onthegomap.planetiler.reader.SourceFeature;
-import com.onthegomap.planetiler.stats.Stats;
-import com.onthegomap.planetiler.util.Translations;
-import com.onthegomap.planetiler.util.ZoomFunction;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Defines the logic for generating map elements for natural land cover polygons like ice, sand, and forest in the
- * {@code landcover} layer from source features.
- *
- * This class is ported to Java from
- * OpenMapTiles landcover sql
- * files.
- */
-public class Landcover implements
- OpenMapTilesSchema.Landcover,
- BasemapProfile.NaturalEarthProcessor,
- Tables.OsmLandcoverPolygon.Handler,
- BasemapProfile.FeaturePostProcessor {
-
- /*
- * Large ice areas come from natural earth and the rest come from OpenStreetMap at higher zoom
- * levels. At render-time, postProcess() merges polygons into larger connected area based
- * on the number of points in the original area. Since postProcess() only has visibility into
- * features on a single tile, process() needs to pass the number of points the original feature
- * had through using a temporary "_numpoints" attribute.
- */
-
- public static final ZoomFunction MIN_PIXEL_SIZE_THRESHOLDS = ZoomFunction.fromMaxZoomThresholds(Map.of(
- 13, 8,
- 10, 4,
- 9, 2
- ));
- private static final String TEMP_NUM_POINTS_ATTR = "_numpoints";
- private static final Set WOOD_OR_FOREST = Set.of(
- FieldValues.SUBCLASS_WOOD,
- FieldValues.SUBCLASS_FOREST
- );
- private final MultiExpression.Index classMapping;
-
- public Landcover(Translations translations, PlanetilerConfig config, Stats stats) {
- this.classMapping = FieldMappings.Class.index();
- }
-
- private String getClassFromSubclass(String subclass) {
- return subclass == null ? null : classMapping.getOrElse(Map.of(Fields.SUBCLASS, subclass), null);
- }
-
- @Override
- public void processNaturalEarth(String table, SourceFeature feature,
- FeatureCollector features) {
- record LandcoverInfo(String subclass, int minzoom, int maxzoom) {}
- LandcoverInfo info = switch (table) {
- case "ne_110m_glaciated_areas" -> new LandcoverInfo(FieldValues.SUBCLASS_GLACIER, 0, 1);
- case "ne_50m_glaciated_areas" -> new LandcoverInfo(FieldValues.SUBCLASS_GLACIER, 2, 4);
- case "ne_10m_glaciated_areas" -> new LandcoverInfo(FieldValues.SUBCLASS_GLACIER, 5, 6);
- case "ne_50m_antarctic_ice_shelves_polys" -> new LandcoverInfo("ice_shelf", 2, 4);
- case "ne_10m_antarctic_ice_shelves_polys" -> new LandcoverInfo("ice_shelf", 5, 6);
- default -> null;
- };
- if (info != null) {
- String clazz = getClassFromSubclass(info.subclass);
- if (clazz != null) {
- features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .setAttr(Fields.CLASS, clazz)
- .setAttr(Fields.SUBCLASS, info.subclass)
- .setZoomRange(info.minzoom, info.maxzoom);
- }
- }
- }
-
- @Override
- public void process(Tables.OsmLandcoverPolygon element, FeatureCollector features) {
- String subclass = element.subclass();
- String clazz = getClassFromSubclass(subclass);
- if (clazz != null) {
- features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .setMinPixelSizeOverrides(MIN_PIXEL_SIZE_THRESHOLDS)
- .setAttr(Fields.CLASS, clazz)
- .setAttr(Fields.SUBCLASS, subclass)
- .setNumPointsAttr(TEMP_NUM_POINTS_ATTR)
- .setMinZoom(7);
- }
- }
-
- @Override
- public List postProcess(int zoom, List items) throws GeometryException {
- if (zoom < 7 || zoom > 13) {
- for (var item : items) {
- item.attrs().remove(TEMP_NUM_POINTS_ATTR);
- }
- return items;
- } else { // z7-13
- // merging only merges polygons with the same attributes, so use this temporary key
- // to separate features into layers that will be merged separately
- String tempGroupKey = "_group";
- List result = new ArrayList<>();
- List toMerge = new ArrayList<>();
- for (var item : items) {
- Map attrs = item.attrs();
- Object numPointsObj = attrs.remove(TEMP_NUM_POINTS_ATTR);
- Object subclassObj = attrs.get(Fields.SUBCLASS);
- if (numPointsObj instanceof Number num && subclassObj instanceof String subclass) {
- long numPoints = num.longValue();
- if (zoom >= 10) {
- if (WOOD_OR_FOREST.contains(subclass) && numPoints < 300) {
- attrs.put(tempGroupKey, "<300");
- toMerge.add(item);
- } else { // don't merge
- result.add(item);
- }
- } else if (zoom == 9) {
- if (WOOD_OR_FOREST.contains(subclass)) {
- attrs.put(tempGroupKey, numPoints < 300 ? "<300" : ">300");
- toMerge.add(item);
- } else { // don't merge
- result.add(item);
- }
- } else { // zoom between 7 and 8
- toMerge.add(item);
- }
- } else {
- result.add(item);
- }
- }
- var merged = FeatureMerge.mergeOverlappingPolygons(toMerge, 4);
- for (var item : merged) {
- item.attrs().remove(tempGroupKey);
- }
- result.addAll(merged);
- return result;
- }
- }
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Landuse.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Landuse.java
deleted file mode 100644
index 54505839a9..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Landuse.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-package com.onthegomap.planetiler.basemap.layers;
-
-import static com.onthegomap.planetiler.basemap.util.Utils.coalesce;
-import static com.onthegomap.planetiler.basemap.util.Utils.nullIfEmpty;
-
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.basemap.BasemapProfile;
-import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema;
-import com.onthegomap.planetiler.basemap.generated.Tables;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.reader.SourceFeature;
-import com.onthegomap.planetiler.stats.Stats;
-import com.onthegomap.planetiler.util.Parse;
-import com.onthegomap.planetiler.util.Translations;
-import com.onthegomap.planetiler.util.ZoomFunction;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Defines the logic for generating map elements for man-made land use polygons like cemeteries, zoos, and hospitals in
- * the {@code landuse} layer from source features.
- *
- * This class is ported to Java from
- * OpenMapTiles landuse sql files.
- */
-public class Landuse implements
- OpenMapTilesSchema.Landuse,
- BasemapProfile.NaturalEarthProcessor,
- Tables.OsmLandusePolygon.Handler {
-
- private static final ZoomFunction MIN_PIXEL_SIZE_THRESHOLDS = ZoomFunction.fromMaxZoomThresholds(Map.of(
- 13, 4,
- 7, 2,
- 6, 1
- ));
- private static final Set Z6_CLASSES = Set.of(
- FieldValues.CLASS_RESIDENTIAL,
- FieldValues.CLASS_SUBURB,
- FieldValues.CLASS_QUARTER,
- FieldValues.CLASS_NEIGHBOURHOOD
- );
-
- public Landuse(Translations translations, PlanetilerConfig config, Stats stats) {}
-
- @Override
- public void processNaturalEarth(String table, SourceFeature feature, FeatureCollector features) {
- if ("ne_50m_urban_areas".equals(table)) {
- Double scalerank = Parse.parseDoubleOrNull(feature.getTag("scalerank"));
- if (scalerank != null && scalerank <= 2) {
- features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .setAttr(Fields.CLASS, FieldValues.CLASS_RESIDENTIAL)
- .setZoomRange(4, 5);
- }
- }
- }
-
- @Override
- public void process(Tables.OsmLandusePolygon element, FeatureCollector features) {
- String clazz = coalesce(
- nullIfEmpty(element.landuse()),
- nullIfEmpty(element.amenity()),
- nullIfEmpty(element.leisure()),
- nullIfEmpty(element.tourism()),
- nullIfEmpty(element.place()),
- nullIfEmpty(element.waterway())
- );
- if (clazz != null) {
- if ("grave_yard".equals(clazz)) {
- clazz = FieldValues.CLASS_CEMETERY;
- }
- features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .setAttr(Fields.CLASS, clazz)
- .setMinPixelSizeOverrides(MIN_PIXEL_SIZE_THRESHOLDS)
- .setMinZoom(Z6_CLASSES.contains(clazz) ? 6 : 9);
- }
- }
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/MountainPeak.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/MountainPeak.java
deleted file mode 100644
index e8b0671337..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/MountainPeak.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-package com.onthegomap.planetiler.basemap.layers;
-
-import static com.onthegomap.planetiler.basemap.util.Utils.elevationTags;
-import static com.onthegomap.planetiler.basemap.util.Utils.nullIfEmpty;
-
-import com.carrotsearch.hppc.LongIntMap;
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.VectorTile;
-import com.onthegomap.planetiler.basemap.BasemapProfile;
-import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema;
-import com.onthegomap.planetiler.basemap.generated.Tables;
-import com.onthegomap.planetiler.basemap.util.LanguageUtils;
-import com.onthegomap.planetiler.collection.Hppc;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.geo.GeometryException;
-import com.onthegomap.planetiler.reader.SourceFeature;
-import com.onthegomap.planetiler.stats.Stats;
-import com.onthegomap.planetiler.util.Parse;
-import com.onthegomap.planetiler.util.Translations;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.locationtech.jts.geom.Geometry;
-import org.locationtech.jts.geom.Point;
-import org.locationtech.jts.geom.prep.PreparedGeometry;
-import org.locationtech.jts.geom.prep.PreparedGeometryFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Defines the logic for generating map elements for mountain peak label points in the {@code mountain_peak} layer from
- * source features.
- *
- * This class is ported to Java from
- * OpenMapTiles mountain_peak
- * sql files.
- */
-public class MountainPeak implements
- BasemapProfile.NaturalEarthProcessor,
- OpenMapTilesSchema.MountainPeak,
- Tables.OsmPeakPoint.Handler,
- Tables.OsmMountainLinestring.Handler,
- BasemapProfile.FeaturePostProcessor {
-
- /*
- * Mountain peaks come from OpenStreetMap data and are ranked by importance (based on if they
- * have a name or wikipedia page) then by elevation. Uses the "label grid" feature to limit
- * label density by only taking the top 5 most important mountain peaks within each 100x100px
- * square.
- */
- private static final Logger LOGGER = LoggerFactory.getLogger(MountainPeak.class);
-
- private final Translations translations;
- private final Stats stats;
- // keep track of areas that prefer feet to meters to set customary_ft=1 (just U.S.)
- private PreparedGeometry unitedStates = null;
- private final AtomicBoolean loggedNoUS = new AtomicBoolean(false);
-
- public MountainPeak(Translations translations, PlanetilerConfig config, Stats stats) {
- this.translations = translations;
- this.stats = stats;
- }
-
- @Override
- public void processNaturalEarth(String table, SourceFeature feature, FeatureCollector features) {
- if ("ne_10m_admin_0_countries".equals(table) && feature.hasTag("iso_a2", "US")) {
- // multiple threads call this method concurrently, US polygon *should* only be found
- // once, but just to be safe synchronize updates to that field
- synchronized (this) {
- try {
- Geometry boundary = feature.polygon();
- unitedStates = PreparedGeometryFactory.prepare(boundary);
- } catch (GeometryException e) {
- LOGGER.error("Failed to get United States Polygon for mountain_peak layer: " + e);
- }
- }
- }
- }
-
- @Override
- public void process(Tables.OsmPeakPoint element, FeatureCollector features) {
- Double meters = Parse.meters(element.ele());
- if (meters != null && Math.abs(meters) < 10_000) {
- var feature = features.point(LAYER_NAME)
- .setAttr(Fields.CLASS, element.source().getTag("natural"))
- .putAttrs(LanguageUtils.getNames(element.source().tags(), translations))
- .putAttrs(elevationTags(meters))
- .setSortKeyDescending(
- meters.intValue() +
- (nullIfEmpty(element.wikipedia()) != null ? 10_000 : 0) +
- (nullIfEmpty(element.name()) != null ? 10_000 : 0)
- )
- .setMinZoom(7)
- // need to use a larger buffer size to allow enough points through to not cut off
- // any label grid squares which could lead to inconsistent label ranks for a feature
- // in adjacent tiles. postProcess() will remove anything outside the desired buffer.
- .setBufferPixels(100)
- .setPointLabelGridSizeAndLimit(13, 100, 5);
-
- if (peakInAreaUsingFeet(element)) {
- feature.setAttr(Fields.CUSTOMARY_FT, 1);
- }
- }
- }
-
- @Override
- public void process(Tables.OsmMountainLinestring element, FeatureCollector features) {
- // TODO rank is approximate to sort important/named ridges before others, should switch to labelgrid for linestrings later
- int rank = 3 -
- (nullIfEmpty(element.wikipedia()) != null ? 1 : 0) -
- (nullIfEmpty(element.name()) != null ? 1 : 0);
- features.line(LAYER_NAME)
- .setAttr(Fields.CLASS, element.source().getTag("natural"))
- .setAttr(Fields.RANK, rank)
- .putAttrs(LanguageUtils.getNames(element.source().tags(), translations))
- .setSortKey(rank)
- .setMinZoom(13)
- .setBufferPixels(100);
- }
-
- /** Returns true if {@code element} is a point in an area where feet are used insead of meters (the US). */
- private boolean peakInAreaUsingFeet(Tables.OsmPeakPoint element) {
- if (unitedStates == null) {
- if (!loggedNoUS.get() && loggedNoUS.compareAndSet(false, true)) {
- LOGGER.warn("No US polygon for inferring mountain_peak customary_ft tag");
- }
- } else {
- try {
- Geometry wayGeometry = element.source().worldGeometry();
- return unitedStates.intersects(wayGeometry);
- } catch (GeometryException e) {
- e.log(stats, "omt_mountain_peak_us_test",
- "Unable to test mountain_peak against US polygon: " + element.source().id());
- }
- }
- return false;
- }
-
- @Override
- public List postProcess(int zoom, List items) {
- LongIntMap groupCounts = Hppc.newLongIntHashMap();
- for (int i = 0; i < items.size(); i++) {
- VectorTile.Feature feature = items.get(i);
- int gridrank = groupCounts.getOrDefault(feature.group(), 1);
- groupCounts.put(feature.group(), gridrank + 1);
- // now that we have accurate ranks, remove anything outside the desired buffer
- if (!insideTileBuffer(feature)) {
- items.set(i, null);
- } else if (!feature.attrs().containsKey(Fields.RANK)) {
- feature.attrs().put(Fields.RANK, gridrank);
- }
- }
- return items;
- }
-
- private static boolean insideTileBuffer(double xOrY) {
- return xOrY >= -BUFFER_SIZE && xOrY <= 256 + BUFFER_SIZE;
- }
-
- private boolean insideTileBuffer(VectorTile.Feature feature) {
- try {
- Geometry geom = feature.geometry().decode();
- return !(geom instanceof Point point) || (insideTileBuffer(point.getX()) && insideTileBuffer(point.getY()));
- } catch (GeometryException e) {
- e.log(stats, "mountain_peak_decode_point", "Error decoding mountain peak point: " + feature.attrs());
- return false;
- }
- }
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Park.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Park.java
deleted file mode 100644
index 4d39424a44..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Park.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-package com.onthegomap.planetiler.basemap.layers;
-
-import static com.onthegomap.planetiler.basemap.util.Utils.coalesce;
-import static com.onthegomap.planetiler.basemap.util.Utils.nullIfEmpty;
-import static com.onthegomap.planetiler.collection.FeatureGroup.SORT_KEY_BITS;
-
-import com.carrotsearch.hppc.LongIntMap;
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.FeatureMerge;
-import com.onthegomap.planetiler.VectorTile;
-import com.onthegomap.planetiler.basemap.BasemapProfile;
-import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema;
-import com.onthegomap.planetiler.basemap.generated.Tables;
-import com.onthegomap.planetiler.basemap.util.LanguageUtils;
-import com.onthegomap.planetiler.collection.Hppc;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.geo.GeoUtils;
-import com.onthegomap.planetiler.geo.GeometryException;
-import com.onthegomap.planetiler.geo.GeometryType;
-import com.onthegomap.planetiler.stats.Stats;
-import com.onthegomap.planetiler.util.SortKey;
-import com.onthegomap.planetiler.util.Translations;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Defines the logic for generating map elements for designated parks polygons and their label points in the {@code
- * park} layer from source features.
- *
- * This class is ported to Java from
- * OpenMapTiles park sql files.
- */
-public class Park implements
- OpenMapTilesSchema.Park,
- Tables.OsmParkPolygon.Handler,
- BasemapProfile.FeaturePostProcessor {
-
- // constants for packing the minimum zoom ordering of park labels into the sort-key field
- private static final int PARK_NATIONAL_PARK_BOOST = 1 << (SORT_KEY_BITS - 1);
- private static final int PARK_WIKIPEDIA_BOOST = 1 << (SORT_KEY_BITS - 2);
-
- // constants for determining the minimum zoom level for a park label based on its area
- private static final double WORLD_AREA_FOR_70K_SQUARE_METERS =
- Math.pow(GeoUtils.metersToPixelAtEquator(0, Math.sqrt(70_000)) / 256d, 2);
- private static final double LOG2 = Math.log(2);
- private static final int PARK_AREA_RANGE = 1 << (SORT_KEY_BITS - 3);
- private static final double SMALLEST_PARK_WORLD_AREA = Math.pow(4, -26); // 2^14 tiles, 2^12 pixels per tile
-
- private final Translations translations;
- private final Stats stats;
-
- public Park(Translations translations, PlanetilerConfig config, Stats stats) {
- this.stats = stats;
- this.translations = translations;
- }
-
- @Override
- public void process(Tables.OsmParkPolygon element, FeatureCollector features) {
- String protectionTitle = element.protectionTitle();
- if (protectionTitle != null) {
- protectionTitle = protectionTitle.replace(' ', '_').toLowerCase(Locale.ROOT);
- }
- String clazz = coalesce(
- nullIfEmpty(protectionTitle),
- nullIfEmpty(element.boundary()),
- nullIfEmpty(element.leisure())
- );
-
- // park shape
- var outline = features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .setAttrWithMinzoom(Fields.CLASS, clazz, 5)
- .setMinPixelSize(2)
- .setMinZoom(4);
-
- // park name label point (if it has one)
- if (element.name() != null) {
- try {
- double area = element.source().area();
- int minzoom = getMinZoomForArea(area);
-
- var names = LanguageUtils.getNamesWithoutTranslations(element.source().tags());
-
- outline.putAttrsWithMinzoom(names, 5);
-
- features.pointOnSurface(LAYER_NAME).setBufferPixels(256)
- .setAttr(Fields.CLASS, clazz)
- .putAttrs(names)
- .putAttrs(LanguageUtils.getNames(element.source().tags(), translations))
- .setPointLabelGridPixelSize(14, 100)
- .setSortKey(SortKey
- .orderByTruesFirst("national_park".equals(clazz))
- .thenByTruesFirst(element.source().hasTag("wikipedia") || element.source().hasTag("wikidata"))
- .thenByLog(area, 1d, SMALLEST_PARK_WORLD_AREA, 1 << (SORT_KEY_BITS - 2) - 1)
- .get()
- ).setMinZoom(minzoom);
- } catch (GeometryException e) {
- e.log(stats, "omt_park_area", "Unable to get park area for " + element.source().id());
- }
- }
- }
-
- private int getMinZoomForArea(double area) {
- // sql filter: area > 70000*2^(20-zoom_level)
- // simplifies to: zoom_level > 20 - log(area / 70000) / log(2)
- int minzoom = (int) Math.floor(20 - Math.log(area / WORLD_AREA_FOR_70K_SQUARE_METERS) / LOG2);
- minzoom = Math.min(14, Math.max(5, minzoom));
- return minzoom;
- }
-
- @Override
- public List postProcess(int zoom, List items) throws GeometryException {
- // infer the "rank" attribute from point ordering within each label grid square
- LongIntMap counts = Hppc.newLongIntHashMap();
- for (VectorTile.Feature feature : items) {
- if (feature.geometry().geomType() == GeometryType.POINT && feature.hasGroup()) {
- int count = counts.getOrDefault(feature.group(), 0) + 1;
- feature.attrs().put("rank", count);
- counts.put(feature.group(), count);
- }
- }
- if (zoom <= 4) {
- items = FeatureMerge.mergeOverlappingPolygons(items, 0);
- }
- return items;
- }
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Place.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Place.java
deleted file mode 100644
index f355727e8b..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Place.java
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-package com.onthegomap.planetiler.basemap.layers;
-
-import static com.onthegomap.planetiler.basemap.util.Utils.coalesce;
-import static com.onthegomap.planetiler.basemap.util.Utils.nullIfEmpty;
-import static com.onthegomap.planetiler.basemap.util.Utils.nullOrEmpty;
-import static com.onthegomap.planetiler.collection.FeatureGroup.SORT_KEY_BITS;
-
-import com.carrotsearch.hppc.LongIntMap;
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.VectorTile;
-import com.onthegomap.planetiler.basemap.BasemapProfile;
-import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema;
-import com.onthegomap.planetiler.basemap.generated.Tables;
-import com.onthegomap.planetiler.basemap.util.LanguageUtils;
-import com.onthegomap.planetiler.collection.Hppc;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.geo.GeoUtils;
-import com.onthegomap.planetiler.geo.GeometryException;
-import com.onthegomap.planetiler.geo.PointIndex;
-import com.onthegomap.planetiler.geo.PolygonIndex;
-import com.onthegomap.planetiler.reader.SourceFeature;
-import com.onthegomap.planetiler.stats.Stats;
-import com.onthegomap.planetiler.util.Parse;
-import com.onthegomap.planetiler.util.SortKey;
-import com.onthegomap.planetiler.util.Translations;
-import com.onthegomap.planetiler.util.ZoomFunction;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.stream.Collectors;
-import java.util.stream.DoubleStream;
-import java.util.stream.Stream;
-import org.apache.commons.lang3.StringUtils;
-import org.locationtech.jts.geom.Point;
-
-/**
- * Defines the logic for generating label points for populated places like continents, countries, cities, and towns in
- * the {@code place} layer from source features.
- *
- * This class is ported to Java from
- * OpenMapTiles place sql files.
- */
-public class Place implements
- OpenMapTilesSchema.Place,
- BasemapProfile.NaturalEarthProcessor,
- Tables.OsmContinentPoint.Handler,
- Tables.OsmCountryPoint.Handler,
- Tables.OsmStatePoint.Handler,
- Tables.OsmIslandPoint.Handler,
- Tables.OsmIslandPolygon.Handler,
- Tables.OsmCityPoint.Handler,
- BasemapProfile.FeaturePostProcessor {
-
- /*
- * Place labels locations and names come from OpenStreetMap, but we also join with natural
- * earth state/country geographic areas and city point labels to give a hint for what rank
- * and minimum zoom level to use for those points.
- */
-
- private static final TreeMap ISLAND_AREA_RANKS = new TreeMap<>(Map.of(
- Double.MAX_VALUE, 3,
- squareMetersToWorldArea(40_000_000), 4,
- squareMetersToWorldArea(15_000_000), 5,
- squareMetersToWorldArea(1_000_000), 6
- ));
- private static final double MIN_ISLAND_WORLD_AREA = Math.pow(4, -26); // 2^14 tiles, 2^12 pixels per tile
- private static final double CITY_JOIN_DISTANCE = GeoUtils.metersToPixelAtEquator(0, 50_000) / 256d;
- // constants for packing place label precedence into the sort-key field
- private static final double MAX_CITY_POPULATION = 100_000_000d;
- private static final Set MAJOR_CITY_PLACES = Set.of("city", "town", "village");
- private static final ZoomFunction LABEL_GRID_LIMITS = ZoomFunction.fromMaxZoomThresholds(Map.of(
- 8, 4,
- 9, 8,
- 10, 12,
- 12, 14
- ), 0);
- private final Translations translations;
- private final Stats stats;
- // spatial indexes for joining natural earth place labels with their corresponding points
- // from openstreetmap
- private PolygonIndex countries = PolygonIndex.create();
- private PolygonIndex states = PolygonIndex.create();
- private PointIndex cities = PointIndex.create();
-
- public Place(Translations translations, PlanetilerConfig config, Stats stats) {
- this.translations = translations;
- this.stats = stats;
- }
-
- /** Returns the portion of the world that {@code squareMeters} covers where 1 is the entire planet. */
- private static double squareMetersToWorldArea(double squareMeters) {
- double oneSideMeters = Math.sqrt(squareMeters);
- double oneSideWorld = GeoUtils.metersToPixelAtEquator(0, oneSideMeters) / 256d;
- return Math.pow(oneSideWorld, 2);
- }
-
- /**
- * Packs place precedence ordering ({@code rank asc, place asc, population desc, name.length asc}) into an integer for
- * the sort-key field.
- */
- static int getSortKey(Integer rank, PlaceType place, long population, String name) {
- return SortKey
- // ORDER BY "rank" ASC NULLS LAST,
- .orderByInt(rank == null ? 15 : rank, 0, 15) // 4 bits
- // place ASC NULLS LAST,
- .thenByInt(place == null ? 15 : place.ordinal(), 0, 15) // 4 bits
- // population DESC NULLS LAST,
- .thenByLog(population, MAX_CITY_POPULATION, 1, 1 << (SORT_KEY_BITS - 13) - 1)
- // length(name) ASC
- .thenByInt(name == null ? 0 : name.length(), 0, 31) // 5 bits
- .get();
- }
-
- @Override
- public void release() {
- countries = null;
- states = null;
- cities = null;
- }
-
- @Override
- public void processNaturalEarth(String table, SourceFeature feature, FeatureCollector features) {
- // store data from natural earth to help with ranks and min zoom levels when actually
- // emitting features from openstreetmap data.
- try {
- switch (table) {
- case "ne_10m_admin_0_countries" -> countries.put(feature.worldGeometry(), new NaturalEarthRegion(
- feature.getString("name"), 6,
- feature.getLong("scalerank"),
- feature.getLong("labelrank")
- ));
- case "ne_10m_admin_1_states_provinces" -> {
- Double scalerank = Parse.parseDoubleOrNull(feature.getTag("scalerank"));
- Double labelrank = Parse.parseDoubleOrNull(feature.getTag("labelrank"));
- if (scalerank != null && scalerank <= 6 && labelrank != null && labelrank <= 7) {
- states.put(feature.worldGeometry(), new NaturalEarthRegion(
- feature.getString("name"), 6,
- scalerank,
- labelrank,
- feature.getLong("datarank")
- ));
- }
- }
- case "ne_10m_populated_places" -> cities.put(feature.worldGeometry(), new NaturalEarthPoint(
- feature.getString("name"),
- feature.getString("wikidataid"),
- (int) feature.getLong("scalerank"),
- Stream.of("name", "namealt", "meganame", "gn_ascii", "nameascii").map(feature::getString)
- .filter(Objects::nonNull)
- .map(s -> s.toLowerCase(Locale.ROOT))
- .collect(Collectors.toSet())
- ));
- }
- } catch (GeometryException e) {
- e.log(stats, "omt_place_ne",
- "Error getting geometry for natural earth feature " + table + " " + feature.getTag("ogc_fid"));
- }
- }
-
- @Override
- public void process(Tables.OsmContinentPoint element, FeatureCollector features) {
- if (!nullOrEmpty(element.name())) {
- features.point(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .putAttrs(LanguageUtils.getNames(element.source().tags(), translations))
- .setAttr(Fields.CLASS, FieldValues.CLASS_CONTINENT)
- .setAttr(Fields.RANK, 1)
- .putAttrs(LanguageUtils.getNames(element.source().tags(), translations))
- .setZoomRange(0, 3);
- }
- }
-
- @Override
- public void process(Tables.OsmCountryPoint element, FeatureCollector features) {
- if (nullOrEmpty(element.name())) {
- return;
- }
- String isoA2 = coalesce(
- nullIfEmpty(element.countryCodeIso31661Alpha2()),
- nullIfEmpty(element.iso31661Alpha2()),
- nullIfEmpty(element.iso31661())
- );
- if (isoA2 == null) {
- return;
- }
- try {
- // set country rank to 6, unless there is a match in natural earth that indicates it
- // should be lower
- int rank = 7;
- NaturalEarthRegion country = countries.get(element.source().worldGeometry().getCentroid());
- var names = LanguageUtils.getNames(element.source().tags(), translations);
-
- if (country != null) {
- if (nullOrEmpty(names.get(Fields.NAME_EN))) {
- names.put(Fields.NAME_EN, country.name);
- }
- rank = country.rank;
- }
-
- rank = Math.max(1, Math.min(6, rank));
-
- features.point(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .putAttrs(names)
- .setAttr(Fields.ISO_A2, isoA2)
- .setAttr(Fields.CLASS, FieldValues.CLASS_COUNTRY)
- .setAttr(Fields.RANK, rank)
- .setMinZoom(rank - 1)
- .setSortKey(rank);
- } catch (GeometryException e) {
- e.log(stats, "omt_place_country",
- "Unable to get point for OSM country " + element.source().id());
- }
- }
-
- @Override
- public void process(Tables.OsmStatePoint element, FeatureCollector features) {
- try {
- // want the containing (not nearest) state polygon since we pre-filter the states in the polygon index
- // use natural earth to filter out any spurious states, and to set the rank field
- NaturalEarthRegion state = states.getOnlyContaining(element.source().worldGeometry().getCentroid());
- if (state != null) {
- var names = LanguageUtils.getNames(element.source().tags(), translations);
- if (nullOrEmpty(names.get(Fields.NAME_EN))) {
- names.put(Fields.NAME_EN, state.name);
- }
- int rank = Math.min(6, Math.max(1, state.rank));
-
- features.point(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .putAttrs(names)
- .setAttr(Fields.CLASS, element.place())
- .setAttr(Fields.RANK, rank)
- .setMinZoom(2)
- .setSortKey(rank);
- }
- } catch (GeometryException e) {
- e.log(stats, "omt_place_state",
- "Unable to get point for OSM state " + element.source().id());
- }
- }
-
- @Override
- public void process(Tables.OsmIslandPolygon element, FeatureCollector features) {
- try {
- double area = element.source().area();
- int rank = ISLAND_AREA_RANKS.ceilingEntry(area).getValue();
- int minzoom = rank <= 3 ? 8 : rank <= 4 ? 9 : 10;
-
- features.pointOnSurface(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .putAttrs(LanguageUtils.getNames(element.source().tags(), translations))
- .setAttr(Fields.CLASS, "island")
- .setAttr(Fields.RANK, rank)
- .setMinZoom(minzoom)
- .setSortKey(SortKey.orderByLog(area, 1d, MIN_ISLAND_WORLD_AREA).get());
- } catch (GeometryException e) {
- e.log(stats, "omt_place_island_poly",
- "Unable to get point for OSM island polygon " + element.source().id());
- }
- }
-
- @Override
- public void process(Tables.OsmIslandPoint element, FeatureCollector features) {
- features.point(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .putAttrs(LanguageUtils.getNames(element.source().tags(), translations))
- .setAttr(Fields.CLASS, "island")
- .setAttr(Fields.RANK, 7)
- .setMinZoom(12);
- }
-
- @Override
- public void process(Tables.OsmCityPoint element, FeatureCollector features) {
- Integer rank = null;
- if (MAJOR_CITY_PLACES.contains(element.place())) {
- // only for major cities, attempt to find a nearby natural earth label with a similar
- // name and use that to set a rank from OSM that causes the label to be shown at lower
- // zoom levels
- try {
- Point point = element.source().worldGeometry().getCentroid();
- List neCities = cities.getWithin(point, CITY_JOIN_DISTANCE);
- String rawName = coalesce(element.name(), "");
- String name = coalesce(rawName, "").toLowerCase(Locale.ROOT);
- String nameEn = coalesce(element.nameEn(), "").toLowerCase(Locale.ROOT);
- String normalizedName = StringUtils.stripAccents(rawName);
- String wikidata = element.source().getString("wikidata", "");
- for (var neCity : neCities) {
- if (wikidata.equals(neCity.wikidata) ||
- neCity.names.contains(name) ||
- neCity.names.contains(nameEn) ||
- normalizedName.equals(neCity.name)) {
- rank = neCity.scaleRank <= 5 ? neCity.scaleRank + 1 : neCity.scaleRank;
- break;
- }
- }
- } catch (GeometryException e) {
- e.log(stats, "omt_place_city",
- "Unable to get point for OSM city " + element.source().id());
- }
- }
-
- String capital = element.capital();
-
- PlaceType placeType = PlaceType.forName(element.place());
-
- int minzoom = rank != null && rank == 1 ? 2 :
- rank != null && rank <= 8 ? Math.max(3, rank - 1) :
- placeType.ordinal() <= PlaceType.TOWN.ordinal() ? 7 :
- placeType.ordinal() <= PlaceType.VILLAGE.ordinal() ? 8 :
- placeType.ordinal() <= PlaceType.SUBURB.ordinal() ? 11 : 14;
-
- var feature = features.point(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .putAttrs(LanguageUtils.getNames(element.source().tags(), translations))
- .setAttr(Fields.CLASS, element.place())
- .setAttr(Fields.RANK, rank)
- .setMinZoom(minzoom)
- .setSortKey(getSortKey(rank, placeType, element.population(), element.name()))
- .setPointLabelGridPixelSize(12, 128);
-
- if (rank == null) {
- feature.setPointLabelGridLimit(LABEL_GRID_LIMITS);
- }
-
- if ("2".equals(capital) || "yes".equals(capital)) {
- feature.setAttr(Fields.CAPITAL, 2);
- } else if ("4".equals(capital)) {
- feature.setAttr(Fields.CAPITAL, 4);
- }
- }
-
- @Override
- public List postProcess(int zoom, List items) {
- // infer the rank field from ordering of the place labels with each label grid square
- LongIntMap groupCounts = Hppc.newLongIntHashMap();
- for (VectorTile.Feature feature : items) {
- int gridrank = groupCounts.getOrDefault(feature.group(), 1);
- groupCounts.put(feature.group(), gridrank + 1);
- if (!feature.attrs().containsKey(Fields.RANK)) {
- feature.attrs().put(Fields.RANK, 10 + gridrank);
- }
- }
- return items;
- }
-
- /** Ordering defines the precedence of place classes. */
- enum PlaceType {
- CITY("city"),
- TOWN("town"),
- VILLAGE("village"),
- HAMLET("hamlet"),
- SUBURB("suburb"),
- QUARTER("quarter"),
- NEIGHBORHOOD("neighbourhood"),
- ISOLATED_DWELLING("isolated_dwelling"),
- UNKNOWN("unknown");
-
- private static final Map byName = new HashMap<>();
-
- static {
- for (PlaceType place : values()) {
- byName.put(place.name, place);
- }
- }
-
- private final String name;
-
- PlaceType(String name) {
- this.name = name;
- }
-
- public static PlaceType forName(String name) {
- return byName.getOrDefault(name, UNKNOWN);
- }
- }
-
- /**
- * Information extracted from a natural earth geographic region that will be inspected when joining with OpenStreetMap
- * data.
- */
- private record NaturalEarthRegion(String name, int rank) {
-
- NaturalEarthRegion(String name, int maxRank, double... ranks) {
- this(name, (int) Math.ceil(DoubleStream.of(ranks).average().orElse(maxRank)));
- }
- }
-
- /**
- * Information extracted from a natural earth place label that will be inspected when joining with OpenStreetMap data.
- */
- private record NaturalEarthPoint(String name, String wikidata, int scaleRank, Set names) {}
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Poi.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Poi.java
deleted file mode 100644
index 5b41aa2bb8..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Poi.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-package com.onthegomap.planetiler.basemap.layers;
-
-import static com.onthegomap.planetiler.basemap.util.Utils.coalesce;
-import static com.onthegomap.planetiler.basemap.util.Utils.nullIfEmpty;
-import static com.onthegomap.planetiler.basemap.util.Utils.nullIfLong;
-import static com.onthegomap.planetiler.basemap.util.Utils.nullOrEmpty;
-import static java.util.Map.entry;
-
-import com.carrotsearch.hppc.LongIntMap;
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.ForwardingProfile;
-import com.onthegomap.planetiler.VectorTile;
-import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema;
-import com.onthegomap.planetiler.basemap.generated.Tables;
-import com.onthegomap.planetiler.basemap.util.LanguageUtils;
-import com.onthegomap.planetiler.collection.Hppc;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.expression.MultiExpression;
-import com.onthegomap.planetiler.stats.Stats;
-import com.onthegomap.planetiler.util.Parse;
-import com.onthegomap.planetiler.util.Translations;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Defines the logic for generating map elements for things like shops, parks, and schools in the {@code poi} layer from
- * source features.
- *
- * This class is ported to Java from
- * OpenMapTiles poi sql files.
- */
-public class Poi implements
- OpenMapTilesSchema.Poi,
- Tables.OsmPoiPoint.Handler,
- Tables.OsmPoiPolygon.Handler,
- ForwardingProfile.FeaturePostProcessor {
-
- /*
- * process() creates the raw POI feature from OSM elements and postProcess()
- * assigns the feature rank from order in the tile at render-time.
- */
-
- private static final Map CLASS_RANKS = Map.ofEntries(
- entry(FieldValues.CLASS_HOSPITAL, 20),
- entry(FieldValues.CLASS_RAILWAY, 40),
- entry(FieldValues.CLASS_BUS, 50),
- entry(FieldValues.CLASS_ATTRACTION, 70),
- entry(FieldValues.CLASS_HARBOR, 75),
- entry(FieldValues.CLASS_COLLEGE, 80),
- entry(FieldValues.CLASS_SCHOOL, 85),
- entry(FieldValues.CLASS_STADIUM, 90),
- entry("zoo", 95),
- entry(FieldValues.CLASS_TOWN_HALL, 100),
- entry(FieldValues.CLASS_CAMPSITE, 110),
- entry(FieldValues.CLASS_CEMETERY, 115),
- entry(FieldValues.CLASS_PARK, 120),
- entry(FieldValues.CLASS_LIBRARY, 130),
- entry("police", 135),
- entry(FieldValues.CLASS_POST, 140),
- entry(FieldValues.CLASS_GOLF, 150),
- entry(FieldValues.CLASS_SHOP, 400),
- entry(FieldValues.CLASS_GROCERY, 500),
- entry(FieldValues.CLASS_FAST_FOOD, 600),
- entry(FieldValues.CLASS_CLOTHING_STORE, 700),
- entry(FieldValues.CLASS_BAR, 800)
- );
- private final MultiExpression.Index classMapping;
- private final Translations translations;
-
- public Poi(Translations translations, PlanetilerConfig config, Stats stats) {
- this.classMapping = FieldMappings.Class.index();
- this.translations = translations;
- }
-
- static int poiClassRank(String clazz) {
- return CLASS_RANKS.getOrDefault(clazz, 1_000);
- }
-
- private String poiClass(String subclass, String mappingKey) {
- subclass = coalesce(subclass, "");
- return classMapping.getOrElse(Map.of(
- "subclass", subclass,
- "mapping_key", coalesce(mappingKey, "")
- ), subclass);
- }
-
- private int minzoom(String subclass, String mappingKey) {
- boolean lowZoom = ("station".equals(subclass) && "railway".equals(mappingKey)) ||
- "halt".equals(subclass) || "ferry_terminal".equals(subclass);
- return lowZoom ? 12 : 14;
- }
-
- @Override
- public void process(Tables.OsmPoiPoint element, FeatureCollector features) {
- // TODO handle uic_ref => agg_stop
- setupPoiFeature(element, features.point(LAYER_NAME));
- }
-
- @Override
- public void process(Tables.OsmPoiPolygon element, FeatureCollector features) {
- setupPoiFeature(element, features.centroidIfConvex(LAYER_NAME));
- }
-
- private void setupPoiFeature(
- T element, FeatureCollector.Feature output) {
- String rawSubclass = element.subclass();
- if ("station".equals(rawSubclass) && "subway".equals(element.station())) {
- rawSubclass = "subway";
- }
- if ("station".equals(rawSubclass) && "yes".equals(element.funicular())) {
- rawSubclass = "halt";
- }
-
- // ATM names fall back to operator, or else network
- String name = element.name();
- var tags = element.source().tags();
- if ("atm".equals(rawSubclass) && nullOrEmpty(name)) {
- name = coalesce(nullIfEmpty(element.operator()), nullIfEmpty(element.network()));
- if (name != null) {
- tags.put("name", name);
- }
- }
-
- String subclass = switch (rawSubclass) {
- case "information" -> nullIfEmpty(element.information());
- case "place_of_worship" -> nullIfEmpty(element.religion());
- case "pitch" -> nullIfEmpty(element.sport());
- default -> rawSubclass;
- };
- String poiClass = poiClass(rawSubclass, element.mappingKey());
- int poiClassRank = poiClassRank(poiClass);
- int rankOrder = poiClassRank + ((nullOrEmpty(name)) ? 2000 : 0);
-
- output.setBufferPixels(BUFFER_SIZE)
- .setAttr(Fields.CLASS, poiClass)
- .setAttr(Fields.SUBCLASS, subclass)
- .setAttr(Fields.LAYER, nullIfLong(element.layer(), 0))
- .setAttr(Fields.LEVEL, Parse.parseLongOrNull(element.source().getTag("level")))
- .setAttr(Fields.INDOOR, element.indoor() ? 1 : null)
- .putAttrs(LanguageUtils.getNames(element.source().tags(), translations))
- .setPointLabelGridPixelSize(14, 64)
- .setSortKey(rankOrder)
- .setMinZoom(minzoom(element.subclass(), element.mappingKey()));
- }
-
- @Override
- public List postProcess(int zoom, List items) {
- // infer the "rank" field from the order of features within each label grid square
- LongIntMap groupCounts = Hppc.newLongIntHashMap();
- for (VectorTile.Feature feature : items) {
- int gridrank = groupCounts.getOrDefault(feature.group(), 1);
- groupCounts.put(feature.group(), gridrank + 1);
- if (!feature.attrs().containsKey(Fields.RANK)) {
- feature.attrs().put(Fields.RANK, gridrank);
- }
- }
- return items;
- }
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Transportation.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Transportation.java
deleted file mode 100644
index dacc80c485..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/Transportation.java
+++ /dev/null
@@ -1,569 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-package com.onthegomap.planetiler.basemap.layers;
-
-import static com.onthegomap.planetiler.basemap.util.Utils.*;
-import static com.onthegomap.planetiler.util.MemoryEstimator.CLASS_HEADER_BYTES;
-import static com.onthegomap.planetiler.util.MemoryEstimator.POINTER_BYTES;
-import static com.onthegomap.planetiler.util.MemoryEstimator.estimateSize;
-import static java.util.Map.entry;
-
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.FeatureMerge;
-import com.onthegomap.planetiler.VectorTile;
-import com.onthegomap.planetiler.basemap.BasemapProfile;
-import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema;
-import com.onthegomap.planetiler.basemap.generated.Tables;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.expression.MultiExpression;
-import com.onthegomap.planetiler.geo.GeoUtils;
-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.MemoryEstimator;
-import com.onthegomap.planetiler.util.Parse;
-import com.onthegomap.planetiler.util.Translations;
-import com.onthegomap.planetiler.util.ZoomFunction;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import org.locationtech.jts.geom.Geometry;
-import org.locationtech.jts.geom.LineString;
-import org.locationtech.jts.geom.prep.PreparedGeometry;
-import org.locationtech.jts.geom.prep.PreparedGeometryFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Defines the logic for generating map elements for roads, shipways, railroads, and paths in the {@code transportation}
- * layer from source features.
- *
- * This class is ported to Java from
- * OpenMapTiles transportation
- * sql files.
- */
-public class Transportation implements
- OpenMapTilesSchema.Transportation,
- Tables.OsmAerialwayLinestring.Handler,
- Tables.OsmHighwayLinestring.Handler,
- Tables.OsmRailwayLinestring.Handler,
- Tables.OsmShipwayLinestring.Handler,
- Tables.OsmHighwayPolygon.Handler,
- BasemapProfile.NaturalEarthProcessor,
- BasemapProfile.FeaturePostProcessor,
- BasemapProfile.OsmRelationPreprocessor,
- BasemapProfile.IgnoreWikidata {
-
- /*
- * Generates the shape for roads, trails, ferries, railways with detailed
- * attributes for rendering, but not any names. The transportation_name
- * layer includes names, but less detailed attributes.
- */
-
- private static final Logger LOGGER = LoggerFactory.getLogger(Transportation.class);
- private static final Pattern GREAT_BRITAIN_REF_NETWORK_PATTERN = Pattern.compile("^[AM][0-9AM()]+");
- private static final MultiExpression.Index classMapping = FieldMappings.Class.index();
- private static final Set RAILWAY_RAIL_VALUES = Set.of(
- FieldValues.SUBCLASS_RAIL,
- FieldValues.SUBCLASS_NARROW_GAUGE,
- FieldValues.SUBCLASS_PRESERVED,
- FieldValues.SUBCLASS_FUNICULAR
- );
- private static final Set RAILWAY_TRANSIT_VALUES = Set.of(
- FieldValues.SUBCLASS_SUBWAY,
- FieldValues.SUBCLASS_LIGHT_RAIL,
- FieldValues.SUBCLASS_MONORAIL,
- FieldValues.SUBCLASS_TRAM
- );
- private static final Set SERVICE_VALUES = Set.of(
- FieldValues.SERVICE_SPUR,
- FieldValues.SERVICE_YARD,
- FieldValues.SERVICE_SIDING,
- FieldValues.SERVICE_CROSSOVER,
- FieldValues.SERVICE_DRIVEWAY,
- FieldValues.SERVICE_ALLEY,
- FieldValues.SERVICE_PARKING_AISLE
- );
- private static final Set SURFACE_UNPAVED_VALUES = Set.of(
- "unpaved", "compacted", "dirt", "earth", "fine_gravel", "grass", "grass_paver", "gravel", "gravel_turf", "ground",
- "ice", "mud", "pebblestone", "salt", "sand", "snow", "woodchips"
- );
- private static final Set SURFACE_PAVED_VALUES = Set.of(
- "paved", "asphalt", "cobblestone", "concrete", "concrete:lanes", "concrete:plates", "metal",
- "paving_stones", "sett", "unhewn_cobblestone", "wood"
- );
- private static final Set ACCESS_NO_VALUES = Set.of(
- "private", "no"
- );
- private static final ZoomFunction.MeterToPixelThresholds MIN_LENGTH = ZoomFunction.meterThresholds()
- .put(7, 50)
- .put(6, 100)
- .put(5, 500)
- .put(4, 1_000);
- // ORDER BY network_type, network, LENGTH(ref), ref)
- private static final Comparator RELATION_ORDERING = Comparator
- .comparingInt(
- r -> r.networkType() != null ? r.networkType.ordinal() : Integer.MAX_VALUE)
- .thenComparing(routeRelation -> coalesce(routeRelation.network(), ""))
- .thenComparingInt(r -> r.ref().length())
- .thenComparing(RouteRelation::ref);
- private final AtomicBoolean loggedNoGb = new AtomicBoolean(false);
- private final boolean z13Paths;
- private PreparedGeometry greatBritain = null;
- private final Map MINZOOMS;
- private final Stats stats;
- private final PlanetilerConfig config;
-
- public Transportation(Translations translations, PlanetilerConfig config, Stats stats) {
- this.config = config;
- this.stats = stats;
- z13Paths = config.arguments().getBoolean(
- "transportation_z13_paths",
- "transportation(_name) layer: show all paths on z13",
- false
- );
- MINZOOMS = Map.ofEntries(
- entry(FieldValues.CLASS_PATH, z13Paths ? 13 : 14),
- entry(FieldValues.CLASS_TRACK, 14),
- entry(FieldValues.CLASS_SERVICE, 13),
- entry(FieldValues.CLASS_MINOR, 13),
- entry(FieldValues.CLASS_RACEWAY, 12),
- entry(FieldValues.CLASS_TERTIARY, 11),
- entry(FieldValues.CLASS_BUSWAY, 11),
- entry(FieldValues.CLASS_SECONDARY, 9),
- entry(FieldValues.CLASS_PRIMARY, 7),
- entry(FieldValues.CLASS_TRUNK, 5),
- entry(FieldValues.CLASS_MOTORWAY, 4)
- );
- }
-
- @Override
- public void processNaturalEarth(String table, SourceFeature feature,
- FeatureCollector features) {
- if ("ne_10m_admin_0_countries".equals(table) && feature.hasTag("iso_a2", "GB")) {
- // multiple threads call this method concurrently, GB polygon *should* only be found
- // once, but just to be safe synchronize updates to that field
- synchronized (this) {
- try {
- Geometry boundary = feature.polygon().buffer(GeoUtils.metersToPixelAtEquator(0, 10_000) / 256d);
- greatBritain = PreparedGeometryFactory.prepare(boundary);
- } catch (GeometryException e) {
- LOGGER.error("Failed to get Great Britain Polygon: " + e);
- }
- }
- }
- }
-
- /** Returns a value for {@code surface} tag constrained to a small set of known values from raw OSM data. */
- private static String surface(String value) {
- return value == null ? null : SURFACE_PAVED_VALUES.contains(value) ? FieldValues.SURFACE_PAVED :
- SURFACE_UNPAVED_VALUES.contains(value) ? FieldValues.SURFACE_UNPAVED : null;
- }
-
- /** Returns a value for {@code access} tag constrained to a small set of known values from raw OSM data. */
- private static String access(String value) {
- return value == null ? null : ACCESS_NO_VALUES.contains(value) ? "no" : null;
- }
-
- /** Returns a value for {@code service} tag constrained to a small set of known values from raw OSM data. */
- private static String service(String value) {
- return (value == null || !SERVICE_VALUES.contains(value)) ? null : value;
- }
-
- private static String railwayClass(String value) {
- return value == null ? null :
- RAILWAY_RAIL_VALUES.contains(value) ? "rail" :
- RAILWAY_TRANSIT_VALUES.contains(value) ? "transit" : null;
- }
-
- static String highwayClass(String highway, String publicTransport, String construction, String manMade) {
- return (!nullOrEmpty(highway) || !nullOrEmpty(publicTransport)) ? classMapping.getOrElse(Map.of(
- "highway", coalesce(highway, ""),
- "public_transport", coalesce(publicTransport, ""),
- "construction", coalesce(construction, "")
- ), null) : isBridgeOrPier(manMade) ? manMade : null;
- }
-
- static String highwaySubclass(String highwayClass, String publicTransport, String highway) {
- return FieldValues.CLASS_PATH.equals(highwayClass) ? coalesce(nullIfEmpty(publicTransport), highway) : null;
- }
-
- static boolean isFootwayOrSteps(String highway) {
- return "footway".equals(highway) || "steps".equals(highway);
- }
-
- static boolean isLink(String highway) {
- return highway != null && highway.endsWith("_link");
- }
-
- private static boolean isResidentialOrUnclassified(String highway) {
- return "residential".equals(highway) || "unclassified".equals(highway);
- }
-
- private static boolean isDrivewayOrParkingAisle(String service) {
- return FieldValues.SERVICE_PARKING_AISLE.equals(service) || FieldValues.SERVICE_DRIVEWAY.equals(service);
- }
-
- private static boolean isBridgeOrPier(String manMade) {
- return "bridge".equals(manMade) || "pier".equals(manMade);
- }
-
- enum RouteNetwork {
-
- US_INTERSTATE("us-interstate"),
- US_HIGHWAY("us-highway"),
- US_STATE("us-state"),
- CA_TRANSCANADA("ca-transcanada"),
- GB_MOTORWAY("gb-motorway"),
- GB_TRUNK("gb-trunk");
-
- final String name;
-
- RouteNetwork(String name) {
- this.name = name;
- }
- }
-
- @Override
- public List preprocessOsmRelation(OsmElement.Relation relation) {
- if (relation.hasTag("route", "road", "hiking")) {
- RouteNetwork networkType = null;
- String network = relation.getString("network");
- String ref = relation.getString("ref");
-
- if ("US:I".equals(network)) {
- networkType = RouteNetwork.US_INTERSTATE;
- } else if ("US:US".equals(network)) {
- networkType = RouteNetwork.US_HIGHWAY;
- } else if (network != null && network.length() == 5 && network.startsWith("US:")) {
- networkType = RouteNetwork.US_STATE;
- } else if (network != null && network.startsWith("CA:transcanada")) {
- networkType = RouteNetwork.CA_TRANSCANADA;
- }
-
- int rank = switch (coalesce(network, "")) {
- case "iwn", "nwn", "rwn" -> 1;
- case "lwn" -> 2;
- default -> (relation.hasTag("osmc:symbol") || relation.hasTag("colour")) ? 2 : 3;
- };
-
- if (network != null || rank < 3) {
- return List.of(new RouteRelation(coalesce(ref, ""), network, networkType, (byte) rank, relation.id()));
- }
- }
- return null;
- }
-
- List getRouteRelations(Tables.OsmHighwayLinestring element) {
- String ref = element.ref();
- List> relations = element.source().relationInfo(RouteRelation.class);
- List result = new ArrayList<>(relations.size() + 1);
- for (var relationMember : relations) {
- var relation = relationMember.relation();
- // avoid duplicates - list should be very small and usually only one
- if (!result.contains(relation)) {
- result.add(relation);
- }
- }
- if (ref != null) {
- // GB doesn't use regular relations like everywhere else, so if we are
- // in GB then use a naming convention instead.
- Matcher refMatcher = GREAT_BRITAIN_REF_NETWORK_PATTERN.matcher(ref);
- if (refMatcher.find()) {
- if (greatBritain == null) {
- if (!loggedNoGb.get() && loggedNoGb.compareAndSet(false, true)) {
- LOGGER.warn("No GB polygon for inferring route network types");
- }
- } else {
- try {
- Geometry wayGeometry = element.source().worldGeometry();
- if (greatBritain.intersects(wayGeometry)) {
- Transportation.RouteNetwork networkType =
- "motorway".equals(element.highway()) ? Transportation.RouteNetwork.GB_MOTORWAY :
- Transportation.RouteNetwork.GB_TRUNK;
- String network = "motorway".equals(element.highway()) ? "omt-gb-motorway" : "omt-gb-trunk";
- result.add(new RouteRelation(refMatcher.group(), network, networkType, (byte) -1,
- 0));
- }
- } catch (GeometryException e) {
- e.log(stats, "omt_transportation_name_gb_test",
- "Unable to test highway against GB route network: " + element.source().id());
- }
- }
- }
- }
- Collections.sort(result);
- return result;
- }
-
- RouteRelation getRouteRelation(Tables.OsmHighwayLinestring element) {
- List all = getRouteRelations(element);
- return all.isEmpty() ? null : all.get(0);
- }
-
- @Override
- public void process(Tables.OsmHighwayLinestring element, FeatureCollector features) {
- if (element.isArea()) {
- return;
- }
-
- RouteRelation routeRelation = getRouteRelation(element);
- RouteNetwork networkType = routeRelation != null ? routeRelation.networkType : null;
-
- String highway = element.highway();
- String highwayClass = highwayClass(element.highway(), element.publicTransport(), element.construction(),
- element.manMade());
- String service = service(element.service());
- if (highwayClass != null) {
- if (isPierPolygon(element)) {
- return;
- }
- int minzoom = getMinzoom(element, highwayClass);
-
- boolean highwayRamp = isLink(highway);
- Integer rampAboveZ12 = (highwayRamp || element.isRamp()) ? 1 : null;
- Integer rampBelowZ12 = highwayRamp ? 1 : null;
-
- FeatureCollector.Feature feature = features.line(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- // main attributes at all zoom levels (used for grouping <= z8)
- .setAttr(Fields.CLASS, highwayClass)
- .setAttr(Fields.SUBCLASS, highwaySubclass(highwayClass, element.publicTransport(), highway))
- .setAttr(Fields.BRUNNEL, brunnel(element.isBridge(), element.isTunnel(), element.isFord()))
- .setAttr(Fields.NETWORK, networkType != null ? networkType.name : null)
- // z8+
- .setAttrWithMinzoom(Fields.EXPRESSWAY, element.expressway() && !"motorway".equals(highway) ? 1 : null, 8)
- // z9+
- .setAttrWithMinzoom(Fields.LAYER, nullIfLong(element.layer(), 0), 9)
- .setAttrWithMinzoom(Fields.BICYCLE, nullIfEmpty(element.bicycle()), 9)
- .setAttrWithMinzoom(Fields.FOOT, nullIfEmpty(element.foot()), 9)
- .setAttrWithMinzoom(Fields.HORSE, nullIfEmpty(element.horse()), 9)
- .setAttrWithMinzoom(Fields.MTB_SCALE, nullIfEmpty(element.mtbScale()), 9)
- .setAttrWithMinzoom(Fields.ACCESS, access(element.access()), 9)
- .setAttrWithMinzoom(Fields.TOLL, element.toll() ? 1 : null, 9)
- // sometimes z9+, sometimes z12+
- .setAttr(Fields.RAMP, minzoom >= 12 ? rampAboveZ12 :
- ((ZoomFunction) z -> z < 9 ? null : z >= 12 ? rampAboveZ12 : rampBelowZ12))
- // z12+
- .setAttrWithMinzoom(Fields.SERVICE, service, 12)
- .setAttrWithMinzoom(Fields.ONEWAY, nullIfInt(element.isOneway(), 0), 12)
- .setAttrWithMinzoom(Fields.SURFACE, surface(element.surface()), 12)
- .setMinPixelSize(0) // merge during post-processing, then limit by size
- .setSortKey(element.zOrder())
- .setMinZoom(minzoom);
-
- if (isFootwayOrSteps(highway)) {
- feature
- .setAttr(Fields.LEVEL, Parse.parseLongOrNull(element.source().getTag("level")))
- .setAttr(Fields.INDOOR, element.indoor() ? 1 : null);
- }
- }
- }
-
- int getMinzoom(Tables.OsmHighwayLinestring element, String highwayClass) {
- List routeRelations = getRouteRelations(element);
- int routeRank = 3;
- for (var rel : routeRelations) {
- if (rel.intRank() < routeRank) {
- routeRank = rel.intRank();
- }
- }
- String highway = element.highway();
-
- int minzoom;
- if ("pier".equals(element.manMade())) {
- minzoom = 13;
- } else if (isResidentialOrUnclassified(highway)) {
- minzoom = 12;
- } else {
- String baseClass = highwayClass.replace("_construction", "");
- minzoom = switch (baseClass) {
- case FieldValues.CLASS_SERVICE -> isDrivewayOrParkingAisle(service(element.service())) ? 14 : 13;
- case FieldValues.CLASS_TRACK, FieldValues.CLASS_PATH -> routeRank == 1 ? 12 :
- (z13Paths || !nullOrEmpty(element.name()) || routeRank <= 2 || !nullOrEmpty(element.sacScale())) ? 13 : 14;
- default -> MINZOOMS.get(baseClass);
- };
- }
-
- if (isLink(highway)) {
- minzoom = Math.max(minzoom, 9);
- }
- return minzoom;
- }
-
- private boolean isPierPolygon(Tables.OsmHighwayLinestring element) {
- if ("pier".equals(element.manMade())) {
- try {
- if (element.source().worldGeometry()instanceof LineString lineString && lineString.isClosed()) {
- // ignore this because it's a polygon
- return true;
- }
- } catch (GeometryException e) {
- e.log(stats, "omt_transportation_pier",
- "Unable to decode pier geometry for " + element.source().id());
- return true;
- }
- }
- return false;
- }
-
- @Override
- public void process(Tables.OsmRailwayLinestring element, FeatureCollector features) {
- String railway = element.railway();
- String clazz = railwayClass(railway);
- if (clazz != null) {
- String service = nullIfEmpty(element.service());
- int minzoom;
- if (service != null) {
- minzoom = 14;
- } else if (FieldValues.SUBCLASS_RAIL.equals(railway)) {
- minzoom = "main".equals(element.usage()) ? 8 : 10;
- } else if (FieldValues.SUBCLASS_NARROW_GAUGE.equals(railway)) {
- minzoom = 10;
- } else if (FieldValues.SUBCLASS_LIGHT_RAIL.equals(railway)) {
- minzoom = 11;
- } else {
- minzoom = 14;
- }
- features.line(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .setAttr(Fields.CLASS, clazz)
- .setAttr(Fields.SUBCLASS, railway)
- .setAttr(Fields.SERVICE, service(service))
- .setAttr(Fields.ONEWAY, nullIfInt(element.isOneway(), 0))
- .setAttr(Fields.RAMP, element.isRamp() ? 1L : null)
- .setAttrWithMinzoom(Fields.BRUNNEL, brunnel(element.isBridge(), element.isTunnel(), element.isFord()), 10)
- .setAttrWithMinzoom(Fields.LAYER, nullIfLong(element.layer(), 0), 9)
- .setSortKey(element.zOrder())
- .setMinPixelSize(0) // merge during post-processing, then limit by size
- .setMinZoom(minzoom);
- }
- }
-
- @Override
- public void process(Tables.OsmAerialwayLinestring element, FeatureCollector features) {
- features.line(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .setAttr(Fields.CLASS, "aerialway")
- .setAttr(Fields.SUBCLASS, element.aerialway())
- .setAttr(Fields.SERVICE, service(element.service()))
- .setAttr(Fields.ONEWAY, nullIfInt(element.isOneway(), 0))
- .setAttr(Fields.RAMP, element.isRamp() ? 1L : null)
- .setAttr(Fields.BRUNNEL, brunnel(element.isBridge(), element.isTunnel(), element.isFord()))
- .setAttr(Fields.LAYER, nullIfLong(element.layer(), 0))
- .setSortKey(element.zOrder())
- .setMinPixelSize(0) // merge during post-processing, then limit by size
- .setMinZoom(12);
- }
-
- @Override
- public void process(Tables.OsmShipwayLinestring element, FeatureCollector features) {
- features.line(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .setAttr(Fields.CLASS, element.shipway()) // "ferry"
- // no subclass
- .setAttr(Fields.SERVICE, service(element.service()))
- .setAttr(Fields.ONEWAY, nullIfInt(element.isOneway(), 0))
- .setAttr(Fields.RAMP, element.isRamp() ? 1L : null)
- .setAttr(Fields.BRUNNEL, brunnel(element.isBridge(), element.isTunnel(), element.isFord()))
- .setAttr(Fields.LAYER, nullIfLong(element.layer(), 0))
- .setSortKey(element.zOrder())
- .setMinPixelSize(0) // merge during post-processing, then limit by size
- .setMinZoom(11);
- }
-
- @Override
- public void process(Tables.OsmHighwayPolygon element, FeatureCollector features) {
- String manMade = element.manMade();
- if (isBridgeOrPier(manMade) ||
- // only allow closed ways where area=yes, and multipolygons
- // and ignore underground pedestrian areas
- (!element.source().canBeLine() && element.layer() >= 0)) {
- String highwayClass = highwayClass(element.highway(), element.publicTransport(), null, element.manMade());
- if (highwayClass != null) {
- features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
- .setAttr(Fields.CLASS, highwayClass)
- .setAttr(Fields.SUBCLASS, highwaySubclass(highwayClass, element.publicTransport(), element.highway()))
- .setAttr(Fields.BRUNNEL, brunnel("bridge".equals(manMade), false, false))
- .setAttr(Fields.LAYER, nullIfLong(element.layer(), 0))
- .setSortKey(element.zOrder())
- .setMinZoom(13);
- }
- }
- }
-
- @Override
- public List postProcess(int zoom, List items) {
- double tolerance = config.tolerance(zoom);
- double minLength = coalesce(MIN_LENGTH.apply(zoom), 0).doubleValue();
- // TODO preserve direction for one-way?
- return FeatureMerge.mergeLineStrings(items, minLength, tolerance, BUFFER_SIZE);
- }
-
- /** Information extracted from route relations to use when processing ways in that relation. */
- record RouteRelation(
- String ref,
- String network,
- RouteNetwork networkType,
- byte rank,
- @Override long id
- ) implements OsmRelationInfo, Comparable {
-
- @Override
- public long estimateMemoryUsageBytes() {
- return CLASS_HEADER_BYTES +
- MemoryEstimator.estimateSize(rank) +
- POINTER_BYTES + estimateSize(ref) +
- POINTER_BYTES + estimateSize(network) +
- POINTER_BYTES + // networkType
- MemoryEstimator.estimateSizeLong(id);
- }
-
- public int intRank() {
- return rank;
- }
-
- @Override
- public int compareTo(RouteRelation o) {
- return RELATION_ORDERING.compare(this, o);
- }
- }
-}
diff --git a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/TransportationName.java b/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/TransportationName.java
deleted file mode 100644
index 8eaeb271e4..0000000000
--- a/planetiler-basemap/src/main/java/com/onthegomap/planetiler/basemap/layers/TransportationName.java
+++ /dev/null
@@ -1,398 +0,0 @@
-/*
-Copyright (c) 2021, MapTiler.com & OpenMapTiles contributors.
-All rights reserved.
-
-Code license: BSD 3-Clause License
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-* Neither the name of the copyright holder nor the names of its
- contributors may be used to endorse or promote products derived from
- this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-Design license: CC-BY 4.0
-
-See https://github.com/openmaptiles/openmaptiles/blob/master/LICENSE.md for details on usage
-*/
-package com.onthegomap.planetiler.basemap.layers;
-
-import static com.onthegomap.planetiler.basemap.layers.Transportation.highwayClass;
-import static com.onthegomap.planetiler.basemap.layers.Transportation.highwaySubclass;
-import static com.onthegomap.planetiler.basemap.layers.Transportation.isFootwayOrSteps;
-import static com.onthegomap.planetiler.basemap.util.Utils.*;
-
-import com.carrotsearch.hppc.LongArrayList;
-import com.carrotsearch.hppc.LongByteMap;
-import com.carrotsearch.hppc.LongHashSet;
-import com.carrotsearch.hppc.LongSet;
-import com.onthegomap.planetiler.FeatureCollector;
-import com.onthegomap.planetiler.FeatureMerge;
-import com.onthegomap.planetiler.ForwardingProfile;
-import com.onthegomap.planetiler.VectorTile;
-import com.onthegomap.planetiler.basemap.BasemapProfile;
-import com.onthegomap.planetiler.basemap.generated.OpenMapTilesSchema;
-import com.onthegomap.planetiler.basemap.generated.Tables;
-import com.onthegomap.planetiler.basemap.util.LanguageUtils;
-import com.onthegomap.planetiler.collection.Hppc;
-import com.onthegomap.planetiler.config.PlanetilerConfig;
-import com.onthegomap.planetiler.reader.osm.OsmElement;
-import com.onthegomap.planetiler.stats.Stats;
-import com.onthegomap.planetiler.util.Parse;
-import com.onthegomap.planetiler.util.Translations;
-import com.onthegomap.planetiler.util.ZoomFunction;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-
-/**
- * Defines the logic for generating map elements for road, shipway, rail, and path names in the {@code
- * transportation_name} layer from source features.
- *
- * This class is ported to Java from
- * OpenMapTiles
- * transportation_name sql files.
- */
-public class TransportationName implements
- OpenMapTilesSchema.TransportationName,
- Tables.OsmHighwayPoint.Handler,
- Tables.OsmHighwayLinestring.Handler,
- Tables.OsmAerialwayLinestring.Handler,
- Tables.OsmShipwayLinestring.Handler,
- BasemapProfile.FeaturePostProcessor,
- BasemapProfile.IgnoreWikidata,
- ForwardingProfile.OsmNodePreprocessor,
- ForwardingProfile.OsmWayPreprocessor {
-
- /*
- * Generate road names from OSM data. Route networkType and ref are copied
- * from relations that roads are a part of - except in Great Britain which
- * uses a naming convention instead of relations.
- *
- * The goal is to make name linestrings as long as possible to give clients
- * the best chance of showing road names at different zoom levels, so do not
- * limit linestrings by length at process time and merge them at tile
- * render-time.
- *
- * Any 3-way nodes and intersections break line merging so set the
- * transportation_name_limit_merge argument to true to add temporary
- * "is link" and "relation" keys to prevent opposite directions of a
- * divided highway or on/off ramps from getting merged for main highways.
- */
-
- // extra temp key used to group on/off-ramps separately from main highways
- private static final String LINK_TEMP_KEY = "__islink";
- private static final String RELATION_ID_TEMP_KEY = "__relid";
-
- private static final ZoomFunction.MeterToPixelThresholds MIN_LENGTH = ZoomFunction.meterThresholds()
- .put(6, 20_000)
- .put(7, 20_000)
- .put(8, 14_000)
- .put(9, 8_000)
- .put(10, 8_000)
- .put(11, 8_000);
- private static final List CONCURRENT_ROUTE_KEYS = List.of(
- Fields.ROUTE_1,
- Fields.ROUTE_2,
- Fields.ROUTE_3,
- Fields.ROUTE_4,
- Fields.ROUTE_5,
- Fields.ROUTE_6
- );
- private final boolean brunnel;
- private final boolean sizeForShield;
- private final boolean limitMerge;
- private final PlanetilerConfig config;
- private final boolean minorRefs;
- private Transportation transportation;
- private final LongByteMap motorwayJunctionHighwayClasses = Hppc.newLongByteHashMap();
- private final LongSet motorwayJunctionNodes = new LongHashSet();
-
- public TransportationName(Translations translations, PlanetilerConfig config, Stats stats) {
- this.config = config;
- this.brunnel = config.arguments().getBoolean(
- "transportation_name_brunnel",
- "transportation_name layer: set to false to omit brunnel and help merge long highways",
- false
- );
- this.sizeForShield = config.arguments().getBoolean(
- "transportation_name_size_for_shield",
- "transportation_name layer: allow road names on shorter segments (ie. they will have a shield)",
- false
- );
- this.limitMerge = config.arguments().getBoolean(
- "transportation_name_limit_merge",
- "transportation_name layer: limit merge so we don't combine different relations to help merge long highways",
- false
- );
- this.minorRefs = config.arguments().getBoolean(
- "transportation_name_minor_refs",
- "transportation_name layer: include name and refs from minor road networks if not present on a way",
- false
- );
- }
-
- public void needsTransportationLayer(Transportation transportation) {
- this.transportation = transportation;
- }
-
-
- @Override
- public void preprocessOsmNode(OsmElement.Node node) {
- if (node.hasTag("highway", "motorway_junction")) {
- synchronized (motorwayJunctionNodes) {
- motorwayJunctionNodes.add(node.id());
- }
- }
- }
-
- @Override
- public void preprocessOsmWay(OsmElement.Way way) {
- String highway = way.getString("highway");
- if (highway != null) {
- HighwayClass cls = HighwayClass.from(highway);
- if (cls != HighwayClass.UNKNOWN) {
- LongArrayList nodes = way.nodes();
- for (int i = 0; i < nodes.size(); i++) {
- long node = nodes.get(i);
- if (motorwayJunctionNodes.contains(node)) {
- synchronized (motorwayJunctionHighwayClasses) {
- byte oldValue = motorwayJunctionHighwayClasses.getOrDefault(node, HighwayClass.UNKNOWN.value);
- byte newValue = cls.value;
- if (newValue > oldValue) {
- motorwayJunctionHighwayClasses.put(node, newValue);
- }
- }
- }
- }
- }
- }
- }
-
- @Override
- public void process(Tables.OsmHighwayPoint element, FeatureCollector features) {
- long id = element.source().id();
- byte value = motorwayJunctionHighwayClasses.getOrDefault(id, (byte) -1);
- if (value > 0) {
- HighwayClass cls = HighwayClass.from(value);
- if (cls != HighwayClass.UNKNOWN) {
- String subclass = FieldValues.SUBCLASS_JUNCTION;
- String ref = element.ref();
-
- features.point(LAYER_NAME)
- .setBufferPixels(BUFFER_SIZE)
- .putAttrs(LanguageUtils.getNamesWithoutTranslations(element.source().tags()))
- .setAttr(Fields.REF, ref)
- .setAttr(Fields.REF_LENGTH, ref != null ? ref.length() : null)
- .setAttr(Fields.CLASS, highwayClass(cls.highwayValue, null, null, null))
- .setAttr(Fields.SUBCLASS, subclass)
- .setAttr(Fields.LAYER, nullIfLong(element.layer(), 0))
- .setSortKeyDescending(element.zOrder())
- .setMinZoom(10);
- }
- }
- }
-
- @Override
- public void process(Tables.OsmHighwayLinestring element, FeatureCollector features) {
- String ref = element.ref();
- List relations = transportation.getRouteRelations(element);
- Transportation.RouteRelation firstRelationWithNetwork = relations.stream()
- .filter(rel -> rel.networkType() != null)
- .findFirst()
- .orElse(null);
-
- if (firstRelationWithNetwork != null && !nullOrEmpty(firstRelationWithNetwork.ref())) {
- ref = firstRelationWithNetwork.ref();
- }
-
- // if transportation_name_minor_refs flag set and we don't have a ref yet, then pull it from any network
- if (nullOrEmpty(ref) && minorRefs && !relations.isEmpty()) {
- ref = relations.stream()
- .map(r -> r.ref())
- .filter(r -> !nullOrEmpty(r))
- .findFirst()
- .orElse(null);
- }
-
- String name = nullIfEmpty(element.name());
- ref = nullIfEmpty(ref);
- String highway = nullIfEmpty(element.highway());
-
- String highwayClass = highwayClass(element.highway(), null, element.construction(), element.manMade());
- if (element.isArea() || highway == null || highwayClass == null || (name == null && ref == null)) {
- return;
- }
-
- boolean isLink = Transportation.isLink(highway);
- String baseClass = highwayClass.replace("_construction", "");
-
- int minzoom = FieldValues.CLASS_TRUNK.equals(baseClass) ? 8 :
- FieldValues.CLASS_MOTORWAY.equals(baseClass) ? 6 :
- isLink ? 13 : 12; // fallback - get from line minzoom, but floor at 12
-
- // inherit min zoom threshold from visible road, and ensure we never show a label on a road that's not visible yet.
- minzoom = Math.max(minzoom, transportation.getMinzoom(element, highwayClass));
-
- FeatureCollector.Feature feature = features.line(LAYER_NAME)
- .setBufferPixels(BUFFER_SIZE)
- .setBufferPixelOverrides(MIN_LENGTH)
- // TODO abbreviate road names - can't port osml10n because it is AGPL
- .putAttrs(LanguageUtils.getNamesWithoutTranslations(element.source().tags()))
- .setAttr(Fields.REF, ref)
- .setAttr(Fields.REF_LENGTH, ref != null ? ref.length() : null)
- .setAttr(Fields.NETWORK,
- firstRelationWithNetwork != null ? firstRelationWithNetwork.networkType().name : !nullOrEmpty(ref) ? "road" :
- null)
- .setAttr(Fields.CLASS, highwayClass)
- .setAttr(Fields.SUBCLASS, highwaySubclass(highwayClass, null, highway))
- .setMinPixelSize(0)
- .setSortKey(element.zOrder())
- .setMinZoom(minzoom);
-
- // populate route_1, route_2, ... tags
- for (int i = 0; i < Math.min(CONCURRENT_ROUTE_KEYS.size(), relations.size()); i++) {
- Transportation.RouteRelation routeRelation = relations.get(i);
- feature.setAttr(CONCURRENT_ROUTE_KEYS.get(i), routeRelation.network() == null ? null :
- routeRelation.network() + "=" + coalesce(routeRelation.ref(), ""));
- }
-
- if (brunnel) {
- feature.setAttr(Fields.BRUNNEL, brunnel(element.isBridge(), element.isTunnel(), element.isFord()));
- }
-
- /*
- * to help group roads into longer segments, add temporary tags to limit which segments get grouped together. Since
- * a divided highway typically has a separate relation for each direction, this ends up keeping segments going
- * opposite directions group getting grouped together and confusing the line merging process
- */
- if (limitMerge) {
- feature
- .setAttr(LINK_TEMP_KEY, isLink ? 1 : 0)
- .setAttr(RELATION_ID_TEMP_KEY, firstRelationWithNetwork == null ? null : firstRelationWithNetwork.id());
- }
-
- if (isFootwayOrSteps(highway)) {
- feature
- .setAttrWithMinzoom(Fields.LAYER, nullIfLong(element.layer(), 0), 12)
- .setAttrWithMinzoom(Fields.LEVEL, Parse.parseLongOrNull(element.source().getTag("level")), 12)
- .setAttrWithMinzoom(Fields.INDOOR, element.indoor() ? 1 : null, 12);
- }
- }
-
- @Override
- public void process(Tables.OsmAerialwayLinestring element, FeatureCollector features) {
- if (!nullOrEmpty(element.name())) {
- features.line(LAYER_NAME)
- .setBufferPixels(BUFFER_SIZE)
- .setBufferPixelOverrides(MIN_LENGTH)
- .putAttrs(LanguageUtils.getNamesWithoutTranslations(element.source().tags()))
- .setAttr(Fields.CLASS, "aerialway")
- .setAttr(Fields.SUBCLASS, element.aerialway())
- .setMinPixelSize(0)
- .setSortKey(element.zOrder())
- .setMinZoom(12);
- }
- }
-
- @Override
- public void process(Tables.OsmShipwayLinestring element, FeatureCollector features) {
- if (!nullOrEmpty(element.name())) {
- features.line(LAYER_NAME)
- .setBufferPixels(BUFFER_SIZE)
- .setBufferPixelOverrides(MIN_LENGTH)
- .putAttrs(LanguageUtils.getNamesWithoutTranslations(element.source().tags()))
- .setAttr(Fields.CLASS, element.shipway())
- .setMinPixelSize(0)
- .setSortKey(element.zOrder())
- .setMinZoom(12);
- }
- }
-
- @Override
- public List postProcess(int zoom, List items) {
- double tolerance = config.tolerance(zoom);
- double minLength = coalesce(MIN_LENGTH.apply(zoom), 0).doubleValue();
- // TODO tolerances:
- // z6: (tolerance: 500)
- // z7: (tolerance: 200)
- // z8: (tolerance: 120)
- // z9-11: (tolerance: 50)
- Function