diff --git a/core/src/main/java/com/graphhopper/routing/QueryGraph.java b/core/src/main/java/com/graphhopper/routing/QueryGraph.java index 10135a8b5e7..e60c3fd6388 100644 --- a/core/src/main/java/com/graphhopper/routing/QueryGraph.java +++ b/core/src/main/java/com/graphhopper/routing/QueryGraph.java @@ -22,6 +22,7 @@ import com.graphhopper.storage.Graph; import com.graphhopper.storage.GraphExtension; import com.graphhopper.storage.NodeAccess; +import com.graphhopper.storage.TurnCostExtension; import com.graphhopper.storage.index.QueryResult; import com.graphhopper.util.*; import com.graphhopper.util.shapes.BBox; @@ -66,6 +67,7 @@ public class QueryGraph implements Graph */ private PointList virtualNodes; private final DistanceCalc distCalc = Helper.DIST_PLANE; + private final GraphExtension wrappedExtension; public QueryGraph( Graph graph ) { @@ -73,6 +75,11 @@ public QueryGraph( Graph graph ) mainNodeAccess = graph.getNodeAccess(); mainNodes = graph.getNodes(); mainEdges = graph.getAllEdges().getCount(); + + if (mainGraph.getExtension() instanceof TurnCostExtension) + wrappedExtension = new QueryGraphTurnExt(this); + else + wrappedExtension = mainGraph.getExtension(); } public Graph getOriginalGraph() @@ -256,6 +263,40 @@ public int compare( QueryResult o1, QueryResult o2 ) }); } + class QueryGraphTurnExt extends TurnCostExtension + { + private final TurnCostExtension mainTurnExtension; + + public QueryGraphTurnExt( QueryGraph qGraph ) + { + this.mainTurnExtension = (TurnCostExtension) mainGraph.getExtension(); + } + + @Override + public long getTurnCostFlags( int edgeFrom, int nodeVia, int edgeTo ) + { + if (isVirtualNode(nodeVia)) + { + return 0; + } else if (isVirtualEdge(edgeFrom) || isVirtualEdge(edgeTo)) + { + if (isVirtualEdge(edgeFrom)) + { + edgeFrom = queryResults.get((edgeFrom - mainEdges) / 4).getClosestEdge().getEdge(); + } + if (isVirtualEdge(edgeTo)) + { + edgeTo = queryResults.get((edgeTo - mainEdges) / 4).getClosestEdge().getEdge(); + } + return mainTurnExtension.getTurnCostFlags(edgeFrom, nodeVia, edgeTo); + + } else + { + return mainTurnExtension.getTurnCostFlags(edgeFrom, nodeVia, edgeTo); + } + } + } + private void createEdges( GHPoint3D prevSnapped, int prevWayIndex, GHPoint3D currSnapped, int wayIndex, PointList fullPL, EdgeIteratorState closestEdge, int prevNodeId, int nodeId, long reverseFlags ) @@ -296,6 +337,16 @@ public NodeAccess getNodeAccess() return nodeAccess; } + private boolean isVirtualNode( int node ) + { + return node >= mainNodes; + } + + private boolean isVirtualEdge( int edgeId ) + { + return edgeId >= mainEdges; + } + private final NodeAccess nodeAccess = new NodeAccess() { @Override @@ -313,7 +364,7 @@ public int getDimension() @Override public double getLatitude( int nodeId ) { - if (nodeId >= mainNodes) + if (isVirtualNode(nodeId)) return virtualNodes.getLatitude(nodeId - mainNodes); return mainNodeAccess.getLatitude(nodeId); } @@ -321,7 +372,7 @@ public double getLatitude( int nodeId ) @Override public double getLongitude( int nodeId ) { - if (nodeId >= mainNodes) + if (isVirtualNode(nodeId)) return virtualNodes.getLongitude(nodeId - mainNodes); return mainNodeAccess.getLongitude(nodeId); } @@ -329,7 +380,7 @@ public double getLongitude( int nodeId ) @Override public double getElevation( int nodeId ) { - if (nodeId >= mainNodes) + if (isVirtualNode(nodeId)) return virtualNodes.getElevation(nodeId - mainNodes); return mainNodeAccess.getElevation(nodeId); } @@ -337,7 +388,7 @@ public double getElevation( int nodeId ) @Override public int getAdditionalNodeField( int nodeId ) { - if (nodeId >= mainNodes) + if (isVirtualNode(nodeId)) return 0; return mainNodeAccess.getAdditionalNodeField(nodeId); } @@ -388,7 +439,7 @@ public BBox getBounds() @Override public EdgeIteratorState getEdgeProps( int origEdgeId, int adjNode ) { - if (origEdgeId < mainEdges) + if (!isVirtualEdge(origEdgeId)) return mainGraph.getEdgeProps(origEdgeId, adjNode); int edgeId = origEdgeId - mainEdges; @@ -507,7 +558,7 @@ private void addVirtualEdges( TIntObjectMap node2EdgeMap, E void fillVirtualEdges( TIntObjectMap node2Edge, int towerNode, EdgeExplorer mainExpl ) { - if (towerNode >= mainNodes) + if (isVirtualNode(towerNode)) throw new IllegalStateException("should not happen:" + towerNode + ", " + node2Edge); VirtualEdgeIterator vIter = node2Edge.get(towerNode); @@ -569,363 +620,11 @@ public Graph copyTo( Graph g ) @Override public GraphExtension getExtension() { - return mainGraph.getExtension(); + return wrappedExtension; } private UnsupportedOperationException exc() { return new UnsupportedOperationException("QueryGraph cannot be modified."); } - - static class VirtualEdgeIterator implements EdgeIterator, EdgeSkipIterState - { - - private final List edges; - private int current; - - public VirtualEdgeIterator( int edgeCount ) - { - edges = new ArrayList(edgeCount); - reset(); - } - - void add( EdgeIteratorState edge ) - { - edges.add(edge); - } - - EdgeIterator reset() - { - current = -1; - return this; - } - - int count() - { - return edges.size(); - } - - @Override - public boolean next() - { - current++; - return current < edges.size(); - } - - @Override - public EdgeIteratorState detach( boolean reverse ) - { - if (reverse) - throw new IllegalStateException("Not yet supported"); - - return edges.get(current); - } - - @Override - public int getEdge() - { - return edges.get(current).getEdge(); - } - - @Override - public int getBaseNode() - { - return edges.get(current).getBaseNode(); - } - - @Override - public int getAdjNode() - { - return edges.get(current).getAdjNode(); - } - - @Override - public PointList fetchWayGeometry( int mode ) - { - return edges.get(current).fetchWayGeometry(mode); - } - - @Override - public EdgeIteratorState setWayGeometry( PointList list ) - { - return edges.get(current).setWayGeometry(list); - } - - @Override - public double getDistance() - { - return edges.get(current).getDistance(); - } - - @Override - public EdgeIteratorState setDistance( double dist ) - { - return edges.get(current).setDistance(dist); - } - - @Override - public long getFlags() - { - return edges.get(current).getFlags(); - } - - @Override - public EdgeIteratorState setFlags( long flags ) - { - return edges.get(current).setFlags(flags); - } - - @Override - public String getName() - { - return edges.get(current).getName(); - } - - @Override - public EdgeIteratorState setName( String name ) - { - return edges.get(current).setName(name); - } - - @Override - public String toString() - { - return edges.toString(); - } - - @Override - public int getAdditionalField() - { - return edges.get(current).getAdditionalField(); - } - - @Override - public EdgeIteratorState setAdditionalField( int value ) - { - return edges.get(current).setAdditionalField(value); - } - - @Override - public EdgeIteratorState copyPropertiesTo( EdgeIteratorState edge ) - { - return edges.get(current).copyPropertiesTo(edge); - } - - @Override - public boolean isShortcut() - { - EdgeIteratorState edge = edges.get(current); - return edge instanceof EdgeSkipIterState && ((EdgeSkipIterState) edge).isShortcut(); - } - - @Override - public double getWeight() - { - // will be called only from PreparationWeighting and if isShortcut is true - return ((EdgeSkipIterState) edges.get(current)).getWeight(); - } - - @Override - public EdgeSkipIterState setWeight( double weight ) - { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public int getSkippedEdge1() - { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public int getSkippedEdge2() - { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public void setSkippedEdges( int edge1, int edge2 ) - { - throw new UnsupportedOperationException("Not supported."); - } - } - - /** - * Creates an edge state decoupled from a graph where nodes, pointList, etc are kept in memory. - */ - private static class VirtualEdgeIState implements EdgeIteratorState, EdgeSkipIterState - { - - private final PointList pointList; - private final int edgeId; - private double distance; - private long flags; - private String name; - private final int baseNode; - private final int adjNode; - - public VirtualEdgeIState( int edgeId, int baseNode, int adjNode, - double distance, long flags, String name, PointList pointList ) - { - this.edgeId = edgeId; - this.baseNode = baseNode; - this.adjNode = adjNode; - this.distance = distance; - this.flags = flags; - this.name = name; - this.pointList = pointList; - } - - @Override - public int getEdge() - { - return edgeId; - } - - @Override - public int getBaseNode() - { - return baseNode; - } - - @Override - public int getAdjNode() - { - return adjNode; - } - - @Override - public PointList fetchWayGeometry( int mode ) - { - if (pointList.getSize() == 0) - return PointList.EMPTY; - - // due to API we need to create a new instance per call! - if (mode == 3) - return pointList.clone(false); - else if (mode == 1) - return pointList.copy(0, pointList.getSize() - 1); - else if (mode == 2) - return pointList.copy(1, pointList.getSize()); - else if (mode == 0) - { - if (pointList.getSize() == 1) - return PointList.EMPTY; - return pointList.copy(1, pointList.getSize() - 1); - } - - throw new UnsupportedOperationException("Illegal mode:" + mode); - } - - @Override - public EdgeIteratorState setWayGeometry( PointList list ) - { - throw new UnsupportedOperationException("Not supported for virtual edge. Set when creating it."); - } - - @Override - public double getDistance() - { - return distance; - } - - @Override - public EdgeIteratorState setDistance( double dist ) - { - this.distance = dist; - return this; - } - - @Override - public long getFlags() - { - return flags; - } - - @Override - public EdgeIteratorState setFlags( long flags ) - { - this.flags = flags; - return this; - } - - @Override - public String getName() - { - return name; - } - - @Override - public EdgeIteratorState setName( String name ) - { - this.name = name; - return this; - } - - @Override - public String toString() - { - return baseNode + "->" + adjNode; - } - - @Override - public boolean isShortcut() - { - return false; - } - - @Override - public int getAdditionalField() - { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public int getSkippedEdge1() - { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public int getSkippedEdge2() - { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public void setSkippedEdges( int edge1, int edge2 ) - { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public EdgeIteratorState detach( boolean reverse ) - { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public EdgeIteratorState setAdditionalField( int value ) - { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public EdgeIteratorState copyPropertiesTo( EdgeIteratorState edge ) - { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public EdgeSkipIterState setWeight( double weight ) - { - throw new UnsupportedOperationException("Not supported."); - } - - @Override - public double getWeight() - { - throw new UnsupportedOperationException("Not supported."); - } - } } diff --git a/core/src/main/java/com/graphhopper/routing/VirtualEdgeIState.java b/core/src/main/java/com/graphhopper/routing/VirtualEdgeIState.java new file mode 100644 index 00000000000..9552052d027 --- /dev/null +++ b/core/src/main/java/com/graphhopper/routing/VirtualEdgeIState.java @@ -0,0 +1,195 @@ +/* + * Copyright 2015 Peter Karich. + * + * Licensed 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.graphhopper.util.EdgeIteratorState; +import com.graphhopper.util.EdgeSkipIterState; +import com.graphhopper.util.PointList; + +/** + * Creates an edge state decoupled from a graph where nodes, pointList, etc are kept in memory. + */ +class VirtualEdgeIState implements EdgeIteratorState, EdgeSkipIterState { + private final PointList pointList; + private final int edgeId; + private double distance; + private long flags; + private String name; + private final int baseNode; + private final int adjNode; + + public VirtualEdgeIState( int edgeId, int baseNode, int adjNode, double distance, long flags, String name, PointList pointList ) + { + this.edgeId = edgeId; + this.baseNode = baseNode; + this.adjNode = adjNode; + this.distance = distance; + this.flags = flags; + this.name = name; + this.pointList = pointList; + } + + @Override + public int getEdge() + { + return edgeId; + } + + @Override + public int getBaseNode() + { + return baseNode; + } + + @Override + public int getAdjNode() + { + return adjNode; + } + + @Override + public PointList fetchWayGeometry( int mode ) + { + if (pointList.getSize() == 0) + return PointList.EMPTY; + // due to API we need to create a new instance per call! + if (mode == 3) + return pointList.clone(false); + else if (mode == 1) + return pointList.copy(0, pointList.getSize() - 1); + else if (mode == 2) + return pointList.copy(1, pointList.getSize()); + else if (mode == 0) + { + if (pointList.getSize() == 1) + return PointList.EMPTY; + return pointList.copy(1, pointList.getSize() - 1); + } + throw new UnsupportedOperationException("Illegal mode:" + mode); + } + + @Override + public EdgeIteratorState setWayGeometry( PointList list ) + { + throw new UnsupportedOperationException("Not supported for virtual edge. Set when creating it."); + } + + @Override + public double getDistance() + { + return distance; + } + + @Override + public EdgeIteratorState setDistance( double dist ) + { + this.distance = dist; + return this; + } + + @Override + public long getFlags() + { + return flags; + } + + @Override + public EdgeIteratorState setFlags( long flags ) + { + this.flags = flags; + return this; + } + + @Override + public String getName() + { + return name; + } + + @Override + public EdgeIteratorState setName( String name ) + { + this.name = name; + return this; + } + + @Override + public String toString() + { + return baseNode + "->" + adjNode; + } + + @Override + public boolean isShortcut() + { + return false; + } + + @Override + public int getAdditionalField() + { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public int getSkippedEdge1() + { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public int getSkippedEdge2() + { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public void setSkippedEdges( int edge1, int edge2 ) + { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public EdgeIteratorState detach( boolean reverse ) + { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public EdgeIteratorState setAdditionalField( int value ) + { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public EdgeIteratorState copyPropertiesTo( EdgeIteratorState edge ) + { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public EdgeSkipIterState setWeight( double weight ) + { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public double getWeight() + { + throw new UnsupportedOperationException("Not supported."); + } + +} diff --git a/core/src/main/java/com/graphhopper/routing/VirtualEdgeIterator.java b/core/src/main/java/com/graphhopper/routing/VirtualEdgeIterator.java new file mode 100644 index 00000000000..22abb0004f6 --- /dev/null +++ b/core/src/main/java/com/graphhopper/routing/VirtualEdgeIterator.java @@ -0,0 +1,198 @@ +/* + * Copyright 2015 Peter Karich. + * + * Licensed 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.graphhopper.util.EdgeIterator; +import com.graphhopper.util.EdgeIteratorState; +import com.graphhopper.util.EdgeSkipIterState; +import com.graphhopper.util.PointList; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Peter Karich + */ +class VirtualEdgeIterator implements EdgeIterator, EdgeSkipIterState { + private final List edges; + private int current; + + public VirtualEdgeIterator( int edgeCount ) + { + edges = new ArrayList(edgeCount); + reset(); + } + + void add( EdgeIteratorState edge ) + { + edges.add(edge); + } + + EdgeIterator reset() + { + current = -1; + return this; + } + + int count() + { + return edges.size(); + } + + @Override + public boolean next() + { + current++; + return current < edges.size(); + } + + @Override + public EdgeIteratorState detach( boolean reverse ) + { + if (reverse) + throw new IllegalStateException("Not yet supported"); + return edges.get(current); + } + + @Override + public int getEdge() + { + return edges.get(current).getEdge(); + } + + @Override + public int getBaseNode() + { + return edges.get(current).getBaseNode(); + } + + @Override + public int getAdjNode() + { + return edges.get(current).getAdjNode(); + } + + @Override + public PointList fetchWayGeometry( int mode ) + { + return edges.get(current).fetchWayGeometry(mode); + } + + @Override + public EdgeIteratorState setWayGeometry( PointList list ) + { + return edges.get(current).setWayGeometry(list); + } + + @Override + public double getDistance() + { + return edges.get(current).getDistance(); + } + + @Override + public EdgeIteratorState setDistance( double dist ) + { + return edges.get(current).setDistance(dist); + } + + @Override + public long getFlags() + { + return edges.get(current).getFlags(); + } + + @Override + public EdgeIteratorState setFlags( long flags ) + { + return edges.get(current).setFlags(flags); + } + + @Override + public String getName() + { + return edges.get(current).getName(); + } + + @Override + public EdgeIteratorState setName( String name ) + { + return edges.get(current).setName(name); + } + + @Override + public String toString() + { + return edges.toString(); + } + + @Override + public int getAdditionalField() + { + return edges.get(current).getAdditionalField(); + } + + @Override + public EdgeIteratorState setAdditionalField( int value ) + { + return edges.get(current).setAdditionalField(value); + } + + @Override + public EdgeIteratorState copyPropertiesTo( EdgeIteratorState edge ) + { + return edges.get(current).copyPropertiesTo(edge); + } + + @Override + public boolean isShortcut() + { + EdgeIteratorState edge = edges.get(current); + return edge instanceof EdgeSkipIterState && ((EdgeSkipIterState) edge).isShortcut(); + } + + @Override + public double getWeight() + { + // will be called only from PreparationWeighting and if isShortcut is true + return ((EdgeSkipIterState) edges.get(current)).getWeight(); + } + + @Override + public EdgeSkipIterState setWeight( double weight ) + { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public int getSkippedEdge1() + { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public int getSkippedEdge2() + { + throw new UnsupportedOperationException("Not supported."); + } + + @Override + public void setSkippedEdges( int edge1, int edge2 ) + { + throw new UnsupportedOperationException("Not supported."); + } + +} diff --git a/core/src/main/java/com/graphhopper/routing/util/TurnWeighting.java b/core/src/main/java/com/graphhopper/routing/util/TurnWeighting.java index 99976efb4fb..bde1c79da6c 100644 --- a/core/src/main/java/com/graphhopper/routing/util/TurnWeighting.java +++ b/core/src/main/java/com/graphhopper/routing/util/TurnWeighting.java @@ -89,7 +89,7 @@ public double calcWeight( EdgeIteratorState edgeState, boolean reverse, int prev public double calcTurnWeight( int edgeFrom, int nodeVia, int edgeTo ) { - long turnFlags = turnCostExt.getTurnCostFlags(nodeVia, edgeFrom, edgeTo); + long turnFlags = turnCostExt.getTurnCostFlags(edgeFrom, nodeVia, edgeTo); if (turnCostEncoder.isTurnRestricted(turnFlags)) return Double.POSITIVE_INFINITY; diff --git a/core/src/main/java/com/graphhopper/storage/TurnCostExtension.java b/core/src/main/java/com/graphhopper/storage/TurnCostExtension.java index 9291ba47333..152cc78179f 100644 --- a/core/src/main/java/com/graphhopper/storage/TurnCostExtension.java +++ b/core/src/main/java/com/graphhopper/storage/TurnCostExtension.java @@ -166,19 +166,19 @@ public void addTurnInfo( int from, int viaNode, int to, long turnFlags ) /** * @return turn flags of the specified node and edge properties. */ - public long getTurnCostFlags( int node, int edgeFrom, int edgeTo ) + public long getTurnCostFlags( int edgeFrom, int nodeVia, int edgeTo ) { if (edgeFrom == EdgeIterator.NO_EDGE || edgeTo == EdgeIterator.NO_EDGE) throw new IllegalArgumentException("from and to edge cannot be NO_EDGE"); - if (node < 0) + if (nodeVia < 0) throw new IllegalArgumentException("via node cannot be negative"); - return nextCostFlags(node, edgeFrom, edgeTo); + return nextCostFlags(edgeFrom, nodeVia, edgeTo); } - private long nextCostFlags( int node, int edgeFrom, int edgeTo ) + private long nextCostFlags( int edgeFrom, int nodeVia, int edgeTo ) { - int turnCostIndex = nodeAccess.getAdditionalNodeField(node); + int turnCostIndex = nodeAccess.getAdditionalNodeField(nodeVia); int i = 0; for (; i < 1000; i++) { diff --git a/core/src/test/java/com/graphhopper/reader/OSMReaderTest.java b/core/src/test/java/com/graphhopper/reader/OSMReaderTest.java index 31016ed2f02..6fc02eeeeae 100644 --- a/core/src/test/java/com/graphhopper/reader/OSMReaderTest.java +++ b/core/src/test/java/com/graphhopper/reader/OSMReaderTest.java @@ -539,26 +539,26 @@ public void testTurnRestrictions() // (2-3)->(3-4) only_straight_on = (2-3)->(3-8) restricted // (4-3)->(3-8) no_right_turn = (4-3)->(3-8) restricted - assertTrue(carEncoder.getTurnCost(tcStorage.getTurnCostFlags(n3, edge2_3, edge3_8)) > 0); - assertTrue(carEncoder.getTurnCost(tcStorage.getTurnCostFlags(n3, edge4_3, edge3_8)) > 0); - assertFalse(carEncoder.isTurnRestricted(tcStorage.getTurnCostFlags(n3, edge2_3, edge3_4))); - assertFalse(carEncoder.isTurnRestricted(tcStorage.getTurnCostFlags(n3, edge2_3, edge3_2))); - assertFalse(carEncoder.isTurnRestricted(tcStorage.getTurnCostFlags(n3, edge2_3, edge3_4))); - assertFalse(carEncoder.isTurnRestricted(tcStorage.getTurnCostFlags(n3, edge4_3, edge3_2))); - assertFalse(carEncoder.isTurnRestricted(tcStorage.getTurnCostFlags(n3, edge8_3, edge3_2))); + assertTrue(carEncoder.getTurnCost(tcStorage.getTurnCostFlags(edge2_3, n3, edge3_8)) > 0); + assertTrue(carEncoder.getTurnCost(tcStorage.getTurnCostFlags(edge4_3, n3, edge3_8)) > 0); + assertFalse(carEncoder.isTurnRestricted(tcStorage.getTurnCostFlags(edge2_3, n3, edge3_4))); + assertFalse(carEncoder.isTurnRestricted(tcStorage.getTurnCostFlags(edge2_3, n3, edge3_2))); + assertFalse(carEncoder.isTurnRestricted(tcStorage.getTurnCostFlags(edge2_3, n3, edge3_4))); + assertFalse(carEncoder.isTurnRestricted(tcStorage.getTurnCostFlags(edge4_3, n3, edge3_2))); + assertFalse(carEncoder.isTurnRestricted(tcStorage.getTurnCostFlags(edge8_3, n3, edge3_2))); // u-turn restriction for (6-1)->(1-6) but not for (1-6)->(6-1) - assertTrue(carEncoder.getTurnCost(tcStorage.getTurnCostFlags(n1, edge1_6, edge1_6)) > 0); - assertFalse(carEncoder.isTurnRestricted(tcStorage.getTurnCostFlags(n6, edge1_6, edge1_6))); + assertTrue(carEncoder.getTurnCost(tcStorage.getTurnCostFlags(edge1_6, n1, edge1_6)) > 0); + assertFalse(carEncoder.isTurnRestricted(tcStorage.getTurnCostFlags(edge1_6, n6, edge1_6))); int edge4_5 = GHUtility.getEdge(graph, n4, n5).getEdge(); int edge5_6 = GHUtility.getEdge(graph, n5, n6).getEdge(); int edge5_1 = GHUtility.getEdge(graph, n5, n1).getEdge(); // (4-5)->(5-1) right_turn_only = (4-5)->(5-6) restricted - long costsFlags = tcStorage.getTurnCostFlags(n5, edge4_5, edge5_6); + long costsFlags = tcStorage.getTurnCostFlags(edge4_5, n5, edge5_6); assertFalse(carEncoder.isTurnRestricted(costsFlags)); - assertTrue(carEncoder.getTurnCost(tcStorage.getTurnCostFlags(n5, edge4_5, edge5_1)) > 0); + assertTrue(carEncoder.getTurnCost(tcStorage.getTurnCostFlags(edge4_5, n5, edge5_1)) > 0); // for bike assertFalse(bikeEncoder.isTurnRestricted(costsFlags)); @@ -570,9 +570,9 @@ public void testTurnRestrictions() int edge10_11 = GHUtility.getEdge(graph, n10, n11).getEdge(); int edge11_14 = GHUtility.getEdge(graph, n11, n14).getEdge(); - assertEquals(0, tcStorage.getTurnCostFlags(n11, edge11_14, edge10_11)); + assertEquals(0, tcStorage.getTurnCostFlags(edge11_14, n11, edge10_11)); - costsFlags = tcStorage.getTurnCostFlags(n11, edge10_11, edge11_14); + costsFlags = tcStorage.getTurnCostFlags(edge10_11, n11, edge11_14); assertFalse(carEncoder.isTurnRestricted(costsFlags)); assertTrue(bikeEncoder.isTurnRestricted(costsFlags)); } diff --git a/core/src/test/java/com/graphhopper/routing/QueryGraphTest.java b/core/src/test/java/com/graphhopper/routing/QueryGraphTest.java index 5aa2a756f55..c8607c1f5e4 100644 --- a/core/src/test/java/com/graphhopper/routing/QueryGraphTest.java +++ b/core/src/test/java/com/graphhopper/routing/QueryGraphTest.java @@ -153,7 +153,7 @@ public void testFillVirtualEdges() { @Override - void fillVirtualEdges( TIntObjectMap node2Edge, int towerNode, EdgeExplorer mainExpl ) + void fillVirtualEdges( TIntObjectMap node2Edge, int towerNode, EdgeExplorer mainExpl ) { super.fillVirtualEdges(node2Edge, towerNode, mainExpl); // ignore nodes should include baseNode == 1 @@ -253,7 +253,7 @@ public void testVirtEdges() EdgeIterator iter = g.createEdgeExplorer().setBaseNode(0); iter.next(); - QueryGraph.VirtualEdgeIterator vi = new QueryGraph.VirtualEdgeIterator(2); + VirtualEdgeIterator vi = new VirtualEdgeIterator(2); vi.add(iter.detach(false)); assertTrue(vi.next()); @@ -439,7 +439,7 @@ public QueryResult createLocationResult( double lat, double lon, } @Test - public void testIterationBug_163() + public void testIteration_Issue163() { EdgeFilter outEdgeFilter = new DefaultEdgeFilter(encodingManager.getEncoder("CAR"), false, true); EdgeFilter inEdgeFilter = new DefaultEdgeFilter(encodingManager.getEncoder("CAR"), true, false); @@ -499,4 +499,44 @@ private void assertEdgeIdsStayingEqual( EdgeExplorer inExplorer, EdgeExplorer ou 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); + + GraphStorage 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, encoder, (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(); + } } diff --git a/core/src/test/java/com/graphhopper/routing/RoutingAlgorithmIT.java b/core/src/test/java/com/graphhopper/routing/RoutingAlgorithmIT.java index d746dab1c6b..6d71b762454 100644 --- a/core/src/test/java/com/graphhopper/routing/RoutingAlgorithmIT.java +++ b/core/src/test/java/com/graphhopper/routing/RoutingAlgorithmIT.java @@ -131,10 +131,8 @@ public void testMoscow() public void testMoscowTurnCosts() { List list = new ArrayList(); - list.add(new OneRun(55.813357, 37.5958585, 55.811042, 37.594689, 1043.99, 12)); - - // TODO #163 - // list.add(new OneRun(55.813159,37.593884, 55.811278,37.594217, 1000, 12)); + list.add(new OneRun(55.813357, 37.5958585, 55.811042, 37.594689, 1043.99, 12)); + list.add(new OneRun(55.813159, 37.593884, 55.811278, 37.594217, 1048, 13)); // TODO include CH boolean testAlsoCH = false, is3D = false; runAlgo(testCollector, "files/moscow.osm.gz", "target/graph-moscow", diff --git a/core/src/test/java/com/graphhopper/storage/GraphHopperStorageWithTurnCostsTest.java b/core/src/test/java/com/graphhopper/storage/GraphHopperStorageWithTurnCostsTest.java index 5cb0a3c3065..f58cd0ed116 100644 --- a/core/src/test/java/com/graphhopper/storage/GraphHopperStorageWithTurnCostsTest.java +++ b/core/src/test/java/com/graphhopper/storage/GraphHopperStorageWithTurnCostsTest.java @@ -85,10 +85,10 @@ public void testSave_and_fileFormat_withTurnCostEntries() throws IOException assertEquals("named street1", graph.getEdgeProps(iter1.getEdge(), iter1.getAdjNode()).getName()); assertEquals("named street2", graph.getEdgeProps(iter2.getEdge(), iter2.getAdjNode()).getName()); - assertEquals(1337, turnCostStorage.getTurnCostFlags(0, iter1.getEdge(), iter2.getEdge())); - assertEquals(666, turnCostStorage.getTurnCostFlags(0, iter2.getEdge(), iter1.getEdge())); - assertEquals(815, turnCostStorage.getTurnCostFlags(1, iter1.getEdge(), iter2.getEdge())); - assertEquals(0, turnCostStorage.getTurnCostFlags(3, iter1.getEdge(), iter2.getEdge())); + assertEquals(1337, turnCostStorage.getTurnCostFlags(iter1.getEdge(), 0, iter2.getEdge())); + assertEquals(666, turnCostStorage.getTurnCostFlags(iter2.getEdge(), 0, iter1.getEdge())); + assertEquals(815, turnCostStorage.getTurnCostFlags(iter1.getEdge(), 1, iter2.getEdge())); + assertEquals(0, turnCostStorage.getTurnCostFlags(iter1.getEdge(), 3, iter2.getEdge())); graph.edge(3, 4, 123, true).setWayGeometry(Helper.createPointList(4.4, 5.5, 6.6, 7.7)); checkGraph(graph);