/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.opentripplanner.graph_builder.impl.osm; import java.io.File; import java.util.HashMap; import java.util.HashSet; import java.util.Set; import junit.framework.TestCase; import org.junit.Before; import org.junit.Test; import org.opentripplanner.common.TurnRestriction; import org.opentripplanner.common.model.P2; import org.opentripplanner.openstreetmap.model.OSMWay; import org.opentripplanner.openstreetmap.model.OSMWithTags; import org.opentripplanner.openstreetmap.impl.FileBasedOpenStreetMapProviderImpl; import org.opentripplanner.routing.core.TraverseModeSet; import org.opentripplanner.routing.edgetype.StreetEdge; import org.opentripplanner.routing.edgetype.StreetTraversalPermission; import org.opentripplanner.routing.graph.Edge; import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.routing.graph.Vertex; import org.opentripplanner.routing.vertextype.IntersectionVertex; public class TestOpenStreetMapGraphBuilder extends TestCase { private HashMap<Class<?>, Object> extra; @Before public void setUp() { extra = new HashMap<Class<?>, Object>(); } @Test public void testGraphBuilder() throws Exception { Graph gg = new Graph(); OpenStreetMapGraphBuilderImpl loader = new OpenStreetMapGraphBuilderImpl(); loader.setDefaultWayPropertySetSource(new DefaultWayPropertySetSource()); FileBasedOpenStreetMapProviderImpl provider = new FileBasedOpenStreetMapProviderImpl(); File file = new File(getClass().getResource("map.osm.gz").getFile()); provider.setPath(file); loader.setProvider(provider); loader.buildGraph(gg, extra); // Kamiennogorska at south end of segment Vertex v1 = gg.getVertex("osm:node:280592578"); // Kamiennogorska at Mariana Smoluchowskiego Vertex v2 = gg.getVertex("osm:node:288969929"); // Mariana Smoluchowskiego, north end Vertex v3 = gg.getVertex("osm:node:280107802"); // Mariana Smoluchowskiego, south end (of segment connected to v2) Vertex v4 = gg.getVertex("osm:node:288970952"); assertNotNull(v1); assertNotNull(v2); assertNotNull(v3); assertNotNull(v4); Edge e1 = null, e2 = null, e3 = null; for (Edge e: v2.getOutgoing()) { if (e.getToVertex() == v1) { e1 = e; } else if (e.getToVertex() == v3) { e2 = e; } else if (e.getToVertex() == v4) { e3 = e; } } assertNotNull(e1); assertNotNull(e2); assertNotNull(e3); assertTrue("name of e1 must be like \"Kamiennog\u00F3rska\"; was " + e1.getName(), e1 .getName().contains("Kamiennog\u00F3rska")); assertTrue("name of e2 must be like \"Mariana Smoluchowskiego\"; was " + e2.getName(), e2 .getName().contains("Mariana Smoluchowskiego")); } /** * Detailed testing of OSM graph building using a very small chunk of NYC (SOHO-ish). * @throws Exception */ @Test public void testBuildGraphDetailed() throws Exception { Graph gg = new Graph(); OpenStreetMapGraphBuilderImpl loader = new OpenStreetMapGraphBuilderImpl(); loader.setDefaultWayPropertySetSource(new DefaultWayPropertySetSource()); FileBasedOpenStreetMapProviderImpl provider = new FileBasedOpenStreetMapProviderImpl(); File file = new File(getClass().getResource("NYC_small.osm.gz").getFile()); provider.setPath(file); loader.setProvider(provider); loader.buildGraph(gg, extra); // These vertices are labeled in the OSM file as having traffic lights. IntersectionVertex iv1 = (IntersectionVertex) gg.getVertex("osm:node:1919595918"); IntersectionVertex iv2 = (IntersectionVertex) gg.getVertex("osm:node:42442273"); IntersectionVertex iv3 = (IntersectionVertex) gg.getVertex("osm:node:1919595927"); IntersectionVertex iv4 = (IntersectionVertex) gg.getVertex("osm:node:42452026"); assertTrue(iv1.isTrafficLight()); assertTrue(iv2.isTrafficLight()); assertTrue(iv3.isTrafficLight()); assertTrue(iv4.isTrafficLight()); // These are not. IntersectionVertex iv5 = (IntersectionVertex) gg.getVertex("osm:node:42435485"); IntersectionVertex iv6 = (IntersectionVertex) gg.getVertex("osm:node:42439335"); IntersectionVertex iv7 = (IntersectionVertex) gg.getVertex("osm:node:42436761"); IntersectionVertex iv8 = (IntersectionVertex) gg.getVertex("osm:node:42442291"); assertFalse(iv5.isTrafficLight()); assertFalse(iv6.isTrafficLight()); assertFalse(iv7.isTrafficLight()); assertFalse(iv8.isTrafficLight()); Set<P2<Integer>> edgeEndpoints = new HashSet<P2<Integer>>(); for (StreetEdge se : gg.getStreetEdges()) { P2<Integer> endpoints = new P2<Integer>(se.getFromVertex().getIndex(), se.getToVertex().getIndex()); // Check that we don't get any duplicate edges on this small graph. if (edgeEndpoints.contains(endpoints)) { assertFalse(true); } edgeEndpoints.add(endpoints); StreetTraversalPermission perm = se.getPermission(); // CAR and CUSTOM_MOTOR_VEHICLE should always have the same permissions. assertEquals(perm.allows(StreetTraversalPermission.CAR), perm.allows(StreetTraversalPermission.CUSTOM_MOTOR_VEHICLE)); // Check turn restriction consistency. // NOTE(flamholz): currently there don't appear to be any turn restrictions // in the OSM file we are loading. for (TurnRestriction tr : se.getTurnRestrictions()) { // All turn restrictions should apply equally to // CAR and CUSTOM_MOTOR_VEHICLE. TraverseModeSet modes = tr.modes; assertEquals(modes.getCar(), modes.getCustomMotorVehicle()); } } } @Test public void testWayDataSet() { OSMWithTags way = new OSMWay(); way.addTag("highway", "footway"); way.addTag("cycleway", "lane"); way.addTag("access", "no"); way.addTag("surface", "gravel"); WayPropertySet wayPropertySet = new WayPropertySet(); // where there are no way specifiers, the default is used assertEquals(wayPropertySet.getDataForWay(way), wayPropertySet.defaultProperties); // add two equal matches: lane only... OSMSpecifier lane_only = new OSMSpecifier(); lane_only.addTag("cycleway", "lane"); WayProperties lane_is_safer = new WayProperties(); lane_is_safer.setSafetyFeatures(new P2<Double>(1.5, 1.5)); wayPropertySet.addProperties(lane_only, lane_is_safer); // and footway only OSMSpecifier footway_only = new OSMSpecifier(); footway_only.addTag("highway", "footway"); WayProperties footways_allow_peds = new WayProperties(); footways_allow_peds.setPermission(StreetTraversalPermission.PEDESTRIAN); wayPropertySet.addProperties(footway_only, footways_allow_peds); WayProperties dataForWay = wayPropertySet.getDataForWay(way); // the first one is found assertEquals(dataForWay, lane_is_safer); // add a better match OSMSpecifier lane_and_footway = new OSMSpecifier(); lane_and_footway.addTag("cycleway", "lane"); lane_and_footway.addTag("highway", "footway"); WayProperties safer_and_peds = new WayProperties(); safer_and_peds.setSafetyFeatures(new P2<Double>(0.75, 0.75)); safer_and_peds.setPermission(StreetTraversalPermission.PEDESTRIAN); wayPropertySet.addProperties(lane_and_footway, safer_and_peds); dataForWay = wayPropertySet.getDataForWay(way); assertEquals(dataForWay, safer_and_peds); // add a mixin OSMSpecifier gravel = new OSMSpecifier("surface=gravel"); WayProperties gravel_is_dangerous = new WayProperties(); gravel_is_dangerous.setSafetyFeatures(new P2<Double>(2.0, 2.0)); wayPropertySet.addProperties(gravel, gravel_is_dangerous, true); dataForWay = wayPropertySet.getDataForWay(way); assertEquals(dataForWay.getSafetyFeatures().getFirst(), 1.5); // test a left-right distinction way = new OSMWay(); way.addTag("highway", "footway"); way.addTag("cycleway", "lane"); way.addTag("cycleway:right", "track"); OSMSpecifier track_only = new OSMSpecifier("highway=footway;cycleway=track"); WayProperties track_is_safest = new WayProperties(); track_is_safest.setSafetyFeatures(new P2<Double>(0.25, 0.25)); wayPropertySet.addProperties(track_only, track_is_safest); dataForWay = wayPropertySet.getDataForWay(way); assertEquals(0.25, dataForWay.getSafetyFeatures().getFirst()); // right (with traffic) comes // from track assertEquals(0.75, dataForWay.getSafetyFeatures().getSecond()); // left comes from lane way = new OSMWay(); way.addTag("highway", "footway"); way.addTag("footway", "sidewalk"); way.addTag("RLIS:reviewed", "no"); WayPropertySet propset = new WayPropertySet(); CreativeNamer namer = new CreativeNamer("platform"); propset.addCreativeNamer(new OSMSpecifier( "railway=platform;highway=footway;footway=sidewalk"), namer); namer = new CreativeNamer("sidewalk"); propset.addCreativeNamer(new OSMSpecifier("highway=footway;footway=sidewalk"), namer); assertEquals("sidewalk", propset.getCreativeNameForWay(way)); } @Test public void testCreativeNaming() { OSMWithTags way = new OSMWay(); way.addTag("highway", "footway"); way.addTag("cycleway", "lane"); way.addTag("access", "no"); CreativeNamer namer = new CreativeNamer(); namer.setCreativeNamePattern("Highway with cycleway {cycleway} and access {access} and morx {morx}"); assertEquals("Highway with cycleway lane and access no and morx ", namer.generateCreativeName(way)); } // disabled pending discussion with author (AMB) // @Test // public void testMultipolygon() throws Exception { // Graph gg = new Graph(); // OpenStreetMapGraphBuilderImpl loader = new OpenStreetMapGraphBuilderImpl(); // // FileBasedOpenStreetMapProviderImpl pr = new FileBasedOpenStreetMapProviderImpl(); // pr.setPath(new File(getClass().getResource("otp-multipolygon-test.osm").getPath())); // loader.setProvider(pr); // // loader.buildGraph(gg, extra); // // assertNotNull(gg.getVertex("way -3535 from 4")); // } }