Commit 7f288173 authored by Michael Zilske's avatar Michael Zilske

Merge branch 'more-realtime'

parents 873d1f59 1ba32cd8
......@@ -19,7 +19,6 @@
package com.graphhopper.reader.gtfs;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.FluentIterable;
import com.graphhopper.routing.VirtualEdgeIteratorState;
import com.graphhopper.routing.util.DefaultEdgeFilter;
import com.graphhopper.storage.Graph;
......@@ -32,10 +31,11 @@ import com.graphhopper.util.PointList;
import java.time.Instant;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
......@@ -48,15 +48,14 @@ final class GraphExplorer {
private final boolean reverse;
private final PtTravelTimeWeighting weighting;
private final PointList extraNodes;
private final List<VirtualEdgeIteratorState> extraEdges;
private final List<EdgeIteratorState> extraEdges = new ArrayList<>();
private final ArrayListMultimap<Integer, VirtualEdgeIteratorState> extraEdgesBySource = ArrayListMultimap.create();
private final ArrayListMultimap<Integer, VirtualEdgeIteratorState> extraEdgesByDestination = ArrayListMultimap.create();
private final Graph graph;
private final boolean walkOnly;
private final boolean profileQuery;
GraphExplorer(Graph graph, PtTravelTimeWeighting weighting, PtFlagEncoder flagEncoder, GtfsStorage gtfsStorage, RealtimeFeed realtimeFeed, boolean reverse, PointList extraNodes, List<VirtualEdgeIteratorState> extraEdges, boolean walkOnly, boolean profileQuery) {
GraphExplorer(Graph graph, PtTravelTimeWeighting weighting, PtFlagEncoder flagEncoder, GtfsStorage gtfsStorage, RealtimeFeed realtimeFeed, boolean reverse, PointList extraNodes, List<VirtualEdgeIteratorState> extraEdges, boolean walkOnly) {
this.graph = graph;
this.edgeExplorer = graph.createEdgeExplorer(new DefaultEdgeFilter(flagEncoder, reverse, !reverse));
this.flagEncoder = flagEncoder;
......@@ -65,64 +64,31 @@ final class GraphExplorer {
this.realtimeFeed = realtimeFeed;
this.reverse = reverse;
this.extraNodes = extraNodes;
this.extraEdges = extraEdges;
this.extraEdges.addAll(extraEdges);
for (VirtualEdgeIteratorState extraEdge : extraEdges) {
if (extraEdge == null) {
throw new RuntimeException();
}
extraEdgesBySource.put(extraEdge.getBaseNode(), extraEdge);
extraEdgesByDestination.put(extraEdge.getAdjNode(), (VirtualEdgeIteratorState) extraEdge.detach(true));
extraEdgesByDestination.put(extraEdge.getAdjNode(), new VirtualEdgeIteratorState(extraEdge.getOriginalTraversalKey(), extraEdge.getEdge(), extraEdge.getAdjNode(), extraEdge.getBaseNode(), extraEdge.getDistance(), extraEdge.getFlags(), extraEdge.getName(), extraEdge.fetchWayGeometry(3)));
}
this.walkOnly = walkOnly;
this.profileQuery = profileQuery;
}
Stream<EdgeIteratorState> exploreEdgesAround(Label label) {
final List<VirtualEdgeIteratorState> extraEdges = reverse ? extraEdgesByDestination.get(label.adjNode) : extraEdgesBySource.get(label.adjNode);
return Stream.concat(
label.adjNode < graph.getNodes() ? mainEdgesAround(label) : Stream.empty(),
extraEdges.stream());
extraEdges.stream()).filter(new EdgeIteratorStatePredicate(label));
}
Stream<EdgeIteratorState> mainEdgesAround(Label label) {
private Stream<EdgeIteratorState> mainEdgesAround(Label label) {
return StreamSupport.stream(new Spliterators.AbstractSpliterator<EdgeIteratorState>(0, 0) {
boolean foundEnteredTimeExpandedNetworkEdge = false;
EdgeIterator edgeIterator = edgeExplorer.setBaseNode(label.adjNode);
@Override
public boolean tryAdvance(Consumer<? super EdgeIteratorState> action) {
while (edgeIterator.next()) {
final GtfsStorage.EdgeType edgeType = flagEncoder.getEdgeType(edgeIterator.getFlags());
if (walkOnly && edgeType != GtfsStorage.EdgeType.HIGHWAY && edgeType != (reverse ? GtfsStorage.EdgeType.EXIT_PT : GtfsStorage.EdgeType.ENTER_PT)) {
continue;
}
if (profileQuery && (edgeType == GtfsStorage.EdgeType.ENTER_PT || edgeType == GtfsStorage.EdgeType.EXIT_PT)) {
continue;
}
if (!isValidOn(edgeIterator, label.currentTime)) {
continue;
}
if (realtimeFeed.isBlocked(edgeIterator.getEdge())) {
continue;
}
if (edgeType == GtfsStorage.EdgeType.WAIT_ARRIVAL && !reverse) {
continue;
}
if (edgeType == GtfsStorage.EdgeType.WAIT && reverse) {
continue;
}
if (edgeType == GtfsStorage.EdgeType.ENTER_TIME_EXPANDED_NETWORK && !reverse) {
if (secondsOnTrafficDay(edgeIterator, label.currentTime) > flagEncoder.getTime(edgeIterator.getFlags())) {
continue;
} else {
if (foundEnteredTimeExpandedNetworkEdge) {
continue;
} else {
foundEnteredTimeExpandedNetworkEdge = true;
}
}
} else if (edgeType == GtfsStorage.EdgeType.LEAVE_TIME_EXPANDED_NETWORK && reverse) {
if (secondsOnTrafficDay(edgeIterator, label.currentTime) < flagEncoder.getTime(edgeIterator.getFlags())) {
continue;
}
}
if (edgeIterator.next()) {
action.accept(edgeIterator);
return true;
}
......@@ -181,19 +147,66 @@ final class GraphExplorer {
}
}
public EdgeIteratorState getEdgeIteratorState(int edge, int adjNode) {
if (edge == -1) {
return extraEdges.iterator().next();
} else {
return graph.getEdgeIteratorState(edge, adjNode);
EdgeIteratorState getEdgeIteratorState(int edgeId, int adjNode) {
if (edgeId == -1) {
throw new RuntimeException();
}
return extraEdges.stream()
.filter(edge -> edge.getEdge() == edgeId)
.findFirst().orElseGet(() -> graph.getEdgeIteratorState(edgeId, adjNode));
}
public NodeAccess getNodeAccess() {
NodeAccess getNodeAccess() {
return graph.getNodeAccess();
}
public Graph getGraph() {
return graph;
}
private class EdgeIteratorStatePredicate implements Predicate<EdgeIteratorState> {
private final Label label;
boolean foundEnteredTimeExpandedNetworkEdge;
EdgeIteratorStatePredicate(Label label) {
this.label = label;
foundEnteredTimeExpandedNetworkEdge = false;
}
@Override
public boolean test(EdgeIteratorState edgeIterator) {
final GtfsStorage.EdgeType edgeType = flagEncoder.getEdgeType(edgeIterator.getFlags());
if (walkOnly && edgeType != GtfsStorage.EdgeType.HIGHWAY && edgeType != (reverse ? GtfsStorage.EdgeType.EXIT_PT : GtfsStorage.EdgeType.ENTER_PT)) {
return false;
}
if (!isValidOn(edgeIterator, label.currentTime)) {
return false;
}
if (realtimeFeed.isBlocked(edgeIterator.getEdge())) {
return false;
}
if (edgeType == GtfsStorage.EdgeType.WAIT_ARRIVAL && !reverse) {
return false;
}
if (edgeType == GtfsStorage.EdgeType.WAIT && reverse) {
return false;
}
if (edgeType == GtfsStorage.EdgeType.ENTER_TIME_EXPANDED_NETWORK && !reverse) {
if (secondsOnTrafficDay(edgeIterator, label.currentTime) > flagEncoder.getTime(edgeIterator.getFlags())) {
return false;
} else {
if (foundEnteredTimeExpandedNetworkEdge) {
return false;
} else {
foundEnteredTimeExpandedNetworkEdge = true;
}
}
} else if (edgeType == GtfsStorage.EdgeType.LEAVE_TIME_EXPANDED_NETWORK && reverse) {
if (secondsOnTrafficDay(edgeIterator, label.currentTime) < flagEncoder.getTime(edgeIterator.getFlags())) {
return false;
}
}
return true;
}
}
}
......@@ -62,7 +62,7 @@ public final class GraphHopperGtfs implements GraphHopperAPI {
}
public GraphHopperGtfs createWith(GtfsRealtime.FeedMessage realtimeFeed) {
return new GraphHopperGtfs(flagEncoder, translationMap, graphHopperStorage, locationIndex, gtfsStorage, RealtimeFeed.fromProtobuf(gtfsStorage, realtimeFeed));
return new GraphHopperGtfs(flagEncoder, translationMap, graphHopperStorage, locationIndex, gtfsStorage, RealtimeFeed.fromProtobuf(graphHopperStorage, gtfsStorage, flagEncoder, realtimeFeed));
}
public GraphHopperGtfs createWithoutRealtimeFeed() {
......@@ -97,12 +97,13 @@ public final class GraphHopperGtfs implements GraphHopperAPI {
private final GHPoint enter;
private final GHPoint exit;
private final Translation translation;
private final List<VirtualEdgeIteratorState> extraEdges = new ArrayList<>();
private final List<VirtualEdgeIteratorState> extraEdges = new ArrayList<>(realtimeFeed.getAdditionalEdges());
private final PointList extraNodes = new PointList();
private final Map<Integer, PathWrapper> walkPaths = new HashMap<>();
private final GHResponse response = new GHResponse();
private final QueryGraph queryGraph = new QueryGraph(graphHopperStorage);
private final Graph graphWithExtraEdges = new WrapperGraph(graphHopperStorage, extraEdges);
private QueryGraph queryGraph = new QueryGraph(graphWithExtraEdges);
private GraphExplorer graphExplorer;
RequestHandler(GHRequest request) {
......@@ -163,32 +164,36 @@ public final class GraphHopperGtfs implements GraphHopperAPI {
}
private void substitutePointWithVirtualNode(int index, boolean reverse, GHPoint ghPoint, ArrayList<QueryResult> allQueryResults) {
final GraphExplorer graphExplorer = new GraphExplorer(queryGraph, weighting, flagEncoder, gtfsStorage, realtimeFeed, reverse, new PointList(), Collections.emptyList(), true, false);
final GraphExplorer graphExplorer = new GraphExplorer(queryGraph, weighting, flagEncoder, gtfsStorage, realtimeFeed, reverse, new PointList(), extraEdges, true);
extraNodes.add(ghPoint);
int newNode = graphHopperStorage.getNodes() + 1000 + index;
int nextNodeId = graphHopperStorage.getNodes() + 10000 + index; // FIXME: A number bigger than the number of nodes QueryGraph adds
int nextEdgeId = graphWithExtraEdges.getAllEdges().getMaxId() + 100; // FIXME: A number bigger than the number of edges QueryGraph adds
final List<Label> stationNodes = findStationNodes(graphExplorer, allQueryResults.get(index).getClosestNode(), reverse);
for (Label stationNode : stationNodes) {
final PathWrapper pathWrapper = stationNode.parent.parent != null ?
tripFromLabel.parseSolutionIntoPath(reverse, flagEncoder, translation, graphExplorer, weighting, stationNode.parent, new PointList()) :
new PathWrapper();
final VirtualEdgeIteratorState newEdge = new VirtualEdgeIteratorState(stationNode.edge,
-1, reverse ? stationNode.adjNode : newNode, reverse ? newNode : stationNode.adjNode, pathWrapper.getDistance(), 0, "", pathWrapper.getPoints());
nextEdgeId++, reverse ? stationNode.adjNode : nextNodeId, reverse ? nextNodeId : stationNode.adjNode, pathWrapper.getDistance(), 0, "", pathWrapper.getPoints());
final VirtualEdgeIteratorState reverseNewEdge = new VirtualEdgeIteratorState(stationNode.edge,
-1, reverse ? newNode : stationNode.adjNode, reverse ? stationNode.adjNode : newNode, pathWrapper.getDistance(), 0, "", pathWrapper.getPoints());
nextEdgeId++, reverse ? nextNodeId : stationNode.adjNode, reverse ? stationNode.adjNode : nextNodeId, pathWrapper.getDistance(), 0, "", pathWrapper.getPoints());
newEdge.setFlags(((PtFlagEncoder) weighting.getFlagEncoder()).setEdgeType(newEdge.getFlags(), reverse ? GtfsStorage.EdgeType.EXIT_PT : GtfsStorage.EdgeType.ENTER_PT));
final long time = pathWrapper.getTime() / 1000;
newEdge.setFlags(((PtFlagEncoder) weighting.getFlagEncoder()).setTime(newEdge.getFlags(), time));
reverseNewEdge.setFlags(newEdge.getFlags());
newEdge.setReverseEdge(reverseNewEdge);
reverseNewEdge.setReverseEdge(newEdge);
newEdge.setDistance(pathWrapper.getDistance());
extraEdges.add(newEdge);
extraEdges.add(reverseNewEdge);
walkPaths.put(stationNode.adjNode, pathWrapper);
}
final QueryResult virtualNode = new QueryResult(ghPoint.getLat(), ghPoint.getLon());
virtualNode.setClosestNode(newNode);
virtualNode.setClosestNode(nextNodeId);
allQueryResults.set(index, virtualNode);
}
......@@ -198,7 +203,6 @@ public final class GraphHopperGtfs implements GraphHopperAPI {
final Stream<Label> labels = router.calcLabels(node, -1, initialTime);
return labels
.filter(current -> current.edge != -1 && flagEncoder.getEdgeType(graphExplorer.getEdgeIteratorState(current.edge, current.adjNode).getFlags()) == edgeType)
// .limit(limitSolutions)
.collect(Collectors.toList());
}
......@@ -249,7 +253,7 @@ public final class GraphHopperGtfs implements GraphHopperAPI {
private List<Label> findPaths(int startNode, int destNode) {
StopWatch stopWatch = new StopWatch().start();
graphExplorer = new GraphExplorer(queryGraph, weighting, flagEncoder, gtfsStorage, realtimeFeed, arriveBy, extraNodes, extraEdges, false, profileQuery);
graphExplorer = new GraphExplorer(queryGraph, weighting, flagEncoder, gtfsStorage, realtimeFeed, arriveBy, extraNodes, extraEdges, false);
MultiCriteriaLabelSetting router = new MultiCriteriaLabelSetting(graphExplorer, weighting, arriveBy, maxWalkDistancePerLeg, maxTransferDistancePerLeg, !ignoreTransfers, profileQuery, maxVisitedNodesForRequest);
final Stream<Label> labels = router.calcLabels(startNode, destNode, initialTime);
List<Label> solutions = labels
......@@ -327,7 +331,7 @@ public final class GraphHopperGtfs implements GraphHopperAPI {
walkNetworkIndex = new EmptyLocationIndex();
}
for (int i = 0; i < id; i++) {
new GtfsReader("gtfs_" + i, graphHopperStorage, walkNetworkIndex).readGraph();
new GtfsReader("gtfs_" + i, graphHopperStorage, ptFlagEncoder, walkNetworkIndex).readGraph();
}
graphHopperStorage.flush();
return graphHopperStorage;
......
......@@ -19,22 +19,50 @@
package com.graphhopper.reader.gtfs;
import com.carrotsearch.hppc.IntHashSet;
import com.carrotsearch.hppc.IntIntHashMap;
import com.conveyal.gtfs.GTFSFeed;
import com.conveyal.gtfs.model.StopTime;
import com.conveyal.gtfs.model.Trip;
import com.google.transit.realtime.GtfsRealtime;
import com.graphhopper.routing.VirtualEdgeIteratorState;
import com.graphhopper.routing.util.AllEdgesIterator;
import com.graphhopper.routing.util.EdgeFilter;
import com.graphhopper.storage.Graph;
import com.graphhopper.storage.GraphExtension;
import com.graphhopper.storage.NodeAccess;
import com.graphhopper.util.EdgeExplorer;
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.BBox;
import java.time.*;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static com.google.transit.realtime.GtfsRealtime.TripUpdate.StopTimeUpdate.ScheduleRelationship.SKIPPED;
import static java.time.temporal.ChronoUnit.DAYS;
public class RealtimeFeed {
private final IntHashSet blockedEdges;
private RealtimeFeed(IntHashSet blockedEdges) {
private final List<VirtualEdgeIteratorState> additionalEdges;
private RealtimeFeed(IntHashSet blockedEdges, List<VirtualEdgeIteratorState> additionalEdges) {
this.blockedEdges = blockedEdges;
this.additionalEdges = additionalEdges;
}
public static RealtimeFeed empty() {
return new RealtimeFeed(new IntHashSet());
return new RealtimeFeed(new IntHashSet(), Collections.emptyList());
}
public static RealtimeFeed fromProtobuf(GtfsStorage staticGtfs, GtfsRealtime.FeedMessage feedMessage) {
public static RealtimeFeed fromProtobuf(Graph graph, GtfsStorage staticGtfs, PtFlagEncoder encoder, GtfsRealtime.FeedMessage feedMessage) {
String feedKey = "gtfs_0"; //FIXME
GTFSFeed feed = staticGtfs.getGtfsFeeds().get(feedKey);
final IntHashSet blockedEdges = new IntHashSet();
feedMessage.getEntityList().stream()
.filter(GtfsRealtime.FeedEntity::hasTripUpdate)
......@@ -50,10 +78,190 @@ public class RealtimeFeed {
blockedEdges.add(leaveEdges[skippedStopSequenceNumber]);
});
});
return new RealtimeFeed(blockedEdges);
final List<VirtualEdgeIteratorState> additionalEdges = new ArrayList<>();
final Graph overlayGraph = new Graph() {
int nNodes = 0;
int firstEdge = graph.getAllEdges().getMaxId()+1;
final NodeAccess nodeAccess = new NodeAccess() {
IntIntHashMap additionalNodeFields = new IntIntHashMap();
@Override
public int getAdditionalNodeField(int nodeId) {
return 0;
}
@Override
public void setAdditionalNodeField(int nodeId, int additionalValue) {
additionalNodeFields.put(nodeId, additionalValue);
}
@Override
public boolean is3D() {
return false;
}
@Override
public int getDimension() {
return 0;
}
@Override
public void ensureNode(int nodeId) {
}
@Override
public void setNode(int nodeId, double lat, double lon) {
}
@Override
public void setNode(int nodeId, double lat, double lon, double ele) {
}
@Override
public double getLatitude(int nodeId) {
return 0;
}
@Override
public double getLat(int nodeId) {
return 0;
}
@Override
public double getLongitude(int nodeId) {
return 0;
}
@Override
public double getLon(int nodeId) {
return 0;
}
@Override
public double getElevation(int nodeId) {
return 0;
}
@Override
public double getEle(int nodeId) {
return 0;
}
};
@Override
public Graph getBaseGraph() {
return null;
}
@Override
public int getNodes() {
return graph.getNodes() + nNodes;
}
@Override
public NodeAccess getNodeAccess() {
return nodeAccess;
}
@Override
public BBox getBounds() {
return null;
}
@Override
public EdgeIteratorState edge(int a, int b) {
return null;
}
@Override
public EdgeIteratorState edge(int a, int b, double distance, boolean bothDirections) {
int edge = firstEdge++;
final VirtualEdgeIteratorState newEdge = new VirtualEdgeIteratorState(-1,
edge, a, b, 0,0, "", new PointList());
final VirtualEdgeIteratorState reverseNewEdge = new VirtualEdgeIteratorState(-1,
edge, b, a, 0,0, "", new PointList());
newEdge.setReverseEdge(reverseNewEdge);
reverseNewEdge.setReverseEdge(newEdge);
additionalEdges.add(newEdge);
// additionalEdges.add(reverseNewEdge); //FIXME
return newEdge;
}
@Override
public EdgeIteratorState getEdgeIteratorState(int edgeId, int adjNode) {
return null;
}
@Override
public AllEdgesIterator getAllEdges() {
return null;
}
@Override
public EdgeExplorer createEdgeExplorer(EdgeFilter filter) {
return null;
}
@Override
public EdgeExplorer createEdgeExplorer() {
return null;
}
@Override
public Graph copyTo(Graph g) {
return null;
}
@Override
public GraphExtension getExtension() {
return staticGtfs;
}
};
final GtfsReader gtfsReader = new GtfsReader(feedKey, overlayGraph, encoder, null);
Instant timestamp = Instant.ofEpochSecond(feedMessage.getHeader().getTimestamp());
LocalDate dateToChange = timestamp.atZone(ZoneId.of(feed.agency.values().iterator().next().agency_timezone)).toLocalDate(); //FIXME
feedMessage.getEntityList().stream()
.filter(GtfsRealtime.FeedEntity::hasTripUpdate)
.map(GtfsRealtime.FeedEntity::getTripUpdate)
.filter(tripUpdate -> tripUpdate.getTrip().getScheduleRelationship() == GtfsRealtime.TripDescriptor.ScheduleRelationship.ADDED)
.map(tripUpdate -> {
Trip trip = new Trip();
trip.trip_id = tripUpdate.getTrip().getTripId();
trip.route_id = tripUpdate.getTrip().getRouteId();
final List<StopTime> stopTimes = tripUpdate.getStopTimeUpdateList().stream()
.map(stopTimeUpdate -> {
final StopTime stopTime = new StopTime();
stopTime.stop_sequence = stopTimeUpdate.getStopSequence();
stopTime.stop_id = stopTimeUpdate.getStopId();
stopTime.trip_id = trip.trip_id;
final ZonedDateTime arrival_time = Instant.ofEpochSecond(stopTimeUpdate.getArrival().getTime()).atZone(ZoneId.of("America/Los_Angeles"));
stopTime.arrival_time = (int) Duration.between(arrival_time.truncatedTo(ChronoUnit.DAYS), arrival_time).getSeconds();
final ZonedDateTime departure_time = Instant.ofEpochSecond(stopTimeUpdate.getArrival().getTime()).atZone(ZoneId.of("America/Los_Angeles"));
stopTime.departure_time = (int) Duration.between(departure_time.truncatedTo(ChronoUnit.DAYS), departure_time).getSeconds();
return stopTime;
})
.collect(Collectors.toList());
BitSet validOnDay = new BitSet();
LocalDate startDate = feed.calculateStats().getStartDate();
validOnDay.set((int) DAYS.between(startDate, dateToChange));
return new GtfsReader.TripWithStopTimes(trip, stopTimes, validOnDay);
})
.forEach(trip -> gtfsReader.addTrips(ZoneId.systemDefault(), Collections.singletonList(trip), 0));
gtfsReader.wireUpStops();
gtfsReader.connectStopsToStationNodes();
return new RealtimeFeed(blockedEdges, additionalEdges);
}
boolean isBlocked(int edgeId) {
return blockedEdges.contains(edgeId);
}
List<VirtualEdgeIteratorState> getAdditionalEdges() {
return additionalEdges;
}
}
......@@ -26,7 +26,6 @@ import com.graphhopper.Trip;
import com.graphhopper.gtfs.fare.Fares;
import com.graphhopper.routing.InstructionsFromEdges;
import com.graphhopper.routing.weighting.Weighting;
import com.graphhopper.storage.Graph;
import com.graphhopper.util.*;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
......
/*
* 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.reader.gtfs;
import com.graphhopper.routing.VirtualEdgeIteratorState;
import com.graphhopper.routing.util.AllEdgesIterator;
import com.graphhopper.routing.util.EdgeFilter;
import com.graphhopper.routing.util.FlagEncoder;
import com.graphhopper.storage.Graph;
import com.graphhopper.storage.GraphExtension;
import com.graphhopper.storage.NodeAccess;
import com.graphhopper.util.EdgeExplorer;
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.BBox;