use of com.graphhopper.PathWrapper in project graphhopper by graphhopper.
the class GraphHopperServlet method doGet.
@Override
public void doGet(HttpServletRequest httpReq, HttpServletResponse httpRes) throws ServletException, IOException {
List<GHPoint> requestPoints = getPoints(httpReq, "point");
GHResponse ghRsp = new GHResponse();
double minPathPrecision = getDoubleParam(httpReq, WAY_POINT_MAX_DISTANCE, 1d);
boolean writeGPX = "gpx".equalsIgnoreCase(getParam(httpReq, "type", "json"));
boolean enableInstructions = writeGPX || getBooleanParam(httpReq, INSTRUCTIONS, true);
boolean calcPoints = getBooleanParam(httpReq, CALC_POINTS, true);
boolean enableElevation = getBooleanParam(httpReq, "elevation", false);
boolean pointsEncoded = getBooleanParam(httpReq, "points_encoded", true);
String vehicleStr = getParam(httpReq, "vehicle", "car");
String weighting = getParam(httpReq, "weighting", "fastest");
String algoStr = getParam(httpReq, "algorithm", "");
String localeStr = getParam(httpReq, "locale", "en");
StopWatch sw = new StopWatch().start();
if (!ghRsp.hasErrors()) {
try {
if (requestPoints.isEmpty()) {
throw new IllegalArgumentException("You have to pass at least one point");
}
List<Double> favoredHeadings = Collections.EMPTY_LIST;
try {
favoredHeadings = getDoubleParamList(httpReq, "heading");
} catch (NumberFormatException e) {
throw new IllegalArgumentException("heading list in wrong format: " + e.getMessage());
}
if (!encodingManager.supports(vehicleStr)) {
throw new IllegalArgumentException("Vehicle not supported: " + vehicleStr);
} else if (enableElevation && !hasElevation) {
throw new IllegalArgumentException("Elevation not supported!");
} else if (favoredHeadings.size() > 1 && favoredHeadings.size() != requestPoints.size()) {
throw new IllegalArgumentException("The number of 'heading' parameters must be <= 1 " + "or equal to the number of points (" + requestPoints.size() + ")");
}
List<String> pointHints = Arrays.asList(getParams(httpReq, POINT_HINT));
if (pointHints.size() > 0 && pointHints.size() != requestPoints.size()) {
throw new IllegalArgumentException("If you pass " + POINT_HINT + ", you need to pass a hint for every point, empty hints will be ignored");
}
List<String> pathDetails = Arrays.asList(getParams(httpReq, PATH_DETAILS));
FlagEncoder algoVehicle = encodingManager.getEncoder(vehicleStr);
GHRequest request;
if (favoredHeadings.size() > 0) {
// if only one favored heading is specified take as start heading
if (favoredHeadings.size() == 1) {
List<Double> paddedHeadings = new ArrayList<Double>(Collections.nCopies(requestPoints.size(), Double.NaN));
paddedHeadings.set(0, favoredHeadings.get(0));
request = new GHRequest(requestPoints, paddedHeadings);
} else {
request = new GHRequest(requestPoints, favoredHeadings);
}
} else {
request = new GHRequest(requestPoints);
}
initHints(request.getHints(), httpReq.getParameterMap());
request.setVehicle(algoVehicle.toString()).setWeighting(weighting).setAlgorithm(algoStr).setLocale(localeStr).setPointHints(pointHints).setPathDetails(pathDetails).getHints().put(CALC_POINTS, calcPoints).put(INSTRUCTIONS, enableInstructions).put(WAY_POINT_MAX_DISTANCE, minPathPrecision);
ghRsp = graphHopper.route(request);
} catch (IllegalArgumentException ex) {
ghRsp.addError(ex);
}
}
float took = sw.stop().getSeconds();
String infoStr = httpReq.getRemoteAddr() + " " + httpReq.getLocale() + " " + httpReq.getHeader("User-Agent");
String logStr = httpReq.getQueryString() + " " + infoStr + " " + requestPoints + ", took:" + took + ", " + algoStr + ", " + weighting + ", " + vehicleStr;
httpRes.setHeader("X-GH-Took", "" + Math.round(took * 1000));
int alternatives = ghRsp.getAll().size();
if (writeGPX && alternatives > 1)
ghRsp.addError(new IllegalArgumentException("Alternatives are currently not yet supported for GPX"));
if (ghRsp.hasErrors()) {
logger.error(logStr + ", errors:" + ghRsp.getErrors());
} else {
PathWrapper altRsp0 = ghRsp.getBest();
logger.info(logStr + ", alternatives: " + alternatives + ", distance0: " + altRsp0.getDistance() + ", time0: " + Math.round(altRsp0.getTime() / 60000f) + "min" + ", points0: " + altRsp0.getPoints().getSize() + ", debugInfo: " + ghRsp.getDebugInfo());
}
if (writeGPX) {
if (ghRsp.hasErrors()) {
httpRes.setStatus(SC_BAD_REQUEST);
httpRes.getWriter().append(errorsToXML(ghRsp.getErrors()));
} else {
// no error => we can now safely call getFirst
String xml = createGPXString(httpReq, httpRes, ghRsp.getBest());
writeResponse(httpRes, xml);
}
} else {
Map<String, Object> map = routeSerializer.toJSON(ghRsp, calcPoints, pointsEncoded, enableElevation, enableInstructions);
Object infoMap = map.get("info");
if (infoMap != null)
((Map) infoMap).put("took", Math.round(took * 1000));
if (ghRsp.hasErrors())
writeJsonError(httpRes, SC_BAD_REQUEST, objectMapper.getNodeFactory().pojoNode(map));
else {
writeJson(httpReq, httpRes, objectMapper.getNodeFactory().pojoNode(map));
}
}
}
use of com.graphhopper.PathWrapper in project graphhopper by graphhopper.
the class AlternativeRoutingTemplate method isReady.
@Override
public boolean isReady(PathMerger pathMerger, Translation tr) {
if (pathList.isEmpty())
throw new RuntimeException("Empty paths for alternative route calculation not expected");
// if alternative route calculation was done then create the responses from single paths
PointList wpList = getWaypoints();
altResponse.setWaypoints(wpList);
ghResponse.add(altResponse);
pathMerger.doWork(altResponse, Collections.singletonList(pathList.get(0)), tr);
for (int index = 1; index < pathList.size(); index++) {
PathWrapper tmpAltRsp = new PathWrapper();
tmpAltRsp.setWaypoints(wpList);
ghResponse.add(tmpAltRsp);
pathMerger.doWork(tmpAltRsp, Collections.singletonList(pathList.get(index)), tr);
}
return true;
}
use of com.graphhopper.PathWrapper in project graphhopper by graphhopper.
the class TestAlgoCollector method assertDistance.
public TestAlgoCollector assertDistance(AlgoHelperEntry algoEntry, List<QueryResult> queryList, OneRun oneRun) {
List<Path> altPaths = new ArrayList<>();
QueryGraph queryGraph = new QueryGraph(algoEntry.getForQueryGraph());
queryGraph.lookup(queryList);
AlgorithmOptions opts = algoEntry.getAlgorithmOptions();
FlagEncoder encoder = opts.getWeighting().getFlagEncoder();
if (encoder.supports(TurnWeighting.class)) {
if (!opts.getTraversalMode().isEdgeBased()) {
errors.add("Cannot use TurnWeighting with a node based traversal");
return this;
}
algoEntry.setAlgorithmOptions(AlgorithmOptions.start(opts).weighting(new TurnWeighting(opts.getWeighting(), (TurnCostExtension) queryGraph.getExtension())).build());
}
RoutingAlgorithmFactory factory = algoEntry.createRoutingFactory();
for (int i = 0; i < queryList.size() - 1; i++) {
RoutingAlgorithm algo = factory.createAlgo(queryGraph, algoEntry.getAlgorithmOptions());
// if (!algoEntry.getExpectedAlgo().equals(algo.toString())) {
// errors.add("Algorithm expected " + algoEntry.getExpectedAlgo() + " but was " + algo.toString());
// return this;
// }
Path path = algo.calcPath(queryList.get(i).getClosestNode(), queryList.get(i + 1).getClosestNode());
altPaths.add(path);
}
PathMerger pathMerger = new PathMerger().setCalcPoints(true).setSimplifyResponse(false).setEnableInstructions(true);
PathWrapper rsp = new PathWrapper();
pathMerger.doWork(rsp, altPaths, trMap.getWithFallBack(Locale.US));
if (rsp.hasErrors()) {
errors.add("response for " + algoEntry + " contains errors. Expected distance: " + oneRun.getDistance() + ", expected points: " + oneRun + ". " + queryList + ", errors:" + rsp.getErrors());
return this;
}
PointList pointList = rsp.getPoints();
double tmpDist = pointList.calcDistance(distCalc);
if (Math.abs(rsp.getDistance() - tmpDist) > 2) {
errors.add(algoEntry + " path.getDistance was " + rsp.getDistance() + "\t pointList.calcDistance was " + tmpDist + "\t (expected points " + oneRun.getLocs() + ", expected distance " + oneRun.getDistance() + ") " + queryList);
}
if (Math.abs(rsp.getDistance() - oneRun.getDistance()) > 2) {
errors.add(algoEntry + " returns path not matching the expected distance of " + oneRun.getDistance() + "\t Returned was " + rsp.getDistance() + "\t (expected points " + oneRun.getLocs() + ", was " + pointList.getSize() + ") " + queryList);
}
// There are real world instances where A-B-C is identical to A-C (in meter precision).
if (Math.abs(pointList.getSize() - oneRun.getLocs()) > 1) {
errors.add(algoEntry + " returns path not matching the expected points of " + oneRun.getLocs() + "\t Returned was " + pointList.getSize() + "\t (expected distance " + oneRun.getDistance() + ", was " + rsp.getDistance() + ") " + queryList);
}
return this;
}
use of com.graphhopper.PathWrapper in project graphhopper by graphhopper.
the class GraphHopperWeb method createPathWrapper.
public static PathWrapper createPathWrapper(JSONObject path, boolean tmpCalcPoints, boolean tmpInstructions, boolean tmpElevation, boolean turnDescription) {
PathWrapper pathWrapper = new PathWrapper();
pathWrapper.addErrors(readErrors(path));
if (pathWrapper.hasErrors())
return pathWrapper;
if (path.has("snapped_waypoints")) {
String snappedPointStr = path.getString("snapped_waypoints");
PointList snappedPoints = WebHelper.decodePolyline(snappedPointStr, 5, tmpElevation);
pathWrapper.setWaypoints(snappedPoints);
}
if (tmpCalcPoints) {
String pointStr = path.getString("points");
PointList pointList = WebHelper.decodePolyline(pointStr, 100, tmpElevation);
pathWrapper.setPoints(pointList);
if (tmpInstructions) {
JSONArray instrArr = path.getJSONArray("instructions");
InstructionList il = new InstructionList(null);
int viaCount = 1;
for (int instrIndex = 0; instrIndex < instrArr.length(); instrIndex++) {
JSONObject jsonObj = instrArr.getJSONObject(instrIndex);
double instDist = jsonObj.getDouble("distance");
String text = turnDescription ? jsonObj.getString("text") : jsonObj.getString("street_name");
long instTime = jsonObj.getLong("time");
int sign = jsonObj.getInt("sign");
JSONArray iv = jsonObj.getJSONArray("interval");
int from = iv.getInt(0);
int to = iv.getInt(1);
PointList instPL = new PointList(to - from, tmpElevation);
for (int j = from; j <= to; j++) {
instPL.add(pointList, j);
}
InstructionAnnotation ia = InstructionAnnotation.EMPTY;
if (jsonObj.has("annotation_importance") && jsonObj.has("annotation_text")) {
ia = new InstructionAnnotation(jsonObj.getInt("annotation_importance"), jsonObj.getString("annotation_text"));
}
Instruction instr;
if (sign == Instruction.USE_ROUNDABOUT || sign == Instruction.LEAVE_ROUNDABOUT) {
RoundaboutInstruction ri = new RoundaboutInstruction(sign, text, ia, instPL);
if (jsonObj.has("exit_number")) {
ri.setExitNumber(jsonObj.getInt("exit_number"));
}
if (jsonObj.has("exited")) {
if (jsonObj.getBoolean("exited"))
ri.setExited();
}
if (jsonObj.has("turn_angle")) {
// TODO provide setTurnAngle setter
double angle = jsonObj.getDouble("turn_angle");
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, ia, instPL);
tmpInstr.setViaCount(viaCount);
viaCount++;
instr = tmpInstr;
} else if (sign == Instruction.FINISH) {
instr = new FinishInstruction(instPL, 0);
} else {
instr = new Instruction(sign, text, ia, instPL);
}
// This can be changed by passing <code>turn_description=false</code>.
if (turnDescription)
instr.setUseRawName();
instr.setDistance(instDist).setTime(instTime);
il.add(instr);
}
pathWrapper.setInstructions(il);
}
}
double distance = path.getDouble("distance");
long time = path.getLong("time");
pathWrapper.setDistance(distance).setTime(time);
return pathWrapper;
}
use of com.graphhopper.PathWrapper in project graphhopper by graphhopper.
the class GraphHopperWeb method route.
@Override
public GHResponse route(GHRequest request) {
try {
String places = "";
for (GHPoint p : request.getPoints()) {
places += "point=" + p.lat + "," + p.lon + "&";
}
boolean tmpInstructions = request.getHints().getBool("instructions", instructions);
boolean tmpCalcPoints = request.getHints().getBool("calc_points", calcPoints);
boolean tmpTurnDescription = request.getHints().getBool("turn_description", turnDescription);
if (tmpInstructions && !tmpCalcPoints)
throw new IllegalStateException("Cannot calculate instructions without points (only points without instructions). " + "Use calc_points=false and instructions=false to disable point and instruction calculation");
boolean tmpElevation = request.getHints().getBool("elevation", elevation);
String url = routeServiceUrl + "?" + places + "&type=json" + "&instructions=" + tmpInstructions + "&points_encoded=true" + "&calc_points=" + tmpCalcPoints + "&algorithm=" + request.getAlgorithm() + "&locale=" + request.getLocale().toString() + "&elevation=" + tmpElevation;
if (!request.getVehicle().isEmpty())
url += "&vehicle=" + request.getVehicle();
if (!key.isEmpty())
url += "&key=" + key;
for (Entry<String, String> entry : request.getHints().toMap().entrySet()) {
String urlKey = entry.getKey();
String urlValue = entry.getValue();
// use lower case conversion for check only!
if (ignoreSet.contains(urlKey.toLowerCase()))
continue;
if (urlValue != null && !urlValue.isEmpty())
url += "&" + WebHelper.encodeURL(urlKey) + "=" + WebHelper.encodeURL(urlValue);
}
String str = downloader.downloadAsString(url, true);
JSONObject json = new JSONObject(str);
GHResponse res = new GHResponse();
res.addErrors(readErrors(json));
if (res.hasErrors())
return res;
JSONArray paths = json.getJSONArray("paths");
for (int index = 0; index < paths.length(); index++) {
JSONObject path = paths.getJSONObject(index);
PathWrapper altRsp = createPathWrapper(path, tmpCalcPoints, tmpInstructions, tmpElevation, tmpTurnDescription);
res.add(altRsp);
}
return res;
} catch (Exception ex) {
throw new RuntimeException("Problem while fetching path " + request.getPoints() + ": " + ex.getMessage(), ex);
}
}
Aggregations