/*
* Licensed to GraphHopper GmbH under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*
* GraphHopper GmbH licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.graphhopper.routing;
import com.carrotsearch.hppc.IntObjectMap;
import com.graphhopper.routing.util.*;
import com.graphhopper.routing.weighting.FastestWeighting;
import com.graphhopper.routing.weighting.TurnWeighting;
import com.graphhopper.storage.*;
import com.graphhopper.storage.index.QueryResult;
import com.graphhopper.util.*;
import com.graphhopper.util.shapes.GHPoint;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import static com.graphhopper.storage.index.QueryResult.Position.*;
import static org.junit.Assert.*;
/**
* @author Peter Karich
*/
public class QueryGraphTest {
private EncodingManager encodingManager;
private FlagEncoder carEncoder;
private GraphHopperStorage g;
@Before
public void setUp() {
carEncoder = new CarFlagEncoder();
encodingManager = new EncodingManager(carEncoder);
g = new GraphHopperStorage(new RAMDirectory(), encodingManager, false, new GraphExtension.NoOpExtension()).create(100);
}
@After
public void tearDown() {
g.close();
}
void initGraph(Graph g) {
//
// /*-*\
// 0 1
// |
// 2
NodeAccess na = g.getNodeAccess();
na.setNode(0, 1, 0);
na.setNode(1, 1, 2.5);
na.setNode(2, 0, 0);
g.edge(0, 2, 10, true);
g.edge(0, 1, 10, true).setWayGeometry(Helper.createPointList(1.5, 1, 1.5, 1.5));
}
@Test
public void testOneVirtualNode() {
initGraph(g);
EdgeExplorer expl = g.createEdgeExplorer();
// snap directly to tower node => pointList could get of size 1?!?
// a)
EdgeIterator iter = expl.setBaseNode(2);
iter.next();
QueryGraph queryGraph = new QueryGraph(g);
QueryResult res = createLocationResult(1, -1, iter, 0, TOWER);
queryGraph.lookup(Arrays.asList(res));
assertEquals(new GHPoint(0, 0), res.getSnappedPoint());
// b)
res = createLocationResult(1, -1, iter, 1, TOWER);
queryGraph = new QueryGraph(g);
queryGraph.lookup(Arrays.asList(res));
assertEquals(new GHPoint(1, 0), res.getSnappedPoint());
// c)
iter = expl.setBaseNode(1);
iter.next();
res = createLocationResult(1.2, 2.7, iter, 0, TOWER);
queryGraph = new QueryGraph(g);
queryGraph.lookup(Arrays.asList(res));
assertEquals(new GHPoint(1, 2.5), res.getSnappedPoint());
// node number stays
assertEquals(3, queryGraph.getNodes());
// snap directly to pillar node
queryGraph = new QueryGraph(g);
iter = expl.setBaseNode(1);
iter.next();
res = createLocationResult(2, 1.5, iter, 1, PILLAR);
queryGraph.lookup(Arrays.asList(res));
assertEquals(new GHPoint(1.5, 1.5), res.getSnappedPoint());
assertEquals(3, res.getClosestNode());
assertEquals(4, getPoints(queryGraph, 0, 3).getSize());
assertEquals(2, getPoints(queryGraph, 3, 1).getSize());
queryGraph = new QueryGraph(g);
res = createLocationResult(2, 1.7, iter, 1, PILLAR);
queryGraph.lookup(Arrays.asList(res));
assertEquals(new GHPoint(1.5, 1.5), res.getSnappedPoint());
assertEquals(3, res.getClosestNode());
assertEquals(4, getPoints(queryGraph, 0, 3).getSize());
assertEquals(2, getPoints(queryGraph, 3, 1).getSize());
// snap to edge which has pillar nodes
queryGraph = new QueryGraph(g);
res = createLocationResult(1.5, 2, iter, 0, EDGE);
queryGraph.lookup(Arrays.asList(res));
assertEquals(new GHPoint(1.300019, 1.899962), res.getSnappedPoint());
assertEquals(3, res.getClosestNode());
assertEquals(4, getPoints(queryGraph, 0, 3).getSize());
assertEquals(2, getPoints(queryGraph, 3, 1).getSize());
// snap to edge which has no pillar nodes
queryGraph = new QueryGraph(g);
iter = expl.setBaseNode(2);
iter.next();
res = createLocationResult(0.5, 0.1, iter, 0, EDGE);
queryGraph.lookup(Arrays.asList(res));
assertEquals(new GHPoint(0.5, 0), res.getSnappedPoint());
assertEquals(3, res.getClosestNode());
assertEquals(2, getPoints(queryGraph, 0, 3).getSize());
assertEquals(2, getPoints(queryGraph, 3, 2).getSize());
}
@Test
public void testFillVirtualEdges() {
initGraph(g);
g.getNodeAccess().setNode(3, 0, 1);
g.edge(1, 3);
final int baseNode = 1;
EdgeIterator iter = g.createEdgeExplorer().setBaseNode(baseNode);
iter.next();
QueryResult res1 = createLocationResult(2, 1.7, iter, 1, PILLAR);
QueryGraph queryGraph = new QueryGraph(g) {
@Override
void fillVirtualEdges(IntObjectMap<VirtualEdgeIterator> node2Edge, int towerNode, EdgeExplorer mainExpl) {
super.fillVirtualEdges(node2Edge, towerNode, mainExpl);
// ignore nodes should include baseNode == 1
if (towerNode == 3)
assertEquals("[3->4]", node2Edge.get(towerNode).toString());
else if (towerNode == 1)
assertEquals("[1->4, 1 1-0]", node2Edge.get(towerNode).toString());
else
throw new IllegalStateException("not allowed " + towerNode);
}
};
queryGraph.lookup(Arrays.asList(res1));
EdgeIteratorState state = GHUtility.getEdge(queryGraph, 0, 1);
assertEquals(4, state.fetchWayGeometry(3).size());
// fetch virtual edge and check way geometry
state = GHUtility.getEdge(queryGraph, 4, 3);
assertEquals(2, state.fetchWayGeometry(3).size());
}
@Test
public void testMultipleVirtualNodes() {
initGraph(g);
// snap to edge which has pillar nodes
EdgeIterator iter = g.createEdgeExplorer().setBaseNode(1);
iter.next();
QueryResult res1 = createLocationResult(2, 1.7, iter, 1, PILLAR);
QueryGraph queryGraph = new QueryGraph(g);
queryGraph.lookup(Arrays.asList(res1));
assertEquals(new GHPoint(1.5, 1.5), res1.getSnappedPoint());
assertEquals(3, res1.getClosestNode());
assertEquals(4, getPoints(queryGraph, 0, 3).getSize());
PointList pl = getPoints(queryGraph, 3, 1);
assertEquals(2, pl.getSize());
assertEquals(new GHPoint(1.5, 1.5), pl.toGHPoint(0));
assertEquals(new GHPoint(1, 2.5), pl.toGHPoint(1));
EdgeIteratorState edge = GHUtility.getEdge(queryGraph, 3, 1);
assertNotNull(queryGraph.getEdgeIteratorState(edge.getEdge(), 3));
assertNotNull(queryGraph.getEdgeIteratorState(edge.getEdge(), 1));
edge = GHUtility.getEdge(queryGraph, 3, 0);
assertNotNull(queryGraph.getEdgeIteratorState(edge.getEdge(), 3));
assertNotNull(queryGraph.getEdgeIteratorState(edge.getEdge(), 0));
// snap again => new virtual node on same edge!
iter = g.createEdgeExplorer().setBaseNode(1);
iter.next();
res1 = createLocationResult(2, 1.7, iter, 1, PILLAR);
QueryResult res2 = createLocationResult(1.5, 2, iter, 0, EDGE);
queryGraph = new QueryGraph(g);
queryGraph.lookup(Arrays.asList(res1, res2));
assertEquals(4, res2.getClosestNode());
assertEquals(new GHPoint(1.300019, 1.899962), res2.getSnappedPoint());
assertEquals(3, res1.getClosestNode());
assertEquals(new GHPoint(1.5, 1.5), res1.getSnappedPoint());
assertEquals(4, getPoints(queryGraph, 3, 0).getSize());
assertEquals(2, getPoints(queryGraph, 3, 4).getSize());
assertEquals(2, getPoints(queryGraph, 4, 1).getSize());
assertNull(GHUtility.getEdge(queryGraph, 4, 0));
assertNull(GHUtility.getEdge(queryGraph, 3, 1));
}
@Test
public void testOneWay() {
NodeAccess na = g.getNodeAccess();
na.setNode(0, 0, 0);
na.setNode(1, 0, 1);
g.edge(0, 1, 10, false);
EdgeIteratorState edge = GHUtility.getEdge(g, 0, 1);
QueryResult res1 = createLocationResult(0.1, 0.1, edge, 0, EDGE);
QueryResult res2 = createLocationResult(0.1, 0.9, edge, 0, EDGE);
QueryGraph queryGraph = new QueryGraph(g);
queryGraph.lookup(Arrays.asList(res2, res1));
assertEquals(2, res1.getClosestNode());
assertEquals(new GHPoint(0, 0.1), res1.getSnappedPoint());
assertEquals(3, res2.getClosestNode());
assertEquals(new GHPoint(0, 0.9), res2.getSnappedPoint());
assertEquals(2, getPoints(queryGraph, 0, 2).getSize());
assertEquals(2, getPoints(queryGraph, 2, 3).getSize());
assertEquals(2, getPoints(queryGraph, 3, 1).getSize());
assertNull(GHUtility.getEdge(queryGraph, 3, 0));
assertNull(GHUtility.getEdge(queryGraph, 2, 1));
}
@Test
public void testVirtEdges() {
initGraph(g);
EdgeIterator iter = g.createEdgeExplorer().setBaseNode(0);
iter.next();
VirtualEdgeIterator vi = new VirtualEdgeIterator(2);
vi.add(iter.detach(false));
assertTrue(vi.next());
}
@Test
public void testUseMeanElevation() {
g.close();
g = new GraphHopperStorage(new RAMDirectory(), encodingManager, true, new GraphExtension.NoOpExtension()).create(100);
NodeAccess na = g.getNodeAccess();
na.setNode(0, 0, 0, 0);
na.setNode(1, 0, 0.0001, 20);
EdgeIteratorState edge = g.edge(0, 1);
EdgeIteratorState edgeReverse = edge.detach(true);
DistanceCalc2D distCalc = new DistanceCalc2D();
QueryResult qr = new QueryResult(0, 0.00005);
qr.setClosestEdge(edge);
qr.setWayIndex(0);
qr.setSnappedPosition(EDGE);
qr.calcSnappedPoint(distCalc);
assertEquals(10, qr.getSnappedPoint().getEle(), 1e-1);
qr = new QueryResult(0, 0.00005);
qr.setClosestEdge(edgeReverse);
qr.setWayIndex(0);
qr.setSnappedPosition(EDGE);
qr.calcSnappedPoint(distCalc);
assertEquals(10, qr.getSnappedPoint().getEle(), 1e-1);
}
@Test
public void testLoopStreet_Issue151() {
// do query at x should result in ignoring only the bottom edge 1-3 not the upper one => getNeighbors are 0, 5, 3 and not only 0, 5
//
// 0--1--3--4
// | |
// x---
//
g.edge(0, 1, 10, true);
g.edge(1, 3, 10, true);
g.edge(3, 4, 10, true);
EdgeIteratorState edge = g.edge(1, 3, 20, true).setWayGeometry(Helper.createPointList(-0.001, 0.001, -0.001, 0.002));
AbstractRoutingAlgorithmTester.updateDistancesFor(g, 0, 0, 0);
AbstractRoutingAlgorithmTester.updateDistancesFor(g, 1, 0, 0.001);
AbstractRoutingAlgorithmTester.updateDistancesFor(g, 3, 0, 0.002);
AbstractRoutingAlgorithmTester.updateDistancesFor(g, 4, 0, 0.003);
QueryResult qr = new QueryResult(-0.0005, 0.001);
qr.setClosestEdge(edge);
qr.setWayIndex(1);
qr.calcSnappedPoint(new DistanceCalc2D());
QueryGraph qg = new QueryGraph(g);
qg.lookup(Arrays.asList(qr));
EdgeExplorer ee = qg.createEdgeExplorer();
assertEquals(GHUtility.asSet(0, 5, 3), GHUtility.getNeighbors(ee.setBaseNode(1)));
}
@Test
public void testOneWayLoop_Issue162() {
// do query at x, where edge is oneway
//
// |\
// | x
// 0<-\
// |
// 1
NodeAccess na = g.getNodeAccess();
na.setNode(0, 0, 0);
na.setNode(1, 0, -0.001);
g.edge(0, 1, 10, true);
// in the case of identical nodes the wayGeometry defines the direction!
EdgeIteratorState edge = g.edge(0, 0).
setDistance(100).
setFlags(carEncoder.setProperties(20, true, false)).
setWayGeometry(Helper.createPointList(0.001, 0, 0, 0.001));
QueryResult qr = new QueryResult(0.0011, 0.0009);
qr.setClosestEdge(edge);
qr.setWayIndex(1);
qr.calcSnappedPoint(new DistanceCalc2D());
QueryGraph qg = new QueryGraph(g);
qg.lookup(Arrays.asList(qr));
EdgeExplorer ee = qg.createEdgeExplorer();
assertTrue(qr.getClosestNode() > 1);
assertEquals(2, GHUtility.count(ee.setBaseNode(qr.getClosestNode())));
EdgeIterator iter = ee.setBaseNode(qr.getClosestNode());
iter.next();
assertTrue(iter.toString(), iter.isForward(carEncoder));
assertFalse(iter.toString(), iter.isBackward(carEncoder));
iter.next();
assertFalse(iter.toString(), iter.isForward(carEncoder));
assertTrue(iter.toString(), iter.isBackward(carEncoder));
}
@Test
public void testEdgesShareOneNode() {
initGraph(g);
EdgeIteratorState iter = GHUtility.getEdge(g, 0, 2);
QueryResult res1 = createLocationResult(0.5, 0, iter, 0, EDGE);
iter = GHUtility.getEdge(g, 1, 0);
QueryResult res2 = createLocationResult(1.5, 2, iter, 0, EDGE);
QueryGraph queryGraph = new QueryGraph(g);
queryGraph.lookup(Arrays.asList(res1, res2));
assertEquals(new GHPoint(0.5, 0), res1.getSnappedPoint());
assertEquals(new GHPoint(1.300019, 1.899962), res2.getSnappedPoint());
assertNotNull(GHUtility.getEdge(queryGraph, 0, 4));
assertNotNull(GHUtility.getEdge(queryGraph, 0, 3));
}
@Test
public void testAvoidDuplicateVirtualNodesIfIdentical() {
initGraph(g);
EdgeIteratorState edgeState = GHUtility.getEdge(g, 0, 2);
QueryResult res1 = createLocationResult(0.5, 0, edgeState, 0, EDGE);
QueryResult res2 = createLocationResult(0.5, 0, edgeState, 0, EDGE);
QueryGraph queryGraph = new QueryGraph(g);
queryGraph.lookup(Arrays.asList(res1, res2));
assertEquals(new GHPoint(0.5, 0), res1.getSnappedPoint());
assertEquals(new GHPoint(0.5, 0), res2.getSnappedPoint());
assertEquals(3, res1.getClosestNode());
assertEquals(3, res2.getClosestNode());
// force skip due to **tower** node snapping in phase 2, but no virtual edges should be created for res1
edgeState = GHUtility.getEdge(g, 0, 1);
res1 = createLocationResult(1, 0, edgeState, 0, EDGE);
// now create virtual edges
edgeState = GHUtility.getEdge(g, 0, 2);
res2 = createLocationResult(0.5, 0, edgeState, 0, EDGE);
queryGraph = new QueryGraph(g);
queryGraph.lookup(Arrays.asList(res1, res2));
// make sure only one virtual node was created
assertEquals(queryGraph.getNodes(), g.getNodes() + 1);
EdgeIterator iter = queryGraph.createEdgeExplorer().setBaseNode(0);
assertEquals(GHUtility.asSet(1, 3), GHUtility.getNeighbors(iter));
}
@Test
public void testGetEdgeProps() {
initGraph(g);
EdgeIteratorState e1 = GHUtility.getEdge(g, 0, 2);
QueryGraph queryGraph = new QueryGraph(g);
QueryResult res1 = createLocationResult(0.5, 0, e1, 0, EDGE);
queryGraph.lookup(Arrays.asList(res1));
// get virtual edge
e1 = GHUtility.getEdge(queryGraph, res1.getClosestNode(), 0);
EdgeIteratorState e2 = queryGraph.getEdgeIteratorState(e1.getEdge(), Integer.MIN_VALUE);
assertEquals(e1.getEdge(), e2.getEdge());
}
PointList getPoints(Graph g, int base, int adj) {
EdgeIteratorState edge = GHUtility.getEdge(g, base, adj);
if (edge == null)
throw new IllegalStateException("edge " + base + "-" + adj + " not found");
return edge.fetchWayGeometry(3);
}
public QueryResult createLocationResult(double lat, double lon,
EdgeIteratorState edge, int wayIndex, QueryResult.Position pos) {
if (edge == null)
throw new IllegalStateException("Specify edge != null");
QueryResult tmp = new QueryResult(lat, lon);
tmp.setClosestEdge(edge);
tmp.setWayIndex(wayIndex);
tmp.setSnappedPosition(pos);
tmp.calcSnappedPoint(new DistanceCalcEarth());
return tmp;
}
@Test
public void testIteration_Issue163() {
EdgeFilter outEdgeFilter = new DefaultEdgeFilter(encodingManager.getEncoder("car"), false, true);
EdgeFilter inEdgeFilter = new DefaultEdgeFilter(encodingManager.getEncoder("car"), true, false);
EdgeExplorer inExplorer = g.createEdgeExplorer(inEdgeFilter);
EdgeExplorer outExplorer = g.createEdgeExplorer(outEdgeFilter);
int nodeA = 0;
int nodeB = 1;
/* init test graph: one directional edge going from A to B, via virtual nodes C and D
*
* (C)-(D)
* / \
* A B
*/
g.getNodeAccess().setNode(nodeA, 1, 0);
g.getNodeAccess().setNode(nodeB, 1, 10);
g.edge(nodeA, nodeB, 10, false).setWayGeometry(Helper.createPointList(1.5, 3, 1.5, 7));
// assert the behavior for classic edgeIterator
assertEdgeIdsStayingEqual(inExplorer, outExplorer, nodeA, nodeB);
// setup query results
EdgeIteratorState it = GHUtility.getEdge(g, nodeA, nodeB);
QueryResult res1 = createLocationResult(1.5, 3, it, 1, QueryResult.Position.EDGE);
QueryResult res2 = createLocationResult(1.5, 7, it, 2, QueryResult.Position.EDGE);
QueryGraph q = new QueryGraph(g);
q.lookup(Arrays.asList(res1, res2));
int nodeC = res1.getClosestNode();
int nodeD = res2.getClosestNode();
inExplorer = q.createEdgeExplorer(inEdgeFilter);
outExplorer = q.createEdgeExplorer(outEdgeFilter);
// assert the same behavior for queryGraph
assertEdgeIdsStayingEqual(inExplorer, outExplorer, nodeA, nodeC);
assertEdgeIdsStayingEqual(inExplorer, outExplorer, nodeC, nodeD);
assertEdgeIdsStayingEqual(inExplorer, outExplorer, nodeD, nodeB);
}
private void assertEdgeIdsStayingEqual(EdgeExplorer inExplorer, EdgeExplorer outExplorer, int startNode, int endNode) {
EdgeIterator it = outExplorer.setBaseNode(startNode);
it.next();
assertEquals(startNode, it.getBaseNode());
assertEquals(endNode, it.getAdjNode());
// we expect the edge id to be the same when exploring in backward direction
int expectedEdgeId = it.getEdge();
assertFalse(it.next());
// backward iteration, edge id should remain the same!!
it = inExplorer.setBaseNode(endNode);
it.next();
assertEquals(endNode, it.getBaseNode());
assertEquals(startNode, it.getAdjNode());
assertEquals("The edge id is not the same,", expectedEdgeId, it.getEdge());
assertFalse(it.next());
}
@Test
public void testTurnCostsProperlyPropagated_Issue282() {
TurnCostExtension turnExt = new TurnCostExtension();
FlagEncoder encoder = new CarFlagEncoder(5, 5, 15);
GraphHopperStorage graphWithTurnCosts = new GraphHopperStorage(new RAMDirectory(),
new EncodingManager(encoder), false, turnExt).
create(100);
NodeAccess na = graphWithTurnCosts.getNodeAccess();
na.setNode(0, .00, .00);
na.setNode(1, .00, .01);
na.setNode(2, .01, .01);
EdgeIteratorState edge0 = graphWithTurnCosts.edge(0, 1, 10, true);
EdgeIteratorState edge1 = graphWithTurnCosts.edge(2, 1, 10, true);
QueryGraph qGraph = new QueryGraph(graphWithTurnCosts);
FastestWeighting weighting = new FastestWeighting(encoder);
TurnWeighting turnWeighting = new TurnWeighting(weighting, (TurnCostExtension) qGraph.getExtension());
assertEquals(0, turnWeighting.calcTurnWeight(edge0.getEdge(), 1, edge1.getEdge()), .1);
// now use turn costs and QueryGraph
turnExt.addTurnInfo(edge0.getEdge(), 1, edge1.getEdge(), encoder.getTurnFlags(false, 10));
assertEquals(10, turnWeighting.calcTurnWeight(edge0.getEdge(), 1, edge1.getEdge()), .1);
QueryResult res1 = createLocationResult(0.000, 0.005, edge0, 0, QueryResult.Position.EDGE);
QueryResult res2 = createLocationResult(0.005, 0.010, edge1, 0, QueryResult.Position.EDGE);
qGraph.lookup(Arrays.asList(res1, res2));
int fromQueryEdge = GHUtility.getEdge(qGraph, res1.getClosestNode(), 1).getEdge();
int toQueryEdge = GHUtility.getEdge(qGraph, res2.getClosestNode(), 1).getEdge();
assertEquals(10, turnWeighting.calcTurnWeight(fromQueryEdge, 1, toQueryEdge), .1);
graphWithTurnCosts.close();
}
private void initHorseshoeGraph(Graph g) {
// setup graph
// ____
// | |
// | |
// 0 1
NodeAccess na = g.getNodeAccess();
na.setNode(0, 0, 0);
na.setNode(1, 0, 2);
g.edge(0, 1, 10, true).setWayGeometry(Helper.createPointList(2, 0, 2, 2));
}
private QueryResult fakeEdgeQueryResult(EdgeIteratorState edge, double lat, double lon, int wayIndex) {
QueryResult qr = new QueryResult(lat, lon);
qr.setClosestEdge(edge);
qr.setWayIndex(wayIndex);
qr.setSnappedPosition(EDGE);
qr.calcSnappedPoint(new DistanceCalc2D());
return qr;
}
private boolean isAvoidEdge(QueryGraph queryGraph, int virtualEdgeTypeId, boolean _default) {
boolean avoidEdge = queryGraph.virtualEdges.get(virtualEdgeTypeId).getBool(EdgeIteratorState.K_UNFAVORED_EDGE, _default);
return avoidEdge;
}
@Test
public void testEnforceHeading() {
initHorseshoeGraph(g);
EdgeIteratorState edge = GHUtility.getEdge(g, 0, 1);
// query result on first vertical part of way (upward)
QueryResult qr = fakeEdgeQueryResult(edge, 1.5, 0, 0);
QueryGraph queryGraph = new QueryGraph(g);
queryGraph.lookup(Arrays.asList(qr));
// enforce going out north
queryGraph.enforceHeading(qr.getClosestNode(), 0., false);
// test penalized south
boolean expect = true;
assertEquals(expect, isAvoidEdge(queryGraph, QueryGraph.VE_BASE_REV, !expect));
assertEquals(expect, isAvoidEdge(queryGraph, QueryGraph.VE_BASE, !expect));
queryGraph.clearUnfavoredStatus();
// test cleared edges south
expect = false;
assertEquals(expect, isAvoidEdge(queryGraph, QueryGraph.VE_BASE_REV, !expect));
assertEquals(expect, isAvoidEdge(queryGraph, QueryGraph.VE_BASE, !expect));
// enforce coming in north
queryGraph.enforceHeading(qr.getClosestNode(), 180., true);
// test penalized south
expect = true;
assertEquals(expect, isAvoidEdge(queryGraph, QueryGraph.VE_BASE_REV, !expect));
assertEquals(expect, isAvoidEdge(queryGraph, QueryGraph.VE_BASE, !expect));
// query result on second vertical part of way (downward)
qr = fakeEdgeQueryResult(edge, 1.5, 2, 2);
queryGraph = new QueryGraph(g);
queryGraph.lookup(Arrays.asList(qr));
// enforce going north
queryGraph.enforceHeading(qr.getClosestNode(), 0., false);
// test penalized south
expect = true;
assertEquals(expect, isAvoidEdge(queryGraph, QueryGraph.VE_ADJ, !expect));
assertEquals(expect, isAvoidEdge(queryGraph, QueryGraph.VE_ADJ_REV, !expect));
queryGraph.clearUnfavoredStatus();
// enforce coming in north
queryGraph.enforceHeading(qr.getClosestNode(), 180., true);
// test penalized south
expect = true;
assertEquals(expect, isAvoidEdge(queryGraph, QueryGraph.VE_ADJ, !expect));
assertEquals(expect, isAvoidEdge(queryGraph, QueryGraph.VE_ADJ_REV, !expect));
}
@Test
public void testunfavorVirtualEdgePair() {
initHorseshoeGraph(g);
EdgeIteratorState edge = GHUtility.getEdge(g, 0, 1);
// query result on first vertical part of way (upward)
QueryResult qr = fakeEdgeQueryResult(edge, 1.5, 0, 0);
QueryGraph queryGraph = new QueryGraph(g);
queryGraph.lookup(Arrays.asList(qr));
// enforce coming in north
queryGraph.unfavorVirtualEdgePair(2, 1);
// test penalized south
VirtualEdgeIteratorState incomingEdge = (VirtualEdgeIteratorState) queryGraph.getEdgeIteratorState(1, 2);
VirtualEdgeIteratorState incomingEdgeReverse = (VirtualEdgeIteratorState) queryGraph.getEdgeIteratorState(1, incomingEdge.getBaseNode());
boolean expect = true; // expect incoming and reverse incoming edge to be avoided
assertEquals(expect, incomingEdge.getBool(EdgeIteratorState.K_UNFAVORED_EDGE, !expect));
assertEquals(expect, incomingEdgeReverse.getBool(EdgeIteratorState.K_UNFAVORED_EDGE, !expect));
assertEquals(new LinkedHashSet<>(Arrays.asList(incomingEdge, incomingEdgeReverse)),
queryGraph.getUnfavoredVirtualEdges());
queryGraph.clearUnfavoredStatus();
expect = false; // expect incoming and reverse incoming edge not to be avoided
assertEquals(expect, incomingEdge.getBool(EdgeIteratorState.K_UNFAVORED_EDGE, !expect));
assertEquals(expect, incomingEdgeReverse.getBool(EdgeIteratorState.K_UNFAVORED_EDGE, !expect));
assertEquals(new LinkedHashSet<>(), queryGraph.getUnfavoredVirtualEdges());
}
@Test
public void testInternalAPIOriginalTraversalKey() {
initGraph(g);
EdgeExplorer explorer = g.createEdgeExplorer();
QueryGraph queryGraph = new QueryGraph(g);
EdgeIterator iter = explorer.setBaseNode(1);
assertTrue(iter.next());
int origEdgeId = iter.getEdge();
QueryResult res = createLocationResult(2, 1.5, iter, 1, PILLAR);
queryGraph.lookup(Arrays.asList(res));
assertEquals(new GHPoint(1.5, 1.5), res.getSnappedPoint());
assertEquals(3, res.getClosestNode());
EdgeExplorer qGraphExplorer = queryGraph.createEdgeExplorer();
iter = qGraphExplorer.setBaseNode(3);
assertTrue(iter.next());
assertEquals(0, iter.getAdjNode());
assertEquals(GHUtility.createEdgeKey(1, 0, origEdgeId, false),
((VirtualEdgeIteratorState) queryGraph.getEdgeIteratorState(iter.getEdge(), 0)).getOriginalTraversalKey());
assertTrue(iter.next());
assertEquals(1, iter.getAdjNode());
assertEquals(GHUtility.createEdgeKey(0, 1, origEdgeId, false),
((VirtualEdgeIteratorState) queryGraph.getEdgeIteratorState(iter.getEdge(), 1)).getOriginalTraversalKey());
}
@Test
public void useEECache() {
initGraph(g);
EdgeExplorer explorer = g.createEdgeExplorer();
EdgeIterator iter = explorer.setBaseNode(1);
assertTrue(iter.next());
QueryResult res = createLocationResult(2, 1.5, iter, 1, PILLAR);
QueryGraph queryGraph = new QueryGraph(g).setUseEdgeExplorerCache(true);
queryGraph.lookup(Arrays.asList(res));
EdgeExplorer edgeExplorer = queryGraph.createEdgeExplorer();
// using cache means same reference
assertTrue(edgeExplorer == queryGraph.createEdgeExplorer());
}
}