Skip to content

Commit

Permalink
add country-coder json [#44]
Browse files Browse the repository at this point in the history
  • Loading branch information
bdon committed Oct 24, 2024
1 parent 1de7755 commit ef6f29c
Show file tree
Hide file tree
Showing 6 changed files with 511 additions and 6 deletions.
14 changes: 9 additions & 5 deletions tiles/src/main/java/com/protomaps/basemap/Basemap.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.onthegomap.planetiler.Planetiler;
import com.onthegomap.planetiler.config.Arguments;
import com.onthegomap.planetiler.util.Downloader;
import com.protomaps.basemap.feature.CountryCoder;
import com.protomaps.basemap.feature.NaturalEarthDb;
import com.protomaps.basemap.feature.QrankDb;
import com.protomaps.basemap.layers.Boundaries;
Expand All @@ -17,6 +18,7 @@
import com.protomaps.basemap.layers.Transit;
import com.protomaps.basemap.layers.Water;
import com.protomaps.basemap.text.FontRegistry;
import java.io.IOException;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
Expand All @@ -25,7 +27,7 @@

public class Basemap extends ForwardingProfile {

public Basemap(NaturalEarthDb naturalEarthDb, QrankDb qrankDb) {
public Basemap(NaturalEarthDb naturalEarthDb, QrankDb qrankDb, CountryCoder countryCoder) {

var admin = new Boundaries();
registerHandler(admin);
Expand All @@ -52,7 +54,7 @@ public Basemap(NaturalEarthDb naturalEarthDb, QrankDb qrankDb) {
registerHandler(poi);
registerSourceHandler("osm", poi::processOsm);

var roads = new Roads();
var roads = new Roads(countryCoder);
registerHandler(roads);
registerSourceHandler("osm", roads::processOsm);

Expand Down Expand Up @@ -116,11 +118,11 @@ public Map<String, String> extraArchiveMetadata() {
return result;
}

public static void main(String[] args) {
public static void main(String[] args) throws IOException {
run(Arguments.fromArgsOrConfigFile(args));
}

static void run(Arguments args) {
static void run(Arguments args) throws IOException {
args = args.orElse(Arguments.of("maxzoom", 15));

Path dataDir = Path.of("data");
Expand All @@ -129,6 +131,8 @@ static void run(Arguments args) {
Path nePath = sourcesDir.resolve("natural_earth_vector.sqlite.zip");
String neUrl = "https://naciscdn.org/naturalearth/packages/natural_earth_vector.sqlite.zip";

var countryCoder = CountryCoder.fromJarResource();

String area = args.getString("area", "geofabrik area to download", "monaco");

var planetiler = Planetiler.create(args)
Expand Down Expand Up @@ -157,7 +161,7 @@ static void run(Arguments args) {

fontRegistry.loadFontBundle("NotoSansDevanagari-Regular", "1", "Devanagari");

planetiler.setProfile(new Basemap(naturalEarthDb, qrankDb)).setOutput(Path.of(area + ".pmtiles"))
planetiler.setProfile(new Basemap(naturalEarthDb, qrankDb, countryCoder)).setOutput(Path.of(area + ".pmtiles"))
.run();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.protomaps.basemap.feature;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.onthegomap.planetiler.geo.GeoUtils;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.locationtech.jts.geom.*;
import org.locationtech.jts.index.strtree.STRtree;

public class CountryCoder {

public record Record(String country, String nameEn, MultiPolygon multiPolygon) {}

private STRtree tree;

public CountryCoder(STRtree tree) {
this.tree = tree;
}

public static CountryCoder fromJarResource() throws IOException {
InputStream inputStream = CountryCoder.class.getResourceAsStream("/borders.json");

String jsonContent = new String(inputStream.readAllBytes());
return fromJsonString(jsonContent);
}

public static CountryCoder fromJsonString(String s) throws IOException {
STRtree tree = new STRtree();

ObjectMapper mapper = new ObjectMapper();
JsonNode featureCollection = mapper.readTree(s);
ArrayNode features = (ArrayNode) featureCollection.get("features");
for (var feature : features) {
JsonNode properties = feature.get("properties");

List<Polygon> polygons = new ArrayList<>();

for (var polygon : feature.get("geometry").get("coordinates")) {
ArrayNode outerRingNode = (ArrayNode) polygon.get(0);
Coordinate[] outerRingCoordinates = parseCoordinates(outerRingNode);
LinearRing outerRing = GeoUtils.JTS_FACTORY.createLinearRing(outerRingCoordinates);

LinearRing[] innerRings = new LinearRing[polygon.size() - 1];
for (int j = 1; j < polygon.size(); j++) {
ArrayNode innerRingNode = (ArrayNode) polygon.get(j);
Coordinate[] innerRingCoordinates = parseCoordinates(innerRingNode);
innerRings[j - 1] = GeoUtils.JTS_FACTORY.createLinearRing(innerRingCoordinates);
}
polygons.add(GeoUtils.JTS_FACTORY.createPolygon(outerRing, innerRings));
}

MultiPolygon multiPolygon = GeoUtils.createMultiPolygon(polygons);
multiPolygon.getEnvelopeInternal();
tree.insert(multiPolygon.getEnvelopeInternal(),
new Record(properties.get("country").asText(), properties.get("nameEn").asText(), multiPolygon));
}
return new CountryCoder(tree);
}

private static Coordinate[] parseCoordinates(ArrayNode coordinateArray) {
Coordinate[] coordinates = new Coordinate[coordinateArray.size()];
for (int i = 0; i < coordinateArray.size(); i++) {
ArrayNode coordinate = (ArrayNode) coordinateArray.get(i);
double x = coordinate.get(0).asDouble();
double y = coordinate.get(1).asDouble();
coordinates[i] = new Coordinate(x, y);
}
return coordinates;
}

public Optional<String> getCountryCode(Point point) {
List<Record> results = tree.query(point.getEnvelopeInternal());
if (results.isEmpty())
return Optional.empty();
return Optional.of(results.getFirst().country);
}
}
7 changes: 7 additions & 0 deletions tiles/src/main/java/com/protomaps/basemap/layers/Roads.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.onthegomap.planetiler.VectorTile;
import com.onthegomap.planetiler.geo.GeometryException;
import com.onthegomap.planetiler.reader.SourceFeature;
import com.protomaps.basemap.feature.CountryCoder;
import com.protomaps.basemap.feature.FeatureId;
import com.protomaps.basemap.locales.CartographicLocale;
import com.protomaps.basemap.locales.US;
Expand All @@ -16,6 +17,12 @@

public class Roads implements ForwardingProfile.LayerPostProcesser {

private CountryCoder countryCoder;

public Roads(CountryCoder countryCoder) {
this.countryCoder = countryCoder;
}

@Override
public String name() {
return "roads";
Expand Down
Loading

0 comments on commit ef6f29c

Please sign in to comment.