package com.onthegomap.planetiler.basemap.layers; import static com.onthegomap.planetiler.TestUtils.newLineString; import static com.onthegomap.planetiler.TestUtils.newPoint; import static com.onthegomap.planetiler.TestUtils.rectangle; import static com.onthegomap.planetiler.basemap.BasemapProfile.NATURAL_EARTH_SOURCE; import static com.onthegomap.planetiler.basemap.BasemapProfile.OSM_SOURCE; import com.onthegomap.planetiler.FeatureCollector; import com.onthegomap.planetiler.basemap.BasemapProfile; import com.onthegomap.planetiler.config.Arguments; import com.onthegomap.planetiler.config.PlanetilerConfig; 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.stats.Stats; import java.util.List; import java.util.Map; import java.util.stream.Stream; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; class TransportationTest extends AbstractLayerTest { @Test void testNamedFootway() { FeatureCollector result = process(lineFeature(Map.of( "name", "Lagoon Path", "surface", "asphalt", "level", "0", "highway", "footway", "indoor", "no", "oneway", "no", "foot", "designated", "bicycle", "dismount" ))); assertFeatures(13, List.of(Map.of( "_layer", "transportation", "_type", "line", "class", "path", "subclass", "footway", "oneway", "", "name", "", "layer", "", "_buffer", 4d, "_minpixelsize", 0d, "_minzoom", 13 ), Map.of( "_layer", "transportation_name", "_type", "line", "class", "path", "subclass", "footway", "name", "Lagoon Path", "name_int", "Lagoon Path", "name:latin", "Lagoon Path", "_minpixelsize", 0d, "_minzoom", 13, "_maxzoom", 14 )), result); assertFeatures(13, List.of(Map.of( "_layer", "transportation", "surface", "paved", "oneway", "", "layer", "", "level", 0L, "ramp", "", "bicycle", "dismount", "foot", "designated" ), Map.of( "_layer", "transportation_name", "level", 0L, "surface", "", "oneway", "", "ramp", "", "bicycle", "", "foot", "" )), result); } @Test void testImportantPath() { var rel = new OsmElement.Relation(1); rel.setTag("colour", "white"); rel.setTag("name", "Appalachian Trail - 11 MA"); rel.setTag("network", "nwn"); rel.setTag("osmc", "symbol white::white_stripe"); rel.setTag("ref", "AT"); rel.setTag("route", "hiking"); rel.setTag("short_name", "AT 11 MA"); rel.setTag("symbol", "white-paint blazes"); rel.setTag("type", "route"); rel.setTag("wikidata", "Q620648"); rel.setTag("wikipedia", "en:Appalachian Trail"); FeatureCollector features = process(lineFeatureWithRelation( profile.preprocessOsmRelation(rel), Map.of( "bicycle", "no", "highway", "path", "horse", "no", "name", "Appalachian Trail", "ref", "AT", "surface", "ground" ))); assertFeatures(12, List.of(Map.of( "_layer", "transportation", "_type", "line", "class", "path", "subclass", "path", "oneway", "", "name", "", "layer", "", "_buffer", 4d, "_minpixelsize", 0d, "_minzoom", 12 ), Map.of( "_layer", "transportation_name", "_type", "line", "class", "path", "subclass", "path", "name", "Appalachian Trail", "name_int", "Appalachian Trail", "name:latin", "Appalachian Trail", "_minpixelsize", 0d, "_minzoom", 12 )), features); } @Test void testUnnamedPath() { assertFeatures(14, List.of(Map.of( "_layer", "transportation", "class", "path", "subclass", "path", "surface", "unpaved", "oneway", "", "_minzoom", 14 )), process(lineFeature(Map.of( "surface", "dirt", "highway", "path" )))); } @Test void testPrivatePath() { assertFeatures(9, List.of(Map.of( "_layer", "transportation", "class", "path", "access", "no" )), process(lineFeature(Map.of( "access", "private", "highway", "path" )))); assertFeatures(9, List.of(Map.of( "_layer", "transportation", "class", "path", "access", "no" )), process(lineFeature(Map.of( "access", "no", "highway", "path" )))); assertFeatures(8, List.of(Map.of( "_layer", "transportation", "class", "path", "access", "" )), process(lineFeature(Map.of( "access", "no", "highway", "path" )))); } @Test void testExpressway() { assertFeatures(8, List.of(Map.of( "_layer", "transportation", "class", "motorway", "expressway", "" )), process(lineFeature(Map.of( "highway", "motorway", "expressway", "yes" )))); assertFeatures(8, List.of(Map.of( "_layer", "transportation", "class", "primary", "expressway", 1 )), process(lineFeature(Map.of( "highway", "primary", "expressway", "yes" )))); assertFeatures(7, List.of(Map.of( "_layer", "transportation", "class", "primary", "expressway", "" )), process(lineFeature(Map.of( "highway", "primary", "expressway", "yes" )))); } @Test void testToll() { assertFeatures(9, List.of(Map.of( "_layer", "transportation", "class", "motorway", "toll", "" )), process(lineFeature(Map.of( "highway", "motorway" )))); assertFeatures(9, List.of(Map.of( "_layer", "transportation", "class", "motorway", "toll", 1 )), process(lineFeature(Map.of( "highway", "motorway", "toll", "yes" )))); assertFeatures(8, List.of(Map.of( "_layer", "transportation", "class", "motorway", "toll", "" )), process(lineFeature(Map.of( "highway", "motorway", "toll", "yes" )))); } @Test void testIndoorTunnelSteps() { assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "path", "subclass", "steps", "brunnel", "tunnel", "indoor", 1, "oneway", 1, "ramp", "" )), process(lineFeature(Map.of( "highway", "steps", "tunnel", "building_passage", "oneway", "yes", "indoor", "yes" )))); } @Test void testInterstateMotorway() { var rel = new OsmElement.Relation(1); rel.setTag("type", "route"); rel.setTag("route", "road"); rel.setTag("network", "US:I"); rel.setTag("ref", "90"); FeatureCollector features = process(lineFeatureWithRelation( profile.preprocessOsmRelation(rel), Map.of( "highway", "motorway", "oneway", "yes", "name", "Massachusetts Turnpike", "ref", "I 90", "surface", "asphalt", "foot", "no", "bicycle", "no", "horse", "no", "bridge", "yes" ))); assertFeatures(13, List.of(mapOf( "_layer", "transportation", "class", "motorway", "surface", "paved", "oneway", 1, "ramp", "", "bicycle", "no", "foot", "no", "horse", "no", "brunnel", "bridge", "network", "us-interstate", "_minzoom", 4 ), Map.of( "_layer", "transportation_name", "class", "motorway", "name", "Massachusetts Turnpike", "name_en", "Massachusetts Turnpike", "ref", "90", "ref_length", 2, "network", "us-interstate", "brunnel", "", "route_1", "US:I=90", "_minzoom", 6 )), features); assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "motorway", "surface", "paved", "oneway", 1, "ramp", "", "bicycle", "no", "foot", "no", "horse", "no", "brunnel", "bridge", "_minzoom", 4 ), Map.of( "_layer", "transportation_name", "class", "motorway", "name", "Massachusetts Turnpike", "name_en", "Massachusetts Turnpike", "ref", "90", "ref_length", 2, "network", "us-interstate", "route_1", "US:I=90", "brunnel", "", "_minzoom", 6 )), features); assertFeatures(8, List.of(Map.of( "_layer", "transportation", "class", "motorway", "surface", "", "oneway", "", "ramp", "", "bicycle", "", "foot", "", "horse", "", "brunnel", "bridge", "_minzoom", 4 ), Map.of( "_layer", "transportation_name", "class", "motorway", "name", "Massachusetts Turnpike", "name_en", "Massachusetts Turnpike", "ref", "90", "ref_length", 2, "network", "us-interstate", "route_1", "US:I=90", "brunnel", "", "_minzoom", 6 )), features); } @Test void testRouteWithoutNetworkType() { var rel1 = new OsmElement.Relation(1); rel1.setTag("type", "route"); rel1.setTag("route", "road"); rel1.setTag("network", "US:NJ:NJTP"); rel1.setTag("ref", "NJTP"); rel1.setTag("name", "New Jersey Turnpike (mainline)"); var rel2 = new OsmElement.Relation(1); rel2.setTag("type", "route"); rel2.setTag("route", "road"); rel2.setTag("network", "US:I"); rel2.setTag("ref", "95"); rel2.setTag("name", "I 95 (NJ)"); FeatureCollector rendered = process(lineFeatureWithRelation( Stream.concat( profile.preprocessOsmRelation(rel1).stream(), profile.preprocessOsmRelation(rel2).stream() ).toList(), Map.of( "highway", "motorway", "name", "New Jersey Turnpike", "ref", "I 95;NJTP" ))); assertFeatures(13, List.of(mapOf( "_layer", "transportation", "class", "motorway", "_minzoom", 4 ), Map.of( "_layer", "transportation_name", "class", "motorway", "name", "New Jersey Turnpike", "ref", "95", "ref_length", 2, "route_1", "US:I=95", "route_2", "US:NJ:NJTP=NJTP", "_minzoom", 6 )), rendered); } @Test void testMinorRouteRef() { var rel1 = new OsmElement.Relation(1); rel1.setTag("type", "route"); rel1.setTag("route", "road"); rel1.setTag("network", "rwn"); rel1.setTag("ref", "GFW"); rel1.setTag("name", "Georg-Fahrbach-Weg"); assertFeatures(13, List.of(mapOf( "_layer", "transportation", "class", "tertiary" )), process(lineFeatureWithRelation( profile.preprocessOsmRelation(rel1), Map.of( "highway", "tertiary" )))); var profileWithMinorRefs = new BasemapProfile(translations, PlanetilerConfig.from(Arguments.of(Map.of( "transportation_name_minor_refs", "true" ))), Stats.inMemory()); SourceFeature feature = lineFeatureWithRelation( profileWithMinorRefs.preprocessOsmRelation(rel1), Map.of( "highway", "tertiary" )); var collector = featureCollectorFactory.get(feature); profileWithMinorRefs.processFeature(feature, collector); assertFeatures(13, List.of(mapOf( "_layer", "transportation", "class", "tertiary" ), mapOf( "_layer", "transportation_name", "class", "tertiary", "ref", "GFW", "network", "road" )), collector); } @Test void testPolishHighwayIssue165() { var rel1 = new OsmElement.Relation(1); rel1.setTag("type", "route"); rel1.setTag("route", "road"); rel1.setTag("network", "e-road"); rel1.setTag("ref", "E 77"); rel1.setTag("name", "European route E 77"); var rel2 = new OsmElement.Relation(2); rel2.setTag("type", "route"); rel2.setTag("route", "road"); rel2.setTag("network", "e-road"); rel2.setTag("ref", "E 28"); rel2.setTag("name", "European route E 28"); FeatureCollector rendered = process(lineFeatureWithRelation( Stream.concat( profile.preprocessOsmRelation(rel1).stream(), profile.preprocessOsmRelation(rel2).stream() ).toList(), Map.of( "highway", "trunk", "ref", "S7" ))); assertFeatures(13, List.of(mapOf( "_layer", "transportation", "class", "trunk" ), Map.of( "_layer", "transportation_name", "class", "trunk", "name", "", "ref", "S7", "ref_length", 2, "route_1", "e-road=E 28", "route_2", "e-road=E 77" )), rendered); } @Test void testMotorwayJunction() { var otherNode1 = new OsmElement.Node(1, 1, 1); var junctionNode = new OsmElement.Node(2, 1, 2); var otherNode2 = new OsmElement.Node(3, 1, 3); var otherNode3 = new OsmElement.Node(4, 2, 3); junctionNode.setTag("highway", "motorway_junction"); junctionNode.setTag("name", "exit 1"); junctionNode.setTag("layer", "1"); junctionNode.setTag("ref", "12"); // 2 ways meet at junctionNode (id=2) - use most important class of a highway intersecting it (motorway) var way1 = new OsmElement.Way(5); way1.setTag("highway", "motorway"); way1.nodes().add(otherNode1.id(), junctionNode.id(), otherNode2.id()); var way2 = new OsmElement.Way(6); way2.setTag("highway", "primary"); way2.nodes().add(junctionNode.id(), otherNode3.id()); profile.preprocessOsmNode(otherNode1); profile.preprocessOsmNode(junctionNode); profile.preprocessOsmNode(otherNode2); profile.preprocessOsmNode(otherNode3); profile.preprocessOsmWay(way1); profile.preprocessOsmWay(way2); FeatureCollector features = process(SimpleFeature.create( newPoint(1, 2), junctionNode.tags(), OSM_SOURCE, null, junctionNode.id() )); assertFeatures(13, List.of(mapOf( "_layer", "transportation_name", "class", "motorway", "subclass", "junction", "name", "exit 1", "ref", "12", "ref_length", 2, "layer", 1L, "_type", "point", "_minzoom", 10 )), features); } @Test void testInterstateMotorwayWithoutWayInfo() { var rel = new OsmElement.Relation(1); rel.setTag("type", "route"); rel.setTag("route", "road"); rel.setTag("network", "US:I"); rel.setTag("ref", "90"); FeatureCollector features = process(lineFeatureWithRelation( profile.preprocessOsmRelation(rel), Map.of( "highway", "motorway" ))); assertFeatures(13, List.of(mapOf( "_layer", "transportation", "class", "motorway", "network", "us-interstate", "_minzoom", 4 ), Map.of( "_layer", "transportation_name", "class", "motorway", "ref", "90", "ref_length", 2, "network", "us-interstate", "brunnel", "", "route_1", "US:I=90", "_minzoom", 6 )), features); } @Test void testPrimaryRoadConstruction() { assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "primary_construction", "brunnel", "bridge", "layer", 1L, "oneway", 1, "_minzoom", 7 ), Map.of( "_layer", "transportation_name", "name", "North Washington Street", "class", "primary_construction", "brunnel", "", "_minzoom", 12 )), process(lineFeature(Map.of( "highway", "construction", "construction", "primary", "bridge", "yes", "layer", "1", "name", "North Washington Street", "oneway", "yes" )))); } @Test void testBridgeConstruction() { assertFeatures(14, List.of(), process(lineFeature(Map.of( "highway", "construction", "construction", "bridge", "man_made", "bridge", "layer", "1" )))); assertFeatures(14, List.of(Map.of( "_layer", "transportation", "class", "minor_construction", "brunnel", "bridge", "layer", 1L )), process(closedWayFeature(Map.of( "highway", "construction", "construction", "bridge", "man_made", "bridge", "layer", "1" )))); } @Test void testIgnoreManMadeWhenNotBridgeOrPier() { // https://github.com/onthegomap/planetiler/issues/69 assertFeatures(14, List.of(), process(lineFeature(Map.of( "man_made", "storage_tank", "service", "driveway" )))); assertFeatures(14, List.of(), process(lineFeature(Map.of( "man_made", "courtyard", "service", "driveway" )))); assertFeatures(14, List.of(), process(lineFeature(Map.of( "man_made", "courtyard", "service", "driveway", "name", "Named Driveway" )))); } @Test void testRaceway() { assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "raceway", "oneway", 1, "_minzoom", 12 ), Map.of( "_layer", "transportation_name", "class", "raceway", "name", "Climbing Turn", "ref", "5", "_minzoom", 12 )), process(lineFeature(Map.of( "highway", "raceway", "oneway", "yes", "ref", "5", "name", "Climbing Turn" )))); } @Test void testDriveway() { assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "service", "service", "driveway", "_minzoom", 14 )), process(lineFeature(Map.of( "highway", "service", "service", "driveway" )))); } @Test void testMountainBikeTrail() { assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "path", "subclass", "path", "mtb_scale", "4", "surface", "unpaved", "bicycle", "yes", "_minzoom", 13 ), Map.of( "_layer", "transportation_name", "class", "path", "subclass", "path", "name", "Path name", "_minzoom", 13 )), process(lineFeature(Map.of( "highway", "path", "mtb:scale", "4", "name", "Path name", "bicycle", "yes", "surface", "ground" )))); } @Test void testNamedTrack() { assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "track", "surface", "unpaved", "horse", "yes", "_minzoom", 13 ), Map.of( "_layer", "transportation_name", "class", "track", "name", "name", "_minzoom", 13 )), process(lineFeature(Map.of( "highway", "track", "surface", "dirt", "horse", "yes", "name", "name" )))); } @Test void testUnnamedTrack() { assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "track", "surface", "unpaved", "horse", "yes", "_minzoom", 14 )), process(lineFeature(Map.of( "highway", "track", "surface", "dirt", "horse", "yes" )))); } @Test void testBusway() { assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "busway", "brunnel", "tunnel", "_minzoom", 11 ), Map.of( "_layer", "transportation_name", "class", "busway", "name", "Silver Line", "_minzoom", 12 )), process(lineFeature(Map.of( "access", "no", "bus", "yes", "highway", "busway", "layer", "-1", "name", "Silver Line", "trolley_wire", "yes", "tunnel", "yes" )))); } final OsmElement.Relation relUS = new OsmElement.Relation(1); { relUS.setTag("type", "route"); relUS.setTag("route", "road"); relUS.setTag("network", "US:US"); relUS.setTag("ref", "3"); } final OsmElement.Relation relMA = new OsmElement.Relation(2); { relMA.setTag("type", "route"); relMA.setTag("route", "road"); relMA.setTag("network", "US:MA"); relMA.setTag("ref", "2"); } @Test void testUSAndStateHighway() { assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "primary", "surface", "paved", "oneway", "", "ramp", "", "network", "us-highway", "_minzoom", 7 ), Map.of( "_layer", "transportation_name", "class", "primary", "name", "Memorial Drive", "name_en", "Memorial Drive", "ref", "3", "ref_length", 1, "network", "us-highway", "route_1", "US:US=3", "route_2", "US:MA=2", "_minzoom", 12 )), process(lineFeatureWithRelation( Stream.concat( profile.preprocessOsmRelation(relUS).stream(), profile.preprocessOsmRelation(relMA).stream() ).toList(), Map.of( "highway", "primary", "name", "Memorial Drive", "ref", "US 3;MA 2", "surface", "asphalt" )))); // swap order assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "primary" ), Map.of( "_layer", "transportation_name", "class", "primary", "route_1", "US:US=3", "route_2", "US:MA=2", "ref", "3", "network", "us-highway" )), process(lineFeatureWithRelation( Stream.concat( profile.preprocessOsmRelation(relMA).stream(), Stream.concat( // ignore duplicates profile.preprocessOsmRelation(relUS).stream(), profile.preprocessOsmRelation(relUS).stream() ) ).toList(), Map.of( "highway", "primary", "name", "Memorial Drive", "ref", "US 3;MA 2", "surface", "asphalt" )))); } @Test void testUsStateHighway() { assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "primary" ), Map.of( "_layer", "transportation_name", "class", "primary", "name", "Memorial Drive", "name_en", "Memorial Drive", "ref", "2", "ref_length", 1, "network", "us-state", "_minzoom", 12 )), process(lineFeatureWithRelation( profile.preprocessOsmRelation(relMA), Map.of( "highway", "primary", "name", "Memorial Drive", "ref", "US 3;MA 2", "surface", "asphalt" )))); } @Test void testCompoundRef() { assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "primary", "network", "" ), Map.of( "_layer", "transportation_name", "class", "primary", "name", "Memorial Drive", "name_en", "Memorial Drive", "ref", "US 3;MA 2", "ref_length", 9, "network", "road", "_minzoom", 12 )), process(lineFeature( Map.of( "highway", "primary", "name", "Memorial Drive", "ref", "US 3;MA 2", "surface", "asphalt" )))); } @Test void testTransCanadaHighway() { var rel = new OsmElement.Relation(1); rel.setTag("type", "route"); rel.setTag("route", "road"); rel.setTag("network", "CA:transcanada:namedRoute"); FeatureCollector features = process(lineFeatureWithRelation( profile.preprocessOsmRelation(rel), Map.of( "highway", "motorway", "oneway", "yes", "name", "Autoroute Claude-Béchard", "ref", "85", "surface", "asphalt" ))); assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "motorway", "surface", "paved", "oneway", 1, "ramp", "", "_minzoom", 4 ), Map.of( "_layer", "transportation_name", "class", "motorway", "name", "Autoroute Claude-Béchard", "name_en", "Autoroute Claude-Béchard", "ref", "85", "ref_length", 2, "network", "ca-transcanada", "_minzoom", 6 )), features); } @Test void testGreatBritainHighway() { process(SimpleFeature.create( rectangle(0, 0.1), Map.of("iso_a2", "GB"), NATURAL_EARTH_SOURCE, "ne_10m_admin_0_countries", 0 )); // in GB assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "motorway", "oneway", 1, "ramp", "", "_minzoom", 4 ), Map.of( "_layer", "transportation_name", "class", "motorway", "ref", "M1", "ref_length", 2, "network", "gb-motorway", "_minzoom", 6 )), process(SimpleFeature.create( newLineString(0, 0, 1, 1), Map.of( "highway", "motorway", "oneway", "yes", "ref", "M1" ), OSM_SOURCE, null, 0 ))); // not in GB assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "motorway", "oneway", 1, "ramp", "", "_minzoom", 4 ), Map.of( "_layer", "transportation_name", "class", "motorway", "ref", "M1", "ref_length", 2, "network", "road", "_minzoom", 6 )), process(SimpleFeature.create( newLineString(1, 0, 0, 1), Map.of( "highway", "motorway", "oneway", "yes", "ref", "M1" ), OSM_SOURCE, null, 0 ))); } @Test void testMergesDisconnectedRoadFeatures() throws GeometryException { testMergesLinestrings(Map.of("class", "motorway"), Transportation.LAYER_NAME, 10, 14); } @Test void testMergesDisconnectedRoadNameFeatures() throws GeometryException { testMergesLinestrings(Map.of("class", "motorway"), TransportationName.LAYER_NAME, 10, 14); } @Test void testLightRail() { assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "transit", "subclass", "light_rail", "brunnel", "tunnel", "layer", -1L, "oneway", "", "ramp", "", "_minzoom", 11, "_maxzoom", 14, "_type", "line" )), process(lineFeature(Map.of( "railway", "light_rail", "name", "Green Line", "tunnel", "yes", "layer", "-1" )))); } @Test void testSubway() { assertFeatures(13, List.of(Map.of( "_layer", "transportation", "class", "transit", "subclass", "subway", "brunnel", "tunnel", "layer", -2L, "oneway", "", "ramp", "", "_minzoom", 14, "_maxzoom", 14, "_type", "line" )), process(lineFeature(Map.of( "railway", "subway", "name", "Red Line", "tunnel", "yes", "layer", "-2", "level", "-2" )))); } @Test void testRail() { assertFeatures(8, List.of(Map.of( "_layer", "transportation", "class", "rail", "subclass", "rail", "brunnel", "", "layer", "", "_minzoom", 8, "_maxzoom", 14, "_type", "line" )), process(lineFeature(Map.of( "railway", "rail", "name", "Boston Subdivision", "usage", "main", "tunnel", "yes", "layer", "-2" )))); assertFeatures(13, List.of(Map.of( "layer", "", "_minzoom", 10 )), process(lineFeature(Map.of( "railway", "rail", "name", "Boston Subdivision" )))); assertFeatures(13, List.of(), process(polygonFeature(Map.of( "railway", "rail" )))); assertFeatures(13, List.of(Map.of( "class", "rail", "subclass", "rail", "_minzoom", 14, "service", "yard" )), process(lineFeature(Map.of( "railway", "rail", "name", "Boston Subdivision", "service", "yard" )))); } @Test void testNarrowGauge() { assertFeatures(10, List.of(Map.of( "_layer", "transportation", "class", "rail", "subclass", "narrow_gauge", "_minzoom", 10, "_maxzoom", 14, "_type", "line" )), process(lineFeature(Map.of( "railway", "narrow_gauge" )))); } @ParameterizedTest @ValueSource(strings = {"gondola", "chair_lift", "j-bar", "mixed_lift"}) void testAerialway(String aerialway) { assertFeatures(12, List.of(Map.of( "_layer", "transportation", "class", "aerialway", "subclass", aerialway, "_minzoom", 12, "_maxzoom", 14, "_type", "line" ), Map.of( "_layer", "transportation_name", "class", "aerialway", "subclass", aerialway, "name", "Summit Gondola", "_minzoom", 12, "_maxzoom", 14, "_type", "line" )), process(lineFeature(Map.of( "aerialway", aerialway, "name", "Summit Gondola" )))); assertFeatures(10, List.of(), process(polygonFeature(Map.of( "aerialway", aerialway, "name", "Summit Gondola" )))); } @Test void testFerry() { assertFeatures(10, List.of(Map.of( "_layer", "transportation", "class", "ferry", "_minzoom", 11, "_maxzoom", 14, "_type", "line" ), Map.of( "_layer", "transportation_name", "class", "ferry", "name", "Boston - Provincetown Ferry", "_minzoom", 12, "_maxzoom", 14, "_type", "line" )), process(lineFeature(Map.of( "route", "ferry", "name", "Boston - Provincetown Ferry", "motor_vehicle", "no", "foot", "yes", "bicycle", "yes" )))); assertFeatures(10, List.of(), process(polygonFeature(Map.of( "route", "ferry", "name", "Boston - Provincetown Ferry", "motor_vehicle", "no", "foot", "yes", "bicycle", "yes" )))); } @Test void testPiers() { // area assertFeatures(10, List.of(Map.of( "_layer", "transportation", "class", "pier", "_minzoom", 13, "_maxzoom", 14, "_type", "polygon" )), process(polygonFeature(Map.of( "man_made", "pier" )))); assertFeatures(10, List.of(Map.of( "_layer", "transportation", "class", "pier", "_minzoom", 13, "_maxzoom", 14, "_type", "line" )), process(lineFeature(Map.of( "man_made", "pier" )))); } @Test void testPedestrianArea() { Map pedestrianArea = Map.of( "_layer", "transportation", "class", "path", "subclass", "pedestrian", "_minzoom", 13, "_maxzoom", 14, "_type", "polygon" ); Map circularPath = Map.of( "_layer", "transportation", "class", "path", "subclass", "pedestrian", "_minzoom", 14, "_maxzoom", 14, "_type", "line" ); assertFeatures(14, List.of(pedestrianArea), process(closedWayFeature(Map.of( "highway", "pedestrian", "area", "yes", "foot", "yes" )))); assertFeatures(14, List.of(pedestrianArea), process(polygonFeature(Map.of( "highway", "pedestrian", "foot", "yes" )))); assertFeatures(14, List.of(circularPath), process(closedWayFeature(Map.of( "highway", "pedestrian", "foot", "yes" )))); assertFeatures(14, List.of(circularPath), process(closedWayFeature(Map.of( "highway", "pedestrian", "foot", "yes", "area", "no" )))); // ignore underground pedestrian areas assertFeatures(14, List.of(), process(polygonFeature(Map.of( "highway", "pedestrian", "area", "yes", "foot", "yes", "layer", "-1" )))); } private int getWaySortKey(Map tags) { var iter = process(lineFeature(tags)).iterator(); return iter.next().getSortKey(); } @Test void testSortKeys() { assertDescending( getWaySortKey(Map.of("highway", "footway", "layer", "2")), getWaySortKey(Map.of("highway", "motorway", "bridge", "yes")), getWaySortKey(Map.of("highway", "footway", "bridge", "yes")), getWaySortKey(Map.of("highway", "motorway")), getWaySortKey(Map.of("highway", "trunk")), getWaySortKey(Map.of("railway", "rail")), getWaySortKey(Map.of("highway", "primary")), getWaySortKey(Map.of("highway", "secondary")), getWaySortKey(Map.of("highway", "tertiary")), getWaySortKey(Map.of("highway", "motorway_link")), getWaySortKey(Map.of("highway", "footway")), getWaySortKey(Map.of("highway", "motorway", "tunnel", "yes")), getWaySortKey(Map.of("highway", "footway", "tunnel", "yes")), getWaySortKey(Map.of("highway", "motorway", "layer", "-2")) ); } @Test void testTransportationNameLayerRequiresTransportationLayer() { var profile = new BasemapProfile(translations, PlanetilerConfig.from(Arguments.of( "only_layers", "transportation_name" )), Stats.inMemory()); SourceFeature feature = lineFeature(Map.of( "highway", "path", "name", "test" )); var collector = featureCollectorFactory.get(feature); profile.processFeature(feature, collector); assertFeatures(14, List.of(Map.of( "_layer", "transportation_name", "class", "path", "name", "test" ), Map.of( "_layer", "transportation", "class", "path" )), collector); } }