mirror of
https://github.com/cfpwastaken/planetiler-openmaptiles.git
synced 2026-02-04 20:41:09 +00:00
Make planetiler-openmaptiles runnable as a standalone project (#19)
This commit is contained in:
123
src/main/java/org/openmaptiles/util/OmtLanguageUtils.java
Normal file
123
src/main/java/org/openmaptiles/util/OmtLanguageUtils.java
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
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 org.openmaptiles.util;
|
||||
|
||||
import static com.onthegomap.planetiler.util.LanguageUtils.*;
|
||||
import static org.openmaptiles.util.Utils.coalesce;
|
||||
|
||||
import com.onthegomap.planetiler.util.LanguageUtils;
|
||||
import com.onthegomap.planetiler.util.Translations;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Utilities to extract common name fields (name, name_en, name_de, name:latin, name:nonlatin, name_int) that the
|
||||
* OpenMapTiles schema uses across any map element with a name.
|
||||
* <p>
|
||||
* Ported from
|
||||
* <a href="https://github.com/openmaptiles/openmaptiles-tools/blob/master/sql/zzz_language.sql">openmaptiles-tools</a>.
|
||||
*/
|
||||
public class OmtLanguageUtils {
|
||||
/**
|
||||
* Returns a map with default name attributes (name, name_en, name_de, name:latin, name:nonlatin, name_int) that every
|
||||
* element should have, derived from name, int_name, name:en, and name:de tags on the input element.
|
||||
*
|
||||
* <ul>
|
||||
* <li>name is the original name value from the element</li>
|
||||
* <li>name_en is the original name:en value from the element, or name if missing</li>
|
||||
* <li>name_de is the original name:de value from the element, or name/ name_en if missing</li>
|
||||
* <li>name:latin is the first of name, int_name, or any name: attribute that contains only latin characters</li>
|
||||
* <li>name:nonlatin is any nonlatin part of name if present</li>
|
||||
* <li>name_int is the first of int_name name:en name:latin name</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static Map<String, Object> getNamesWithoutTranslations(Map<String, Object> tags) {
|
||||
return getNames(tags, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map with default name attributes that {@link #getNamesWithoutTranslations(Map)} adds, but also
|
||||
* translations for every language that {@code translations} is configured to handle.
|
||||
*/
|
||||
public static Map<String, Object> getNames(Map<String, Object> tags, Translations translations) {
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
|
||||
String name = string(tags.get("name"));
|
||||
String intName = string(tags.get("int_name"));
|
||||
String nameEn = string(tags.get("name:en"));
|
||||
String nameDe = string(tags.get("name:de"));
|
||||
|
||||
boolean isLatin = containsOnlyLatinCharacters(name);
|
||||
String latin = isLatin ? name :
|
||||
Stream
|
||||
.concat(Stream.of(nameEn, intName, nameDe), getAllNameTranslationsBesidesEnglishAndGerman(tags))
|
||||
.filter(LanguageUtils::containsOnlyLatinCharacters)
|
||||
.findFirst().orElse(null);
|
||||
if (latin == null && translations != null && translations.getShouldTransliterate()) {
|
||||
latin = transliteratedName(tags);
|
||||
}
|
||||
String nonLatin = isLatin ? null : removeLatinCharacters(name);
|
||||
if (coalesce(nonLatin, "").equals(latin)) {
|
||||
nonLatin = null;
|
||||
}
|
||||
|
||||
putIfNotEmpty(result, "name", name);
|
||||
putIfNotEmpty(result, "name_en", coalesce(nameEn, name));
|
||||
putIfNotEmpty(result, "name_de", coalesce(nameDe, name, nameEn));
|
||||
putIfNotEmpty(result, "name:latin", latin);
|
||||
putIfNotEmpty(result, "name:nonlatin", nonLatin);
|
||||
putIfNotEmpty(result, "name_int", coalesce(
|
||||
intName,
|
||||
nameEn,
|
||||
latin,
|
||||
name
|
||||
));
|
||||
|
||||
if (translations != null) {
|
||||
translations.addTranslations(result, tags);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Stream<String> getAllNameTranslationsBesidesEnglishAndGerman(Map<String, Object> tags) {
|
||||
return tags.entrySet().stream()
|
||||
.filter(e -> !EN_DE_NAME_KEYS.contains(e.getKey()) && VALID_NAME_TAGS.test(e.getKey()))
|
||||
.map(Map.Entry::getValue)
|
||||
.map(LanguageUtils::string);
|
||||
}
|
||||
}
|
||||
78
src/main/java/org/openmaptiles/util/Utils.java
Normal file
78
src/main/java/org/openmaptiles/util/Utils.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package org.openmaptiles.util;
|
||||
|
||||
import com.onthegomap.planetiler.util.Parse;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Common utilities for working with data and the OpenMapTiles schema in {@code layers} implementations.
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
public static <T> T coalesce(T a, T b) {
|
||||
return a != null ? a : b;
|
||||
}
|
||||
|
||||
public static <T> T coalesce(T a, T b, T c) {
|
||||
return a != null ? a : b != null ? b : c;
|
||||
}
|
||||
|
||||
public static <T> T coalesce(T a, T b, T c, T d) {
|
||||
return a != null ? a : b != null ? b : c != null ? c : d;
|
||||
}
|
||||
|
||||
public static <T> T coalesce(T a, T b, T c, T d, T e) {
|
||||
return a != null ? a : b != null ? b : c != null ? c : d != null ? d : e;
|
||||
}
|
||||
|
||||
public static <T> T coalesce(T a, T b, T c, T d, T e, T f) {
|
||||
return a != null ? a : b != null ? b : c != null ? c : d != null ? d : e != null ? e : f;
|
||||
}
|
||||
|
||||
/** Boxes {@code a} into an {@link Integer}, or {@code null} if {@code a} is {@code nullValue}. */
|
||||
public static Long nullIfLong(long a, long nullValue) {
|
||||
return a == nullValue ? null : a;
|
||||
}
|
||||
|
||||
/** Boxes {@code a} into a {@link Long}, or {@code null} if {@code a} is {@code nullValue}. */
|
||||
public static Integer nullIfInt(int a, int nullValue) {
|
||||
return a == nullValue ? null : a;
|
||||
}
|
||||
|
||||
/** Returns {@code a}, or null if {@code a} is "". */
|
||||
public static String nullIfEmpty(String a) {
|
||||
return (a == null || a.isEmpty()) ? null : a;
|
||||
}
|
||||
|
||||
/** Returns true if {@code a} is null, or its {@link Object#toString()} value is "". */
|
||||
public static boolean nullOrEmpty(Object a) {
|
||||
return a == null || a.toString().isEmpty();
|
||||
}
|
||||
|
||||
/** Returns a map with {@code ele} (meters) and {ele_ft} attributes from an elevation in meters. */
|
||||
public static Map<String, Object> elevationTags(double meters) {
|
||||
return Map.of(
|
||||
"ele", (int) Math.round(meters),
|
||||
"ele_ft", (int) Math.round(meters * 3.2808399)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map with {@code ele} (meters) and {ele_ft} attributes from an elevation string in meters, if {@code
|
||||
* meters} can be parsed as a valid number.
|
||||
*/
|
||||
public static Map<String, Object> elevationTags(String meters) {
|
||||
Double ele = Parse.meters(meters);
|
||||
return ele == null ? Map.of() : elevationTags(ele);
|
||||
}
|
||||
|
||||
/** Returns "bridge" or "tunnel" string used for "brunnel" attribute by OpenMapTiles schema. */
|
||||
public static String brunnel(boolean isBridge, boolean isTunnel) {
|
||||
return brunnel(isBridge, isTunnel, false);
|
||||
}
|
||||
|
||||
/** Returns "bridge" or "tunnel" or "ford" string used for "brunnel" attribute by OpenMapTiles schema. */
|
||||
public static String brunnel(boolean isBridge, boolean isTunnel, boolean isFord) {
|
||||
return isBridge ? "bridge" : isTunnel ? "tunnel" : isFord ? "ford" : null;
|
||||
}
|
||||
|
||||
}
|
||||
44
src/main/java/org/openmaptiles/util/VerifyMonaco.java
Normal file
44
src/main/java/org/openmaptiles/util/VerifyMonaco.java
Normal file
@@ -0,0 +1,44 @@
|
||||
package org.openmaptiles.util;
|
||||
|
||||
import com.onthegomap.planetiler.mbtiles.Mbtiles;
|
||||
import com.onthegomap.planetiler.mbtiles.Verify;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import org.locationtech.jts.geom.Envelope;
|
||||
import org.locationtech.jts.geom.LineString;
|
||||
import org.locationtech.jts.geom.Point;
|
||||
import org.locationtech.jts.geom.Polygon;
|
||||
|
||||
/**
|
||||
* A utility to check the contents of an mbtiles file generated for Monaco.
|
||||
*/
|
||||
public class VerifyMonaco {
|
||||
|
||||
public static final Envelope MONACO_BOUNDS = new Envelope(7.40921, 7.44864, 43.72335, 43.75169);
|
||||
|
||||
/**
|
||||
* Returns a verification result with a basic set of checks against an openmaptiles map built from an extract for
|
||||
* Monaco.
|
||||
*/
|
||||
public static Verify verify(Mbtiles mbtiles) {
|
||||
Verify verify = Verify.verify(mbtiles);
|
||||
verify.checkMinFeatureCount(MONACO_BOUNDS, "building", Map.of(), 13, 14, 100, Polygon.class);
|
||||
verify.checkMinFeatureCount(MONACO_BOUNDS, "transportation", Map.of(), 10, 14, 5, LineString.class);
|
||||
verify.checkMinFeatureCount(MONACO_BOUNDS, "landcover", Map.of(
|
||||
"class", "grass",
|
||||
"subclass", "park"
|
||||
), 14, 10, Polygon.class);
|
||||
verify.checkMinFeatureCount(MONACO_BOUNDS, "water", Map.of("class", "ocean"), 0, 14, 1, Polygon.class);
|
||||
verify.checkMinFeatureCount(MONACO_BOUNDS, "place", Map.of("class", "country"), 2, 14, 1, Point.class);
|
||||
return verify;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
try (var mbtiles = Mbtiles.newReadOnlyDatabase(Path.of(args[0]))) {
|
||||
var result = verify(mbtiles);
|
||||
result.print();
|
||||
result.failIfErrors();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user