/* 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.util.HashSet; import org.opentripplanner.common.IterableLibrary; import org.opentripplanner.openstreetmap.model.OSMWithTags; import org.opentripplanner.graph_builder.services.osm.CustomNamer; import org.opentripplanner.routing.edgetype.PlainStreetEdge; import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.routing.graph.Vertex; /** * These rules were developed in consultation with Grant Humphries, PJ Houser, and Mele Sax-Barnett. * They describe which sidewalks and paths in the Portland area should be specially designated in * the narrative. * * @author novalis * */ public class PortlandCustomNamer implements CustomNamer { public static String[] STREET_SUFFIXES = { "Avenue", "Street", "Drive", "Court", "Highway", "Lane", "Way", "Place", "Road", "Boulevard", "Alley" }; public static String[] PATH_WORDS = { "Trail", "Trails", "Greenway", "Esplanade", "Spur", "Loop" }; private HashSet<PlainStreetEdge> nameByOrigin = new HashSet<PlainStreetEdge>(); private HashSet<PlainStreetEdge> nameByDestination = new HashSet<PlainStreetEdge>(); @Override public String name(OSMWithTags way, String defaultName) { if (!way.hasTag("name")) { // this is already a generated name, so there's no need to add any // additional data return defaultName; } if (way.isTag("footway", "sidewalk") || way.isTag("path", "sidewalk")) { if (isStreet(defaultName)) { return sidewalk(defaultName); } } String highway = way.getTag("highway"); if ("footway".equals(highway) || "path".equals(highway) || "cycleway".equals(highway)) { if (!isObviouslyPath(defaultName)) { return path(defaultName); } } if ("pedestrian".equals(highway)) { return pedestrianStreet(defaultName); } return defaultName; } private boolean isStreet(String defaultName) { for (String suffix : STREET_SUFFIXES) { if (defaultName.endsWith(suffix)) { return true; } } return false; } private boolean isObviouslyPath(String defaultName) { for (String word : PATH_WORDS) { if (defaultName.contains(word)) { return true; } } return false; } private String path(String name) { if (!name.toLowerCase().contains("path")) { name = name + " (path)".intern(); } return name; } private String pedestrianStreet(String name) { if (!name.toLowerCase().contains("pedestrian street")) { name = name + " (pedestrian street)".intern(); } return name; } private String sidewalk(String name) { if (!name.toLowerCase().contains("sidewalk")) { name = name + " (sidewalk)".intern(); } return name; } @Override public void nameWithEdge(OSMWithTags way, PlainStreetEdge edge) { if (!edge.hasBogusName()) { return; // this edge already has a real name so there is nothing to do } String highway = way.getTag("highway"); if ("motorway_link".equals(highway) || "trunk_link".equals(highway)) { if (edge.back) { nameByDestination.add(edge); } else { nameByOrigin.add(edge); } } else if ("secondary_link".equals(highway) || "primary_link".equals(highway) || "tertiary_link".equals(highway)) { if (edge.back) { nameByOrigin.add(edge); } else { nameByDestination.add(edge); } } } @Override public void postprocess(Graph graph) { for (PlainStreetEdge e : nameByOrigin) { nameAccordingToOrigin(graph, e, 15); } for (PlainStreetEdge e : nameByDestination) { nameAccordingToDestination(graph, e, 15); } } private String nameAccordingToDestination(Graph graph, PlainStreetEdge e, int maxDepth) { if (maxDepth == 0) { return null; } Vertex toVertex = e.getToVertex(); for (PlainStreetEdge out : IterableLibrary.filter(toVertex.getOutgoing(), PlainStreetEdge.class)) { if (out.hasBogusName()) { String name = nameAccordingToDestination(graph, out, maxDepth - 1); if (name == null) { continue; } e.setName(name); return name; } else { String name = out.getName(); e.setName(name); return name; } } return null; } private String nameAccordingToOrigin(Graph graph, PlainStreetEdge e, int maxDepth) { if (maxDepth == 0) { return null; } Vertex fromVertex = e.getFromVertex(); for (PlainStreetEdge in : IterableLibrary.filter(fromVertex.getIncoming(), PlainStreetEdge.class)) { if (in.hasBogusName()) { String name = nameAccordingToOrigin(graph, in, maxDepth - 1); if (name == null) { continue; } e.setName(name); return name; } else { String name = in.getName(); e.setName(name); return name; } } return null; } }