use of com.graphhopper.routing.util.DefaultEdgeFilter in project graphhopper by graphhopper.
the class QueryGraph method createEdgeExplorer.
@Override
public EdgeExplorer createEdgeExplorer(final EdgeFilter edgeFilter) {
if (!isInitialized())
throw new IllegalStateException("Call lookup before using this graph");
if (useEdgeExplorerCache) {
int counter = -1;
if (edgeFilter instanceof DefaultEdgeFilter) {
DefaultEdgeFilter dee = (DefaultEdgeFilter) edgeFilter;
counter = 0;
if (dee.acceptsBackward())
counter = 1;
if (dee.acceptsForward())
counter += 2;
if (counter == 0)
throw new IllegalStateException("You tried to use an edge filter blocking every access");
} else if (edgeFilter == EdgeFilter.ALL_EDGES) {
counter = 4;
}
if (counter >= 0) {
EdgeExplorer cached = cacheMap.get(counter);
if (cached == null) {
cached = createUncachedEdgeExplorer(edgeFilter);
cacheMap.put(counter, cached);
}
return cached;
}
}
return createUncachedEdgeExplorer(edgeFilter);
}
use of com.graphhopper.routing.util.DefaultEdgeFilter in project graphhopper by graphhopper.
the class PrepareRoutingSubnetworks method removeDeadEndUnvisitedNetworks.
/**
* This method removes networks that will be never be visited by this filter. See #235 for
* example, small areas like parking lots are sometimes connected to the whole network through a
* one-way road. This is clearly an error - but is causes the routing to fail when a point gets
* connected to this small area. This routine removes all these networks from the graph.
* <p>
*
* @return number of removed edges
*/
int removeDeadEndUnvisitedNetworks(final PrepEdgeFilter bothFilter) {
StopWatch sw = new StopWatch(bothFilter.getEncoder() + " findComponents").start();
final EdgeFilter outFilter = new DefaultEdgeFilter(bothFilter.getEncoder(), false, true);
// partition graph into strongly connected components using Tarjan's algorithm
TarjansSCCAlgorithm tarjan = new TarjansSCCAlgorithm(ghStorage, outFilter, true);
List<IntArrayList> components = tarjan.findComponents();
logger.info(sw.stop() + ", size:" + components.size());
return removeEdges(bothFilter, components, minOneWayNetworkSize);
}
use of com.graphhopper.routing.util.DefaultEdgeFilter in project graphhopper by graphhopper.
the class ChangeGraphHelper method applyChange.
private long applyChange(JsonFeature jsonFeature, FlagEncoder encoder) {
long updates = 0;
EdgeFilter filter = new DefaultEdgeFilter(encoder);
GHIntHashSet edges = new GHIntHashSet();
if (jsonFeature.hasGeometry()) {
graphBrowser.fillEdgeIDs(edges, jsonFeature.getGeometry(), filter);
} else if (jsonFeature.getBBox() != null) {
graphBrowser.findEdgesInShape(edges, jsonFeature.getBBox(), filter);
} else
throw new IllegalArgumentException("Feature " + jsonFeature.getId() + " has no geometry and no bbox");
Iterator<IntCursor> iter = edges.iterator();
Map<String, Object> props = jsonFeature.getProperties();
while (iter.hasNext()) {
int edgeId = iter.next().value;
EdgeIteratorState edge = graph.getEdgeIteratorState(edgeId, Integer.MIN_VALUE);
if (props.containsKey("access")) {
boolean value = (boolean) props.get("access");
updates++;
if (enableLogging)
logger.info(encoder.toString() + " - access change via feature " + jsonFeature.getId());
edge.setFlags(encoder.setAccess(edge.getFlags(), value, value));
} else if (props.containsKey("speed")) {
// TODO use different speed for the different directions (see e.g. Bike2WeightFlagEncoder)
double value = ((Number) props.get("speed")).doubleValue();
double oldSpeed = encoder.getSpeed(edge.getFlags());
if (oldSpeed != value) {
updates++;
if (enableLogging)
logger.info(encoder.toString() + " - speed change via feature " + jsonFeature.getId() + ". Old: " + oldSpeed + ", new:" + value);
edge.setFlags(encoder.setSpeed(edge.getFlags(), value));
}
}
}
return updates;
}
use of com.graphhopper.routing.util.DefaultEdgeFilter in project graphhopper by graphhopper.
the class RoundTripRoutingTemplate method lookup.
@Override
public List<QueryResult> lookup(List<GHPoint> points, FlagEncoder encoder) {
if (points.isEmpty())
throw new IllegalStateException("For round trip calculation one point is required");
final double distanceInMeter = ghRequest.getHints().getDouble(RoundTrip.DISTANCE, 10000);
final long seed = ghRequest.getHints().getLong(RoundTrip.SEED, 0L);
final double initialHeading = ghRequest.getHints().getDouble(RoundTrip.HEADING, Double.NaN);
final int roundTripPointCount = Math.min(20, ghRequest.getHints().getInt(Algorithms.ROUND_TRIP + ".points", 2 + (int) (distanceInMeter / 50000)));
final GHPoint start = ghRequest.getPoints().get(0);
TourStrategy strategy = new MultiPointTour(new Random(seed), distanceInMeter, roundTripPointCount, initialHeading);
queryResults = new ArrayList<>(2 + strategy.getNumberOfGeneratedPoints());
EdgeFilter edgeFilter = new DefaultEdgeFilter(encoder);
QueryResult startQR = locationIndex.findClosest(start.lat, start.lon, edgeFilter);
if (!startQR.isValid())
throw new PointNotFoundException("Cannot find point 0: " + start, 0);
queryResults.add(startQR);
GHPoint last = points.get(0);
for (int i = 0; i < strategy.getNumberOfGeneratedPoints(); i++) {
double heading = strategy.getHeadingForIteration(i);
QueryResult result = generateValidPoint(last, strategy.getDistanceForIteration(i), heading, edgeFilter);
if (result == null) {
ghResponse.addError(new IllegalStateException("Could not find a valid point after " + maxRetries + " tries, for the point:" + last));
return Collections.emptyList();
}
last = result.getSnappedPoint();
queryResults.add(result);
}
queryResults.add(startQR);
return queryResults;
}
use of com.graphhopper.routing.util.DefaultEdgeFilter in project graphhopper by graphhopper.
the class Path method calcInstructions.
/**
* @return the list of instructions for this path.
*/
public InstructionList calcInstructions(final Translation tr) {
final InstructionList ways = new InstructionList(edgeIds.size() / 4, tr);
if (edgeIds.isEmpty()) {
if (isFound()) {
ways.add(new FinishInstruction(nodeAccess, endNode));
}
return ways;
}
final int tmpNode = getFromNode();
forEveryEdge(new EdgeVisitor() {
/*
* We need three points to make directions
*
* (1)----(2)
* /
* /
* (0)
*
* 0 is the node visited at t-2, 1 is the node visited
* at t-1 and 2 is the node being visited at instant t.
* orientation is the angle of the vector(1->2) expressed
* as atan2, while previousOrientation is the angle of the
* vector(0->1)
* Intuitively, if orientation is smaller than
* previousOrientation, then we have to turn right, while
* if it is greater we have to turn left. To make this
* algorithm work, we need to make the comparison by
* considering orientation belonging to the interval
* [ - pi + previousOrientation , + pi + previousOrientation ]
*/
private double prevLat = nodeAccess.getLatitude(tmpNode);
private double prevLon = nodeAccess.getLongitude(tmpNode);
// Lat and Lon of node t-2
private double doublePrevLat, doublePrevLong;
private int prevNode = -1;
private double prevOrientation;
private Instruction prevInstruction;
private boolean prevInRoundabout = false;
private String name, prevName = null;
private InstructionAnnotation annotation, prevAnnotation;
private EdgeExplorer outEdgeExplorer = graph.createEdgeExplorer(new DefaultEdgeFilter(encoder, false, true));
@Override
public void next(EdgeIteratorState edge, int index) {
// baseNode is the current node and adjNode is the next
int adjNode = edge.getAdjNode();
int baseNode = edge.getBaseNode();
long flags = edge.getFlags();
double adjLat = nodeAccess.getLatitude(adjNode);
double adjLon = nodeAccess.getLongitude(adjNode);
double latitude, longitude;
PointList wayGeo = edge.fetchWayGeometry(3);
boolean isRoundabout = encoder.isBool(flags, FlagEncoder.K_ROUNDABOUT);
if (wayGeo.getSize() <= 2) {
latitude = adjLat;
longitude = adjLon;
} else {
latitude = wayGeo.getLatitude(1);
longitude = wayGeo.getLongitude(1);
assert Double.compare(prevLat, nodeAccess.getLatitude(baseNode)) == 0;
assert Double.compare(prevLon, nodeAccess.getLongitude(baseNode)) == 0;
}
name = edge.getName();
annotation = encoder.getAnnotation(flags, tr);
if (// very first instruction (if not in Roundabout)
(prevName == null) && (!isRoundabout)) {
int sign = Instruction.CONTINUE_ON_STREET;
prevInstruction = new Instruction(sign, name, annotation, new PointList(10, nodeAccess.is3D()));
ways.add(prevInstruction);
prevName = name;
prevAnnotation = annotation;
} else if (isRoundabout) {
// remark: names and annotations within roundabout are ignored
if (//just entered roundabout
!prevInRoundabout) {
int sign = Instruction.USE_ROUNDABOUT;
RoundaboutInstruction roundaboutInstruction = new RoundaboutInstruction(sign, name, annotation, new PointList(10, nodeAccess.is3D()));
if (prevName != null) {
// check if there is an exit at the same node the roundabout was entered
EdgeIterator edgeIter = outEdgeExplorer.setBaseNode(baseNode);
while (edgeIter.next()) {
if ((edgeIter.getAdjNode() != prevNode) && !encoder.isBool(edgeIter.getFlags(), FlagEncoder.K_ROUNDABOUT)) {
roundaboutInstruction.increaseExitNumber();
break;
}
}
// previous orientation is last orientation before entering roundabout
prevOrientation = AC.calcOrientation(doublePrevLat, doublePrevLong, prevLat, prevLon);
// calculate direction of entrance turn to determine direction of rotation
// right turn == counterclockwise and vice versa
double orientation = AC.calcOrientation(prevLat, prevLon, latitude, longitude);
orientation = AC.alignOrientation(prevOrientation, orientation);
double delta = (orientation - prevOrientation);
roundaboutInstruction.setDirOfRotation(delta);
} else // first instructions is roundabout instruction
{
prevOrientation = AC.calcOrientation(prevLat, prevLon, latitude, longitude);
prevName = name;
prevAnnotation = annotation;
}
prevInstruction = roundaboutInstruction;
ways.add(prevInstruction);
}
// Add passed exits to instruction. A node is counted if there is at least one outgoing edge
// out of the roundabout
EdgeIterator edgeIter = outEdgeExplorer.setBaseNode(adjNode);
while (edgeIter.next()) {
if (!encoder.isBool(edgeIter.getFlags(), FlagEncoder.K_ROUNDABOUT)) {
((RoundaboutInstruction) prevInstruction).increaseExitNumber();
break;
}
}
} else if (//previously in roundabout but not anymore
prevInRoundabout) {
prevInstruction.setName(name);
// calc angle between roundabout entrance and exit
double orientation = AC.calcOrientation(prevLat, prevLon, latitude, longitude);
orientation = AC.alignOrientation(prevOrientation, orientation);
double deltaInOut = (orientation - prevOrientation);
// calculate direction of exit turn to determine direction of rotation
// right turn == counterclockwise and vice versa
double recentOrientation = AC.calcOrientation(doublePrevLat, doublePrevLong, prevLat, prevLon);
orientation = AC.alignOrientation(recentOrientation, orientation);
double deltaOut = (orientation - recentOrientation);
prevInstruction = ((RoundaboutInstruction) prevInstruction).setRadian(deltaInOut).setDirOfRotation(deltaOut).setExited();
prevName = name;
prevAnnotation = annotation;
} else if ((!name.equals(prevName)) || (!annotation.equals(prevAnnotation))) {
prevOrientation = AC.calcOrientation(doublePrevLat, doublePrevLong, prevLat, prevLon);
double orientation = AC.calcOrientation(prevLat, prevLon, latitude, longitude);
orientation = AC.alignOrientation(prevOrientation, orientation);
double delta = orientation - prevOrientation;
double absDelta = Math.abs(delta);
int sign;
if (absDelta < 0.2) {
// 0.2 ~= 11°
sign = Instruction.CONTINUE_ON_STREET;
} else if (absDelta < 0.8) {
// 0.8 ~= 40°
if (delta > 0)
sign = Instruction.TURN_SLIGHT_LEFT;
else
sign = Instruction.TURN_SLIGHT_RIGHT;
} else if (absDelta < 1.8) {
// 1.8 ~= 103°
if (delta > 0)
sign = Instruction.TURN_LEFT;
else
sign = Instruction.TURN_RIGHT;
} else if (delta > 0)
sign = Instruction.TURN_SHARP_LEFT;
else
sign = Instruction.TURN_SHARP_RIGHT;
prevInstruction = new Instruction(sign, name, annotation, new PointList(10, nodeAccess.is3D()));
ways.add(prevInstruction);
prevName = name;
prevAnnotation = annotation;
}
updatePointsAndInstruction(edge, wayGeo);
if (wayGeo.getSize() <= 2) {
doublePrevLat = prevLat;
doublePrevLong = prevLon;
} else {
int beforeLast = wayGeo.getSize() - 2;
doublePrevLat = wayGeo.getLatitude(beforeLast);
doublePrevLong = wayGeo.getLongitude(beforeLast);
}
prevInRoundabout = isRoundabout;
prevNode = baseNode;
prevLat = adjLat;
prevLon = adjLon;
boolean lastEdge = index == edgeIds.size() - 1;
if (lastEdge) {
if (isRoundabout) {
// calc angle between roundabout entrance and finish
double orientation = AC.calcOrientation(doublePrevLat, doublePrevLong, prevLat, prevLon);
orientation = AC.alignOrientation(prevOrientation, orientation);
double delta = (orientation - prevOrientation);
((RoundaboutInstruction) prevInstruction).setRadian(delta);
}
ways.add(new FinishInstruction(nodeAccess, adjNode));
}
}
private void updatePointsAndInstruction(EdgeIteratorState edge, PointList pl) {
// skip adjNode
int len = pl.size() - 1;
for (int i = 0; i < len; i++) {
prevInstruction.getPoints().add(pl, i);
}
double newDist = edge.getDistance();
prevInstruction.setDistance(newDist + prevInstruction.getDistance());
prevInstruction.setTime(weighting.calcMillis(edge, false, EdgeIterator.NO_EDGE) + prevInstruction.getTime());
}
});
return ways;
}
Aggregations