All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.opentripplanner.graph_builder.module.map.BusRouteStreetMatcher Maven / Gradle / Ivy

There is a newer version: 2.5.0
Show newest version
/* 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
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy