/* 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.map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
import org.opentripplanner.common.TurnRestriction;
import org.opentripplanner.common.geometry.PackedCoordinateSequence;
import org.opentripplanner.routing.core.State;
import org.opentripplanner.routing.core.StateEditor;
import org.opentripplanner.routing.core.TraverseMode;
import org.opentripplanner.routing.core.RoutingRequest;
import org.opentripplanner.routing.core.TraverseModeSet;
import org.opentripplanner.routing.edgetype.StreetEdge;
import org.opentripplanner.routing.edgetype.StreetTraversalPermission;
import org.opentripplanner.routing.graph.Edge;
import org.opentripplanner.routing.graph.Graph;
import org.opentripplanner.common.geometry.SphericalDistanceLibrary;
import org.opentripplanner.routing.patch.Alert;
import org.opentripplanner.routing.util.ElevationProfileSegment;
import org.opentripplanner.routing.vertextype.StreetVertex;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
public class TestStreetMatcher {
static GeometryFactory gf = new GeometryFactory();
private Graph _graph;
@Before
public void before() {
_graph = new Graph();
vertex("56th_24th", 47.669457, -122.387577);
vertex("56th_22nd", 47.669462, -122.384739);
vertex("56th_20th", 47.669457, -122.382106);
vertex("market_24th", 47.668690, -122.387577);
vertex("market_ballard", 47.668683, -122.386096);
vertex("market_22nd", 47.668686, -122.384749);
vertex("market_leary", 47.668669, -122.384392);
vertex("market_russell", 47.668655, -122.382997);
vertex("market_20th", 47.668684, -122.382117);
vertex("shilshole_24th", 47.668419, -122.387534);
vertex("shilshole_22nd", 47.666519, -122.384744);
vertex("shilshole_vernon", 47.665938, -122.384048);
vertex("shilshole_20th", 47.664356, -122.382192);
vertex("ballard_turn", 47.668509, -122.386069);
vertex("ballard_22nd", 47.667624, -122.384744);
vertex("ballard_vernon", 47.666422, -122.383158);
vertex("ballard_20th", 47.665476, -122.382128);
vertex("leary_vernon", 47.666863, -122.382353);
vertex("leary_20th", 47.666682, -122.382160);
vertex("russell_20th", 47.667846, -122.382128);
edges("56th_24th", "56th_22nd", "56th_20th");
edges("56th_24th", "market_24th");
edges("56th_22nd", "market_22nd");
edges("56th_20th", "market_20th");
edges("market_24th", "market_ballard", "market_22nd", "market_leary", "market_russell",
"market_20th");
edges("market_24th", "shilshole_24th", "shilshole_22nd", "shilshole_vernon",
"shilshole_20th");
edges("market_ballard", "ballard_turn", "ballard_22nd", "ballard_vernon", "ballard_20th");
edges("market_leary", "leary_vernon", "leary_20th");
edges("market_russell", "russell_20th");
edges("market_22nd", "ballard_22nd", "shilshole_22nd");
edges("leary_vernon", "ballard_vernon", "shilshole_vernon");
edges("market_20th", "russell_20th", "leary_20th", "ballard_20th", "shilshole_20th");
}
@Test
public void testStreetMatcher() {
LineString geometry = geometry(-122.385689, 47.669484, -122.387384, 47.669470);
StreetMatcher matcher = new StreetMatcher(_graph);
List<Edge> match = matcher.match(geometry);
assertNotNull(match);
assertEquals(1, match.size());
assertEquals("56th_24th", match.get(0).getToVertex().getLabel());
geometry = geometry(-122.385689, 47.669484, -122.387384, 47.669470, -122.387588, 47.669325);
match = matcher.match(geometry);
assertNotNull(match);
assertEquals(2, match.size());
geometry = geometry(-122.385689, 47.669484, -122.387384, 47.669470, -122.387588, 47.669325,
-122.387255, 47.668675);
match = matcher.match(geometry);
assertNotNull(match);
assertEquals(3, match.size());
geometry = geometry(-122.384756, 47.669260, -122.384777, 47.667454, -122.383554, 47.666789,
-122.3825, 47.666);
match = matcher.match(geometry);
assertNotNull(match);
System.out.println(match);
assertEquals(4, match.size());
assertEquals("ballard_20th", match.get(3).getToVertex().getLabel());
}
private LineString geometry(double... ordinates) {
Coordinate[] coords = new Coordinate[ordinates.length / 2];
for (int i = 0; i < ordinates.length; i += 2) {
coords[i / 2] = new Coordinate(ordinates[i], ordinates[i + 1]);
}
return gf.createLineString(coords);
}
/****
* Private Methods
****/
private SimpleVertex vertex(String label, double lat, double lon) {
SimpleVertex v = new SimpleVertex(_graph, label, lat, lon);
return v;
}
private void edges(String... vLabels) {
for (int i = 0; i < vLabels.length - 1; i++) {
StreetVertex vA = (StreetVertex) _graph.getVertex(vLabels[i]);
StreetVertex vB = (StreetVertex) _graph.getVertex(vLabels[i + 1]);
new SimpleEdge(vA, vB);
new SimpleEdge(vB, vA);
}
}
private static class SimpleVertex extends StreetVertex {
private static final long serialVersionUID = 1L;
public SimpleVertex(Graph g, String label, double lat, double lon) {
super(g, label, lon, lat, label);
}
}
private static class SimpleEdge extends StreetEdge {
private static final long serialVersionUID = 1L;
public SimpleEdge(StreetVertex v1, StreetVertex v2) {
super(v1, v2);
}
public Set<Alert> getNotes () {
return null;
}
@Override
public State traverse(State s0) {
double d = getDistance();
TraverseMode mode = s0.getNonTransitMode();
int t = (int) (d / s0.getOptions().getSpeed(mode));
StateEditor s1 = s0.edit(this);
s1.incrementTimeInSeconds(t);
s1.incrementWeight(d);
return s1.makeState();
}
@Override
public String getName() {
return null;
}
@Override
public LineString getGeometry() {
return gf.createLineString(new Coordinate[] { fromv.getCoordinate(),
tov.getCoordinate() });
}
@Override
public double getDistance() {
return SphericalDistanceLibrary.getInstance().distance(getFromVertex().getCoordinate(),
getToVertex().getCoordinate());
}
@Override
public PackedCoordinateSequence getElevationProfile() {
return null;
}
@Override
public PackedCoordinateSequence getElevationProfile(double from, double to) {
return null;
}
@Override
public boolean setElevationProfile(PackedCoordinateSequence elevPCS, boolean computed) {
return false;
}
@Override
public boolean canTraverse(RoutingRequest options) {
return true;
}
@Override
public boolean canTraverse(TraverseModeSet modes) {
return true;
}
@Override
public double getLength() {
return getDistance();
}
@Override
public StreetTraversalPermission getPermission() {
return StreetTraversalPermission.ALL;
}
@Override
public boolean isNoThruTraffic() {
return false;
}
public String toString() {
return "SimpleEdge(" + fromv + ", " + tov + ")";
}
public Set<Alert> getWheelchairNotes () {
return null;
}
@Override
public int getStreetClass() {
return StreetEdge.CLASS_STREET;
}
@Override
public boolean isWheelchairAccessible() {
return true;
}
public boolean isElevationFlattened() {
return false;
}
@Override
public ElevationProfileSegment getElevationProfileSegment() {
return null;
}
@Override
public List<TurnRestriction> getTurnRestrictions() {
return Collections.emptyList();
}
@Override
public float getCarSpeed() {
return 11.2f;
}
@Override
public int getInAngle() {
return 0;
}
@Override
public int getOutAngle() {
return 0;
}
@Override
public void setCarSpeed(float carSpeed) {}
@Override
public String getLabel() {
return "label";
}
}
}