Skip to content

Commit

Permalink
Merge pull request #36 from phanecak-maptiler/omt3_15-zlw-indigenous-…
Browse files Browse the repository at this point in the history
…boundary

Move aboriginal lands boundaries to boundary layer
  • Loading branch information
phanecak-maptiler committed Jan 29, 2024
2 parents 0282d93 + 2cf1f7f commit f4a55b3
Show file tree
Hide file tree
Showing 8 changed files with 158 additions and 54 deletions.
30 changes: 19 additions & 11 deletions src/main/java/org/openmaptiles/generated/OpenMapTilesSchema.java
Original file line number Diff line number Diff line change
Expand Up @@ -619,10 +619,6 @@ final class FieldMappings {
* <a href=
* "https://wiki.openstreetmap.org/wiki/Tag:boundary%3Dprotected_area"><code>boundary=protected_area</code></a>, or
* <a href="https://wiki.openstreetmap.org/wiki/Tag:leisure%3Dnature_reserve"><code>leisure=nature_reserve</code></a>.
* This layer also includes boundaries for indigenous lands tagged with <a href=
* "https://wiki.openstreetmap.org/wiki/Tag:boundary%3Daboriginal_lands"><code>boundary=aboriginal_lands</code></a>.
* Indigenous boundaries are not parks, but they are included in this layer for technical reasons related to data
* processing. These boundaries represent areas with special legal and administrative status for indigenous peoples.
*
* Generated from
* <a href="https://github.com/openmaptiles/openmaptiles/blob/master/layers/park/park.yaml">park.yaml</a>
Expand All @@ -640,15 +636,14 @@ default String name() {
final class Fields {
/**
* Use the <strong>class</strong> to differentiate between different kinds of features in the <code>parks</code>
* layer, for example between parks and non-parks. The class for <code>boundary=protected_area</code> parks is the
* lower-case of the
* layer. The class for <code>boundary=protected_area</code> parks is the lower-case of the
* <a href="http://wiki.openstreetmap.org/wiki/key:protection_title"><code>protection_title</code></a> value with
* blanks replaced by <code>_</code>. <code>national_park</code> is the class of
* <code>protection_title=National Park</code> and <code>boundary=national_park</code>.
* <code>nature_reserve</code> is the class of <code>protection_title=Nature Reserve</code> and
* <code>leisure=nature_reserve</code>. The class for other
* <a href="http://wiki.openstreetmap.org/wiki/key:protection_title"><code>protection_title</code></a> values is
* similarly assigned. The class for <code>boundary=aboriginal_lands</code> is <code>aboriginal_lands</code>.
* similarly assigned.
*/
public static final String CLASS = "class";
/**
Expand Down Expand Up @@ -679,7 +674,7 @@ final class FieldMappings {
}
}
/**
* Contains administrative boundaries as linestrings. Until z4
* Contains administrative boundaries as linestrings and aboriginal lands as polygons. Until z4
* <a href="http://www.naturalearthdata.com/downloads/">Natural Earth data</a> is used after which OSM boundaries
* (<a href=
* "http://wiki.openstreetmap.org/wiki/Tag:boundary%3Dadministrative"><code>boundary=administrative</code></a>) are
Expand All @@ -702,6 +697,15 @@ default String name() {

/** Attribute names for map elements in the boundary layer. */
final class Fields {
/**
* Use the <strong>class</strong> to differentiate between different kinds of boundaries. The class for
* <code>boundary=aboriginal_lands</code> is <code>aboriginal_lands</code>.
*/
public static final String CLASS = "class";
/**
* The OSM <a href="http://wiki.openstreetmap.org/wiki/Key:name"><code>name</code></a> value (area features only).
*/
public static final String NAME = "name";
/**
* OSM <a href="http://wiki.openstreetmap.org/wiki/Tag:boundary%3Dadministrative#admin_level">admin_level</a>
* indicating the level of importance of this boundary. The <code>admin_level</code> corresponds to the lowest
Expand Down Expand Up @@ -1599,7 +1603,8 @@ final class Fields {
* Original value of the <a href="http://wiki.openstreetmap.org/wiki/Key:place"><code>place</code></a> tag.
* Distinguish between continents, countries, states, islands and places like settlements or smaller entities. Use
* <strong>class</strong> to separately style the different places and build a text hierarchy according to their
* importance.
* importance. For places derived from boundaries, the original value of the
* <a href="http://wiki.openstreetmap.org/wiki/Key:boundary"><code>boundary</code></a> tag.
* <p>
* allowed values:
* <ul>
Expand All @@ -1617,6 +1622,7 @@ final class Fields {
* <li>"neighbourhood"
* <li>"isolated_dwelling"
* <li>"island"
* <li>"aboriginal_lands"
* </ul>
*/
public static final String CLASS = "class";
Expand Down Expand Up @@ -1655,8 +1661,10 @@ final class FieldValues {
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<String> CLASS_VALUES = Set.of("continent", "country", "state", "province", "city", "town",
"village", "hamlet", "borough", "suburb", "quarter", "neighbourhood", "isolated_dwelling", "island");
public static final String CLASS_ABORIGINAL_LANDS = "aboriginal_lands";
public static final Set<String> CLASS_VALUES =
Set.of("continent", "country", "state", "province", "city", "town", "village", "hamlet", "borough", "suburb",
"quarter", "neighbourhood", "isolated_dwelling", "island", "aboriginal_lands");
}
/** Complex mappings to generate attribute values from OSM element tags in the place layer. */
final class FieldMappings {
Expand Down
30 changes: 28 additions & 2 deletions src/main/java/org/openmaptiles/generated/Tables.java
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,9 @@ public OsmParkPolygon(SourceFeature source, String mappingKey) {
}

/** 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", "aboriginal_lands")), matchType("polygon"));
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
Expand All @@ -259,6 +260,25 @@ public interface Handler {
void process(OsmParkPolygon element, FeatureCollector features);
}
}
/** An OSM element that would appear in the {@code osm_boundary_polygon} table generated by imposm3. */
public record OsmBoundaryPolygon(@Override String name, @Override String boundary, @Override SourceFeature source)
implements Row, WithName, WithBoundary, WithSource {
public OsmBoundaryPolygon(SourceFeature source, String mappingKey) {
this(source.getString("name"), source.getString("boundary"), source);
}

/** Imposm3 "mapping" to filter OSM elements that should appear in this "table". */
public static final Expression MAPPING =
and(matchAny("boundary", "aboriginal_lands"), matchAny("type", "boundary"), matchType("polygon"));

/**
* Interface for layer implementations to extend to subscribe to OSM elements filtered and parsed as
* {@link OsmBoundaryPolygon}.
*/
public interface Handler {
void process(OsmBoundaryPolygon 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 {
Expand Down Expand Up @@ -1331,6 +1351,8 @@ public interface WithZOrder {
OsmMountainLinestring.MAPPING),
MultiExpression.entry(new RowClassAndConstructor(OsmParkPolygon.class, OsmParkPolygon::new),
OsmParkPolygon.MAPPING),
MultiExpression.entry(new RowClassAndConstructor(OsmBoundaryPolygon.class, OsmBoundaryPolygon::new),
OsmBoundaryPolygon.MAPPING),
MultiExpression.entry(new RowClassAndConstructor(OsmAerowayPolygon.class, OsmAerowayPolygon::new),
OsmAerowayPolygon.MAPPING),
MultiExpression.entry(new RowClassAndConstructor(OsmAerowayLinestring.class, OsmAerowayLinestring::new),
Expand Down Expand Up @@ -1406,6 +1428,10 @@ public static Map<Class<? extends Row>, List<RowHandlerAndClass<?>>> generateDis
result.computeIfAbsent(OsmParkPolygon.class, cls -> new ArrayList<>())
.add(new RowHandlerAndClass<>(typedHandler.getClass(), typedHandler::process));
}
if (handler instanceof OsmBoundaryPolygon.Handler typedHandler) {
result.computeIfAbsent(OsmBoundaryPolygon.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));
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/org/openmaptiles/layers/Boundary.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
import org.locationtech.jts.operation.polygonize.Polygonizer;
import org.openmaptiles.OpenMapTilesProfile;
import org.openmaptiles.generated.OpenMapTilesSchema;
import org.openmaptiles.generated.Tables;
import org.openmaptiles.util.OmtLanguageUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -95,6 +97,7 @@ public class Boundary implements
OpenMapTilesProfile.NaturalEarthProcessor,
OpenMapTilesProfile.OsmRelationPreprocessor,
OpenMapTilesProfile.OsmAllProcessor,
Tables.OsmBoundaryPolygon.Handler,
OpenMapTilesProfile.FeaturePostProcessor,
OpenMapTilesProfile.FinishHandler {

Expand Down Expand Up @@ -127,6 +130,7 @@ public class Boundary implements
private final Map<Long, List<Geometry>> regionGeometries = new HashMap<>();
private final Map<CountryBoundaryComponent, List<Geometry>> boundariesToMerge = new HashMap<>();
private final PlanetilerConfig config;
private final Translations translations;

public Boundary(Translations translations, PlanetilerConfig config, Stats stats) {
this.config = config;
Expand All @@ -141,6 +145,7 @@ public Boundary(Translations translations, PlanetilerConfig config, Stats stats)
false
);
this.stats = stats;
this.translations = translations;
}

private static boolean isDisputed(Map<String, Object> tags) {
Expand Down Expand Up @@ -306,6 +311,15 @@ public void processAllOsm(SourceFeature feature, FeatureCollector features) {
}
}

@Override
public void process(Tables.OsmBoundaryPolygon element, FeatureCollector features) {
features.polygon(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
.putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
.setAttr(OpenMapTilesSchema.Boundary.Fields.CLASS, element.boundary())
.setMinPixelSizeBelowZoom(13, 4) // for Z4: `sql_filter: area>power(ZRES3,2)`, etc.
.setMinZoom(4);
}

@Override
public void finish(String sourceName, FeatureCollector.Factory featureCollectors,
Consumer<FeatureCollector.Feature> emit) {
Expand Down
21 changes: 8 additions & 13 deletions src/main/java/org/openmaptiles/layers/Park.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,20 +91,15 @@ public Park(Translations translations, PlanetilerConfig config, Stats stats) {

@Override
public void process(Tables.OsmParkPolygon element, FeatureCollector features) {
String clazz;
if ("aboriginal_lands".equals(element.boundary())) {
clazz = "aboriginal_lands";
} else {
String protectionTitle = element.protectionTitle();
if (protectionTitle != null) {
protectionTitle = protectionTitle.replace(' ', '_').toLowerCase(Locale.ROOT);
}
clazz = coalesce(
nullIfEmpty(protectionTitle),
nullIfEmpty(element.boundary()),
nullIfEmpty(element.leisure())
);
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)
Expand Down
26 changes: 23 additions & 3 deletions src/main/java/org/openmaptiles/layers/Place.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public class Place implements
Tables.OsmIslandPoint.Handler,
Tables.OsmIslandPolygon.Handler,
Tables.OsmCityPoint.Handler,
Tables.OsmBoundaryPolygon.Handler,
OpenMapTilesProfile.FeaturePostProcessor {

/*
Expand All @@ -96,8 +97,10 @@ public class Place implements
* and minimum zoom level to use for those points.
*/

private static final TreeMap<Double, Integer> ISLAND_AREA_RANKS = new TreeMap<>(Map.of(
Double.MAX_VALUE, 3,
private static final TreeMap<Double, Integer> AREA_RANKS = new TreeMap<>(Map.of(
Double.MAX_VALUE, 1,
squareMetersToWorldArea(640_000_000), 2,
squareMetersToWorldArea(160_000_000), 3,
squareMetersToWorldArea(40_000_000), 4,
squareMetersToWorldArea(15_000_000), 5,
squareMetersToWorldArea(1_000_000), 6
Expand Down Expand Up @@ -282,7 +285,7 @@ public void process(Tables.OsmStatePoint element, FeatureCollector features) {
public void process(Tables.OsmIslandPolygon element, FeatureCollector features) {
try {
double area = element.source().area();
int rank = ISLAND_AREA_RANKS.ceilingEntry(area).getValue();
int rank = AREA_RANKS.ceilingEntry(area).getValue();
int minzoom = rank <= 3 ? 8 : rank <= 4 ? 9 : 10;

features.pointOnSurface(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
Expand Down Expand Up @@ -369,6 +372,23 @@ public void process(Tables.OsmCityPoint element, FeatureCollector features) {
}
}

@Override
public void process(Tables.OsmBoundaryPolygon element, FeatureCollector features) {
try {
int rank = AREA_RANKS.ceilingEntry(element.source().area()).getValue();
int minzoom = rank <= 4 ? rank + 5 : 10;

features.centroid(LAYER_NAME).setBufferPixels(BUFFER_SIZE)
.putAttrs(OmtLanguageUtils.getNames(element.source().tags(), translations))
.setAttr(OpenMapTilesSchema.Boundary.Fields.CLASS, element.boundary())
.setAttr(Fields.RANK, rank)
.setMinZoom(minzoom);
} catch (GeometryException e) {
e.log(stats, "omt_boundary_poly",
"Unable to get point for OSM boundary polygon " + element.source().id());
}
}

@Override
public List<VectorTile.Feature> postProcess(int zoom, List<VectorTile.Feature> items) {
// infer the rank field from ordering of the place labels with each label grid square
Expand Down
22 changes: 22 additions & 0 deletions src/test/java/org/openmaptiles/layers/BoundaryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -714,4 +714,26 @@ void testOsmBoundariesOnly() {
assertFeatures(14, List.of(Map.of("_minzoom", 1)),
processOsmOnly(lineFeatureWithRelation(profile.preprocessOsmRelation(relation), Map.of())));
}

@Test
void testIndigenousLand() {
assertFeatures(0, List.of(Map.of(
"_layer", "boundary",
"class", "aboriginal_lands",
"name", "Seminole Nation",
"name_en", "Seminole Nation",
"name:latin", "Seminole Nation",

"_type", "polygon",
"_minzoom", 4
), Map.of(
"_layer", "place"
)), process(polygonFeatureWithArea(1,
Map.of(
"type", "boundary",
"boundary", "aboriginal_lands",
"name", "Seminole Nation",
"name:en", "Seminole Nation"
))));
}
}
24 changes: 0 additions & 24 deletions src/test/java/org/openmaptiles/layers/ParkTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,30 +45,6 @@ void testNationalPark() {
))));
}

@Test
void testAbotiginalLand() {
assertFeatures(13, List.of(Map.of(
"_layer", "park",
"_type", "polygon",
"class", "aboriginal_lands",
"name", "Hualapai Tribe",
"_minpixelsize", 2d,
"_minzoom", 4,
"_maxzoom", 14
), Map.of(
"_layer", "park",
"_type", "point",
"class", "aboriginal_lands",
"name", "Hualapai Tribe",
"_minzoom", 5,
"_maxzoom", 14
)), process(polygonFeature(Map.of(
"boundary", "aboriginal_lands",
"name", "Hualapai Tribe",
"protection_title", "National Park"
))));
}

@Test
void testSmallerPark() {
double z11area = Math.pow((GeoUtils.metersToPixelAtEquator(0, Math.sqrt(70_000)) / 256d), 2) * Math.pow(2, 20 - 11);
Expand Down
45 changes: 44 additions & 1 deletion src/test/java/org/openmaptiles/layers/PlaceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ void testIslandPolygon() {
"name", "Nantucket",
"name_en", "Nantucket",
"name:latin", "Nantucket",
"rank", 3,
"rank", 1,

"_type", "point",
"_minzoom", 8
Expand Down Expand Up @@ -287,6 +287,49 @@ void testIslandPolygon() {
))));
}

@Test
void testIndigenousLand() {
assertFeatures(0, List.of(Map.of(
"_layer", "place",
"class", "aboriginal_lands",
"name", "Seminole Nation",
"name_en", "Seminole Nation",
"name:latin", "Seminole Nation",
"rank", 1,

"_type", "point",
"_minzoom", 6
), Map.of(
"_layer", "boundary"
)), process(polygonFeatureWithArea(1,
Map.of(
"type", "boundary",
"boundary", "aboriginal_lands",
"name", "Seminole Nation",
"name:en", "Seminole Nation"
))));

double rank2area = Math.pow(GeoUtils.metersToPixelAtEquator(0, Math.sqrt(640_000_000 - 1)) / 256d, 2);

assertFeatures(0, List.of(Map.of(
"_layer", "place",
"class", "aboriginal_lands",
"name", "Seminole Nation",
"rank", 2,

"_type", "point",
"_minzoom", 7
), Map.of(
"_layer", "boundary"
)), process(polygonFeatureWithArea(rank2area,
Map.of(
"type", "boundary",
"boundary", "aboriginal_lands",
"name", "Seminole Nation",
"name:en", "Seminole Nation"
))));
}

@Test
void testPlaceSortKeyRanking() {
int[] sortKeys = new int[]{
Expand Down

0 comments on commit f4a55b3

Please sign in to comment.