Skip to content

Commit

Permalink
Make projection configurable for yaml sources (#1066)
Browse files Browse the repository at this point in the history
  • Loading branch information
msbarry authored Oct 13, 2024
1 parent c757f1e commit f259a9f
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 9 deletions.
4 changes: 4 additions & 0 deletions planetiler-custommap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ A description that tells planetiler how to read geospatial objects with tags fro
For [geofabrik](https://download.geofabrik.de/) named areas, use `geofabrik:` prefixes, for
example `geofabrik:rhode-island`. Can be a string or [expression](#expression) that can
reference [argument values](#arguments).
- `projection` - Planetiler will try to determine the projection automatically for shapefile/geopackage sources, but if
that is not correct you can override the projection by specifying a coordinate reference system authority code
like `EPSG:3857` or `EPSG:4326` here. Can be a string or [expression](#expression) that can
reference [argument values](#arguments).

For example:

Expand Down
14 changes: 14 additions & 0 deletions planetiler-custommap/planetiler.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,20 @@
"local_path": {
"description": "Local path to the file to use, inferred from `url` if missing",
"$ref": "#/$defs/expression"
},
"projection": {
"description": "Override the coordinate reference system authority code for a shapefile or geopackage source if it can not be determined automatically",
"anyOf": [
{
"enum": [
"EPSG:3857",
"EPSG:4326"
]
},
{
"type": "#/$defs/expression"
}
]
}
},
"anyOf": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ private static void configureSource(Planetiler planetiler, Path sourcesDir, Sour

DataSourceType sourceType = source.type();
Path localPath = source.localPath();
String projection = source.projection();
if (localPath == null) {
if (source.url() == null) {
throw new ParseException("Must provide either a url or path for " + source.id());
Expand All @@ -71,8 +72,8 @@ private static void configureSource(Planetiler planetiler, Path sourcesDir, Sour

switch (sourceType) {
case OSM -> planetiler.addOsmSource(source.id(), localPath, source.url());
case SHAPEFILE -> planetiler.addShapefileSource(source.id(), localPath, source.url());
case GEOPACKAGE -> planetiler.addGeoPackageSource(source.id(), localPath, source.url());
case SHAPEFILE -> planetiler.addShapefileSource(projection, source.id(), localPath, source.url());
case GEOPACKAGE -> planetiler.addGeoPackageSource(projection, source.id(), localPath, source.url());
default -> throw new IllegalArgumentException("Unhandled source type for " + source.id() + ": " + sourceType);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,18 @@ public String description() {
public List<Source> sources() {
List<Source> sources = new ArrayList<>();
schema.sources().forEach((key, value) -> {
var url = ConfigExpressionParser.tryStaticEvaluate(rootContext, value.url(), String.class).get();
var path = ConfigExpressionParser.tryStaticEvaluate(rootContext, value.localPath(), String.class).get();
sources.add(new Source(key, value.type(), url, path == null ? null : Path.of(path)));
var url = evaluate(value.url(), String.class);
var path = evaluate(value.localPath(), String.class);
var projection = evaluate(value.projection(), String.class);
sources.add(new Source(key, value.type(), url, path == null ? null : Path.of(path), projection));
});
return sources;
}

private <T> T evaluate(Object expression, Class<T> returnType) {
return ConfigExpressionParser.tryStaticEvaluate(rootContext, expression, returnType).get();
}

public FeatureLayer findFeatureLayer(String layerId) {
return layersById.get(layerId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ public record Source(
String id,
DataSourceType type,
String url,
Path localPath
Path localPath,
String projection
) {

public String defaultFileUrl() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
public record DataSource(
DataSourceType type,
Object url,
@JsonProperty("local_path") Object localPath
@JsonProperty("local_path") Object localPath,
Object projection
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ sources:
water_polygons:
type: shapefile
url: https://osmdata.openstreetmap.de/download/water-polygons-split-3857.zip
projection: EPSG:3857
osm:
type: osm
url: geofabrik:monaco
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,7 @@ void testUseArgumentInSourceUrlPath() {
"osm",
DataSourceType.OSM,
"geofabrik:boston",
null,
null
)), loadConfig(config).sources());

Expand All @@ -1125,6 +1126,7 @@ void testUseArgumentInSourceUrlPath() {
"osm",
DataSourceType.OSM,
"geofabrik:rhode-island",
null,
null
)), loadConfig(config).sources());

Expand All @@ -1137,6 +1139,35 @@ void testUseArgumentInSourceUrlPath() {
assertEquals("example.com_file.osm.pbf", loadConfig(config).sources().get(0).defaultFileUrl());
}

@ParameterizedTest
@CsvSource({
"EPSG:3875, EPSG:3875",
"${'EPSG:' + '3875'}, EPSG:3875",
})
void testSetProjection(String in, String out) {
var config = """
sources:
osm:
type: osm
url: geofabrik:rhode-island
projection: %s
layers:
- id: testLayer
features:
- source: osm
geometry: point
""".formatted(in);

this.planetilerConfig = PlanetilerConfig.from(Arguments.of(Map.of()));
assertEquals(List.of(new Source(
"osm",
DataSourceType.OSM,
"geofabrik:rhode-island",
null,
out
)), loadConfig(config).sources());
}

@ParameterizedTest
@CsvSource("""
10,10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,11 @@ void ensureValidGeometries() throws Exception {
}
}

// @Test --TODO FIX after adding water layer
@Test
void testContainsOceanPolyons() {
assertMinFeatures("water", Map.of(
"natural", "water"
), 0, 1, Polygon.class);
), 6, 1, Polygon.class);
}

@Test
Expand Down

0 comments on commit f259a9f

Please sign in to comment.