org.opentripplanner.graph_builder.module.map.BusRouteStreetMatcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of otp Show documentation
Show all versions of otp Show documentation
The OpenTripPlanner multimodal journey planning system
/* 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 . */
package org.opentripplanner.graph_builder.module.map;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.LineString;
import org.onebusaway.gtfs.model.Route;
import org.opentripplanner.common.geometry.GeometryUtils;
import org.opentripplanner.extra_graph.EdgesForRoute;
import org.opentripplanner.graph_builder.services.GraphBuilderModule;
import org.opentripplanner.routing.core.TraverseMode;
import org.opentripplanner.routing.edgetype.TripPattern;
import org.opentripplanner.routing.graph.Edge;
import org.opentripplanner.routing.graph.Graph;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import org.opentripplanner.routing.impl.DefaultStreetVertexIndexFactory;
/**
* Uses the shapes from GTFS to determine which streets buses drive on. This is used to improve the quality of
* the stop-to-street linkage. It encourages the linker to link to streets where transit actually travels.
*
* GTFS provides a mapping from trips->shapes. This module provides a mapping from stops->trips and shapes->edges.
* Then transitively we get a mapping from stop->edges.
* The edges that "belong" to a stop are favored when linking that stop to the street network.
*/
public class BusRouteStreetMatcher implements GraphBuilderModule {
private static final Logger log = LoggerFactory.getLogger(BusRouteStreetMatcher.class);
public List provides() {
return Arrays.asList("edge matching");
}
public List getPrerequisites() {
return Arrays.asList("streets", "transit");
}
/*
The "extra" parameter is a mechanism for passing arbitrary things between graph builder modules.
Whether or not this is a good idea is open to debate, but that's what it is.
An EdgesForRoute instance is generated by MapBuilder and StreetMatcher, then retrieved later by the
NetworkLinkerLibrary later (actually in LinkRequests).
*/
public void buildGraph(Graph graph, HashMap, Object> extra) {
//Mapbuilder needs transit index
graph.index(new DefaultStreetVertexIndexFactory());
StreetMatcher matcher = new StreetMatcher(graph);
EdgesForRoute edgesForRoute = new EdgesForRoute();
extra.put(EdgesForRoute.class, edgesForRoute);
log.info("Finding corresponding street edges for trip patterns...");
// Why do we need to iterate over the routes? Why not just patterns?
for (Route route : graph.index.routeForId.values()) {
for (TripPattern pattern : graph.index.patternsForRoute.get(route)) {
if (pattern.mode == TraverseMode.BUS) {
/* we can only match geometry to streets on bus routes */
log.debug("Matching {}", pattern);
//If there are no shapes in GTFS pattern geometry is generated
//generated geometry is useless for street matching
//that is why pattern.geometry is null in that case
if (pattern.geometry == null) {
continue;
}
List edges = matcher.match(pattern.geometry);
if (edges == null || edges.isEmpty()) {
log.warn("Could not match to street network: {}", pattern);
continue;
}
List coordinates = new ArrayList();
for (Edge e : edges) {
coordinates.addAll(Arrays.asList(e.getGeometry().getCoordinates()));
edgesForRoute.edgesForRoute.put(route, e);
}
Coordinate[] coordinateArray = new Coordinate[coordinates.size()];
LineString ls = GeometryUtils.getGeometryFactory().createLineString(coordinates.toArray(coordinateArray));
// Replace the pattern's geometry from GTFS with that of the equivalent OSM edges.
pattern.geometry = ls;
}
}
}
}
@Override
public void checkInputs() {
//no file inputs
}
}