use of com.graphhopper.ResponsePath in project graphhopper by graphhopper.
the class RoutingAdditivityTest method testBoundedAdditivityOfGraphhopperTravelTimes.
@Test
public void testBoundedAdditivityOfGraphhopperTravelTimes() {
ResponsePath route1 = graphHopper.route(new GHRequest(new GHPoint(51.23, 12.18), new GHPoint(51.45, 12.59)).setProfile("my_profile")).getBest();
// Re-route from snapped point to snapped point.
// It's the only way to be sure.
ResponsePath route2 = graphHopper.route(new GHRequest(route1.getWaypoints().get(0), route1.getWaypoints().get(1)).setProfile("my_profile")).getBest();
assertThat(route1.getTime(), is(equalTo(route2.getTime())));
long travelTime = 0L;
for (int i = 0; i < route2.getPoints().size() - 1; i++) {
ResponsePath segment = graphHopper.route(new GHRequest(route2.getPoints().get(i), route2.getPoints().get(i + 1)).setProfile("my_profile")).getBest();
travelTime += segment.getTime();
}
// Even though I route from node to node, and travel times are longs, not doubles,
// I apparently don't get the exact result if I sum up the travel times between segments.
// But it's within one second.
assertThat(Math.abs(travelTime - route2.getTime()), is(lessThan(1000L)));
}
use of com.graphhopper.ResponsePath in project graphhopper by graphhopper.
the class RouteResourceTest method testGraphHopperWeb.
@Test
public void testGraphHopperWeb() {
GraphHopperWeb hopper = new GraphHopperWeb(clientUrl(app, "/route"));
GHResponse rsp = hopper.route(new GHRequest(42.554851, 1.536198, 42.510071, 1.548128).setProfile("my_car"));
assertFalse(rsp.hasErrors(), rsp.getErrors().toString());
assertTrue(rsp.getErrors().isEmpty(), rsp.getErrors().toString());
ResponsePath res = rsp.getBest();
assertTrue(res.getDistance() > 9000, "distance wasn't correct:" + res.getDistance());
assertTrue(res.getDistance() < 9500, "distance wasn't correct:" + res.getDistance());
rsp = hopper.route(new GHRequest().setProfile("my_car").addPoint(new GHPoint(42.554851, 1.536198)).addPoint(new GHPoint(42.531896, 1.553278)).addPoint(new GHPoint(42.510071, 1.548128)));
assertTrue(rsp.getErrors().isEmpty(), rsp.getErrors().toString());
res = rsp.getBest();
assertTrue(res.getDistance() > 20000, "distance wasn't correct:" + res.getDistance());
assertTrue(res.getDistance() < 21000, "distance wasn't correct:" + res.getDistance());
InstructionList instructions = res.getInstructions();
assertEquals(24, instructions.size());
assertEquals("Continue onto la Callisa", instructions.get(0).getTurnDescription(null));
assertEquals("At roundabout, take exit 2", instructions.get(4).getTurnDescription(null));
assertEquals(true, instructions.get(4).getExtraInfoJSON().get("exited"));
assertEquals(false, instructions.get(22).getExtraInfoJSON().get("exited"));
}
use of com.graphhopper.ResponsePath in project graphhopper by graphhopper.
the class PathMerger method doWork.
public ResponsePath doWork(PointList waypoints, List<Path> paths, EncodedValueLookup evLookup, Translation tr) {
ResponsePath responsePath = new ResponsePath();
int origPoints = 0;
long fullTimeInMillis = 0;
double fullWeight = 0;
double fullDistance = 0;
boolean allFound = true;
InstructionList fullInstructions = new InstructionList(tr);
PointList fullPoints = PointList.EMPTY;
List<String> description = new ArrayList<>();
for (int pathIndex = 0; pathIndex < paths.size(); pathIndex++) {
Path path = paths.get(pathIndex);
if (!path.isFound()) {
allFound = false;
continue;
}
description.addAll(path.getDescription());
fullTimeInMillis += path.getTime();
fullDistance += path.getDistance();
fullWeight += path.getWeight();
if (enableInstructions) {
InstructionList il = InstructionsFromEdges.calcInstructions(path, graph, weighting, evLookup, tr);
if (!il.isEmpty()) {
fullInstructions.addAll(il);
// for all paths except the last replace the FinishInstruction with a ViaInstruction
if (pathIndex + 1 < paths.size()) {
ViaInstruction newInstr = new ViaInstruction(fullInstructions.get(fullInstructions.size() - 1));
newInstr.setViaCount(pathIndex + 1);
fullInstructions.set(fullInstructions.size() - 1, newInstr);
}
}
}
if (calcPoints || enableInstructions) {
PointList tmpPoints = path.calcPoints();
if (fullPoints.isEmpty())
fullPoints = new PointList(tmpPoints.size(), tmpPoints.is3D());
// Remove duplicated points, see #1138
if (pathIndex + 1 < paths.size()) {
tmpPoints.removeLastPoint();
}
fullPoints.add(tmpPoints);
responsePath.addPathDetails(PathDetailsFromEdges.calcDetails(path, evLookup, weighting, requestedPathDetails, pathBuilderFactory, origPoints));
origPoints = fullPoints.size();
}
allFound = allFound && path.isFound();
}
if (!fullPoints.isEmpty()) {
responsePath.addDebugInfo("simplify (" + origPoints + "->" + fullPoints.size() + ")");
if (fullPoints.is3D)
calcAscendDescend(responsePath, fullPoints);
}
if (enableInstructions) {
fullInstructions = updateInstructionsWithContext(fullInstructions);
responsePath.setInstructions(fullInstructions);
}
if (!allFound) {
responsePath.addError(new ConnectionNotFoundException("Connection between locations not found", Collections.<String, Object>emptyMap()));
}
responsePath.setDescription(description).setPoints(fullPoints).setRouteWeight(fullWeight).setDistance(fullDistance).setTime(fullTimeInMillis).setWaypoints(waypoints);
if (allFound && simplifyResponse && (calcPoints || enableInstructions)) {
PathSimplification.simplify(responsePath, douglasPeucker, enableInstructions);
}
return responsePath;
}
use of com.graphhopper.ResponsePath in project graphhopper by graphhopper.
the class ResponsePathDeserializer method createResponsePath.
public static ResponsePath createResponsePath(ObjectMapper objectMapper, JsonNode path, boolean hasElevation, boolean turnDescription) {
ResponsePath responsePath = new ResponsePath();
responsePath.addErrors(readErrors(objectMapper, path));
if (responsePath.hasErrors())
return responsePath;
if (path.has("snapped_waypoints")) {
JsonNode snappedWaypoints = path.get("snapped_waypoints");
PointList snappedPoints = deserializePointList(objectMapper, snappedWaypoints, hasElevation);
responsePath.setWaypoints(snappedPoints);
}
if (path.has("ascend")) {
responsePath.setAscend(path.get("ascend").asDouble());
}
if (path.has("descend")) {
responsePath.setDescend(path.get("descend").asDouble());
}
if (path.has("weight")) {
responsePath.setRouteWeight(path.get("weight").asDouble());
}
if (path.has("description")) {
JsonNode descriptionNode = path.get("description");
if (descriptionNode.isArray()) {
List<String> description = new ArrayList<>(descriptionNode.size());
for (JsonNode descNode : descriptionNode) {
description.add(descNode.asText());
}
responsePath.setDescription(description);
} else {
throw new IllegalStateException("Description has to be an array");
}
}
if (path.has("points")) {
final PointList pointList = deserializePointList(objectMapper, path.get("points"), hasElevation);
responsePath.setPoints(pointList);
if (path.has("instructions")) {
JsonNode instrArr = path.get("instructions");
InstructionList il = new InstructionList(null);
int viaCount = 1;
for (JsonNode jsonObj : instrArr) {
double instDist = jsonObj.get("distance").asDouble();
String text = turnDescription ? jsonObj.get("text").asText() : jsonObj.get("street_name").asText();
long instTime = jsonObj.get("time").asLong();
int sign = jsonObj.get("sign").asInt();
JsonNode iv = jsonObj.get("interval");
int from = iv.get(0).asInt();
int to = iv.get(1).asInt();
PointList instPL = new PointList(to - from, hasElevation);
for (int j = from; j <= to; j++) {
instPL.add(pointList, j);
}
Instruction instr;
if (sign == Instruction.USE_ROUNDABOUT || sign == Instruction.LEAVE_ROUNDABOUT) {
RoundaboutInstruction ri = new RoundaboutInstruction(sign, text, instPL);
if (jsonObj.has("exit_number")) {
ri.setExitNumber(jsonObj.get("exit_number").asInt());
}
if (jsonObj.has("exited")) {
if (jsonObj.get("exited").asBoolean())
ri.setExited();
}
if (jsonObj.has("turn_angle")) {
// TODO provide setTurnAngle setter
double angle = jsonObj.get("turn_angle").asDouble();
ri.setDirOfRotation(angle);
ri.setRadian((angle < 0 ? -Math.PI : Math.PI) - angle);
}
instr = ri;
} else if (sign == Instruction.REACHED_VIA) {
ViaInstruction tmpInstr = new ViaInstruction(text, instPL);
tmpInstr.setViaCount(viaCount);
viaCount++;
instr = tmpInstr;
} else if (sign == Instruction.FINISH) {
instr = new FinishInstruction(text, instPL, 0);
} else {
instr = new Instruction(sign, text, instPL);
if (sign == Instruction.CONTINUE_ON_STREET) {
if (jsonObj.has("heading")) {
instr.setExtraInfo("heading", jsonObj.get("heading").asDouble());
}
}
}
// This can be changed by passing <code>turn_description=false</code>.
if (turnDescription)
instr.setUseRawName();
instr.setDistance(instDist).setTime(instTime);
il.add(instr);
}
responsePath.setInstructions(il);
}
if (path.has("details")) {
JsonNode details = path.get("details");
Map<String, List<PathDetail>> pathDetails = new HashMap<>(details.size());
Iterator<Map.Entry<String, JsonNode>> detailIterator = details.fields();
while (detailIterator.hasNext()) {
Map.Entry<String, JsonNode> detailEntry = detailIterator.next();
List<PathDetail> pathDetailList = new ArrayList<>();
for (JsonNode pathDetail : detailEntry.getValue()) {
PathDetail pd = objectMapper.convertValue(pathDetail, PathDetail.class);
pathDetailList.add(pd);
}
pathDetails.put(detailEntry.getKey(), pathDetailList);
}
responsePath.addPathDetails(pathDetails);
}
}
if (path.has("points_order")) {
responsePath.setPointsOrder((List<Integer>) objectMapper.convertValue(path.get("points_order"), List.class));
} else {
List<Integer> list = new ArrayList<>(responsePath.getWaypoints().size());
for (int i = 0; i < responsePath.getWaypoints().size(); i++) {
list.add(i);
}
responsePath.setPointsOrder(list);
}
double distance = path.get("distance").asDouble();
long time = path.get("time").asLong();
responsePath.setDistance(distance).setTime(time);
return responsePath;
}
use of com.graphhopper.ResponsePath in project graphhopper by graphhopper.
the class Router method routeVia.
protected GHResponse routeVia(GHRequest request, Solver solver) {
GHResponse ghRsp = new GHResponse();
StopWatch sw = new StopWatch().start();
DirectedEdgeFilter directedEdgeFilter = solver.createDirectedEdgeFilter();
List<Snap> snaps = ViaRouting.lookup(encodingManager, request.getPoints(), solver.createSnapFilter(), locationIndex, request.getSnapPreventions(), request.getPointHints(), directedEdgeFilter, request.getHeadings());
ghRsp.addDebugInfo("idLookup:" + sw.stop().getSeconds() + "s");
// (base) query graph used to resolve headings, curbsides etc. this is not necessarily the same thing as
// the (possibly implementation specific) query graph used by PathCalculator
QueryGraph queryGraph = QueryGraph.create(ghStorage, snaps);
PathCalculator pathCalculator = solver.createPathCalculator(queryGraph);
boolean passThrough = getPassThrough(request.getHints());
boolean forceCurbsides = getForceCurbsides(request.getHints());
ViaRouting.Result result = ViaRouting.calcPaths(request.getPoints(), queryGraph, snaps, directedEdgeFilter, pathCalculator, request.getCurbsides(), forceCurbsides, request.getHeadings(), passThrough);
if (request.getPoints().size() != result.paths.size() + 1)
throw new RuntimeException("There should be exactly one more point than paths. points:" + request.getPoints().size() + ", paths:" + result.paths.size());
// here each path represents one leg of the via-route and we merge them all together into one response path
ResponsePath responsePath = concatenatePaths(request, solver.weighting, queryGraph, result.paths, getWaypoints(snaps));
responsePath.addDebugInfo(result.debug);
ghRsp.add(responsePath);
ghRsp.getHints().putObject("visited_nodes.sum", result.visitedNodes);
ghRsp.getHints().putObject("visited_nodes.average", (float) result.visitedNodes / (snaps.size() - 1));
return ghRsp;
}
Aggregations