/* 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.algorithm;
import junit.framework.TestCase;
import org.opentripplanner.common.geometry.GeometryUtils;
import org.opentripplanner.routing.algorithm.strategies.InterleavedBidirectionalHeuristic;
import org.opentripplanner.routing.bike_park.BikePark;
import org.opentripplanner.routing.core.RoutingRequest;
import org.opentripplanner.routing.core.State;
import org.opentripplanner.routing.core.TraverseMode;
import org.opentripplanner.routing.core.TraverseModeSet;
import org.opentripplanner.routing.edgetype.*;
import org.opentripplanner.routing.graph.Edge;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.routing.spt.GraphPath;
import org.opentripplanner.routing.spt.ShortestPathTree;
import org.opentripplanner.routing.vertextype.BikeParkVertex;
import org.opentripplanner.routing.vertextype.IntersectionVertex;
import org.opentripplanner.routing.vertextype.ParkAndRideVertex;
import org.opentripplanner.routing.vertextype.StreetVertex;
import org.opentripplanner.util.NonLocalizedString;
/**
* Test P+R (both car P+R and bike P+R).
*
* @author laurent
*/
public class TestParkAndRide extends TestCase {
private Graph graph;
private StreetVertex A,B,C,D;
@Override
protected void setUp() throws Exception {
graph = new Graph();
// Generate a very simple graph
A = new IntersectionVertex(graph, "A", 0.000, 45, "A");
B = new IntersectionVertex(graph, "B", 0.001, 45, "B");
C = new IntersectionVertex(graph, "C", 0.002, 45, "C");
D = new IntersectionVertex(graph, "D", 0.003, 45, "D");
@SuppressWarnings("unused")
Edge driveOnly = new StreetEdge(A, B, GeometryUtils.makeLineString(0.000, 45, 0.001, 45),
"AB street", 87, StreetTraversalPermission.CAR, false);
@SuppressWarnings("unused")
Edge walkAndBike = new StreetEdge(B, C, GeometryUtils.makeLineString(0.001, 45, 0.002,
45), "BC street", 87, StreetTraversalPermission.PEDESTRIAN_AND_BICYCLE, false);
@SuppressWarnings("unused")
Edge walkOnly = new StreetEdge(C, D, GeometryUtils.makeLineString(0.002, 45, 0.003,
45), "CD street", 87, StreetTraversalPermission.PEDESTRIAN, false);
};
public void testCar() throws Exception {
AStar aStar = new AStar();
// It is impossible to get from A to C in WALK mode,
RoutingRequest options = new RoutingRequest(new TraverseModeSet("WALK"));
options.setRoutingContext(graph, A, C);
ShortestPathTree tree = aStar.getShortestPathTree(options);
GraphPath path = tree.getPath(C, false);
assertNull(path);
// or CAR+WALK (no P+R).
options = new RoutingRequest("WALK,CAR");
options.freezeTraverseMode();
options.setRoutingContext(graph, A, C);
tree = aStar.getShortestPathTree(options);
path = tree.getPath(C, false);
assertNull(path);
// So we Add a P+R at B.
ParkAndRideVertex PRB = new ParkAndRideVertex(graph, "P+R", "P+R.B", 0.001, 45.00001,
new NonLocalizedString("P+R B"));
new ParkAndRideEdge(PRB);
new ParkAndRideLinkEdge(PRB, B);
new ParkAndRideLinkEdge(B, PRB);
// But it is still impossible to get from A to C by WALK only
// (AB is CAR only).
options = new RoutingRequest("WALK");
options.freezeTraverseMode();
options.setRoutingContext(graph, A, C);
tree = aStar.getShortestPathTree(options);
path = tree.getPath(C, false);
assertNull(path);
// Or CAR only (BC is WALK only).
options = new RoutingRequest("CAR");
options.freezeTraverseMode();
options.setRoutingContext(graph, A, C);
tree = aStar.getShortestPathTree(options);
path = tree.getPath(C, false);
assertNull(path);
// But we can go from A to C with CAR+WALK mode using P+R. arriveBy false
options = new RoutingRequest("WALK,CAR_PARK,TRANSIT");
//options.arriveBy
options.setRoutingContext(graph, A, C);
tree = aStar.getShortestPathTree(options);
path = tree.getPath(C, false);
assertNotNull(path);
// But we can go from A to C with CAR+WALK mode using P+R. arriveBy true
options = new RoutingRequest("WALK,CAR_PARK,TRANSIT");
options.setArriveBy(true);
options.setRoutingContext(graph, A, C);
tree = aStar.getShortestPathTree(options);
path = tree.getPath(A, false);
assertNotNull(path);
// But we can go from A to C with CAR+WALK mode using P+R. arriveBy true interleavedBidiHeuristic
options = new RoutingRequest("WALK,CAR_PARK,TRANSIT");
options.setArriveBy(true);
options.setRoutingContext(graph, A, C);
options.rctx.remainingWeightHeuristic = new InterleavedBidirectionalHeuristic();
tree = aStar.getShortestPathTree(options);
path = tree.getPath(A, false);
assertNotNull(path);
// But we can go from A to C with CAR+WALK mode using P+R. arriveBy false interleavedBidiHeuristic
options = new RoutingRequest("WALK,CAR_PARK,TRANSIT");
//options.arriveBy
options.setRoutingContext(graph, A, C);
options.rctx.remainingWeightHeuristic = new InterleavedBidirectionalHeuristic();
tree = aStar.getShortestPathTree(options);
path = tree.getPath(C, false);
assertNotNull(path);
}
public void testBike() throws Exception {
AStar aStar = new AStar();
// Impossible to get from B to D in BIKE+WALK (no bike P+R).
RoutingRequest options = new RoutingRequest("BICYCLE_PARK,TRANSIT");
options.freezeTraverseMode();
options.setRoutingContext(graph, B, D);
ShortestPathTree tree = aStar.getShortestPathTree(options);
GraphPath path = tree.getPath(D, false);
assertNull(path);
// So we add a bike P+R at C.
BikePark bpc = new BikePark();
bpc.id = "bpc";
bpc.name = "Bike Park C";
bpc.x = 0.002;
bpc.y = 45.00001;
bpc.spacesAvailable = 1;
BikeParkVertex BPRC = new BikeParkVertex(graph, bpc);
new BikeParkEdge(BPRC);
new StreetBikeParkLink(BPRC, C);
new StreetBikeParkLink(C, BPRC);
// Still impossible from B to D by bike only (CD is WALK only).
options = new RoutingRequest("BICYCLE");
options.setRoutingContext(graph, B, D);
tree = aStar.getShortestPathTree(options);
path = tree.getPath(D, false);
assertNotNull(path);
State s = tree.getState(D);
assertFalse(s.isBikeParked());
// TODO backWalkingBike flag is broken
// assertTrue(s.isBackWalkingBike());
assertTrue(s.getBackMode() == TraverseMode.WALK);
// But we can go from B to D using bike P+R.
options = new RoutingRequest("BICYCLE_PARK,WALK,TRANSIT");
options.setRoutingContext(graph, B, D);
tree = aStar.getShortestPathTree(options);
path = tree.getPath(D, false);
assertNotNull(path);
s = tree.getState(D);
assertTrue(s.isBikeParked());
assertFalse(s.isBackWalkingBike());
}
}