/* 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.routing.edgetype.factory;
import java.util.HashSet;
import org.opentripplanner.common.pqueue.BinHeap;
import org.opentripplanner.routing.algorithm.NegativeWeightException;
import org.opentripplanner.routing.core.State;
import org.opentripplanner.routing.core.TraverseMode;
import org.opentripplanner.routing.core.TraverseModeSet;
import org.opentripplanner.routing.core.RoutingRequest;
import org.opentripplanner.routing.graph.Edge;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.routing.graph.Vertex;
import org.opentripplanner.routing.spt.BasicShortestPathTree;
import org.opentripplanner.routing.vertextype.StreetVertex;
import org.opentripplanner.routing.vertextype.TransitStop;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FindMaxWalkDistances {
private final static Logger LOG = LoggerFactory.getLogger(FindMaxWalkDistances.class);
public static void find(Graph graph) {
LOG.debug("finding max walk distances");
for (Vertex gv : graph.getVertices()) {
gv.setDistanceToNearestTransitStop(Double.MAX_VALUE);
}
for (Vertex gv : graph.getVertices()) {
if (gv instanceof TransitStop) {
assignStopDistances(graph, (TransitStop) gv);
}
}
for (Vertex gv : graph.getVertices()) {
if (gv.getDistanceToNearestTransitStop() == Double.MAX_VALUE) {
/* transit vertices don't get explored by assignStopDistances */
gv.setDistanceToNearestTransitStop(0);
}
}
}
/**
* TODO - Can this reuse one of the existing search algorithms?
*/
private static void assignStopDistances(Graph graph, TransitStop origin) {
RoutingRequest options = new RoutingRequest(new TraverseModeSet(TraverseMode.WALK));
options.setMaxWalkDistance(Double.MAX_VALUE);
options.walkReluctance = 1.0;
options.setWalkSpeed(1.0);
// Iteration Variables
State u, v;
HashSet<Vertex> closed = new HashSet<Vertex>();
BinHeap<State> queue = new BinHeap<State>(50);
BasicShortestPathTree spt = new BasicShortestPathTree(options);
State init = new State(origin, options);
spt.add(init);
queue.insert(init, init.getWeight());
while (!queue.empty()) { // Until the priority queue is empty:
u = queue.extract_min(); // get the lowest-weightSum Vertex 'u',
Vertex fromv = u.getVertex();
closed.add(fromv);
Iterable<Edge> outgoing = fromv.getOutgoing();
for (Edge edge : outgoing) {
v = edge.traverse(u);
// When an edge leads nowhere (as indicated by returning NULL), the iteration is
// over.
if (v == null)
continue;
double dw = v.getWeightDelta();
if (dw < 0) {
throw new NegativeWeightException(String.valueOf(dw));
}
Vertex toVertex = v.getVertex();
if (closed.contains(toVertex)) {
continue;
}
double new_w = v.getWeight();
if (toVertex instanceof StreetVertex) {
StreetVertex sv = (StreetVertex) toVertex;
if (sv.getDistanceToNearestTransitStop() <= new_w) {
continue;
}
sv.setDistanceToNearestTransitStop(new_w);
}
if (spt.add(v))
queue.insert(v, new_w);
}
}
}
}