From 73800f51ef6af6faa3b18e279188642a164f0adb Mon Sep 17 00:00:00 2001 From: takb Date: Wed, 23 Jan 2019 12:15:51 +0100 Subject: [PATCH 01/24] added search option alternative_routes, added RouteResult processing for GHResponse with multiple paths, minor refactoring in RouteResultBuilder and RoutingRequestProcessor --- .../ors/routing/RouteResultBuilder.java | 763 +++++++++++------- .../ors/routing/RouteSearchParameters.java | 19 + .../heigit/ors/routing/RoutingProfile.java | 9 + .../ors/routing/RoutingProfileManager.java | 4 +- .../RoutingRequestProcessor.java | 12 +- 5 files changed, 529 insertions(+), 278 deletions(-) diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteResultBuilder.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteResultBuilder.java index db530cfa85..241ee7ae20 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RouteResultBuilder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteResultBuilder.java @@ -54,293 +54,516 @@ public RouteResultBuilder() _distCalc = new DistanceCalcEarth(); } - public RouteResult createRouteResult(List routes, RoutingRequest request, List extras) throws Exception - { - RouteResult result = new RouteResult(request.getExtraInfo()); - - if (routes.isEmpty()) - return result; - - if(!LocalizationManager.getInstance().isLanguageSupported(request.getLanguage())) - throw new Exception("Specified language '" + request.getLanguage() + "' is not supported."); - - InstructionTranslator instrTranslator = InstructionTranslatorsCache.getInstance().getTranslator(request.getLanguage()); - - boolean formatInstructions = request.getInstructionsFormat() == RouteInstructionsFormat.HTML; - int nRoutes = routes.size(); - double distance = 0.0; - double duration = 0.0; - double ascent = 0.0; - double descent = 0.0; - //MARQ24 removed not implemented -> double distanceActual = 0.0; - double durationTraffic = 0.0; - - double lon0 = 0, lat0 = 0, lat1 = 0, lon1 = 0; - boolean includeDetourFactor = request.hasAttribute("detourfactor"); - boolean includeElev = request.getIncludeElevation(); - DistanceUnit units = request.getUnits(); - int unitDecimals = FormatUtility.getUnitDecimals(units); - PointList prevSegPoints = null, segPoints, nextSegPoints; - - PointList summary_pointlist = null; - BBox bbox = null; - int[] routeWayPoints = null; - - if (request.getIncludeGeometry()) - { - routeWayPoints = new int[nRoutes + 1]; - routeWayPoints[0] = 0; - } - - if (extras != null) { - // only add the extras we requested unless a "warning" has been generated - for(RouteExtraInfo extra : extras) { - if(RouteExtraInfoFlag.isSet(request.getExtraInfo(), RouteExtraInfoFlag.getFromString(extra.getName()))) { - result.addExtraInfo(extra); - } else { - if (extra.isUsedForWarnings() && extra.getWarningGraphExtension() instanceof WarningGraphExtension) { - WarningGraphExtension warningExtension = extra.getWarningGraphExtension(); - if(warningExtension.generatesWarning(extra)) { - result.addWarning(warningExtension.getWarning()); - result.addExtraInfo(extra); - } - } - } - } - } - - for (int ri = 0; ri < nRoutes; ++ri) - { - GHResponse resp = routes.get(ri); - - if (resp.hasErrors()) - throw new InternalServerException(RoutingErrorCodes.UNKNOWN, String.format("Unable to find a route between points %d (%s) and %d (%s)", ri, FormatUtility.formatCoordinate(request.getCoordinates()[ri]), ri + 1, FormatUtility.formatCoordinate(request.getCoordinates()[ri+1]))); - - PathWrapper path = resp.getBest(); - PointList routePoints = path.getPoints(); - if (summary_pointlist == null) { - summary_pointlist = path.getPoints(); - } else { - PointList new_points = path.getPoints(); - summary_pointlist.add(new_points); - } - if (bbox == null) - bbox = new BBox(routePoints.getLon(0), routePoints.getLon(0), routePoints.getLat(0), routePoints.getLat(0)); - bbox = GeomUtility.CalculateBoundingBox(path.getPoints(), bbox); - - if (request.getIncludeGeometry()) - { - result.addPoints(routePoints, ri > 0, includeElev); - - routeWayPoints[ri + 1] = result.getGeometry().length - 1; - - if (request.getIncludeInstructions()) - { - InstructionList instructions = path.getInstructions(); - int startWayPointIndex = routeWayPoints[ri]; - int nInstructions = instructions.size(); - //if (nInstructions > 1) // last is finishinstruction - // nInstructions -= 1; - - Instruction instr, prevInstr = null; - InstructionType instrType = InstructionType.UNKNOWN; - RouteSegment seg = new RouteSegment(path, units); + public RouteResult[] createRouteResults(List routes, RoutingRequest request, List extras) throws Exception { + if (routes.isEmpty()) + return new RouteResult[]{new RouteResult(request.getExtraInfo())}; + + if (routes.size() > 1) { + if (request.getSearchParameters().getAlternativeRoutes() > 1) { + throw new InternalServerException(RoutingErrorCodes.INVALID_PARAMETER_VALUE, "Alternative routes algorithm does not support more than two way points"); + } + return new RouteResult[]{createRouteResult(routes, request, extras)}; + } + return createRouteResultSet(routes.get(0), request, extras); + } - if (includeDetourFactor) - { - lat0 = routePoints.getLat(0); - lon0 = routePoints.getLon(0); + public RouteResult createRouteResult(List routes, RoutingRequest request, List extras) throws Exception { - lat1 = routePoints.getLat(routePoints.getSize() - 1); - lon1 = routePoints.getLon(routePoints.getSize() - 1); + RouteResult result = new RouteResult(request.getExtraInfo()); - double dist = _distCalc.calcDist(lat0, lon0, lat1, lon1); - seg.setDetourFactor((dist == 0) ? 0 : FormatUtility.roundToDecimals(path.getDistance()/dist, 2)); - } + InstructionTranslator instrTranslator = InstructionTranslatorsCache.getInstance().getTranslator(request.getLanguage()); - String instrText = ""; - double stepDistance, stepDuration; + boolean formatInstructions = request.getInstructionsFormat() == RouteInstructionsFormat.HTML; + int nRoutes = routes.size(); + double distance = 0.0; + double duration = 0.0; + double ascent = 0.0; + double descent = 0.0; + //MARQ24 removed not implemented -> double distanceActual = 0.0; + double durationTraffic = 0.0; - for (int ii = 0; ii < nInstructions; ++ii) - { - instr = instructions.get(ii); - InstructionAnnotation instrAnnotation = instr.getAnnotation(); - instrType = getInstructionType(ii == 0, instr); - segPoints = instr.getPoints(); - nextSegPoints = (ii + 1 < nInstructions) ? instructions.get(ii + 1).getPoints() : getNextSegPoints(routes, ri + 1, 0); + double lon0 = 0, lat0 = 0, lat1 = 0, lon1 = 0; + boolean includeDetourFactor = request.hasAttribute("detourfactor"); + boolean includeElev = request.getIncludeElevation(); + DistanceUnit units = request.getUnits(); + int unitDecimals = FormatUtility.getUnitDecimals(units); + PointList prevSegPoints = null, segPoints, nextSegPoints; - String roadName = formatInstructions && !Helper.isEmpty(instr.getName()) ? "" + instr.getName() + "" : instr.getName(); - instrText = ""; + PointList summary_pointlist = null; + BBox bbox = null; + int[] routeWayPoints = null; - stepDistance = FormatUtility.roundToDecimals(DistanceUnitUtil.convert(instr.getDistance(), DistanceUnit.Meters, units), unitDecimals); - stepDuration = FormatUtility.roundToDecimals(instr.getTime()/1000.0, 1); + if (request.getIncludeGeometry()) { + routeWayPoints = new int[nRoutes + 1]; + routeWayPoints[0] = 0; + } - RouteStep step = new RouteStep(); + if (extras != null) { + // only add the extras we requested unless a "warning" has been generated + for (RouteExtraInfo extra : extras) { + if (RouteExtraInfoFlag.isSet(request.getExtraInfo(), RouteExtraInfoFlag.getFromString(extra.getName()))) { + result.addExtraInfo(extra); + } else { + if (extra.isUsedForWarnings() && extra.getWarningGraphExtension() instanceof WarningGraphExtension) { + WarningGraphExtension warningExtension = extra.getWarningGraphExtension(); + if (warningExtension.generatesWarning(extra)) { + result.addWarning(warningExtension.getWarning()); + result.addExtraInfo(extra); + } + } + } + } + } - if (ii == 0) - { - if (segPoints.size() == 1) - { - if (ii + 1 < nInstructions) - { - lat1 = nextSegPoints.getLat(0); - lon1 = nextSegPoints.getLon(0); - } - else - { - lat1 = segPoints.getLat(ii); - lon1 = segPoints.getLon(ii); - } - } - else - { - lat1 = segPoints.getLat(ii+1); - lon1 = segPoints.getLon(ii+1); - } - - CardinalDirection dir = calcDirection(segPoints.getLat(ii), segPoints.getLon(ii), lat1, lon1); - instrText = instrTranslator.getDepart(dir, roadName); - } - else - { - if (instr instanceof RoundaboutInstruction) - { - RoundaboutInstruction raInstr = (RoundaboutInstruction)instr; - step.setExitNumber(raInstr.getExitNumber()); - instrText = instrTranslator.getRoundabout(raInstr.getExitNumber(), roadName); - } - else - { - if (isTurnInstruction(instrType)) { + for (int ri = 0; ri < nRoutes; ++ri) { + GHResponse resp = routes.get(ri); + + if (resp.hasErrors()) + throw new InternalServerException(RoutingErrorCodes.UNKNOWN, String.format("Unable to find a route between points %d (%s) and %d (%s)", ri, FormatUtility.formatCoordinate(request.getCoordinates()[ri]), ri + 1, FormatUtility.formatCoordinate(request.getCoordinates()[ri + 1]))); + + PathWrapper path = resp.getBest(); + PointList routePoints = path.getPoints(); + if (summary_pointlist == null) { + summary_pointlist = path.getPoints(); + } else { + PointList new_points = path.getPoints(); + summary_pointlist.add(new_points); + } + if (bbox == null) + bbox = new BBox(routePoints.getLon(0), routePoints.getLon(0), routePoints.getLat(0), routePoints.getLat(0)); + bbox = GeomUtility.CalculateBoundingBox(path.getPoints(), bbox); + + if (request.getIncludeGeometry()) { + result.addPoints(routePoints, ri > 0, includeElev); + + routeWayPoints[ri + 1] = result.getGeometry().length - 1; + + if (request.getIncludeInstructions()) { + InstructionList instructions = path.getInstructions(); + int startWayPointIndex = routeWayPoints[ri]; + int nInstructions = instructions.size(); + //if (nInstructions > 1) // last is finishinstruction + // nInstructions -= 1; + + Instruction instr, prevInstr = null; + InstructionType instrType = InstructionType.UNKNOWN; + RouteSegment seg = new RouteSegment(path, units); + + if (includeDetourFactor) { + lat0 = routePoints.getLat(0); + lon0 = routePoints.getLon(0); + + lat1 = routePoints.getLat(routePoints.getSize() - 1); + lon1 = routePoints.getLon(routePoints.getSize() - 1); + + double dist = _distCalc.calcDist(lat0, lon0, lat1, lon1); + seg.setDetourFactor((dist == 0) ? 0 : FormatUtility.roundToDecimals(path.getDistance() / dist, 2)); + } + + String instrText = ""; + double stepDistance, stepDuration; + + for (int ii = 0; ii < nInstructions; ++ii) { + instr = instructions.get(ii); + InstructionAnnotation instrAnnotation = instr.getAnnotation(); + instrType = getInstructionType(ii == 0, instr); + segPoints = instr.getPoints(); + nextSegPoints = (ii + 1 < nInstructions) ? instructions.get(ii + 1).getPoints() : getNextSegPoints(routes, ri + 1, 0); + + String roadName = formatInstructions && !Helper.isEmpty(instr.getName()) ? "" + instr.getName() + "" : instr.getName(); + instrText = ""; + + stepDistance = FormatUtility.roundToDecimals(DistanceUnitUtil.convert(instr.getDistance(), DistanceUnit.Meters, units), unitDecimals); + stepDuration = FormatUtility.roundToDecimals(instr.getTime() / 1000.0, 1); + + RouteStep step = new RouteStep(); + + if (ii == 0) { + if (segPoints.size() == 1) { + if (ii + 1 < nInstructions) { + lat1 = nextSegPoints.getLat(0); + lon1 = nextSegPoints.getLon(0); + } else { + lat1 = segPoints.getLat(ii); + lon1 = segPoints.getLon(ii); + } + } else { + lat1 = segPoints.getLat(ii + 1); + lon1 = segPoints.getLon(ii + 1); + } + + CardinalDirection dir = calcDirection(segPoints.getLat(ii), segPoints.getLon(ii), lat1, lon1); + instrText = instrTranslator.getDepart(dir, roadName); + } else { + if (instr instanceof RoundaboutInstruction) { + RoundaboutInstruction raInstr = (RoundaboutInstruction) instr; + step.setExitNumber(raInstr.getExitNumber()); + instrText = instrTranslator.getRoundabout(raInstr.getExitNumber(), roadName); + } else { + if (isTurnInstruction(instrType)) { instrText = instrTranslator.getTurn(instrType, roadName); - } else if (isKeepInstruction(instrType)){ + } else if (isKeepInstruction(instrType)) { instrText = instrTranslator.getKeep(instrType, roadName); } else if (instrType == InstructionType.CONTINUE) { instrText = instrTranslator.getContinue(instrType, roadName); } else if (instrType == InstructionType.FINISH) { - instrText = instrTranslator.getArrive(getArrivalDirection(routePoints, request.getDestination()), prevInstr.getName()); - } - else - instrText = "Oops! Fix me"; - } - } - - - _nameAppendix = null; - - step.setDistance(stepDistance); - step.setDuration(stepDuration); - step.setInstruction(instrText); - step.setName(instr.getName()); - step.setType(instrType.ordinal()); - step.setWayPoints(new int[] { startWayPointIndex, getWayPointEndIndex(startWayPointIndex, instrType, instr)}); - - boolean incMan = request.getIncludeManeuvers(); - boolean isSlightLeftOrRight = instrType.equals(InstructionType.TURN_SLIGHT_RIGHT) || instrType.equals(InstructionType.TURN_SLIGHT_LEFT); - if(incMan || isSlightLeftOrRight){ - RouteStepManeuver man = calcManeuver(instrType, prevSegPoints, segPoints, nextSegPoints); - if(incMan){ - step.setManeuver(man); - } - if(isSlightLeftOrRight){ - // see com.graphhopper.routing.InstructionsFromEdges.getTurn(...) - // is generating the TurnInformation - for what EVER reason this - // is not correct from time to time - so I ADJUST THEM! - if(Math.abs(man.getBearingAfter() - man.getBearingBefore())< 6){ - step.setInstruction(instrTranslator.getContinue(InstructionType.CONTINUE, roadName)); - step.setType(InstructionType.CONTINUE.ordinal()); - } - } - } - - seg.addStep(step); - - // step.setMessage(message); - // add message and message type - - startWayPointIndex += instr.getPoints().size(); - //step.setMode // walking, cycling, etc. for multimodal routing - - //MARQ24 removed not implemented - //if (instrAnnotation != null && instrAnnotation.getWayType() != 1) // Ferry, Steps as pushing sections - // distanceActual += stepDistance; - - prevInstr = instr; - prevSegPoints = segPoints; - } - - result.addSegment(seg); - - distance += seg.getDistance(); - duration += seg.getDuration(); - } - else - { - distance += FormatUtility.roundToDecimals(DistanceUnitUtil.convert(path.getDistance(), DistanceUnit.Meters, units), FormatUtility.getUnitDecimals(units)); - duration += FormatUtility.roundToDecimals(path.getTime()/1000.0, 1); - } - } - else - { - InstructionList instructions = path.getInstructions(); - int nInstructions = instructions.size(); - if (nInstructions > 1) - nInstructions -= 1; - - for (int j = 0; j < nInstructions; ++j) - { - Instruction instr = instructions.get(j); - InstructionAnnotation instrAnnotation = instr.getAnnotation(); - - //MARQ24 removed not implemented - //if (instrAnnotation != null && instrAnnotation.getWayType() != 1) // Ferry, Steps as pushing sections - // distanceActual += FormatUtility.roundToDecimals(DistanceUnitUtil.convert(instr.getDistance(), DistanceUnit.Meters, units), unitDecimals); - } - - distance += FormatUtility.roundToDecimals(DistanceUnitUtil.convert(path.getDistance(), DistanceUnit.Meters, units), unitDecimals); - duration += FormatUtility.roundToDecimals(path.getTime()/1000.0, 1); - } - - if (includeElev) - { - ascent += path.getAscend(); - descent += path.getDescend(); - } - - durationTraffic += path.getRouteWeight(); - } - - RouteSummary routeSummary = result.getSummary(); - - routeSummary.setDuration(request.getSearchParameters().getConsiderTraffic() ? durationTraffic : duration); - routeSummary.setDistance(FormatUtility.roundToDecimals(distance, unitDecimals)); - //MARQ24 removed not implemented - //routeSummary.setDistanceActual(FormatUtility.roundToDecimals(distanceActual, unitDecimals)); - routeSummary.setAverageSpeed(FormatUtility.roundToDecimals(distance/(units == DistanceUnit.Meters ? 1000 : 1)/(routeSummary.getDuration() / 3600), 1)); - routeSummary.setAscent(FormatUtility.roundToDecimals(ascent, 1)); - routeSummary.setDescent(FormatUtility.roundToDecimals(descent, 1)); - - if (routeWayPoints != null) - result.setWayPointsIndices(routeWayPoints); + instrText = instrTranslator.getArrive(getArrivalDirection(routePoints, request.getDestination()), prevInstr.getName()); + } else + instrText = "Oops! Fix me"; + } + } + + + _nameAppendix = null; + + step.setDistance(stepDistance); + step.setDuration(stepDuration); + step.setInstruction(instrText); + step.setName(instr.getName()); + step.setType(instrType.ordinal()); + step.setWayPoints(new int[]{startWayPointIndex, getWayPointEndIndex(startWayPointIndex, instrType, instr)}); + + boolean incMan = request.getIncludeManeuvers(); + boolean isSlightLeftOrRight = instrType.equals(InstructionType.TURN_SLIGHT_RIGHT) || instrType.equals(InstructionType.TURN_SLIGHT_LEFT); + if (incMan || isSlightLeftOrRight) { + RouteStepManeuver man = calcManeuver(instrType, prevSegPoints, segPoints, nextSegPoints); + if (incMan) { + step.setManeuver(man); + } + if (isSlightLeftOrRight) { + // see com.graphhopper.routing.InstructionsFromEdges.getTurn(...) + // is generating the TurnInformation - for what EVER reason this + // is not correct from time to time - so I ADJUST THEM! + if (Math.abs(man.getBearingAfter() - man.getBearingBefore()) < 6) { + step.setInstruction(instrTranslator.getContinue(InstructionType.CONTINUE, roadName)); + step.setType(InstructionType.CONTINUE.ordinal()); + } + } + } + + seg.addStep(step); + + // step.setMessage(message); + // add message and message type + + startWayPointIndex += instr.getPoints().size(); + //step.setMode // walking, cycling, etc. for multimodal routing + + //MARQ24 removed not implemented + //if (instrAnnotation != null && instrAnnotation.getWayType() != 1) // Ferry, Steps as pushing sections + // distanceActual += stepDistance; + + prevInstr = instr; + prevSegPoints = segPoints; + } + + result.addSegment(seg); + + distance += seg.getDistance(); + duration += seg.getDuration(); + } else { + distance += FormatUtility.roundToDecimals(DistanceUnitUtil.convert(path.getDistance(), DistanceUnit.Meters, units), FormatUtility.getUnitDecimals(units)); + duration += FormatUtility.roundToDecimals(path.getTime() / 1000.0, 1); + } + } else { + InstructionList instructions = path.getInstructions(); + int nInstructions = instructions.size(); + if (nInstructions > 1) + nInstructions -= 1; + + for (int j = 0; j < nInstructions; ++j) { + Instruction instr = instructions.get(j); + InstructionAnnotation instrAnnotation = instr.getAnnotation(); + + //MARQ24 removed not implemented + //if (instrAnnotation != null && instrAnnotation.getWayType() != 1) // Ferry, Steps as pushing sections + // distanceActual += FormatUtility.roundToDecimals(DistanceUnitUtil.convert(instr.getDistance(), DistanceUnit.Meters, units), unitDecimals); + } + + distance += FormatUtility.roundToDecimals(DistanceUnitUtil.convert(path.getDistance(), DistanceUnit.Meters, units), unitDecimals); + duration += FormatUtility.roundToDecimals(path.getTime() / 1000.0, 1); + } + + if (includeElev) { + ascent += path.getAscend(); + descent += path.getDescend(); + } + + durationTraffic += path.getRouteWeight(); + } - if (summary_pointlist != null) { - if (summary_pointlist.getSize() > 0) { - // The bounding box function of graphhopper returns wrong bboxes. This one should fix it. - BBox summary_bbox = GeomUtility.CalculateBoundingBox(summary_pointlist, bbox); - routeSummary.setBBox(summary_bbox); - } - } - else - if (bbox != null) - routeSummary.setBBox(bbox); + RouteSummary routeSummary = result.getSummary(); + + routeSummary.setDuration(request.getSearchParameters().getConsiderTraffic() ? durationTraffic : duration); + routeSummary.setDistance(FormatUtility.roundToDecimals(distance, unitDecimals)); + //MARQ24 removed not implemented + //routeSummary.setDistanceActual(FormatUtility.roundToDecimals(distanceActual, unitDecimals)); + routeSummary.setAverageSpeed(FormatUtility.roundToDecimals(distance / (units == DistanceUnit.Meters ? 1000 : 1) / (routeSummary.getDuration() / 3600), 1)); + routeSummary.setAscent(FormatUtility.roundToDecimals(ascent, 1)); + routeSummary.setDescent(FormatUtility.roundToDecimals(descent, 1)); + + if (routeWayPoints != null) + result.setWayPointsIndices(routeWayPoints); + + if (summary_pointlist != null) { + if (summary_pointlist.getSize() > 0) { + // The bounding box function of graphhopper returns wrong bboxes. This one should fix it. + BBox summary_bbox = GeomUtility.CalculateBoundingBox(summary_pointlist, bbox); + routeSummary.setBBox(summary_bbox); + } + } else if (bbox != null) + routeSummary.setBBox(bbox); + + return result; + } - return result; - } + private RouteResult[] createRouteResultSet(GHResponse route, RoutingRequest request, List extras) throws Exception { + + if (route.hasErrors()) + throw new InternalServerException(RoutingErrorCodes.UNKNOWN, String.format("Unable to find a route between points %d (%s) and %d (%s)", 0, FormatUtility.formatCoordinate(request.getCoordinates()[0]), 1, FormatUtility.formatCoordinate(request.getCoordinates()[1]))); + + InstructionTranslator instrTranslator = InstructionTranslatorsCache.getInstance().getTranslator(request.getLanguage()); + boolean formatInstructions = request.getInstructionsFormat() == RouteInstructionsFormat.HTML; + boolean includeDetourFactor = request.hasAttribute("detourfactor"); + boolean includeElev = request.getIncludeElevation(); + DistanceUnit units = request.getUnits(); + int unitDecimals = FormatUtility.getUnitDecimals(units); + + RouteResult[] resultSet = new RouteResult[route.getAll().size()]; + + for (PathWrapper path : route.getAll()) { + RouteResult result = new RouteResult(request.getExtraInfo()); + + double distance = 0.0; + double duration = 0.0; + double ascent = 0.0; + double descent = 0.0; + double durationTraffic = 0.0; + double lon0 = 0, lat0 = 0, lat1 = 0, lon1 = 0; + PointList prevSegPoints = null, segPoints, nextSegPoints; + PointList summary_pointlist = null; + int[] routeWayPoints = null; + + if (request.getIncludeGeometry()) { + routeWayPoints = new int[2]; + routeWayPoints[0] = 0; + } + + if (extras != null) { + // only add the extras we requested unless a "warning" has been generated + for (RouteExtraInfo extra : extras) { + if (RouteExtraInfoFlag.isSet(request.getExtraInfo(), RouteExtraInfoFlag.getFromString(extra.getName()))) { + result.addExtraInfo(extra); + } else { + if (extra.isUsedForWarnings() && extra.getWarningGraphExtension() instanceof WarningGraphExtension) { + WarningGraphExtension warningExtension = extra.getWarningGraphExtension(); + if (warningExtension.generatesWarning(extra)) { + result.addWarning(warningExtension.getWarning()); + result.addExtraInfo(extra); + } + } + } + } + } + + PointList routePoints = path.getPoints(); + if (summary_pointlist == null) { + summary_pointlist = path.getPoints(); + } else { + PointList new_points = path.getPoints(); + summary_pointlist.add(new_points); + } + + BBox bbox = new BBox(routePoints.getLon(0), routePoints.getLon(0), routePoints.getLat(0), routePoints.getLat(0)); + bbox = GeomUtility.CalculateBoundingBox(path.getPoints(), bbox); + + if (request.getIncludeGeometry()) { + result.addPoints(routePoints, false, includeElev); + + routeWayPoints[1] = result.getGeometry().length - 1; + + if (request.getIncludeInstructions()) { + InstructionList instructions = path.getInstructions(); + int startWayPointIndex = routeWayPoints[0]; + int nInstructions = instructions.size(); + + Instruction instr, prevInstr = null; + InstructionType instrType = InstructionType.UNKNOWN; + RouteSegment seg = new RouteSegment(path, units); + + if (includeDetourFactor) { + lat0 = routePoints.getLat(0); + lon0 = routePoints.getLon(0); + + lat1 = routePoints.getLat(routePoints.getSize() - 1); + lon1 = routePoints.getLon(routePoints.getSize() - 1); + + double dist = _distCalc.calcDist(lat0, lon0, lat1, lon1); + seg.setDetourFactor((dist == 0) ? 0 : FormatUtility.roundToDecimals(path.getDistance() / dist, 2)); + } + + String instrText = ""; + double stepDistance, stepDuration; + + for (int ii = 0; ii < nInstructions; ++ii) { + instr = instructions.get(ii); + InstructionAnnotation instrAnnotation = instr.getAnnotation(); + instrType = getInstructionType(ii == 0, instr); + segPoints = instr.getPoints(); + nextSegPoints = (ii + 1 < nInstructions) ? instructions.get(ii + 1).getPoints() : null; + + String roadName = formatInstructions && !Helper.isEmpty(instr.getName()) ? "" + instr.getName() + "" : instr.getName(); + instrText = ""; + + stepDistance = FormatUtility.roundToDecimals(DistanceUnitUtil.convert(instr.getDistance(), DistanceUnit.Meters, units), unitDecimals); + stepDuration = FormatUtility.roundToDecimals(instr.getTime() / 1000.0, 1); + + RouteStep step = new RouteStep(); + + if (ii == 0) { + if (segPoints.size() == 1) { + if (ii + 1 < nInstructions) { + lat1 = nextSegPoints.getLat(0); + lon1 = nextSegPoints.getLon(0); + } else { + lat1 = segPoints.getLat(ii); + lon1 = segPoints.getLon(ii); + } + } else { + lat1 = segPoints.getLat(ii + 1); + lon1 = segPoints.getLon(ii + 1); + } + + CardinalDirection dir = calcDirection(segPoints.getLat(ii), segPoints.getLon(ii), lat1, lon1); + instrText = instrTranslator.getDepart(dir, roadName); + } else { + if (instr instanceof RoundaboutInstruction) { + RoundaboutInstruction raInstr = (RoundaboutInstruction) instr; + step.setExitNumber(raInstr.getExitNumber()); + instrText = instrTranslator.getRoundabout(raInstr.getExitNumber(), roadName); + } else { + if (isTurnInstruction(instrType)) { + instrText = instrTranslator.getTurn(instrType, roadName); + } else if (isKeepInstruction(instrType)) { + instrText = instrTranslator.getKeep(instrType, roadName); + } else if (instrType == InstructionType.CONTINUE) { + instrText = instrTranslator.getContinue(instrType, roadName); + } else if (instrType == InstructionType.FINISH) { + instrText = instrTranslator.getArrive(getArrivalDirection(routePoints, request.getDestination()), prevInstr.getName()); + } else + instrText = "Oops! Fix me"; + } + } + + + _nameAppendix = null; + + step.setDistance(stepDistance); + step.setDuration(stepDuration); + step.setInstruction(instrText); + step.setName(instr.getName()); + step.setType(instrType.ordinal()); + step.setWayPoints(new int[]{startWayPointIndex, getWayPointEndIndex(startWayPointIndex, instrType, instr)}); + + boolean incMan = request.getIncludeManeuvers(); + boolean isSlightLeftOrRight = instrType.equals(InstructionType.TURN_SLIGHT_RIGHT) || instrType.equals(InstructionType.TURN_SLIGHT_LEFT); + if (incMan || isSlightLeftOrRight) { + RouteStepManeuver man = calcManeuver(instrType, prevSegPoints, segPoints, nextSegPoints); + if (incMan) { + step.setManeuver(man); + } + if (isSlightLeftOrRight) { + // see com.graphhopper.routing.InstructionsFromEdges.getTurn(...) + // is generating the TurnInformation - for what EVER reason this + // is not correct from time to time - so I ADJUST THEM! + if (Math.abs(man.getBearingAfter() - man.getBearingBefore()) < 6) { + step.setInstruction(instrTranslator.getContinue(InstructionType.CONTINUE, roadName)); + step.setType(InstructionType.CONTINUE.ordinal()); + } + } + } + + seg.addStep(step); + + // step.setMessage(message); + // add message and message type + + startWayPointIndex += instr.getPoints().size(); + //step.setMode // walking, cycling, etc. for multimodal routing + + //MARQ24 removed not implemented + //if (instrAnnotation != null && instrAnnotation.getWayType() != 1) // Ferry, Steps as pushing sections + // distanceActual += stepDistance; + + prevInstr = instr; + prevSegPoints = segPoints; + } + + result.addSegment(seg); + + distance += seg.getDistance(); + duration += seg.getDuration(); + } else { + distance += FormatUtility.roundToDecimals(DistanceUnitUtil.convert(path.getDistance(), DistanceUnit.Meters, units), FormatUtility.getUnitDecimals(units)); + duration += FormatUtility.roundToDecimals(path.getTime() / 1000.0, 1); + } + } else { + // TAKB What was that for? +// InstructionList instructions = path.getInstructions(); +// int nInstructions = instructions.size(); +// if (nInstructions > 1) +// nInstructions -= 1; +// +// for (int j = 0; j < nInstructions; ++j) { +// Instruction instr = instructions.get(j); +// InstructionAnnotation instrAnnotation = instr.getAnnotation(); +// +// //MARQ24 removed not implemented +// //if (instrAnnotation != null && instrAnnotation.getWayType() != 1) // Ferry, Steps as pushing sections +// // distanceActual += FormatUtility.roundToDecimals(DistanceUnitUtil.convert(instr.getDistance(), DistanceUnit.Meters, units), unitDecimals); +// } + + distance += FormatUtility.roundToDecimals(DistanceUnitUtil.convert(path.getDistance(), DistanceUnit.Meters, units), unitDecimals); + duration += FormatUtility.roundToDecimals(path.getTime() / 1000.0, 1); + } + + if (includeElev) { + ascent += path.getAscend(); + descent += path.getDescend(); + } + + durationTraffic += path.getRouteWeight(); + + RouteSummary routeSummary = result.getSummary(); + + routeSummary.setDuration(request.getSearchParameters().getConsiderTraffic() ? durationTraffic : duration); + routeSummary.setDistance(FormatUtility.roundToDecimals(distance, unitDecimals)); + //MARQ24 removed not implemented + //routeSummary.setDistanceActual(FormatUtility.roundToDecimals(distanceActual, unitDecimals)); + routeSummary.setAverageSpeed(FormatUtility.roundToDecimals(distance / (units == DistanceUnit.Meters ? 1000 : 1) / (routeSummary.getDuration() / 3600), 1)); + routeSummary.setAscent(FormatUtility.roundToDecimals(ascent, 1)); + routeSummary.setDescent(FormatUtility.roundToDecimals(descent, 1)); + + if (routeWayPoints != null) + result.setWayPointsIndices(routeWayPoints); + + if (summary_pointlist != null) { + if (summary_pointlist.getSize() > 0) { + // The bounding box function of graphhopper returns wrong bboxes. This one should fix it. + BBox summary_bbox = GeomUtility.CalculateBoundingBox(summary_pointlist, bbox); + routeSummary.setBBox(summary_bbox); + } + } else if (bbox != null) + routeSummary.setBBox(bbox); + + resultSet[route.getAll().indexOf(path)] = result; + } + return resultSet; + } - private ArrivalDirection getArrivalDirection(PointList points, Coordinate destination) - { - if (points.size() < 2) - return ArrivalDirection.Unknown; + private ArrivalDirection getArrivalDirection(PointList points, Coordinate destination) { + if (points.size() < 2) + return ArrivalDirection.Unknown; int lastIndex = points.size() - 1; double lon0 = points.getLon(lastIndex - 1); diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java index ac3a0bc69c..4db103dab7 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java @@ -65,6 +65,8 @@ public class RouteSearchParameters { private int[] _avoidCountries = null; private BordersExtractor.Avoid _avoidBorders = BordersExtractor.Avoid.NONE; + private int _alternativeRoutes = -1; + private String _options; public int getProfileType() { @@ -166,6 +168,14 @@ public void setVehicleType(int vehicleType) { this._vehicleType = vehicleType; } + public int getAlternativeRoutes() { + return _alternativeRoutes; + } + + public void setAlternativeRoutes(int _alternativeRoutes) { + this._alternativeRoutes = _alternativeRoutes; + } + public String getOptions() { return _options; } @@ -397,6 +407,15 @@ else if (jProfileParams.has("maximum_gradient")) throw new ParameterValueException(RoutingErrorCodes.INVALID_PARAMETER_VALUE, "avoid_polygons"); } } + + if (json.has("alternative_routes")) { + try { + _alternativeRoutes = json.getInt("alternative_routes"); + } catch (Exception ex) { + throw new ParameterValueException(RoutingErrorCodes.INVALID_PARAMETER_FORMAT, "alternative_routes", json.getString("alternative_routes")); + } + } + } private void processWeightings(JSONObject json, ProfileParameters profileParams) throws Exception { diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java index 021ae02dc5..4e67a706b6 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java @@ -916,6 +916,15 @@ else if (bearings[1] == null) if (_astarApproximation != null) req.getHints().put("astarbi.approximation", _astarApproximation); + if (searchParams.getAlternativeRoutes() > 0) { + req.setAlgorithm("alternative_route"); + req.getHints().put("alternative_route.max_paths", searchParams.getAlternativeRoutes()); +// TAKB: TODO more testing required to find out if we can tweak here to remove irregular alternative paths +// req.getHints().put("alternative_route.max_weight_factor", 1.4); +// req.getHints().put("alternative_route.max_share_factor", 0.6); + req.getHints().put("ch.disable", true); + } + /*if (directedSegment) resp = mGraphHopper.directRoute(req); NOTE IMPLEMENTED!!! else */ diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java index be5f21cae4..8e525b8082 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java @@ -346,7 +346,7 @@ public RouteResult matchTrack(MapMatchingRequest req) throws Exception { return null; } - public RouteResult computeRoute(RoutingRequest req) throws Exception { + public RouteResult[] computeRoute(RoutingRequest req) throws Exception { List routes = new ArrayList(); //System.out.println("PATCHED!!!!"); @@ -436,7 +436,7 @@ public RouteResult computeRoute(RoutingRequest req) throws Exception { c0 = c1; } - return new RouteResultBuilder().createRouteResult(routes, req, (pathProcessor != null && (pathProcessor instanceof ExtraInfoProcessor)) ? ((ExtraInfoProcessor) pathProcessor).getExtras() : null); + return new RouteResultBuilder().createRouteResults(routes, req, (pathProcessor != null && (pathProcessor instanceof ExtraInfoProcessor)) ? ((ExtraInfoProcessor) pathProcessor).getExtras() : null); } private double getHeadingDirection(GHResponse resp) { diff --git a/openrouteservice/src/main/java/heigit/ors/services/routing/requestprocessors/RoutingRequestProcessor.java b/openrouteservice/src/main/java/heigit/ors/services/routing/requestprocessors/RoutingRequestProcessor.java index 19de86c74c..6a61c4c2a4 100644 --- a/openrouteservice/src/main/java/heigit/ors/services/routing/requestprocessors/RoutingRequestProcessor.java +++ b/openrouteservice/src/main/java/heigit/ors/services/routing/requestprocessors/RoutingRequestProcessor.java @@ -78,8 +78,8 @@ public void process(HttpServletResponse response) throws Exception { String geometryFormat = rreq.getGeometryFormat(); if (Helper.isEmpty(respFormat) || "json".equalsIgnoreCase(respFormat)) { - RouteResult result = RoutingProfileManager.getInstance().computeRoute(rreq); - json = JsonRoutingResponseWriter.toJson(rreq, new RouteResult[]{result}); + RouteResult[] result = RoutingProfileManager.getInstance().computeRoute(rreq); + json = JsonRoutingResponseWriter.toJson(rreq, result); if (json != null) { ServletUtility.write(response, json, "UTF-8"); @@ -93,8 +93,8 @@ public void process(HttpServletResponse response) throws Exception { if (Helper.isEmpty(geometryFormat) || !geometryFormat.equals("geojson")) { rreq.setGeometryFormat("geojson"); } - RouteResult result = RoutingProfileManager.getInstance().computeRoute(rreq); - geojson = new GlobalResponseProcessor(rreq, new RouteResult[]{result}).toGeoJson(); + RouteResult[] result = RoutingProfileManager.getInstance().computeRoute(rreq); + geojson = new GlobalResponseProcessor(rreq, result).toGeoJson(); if (geojson != null) { ServletUtility.write(response, geojson, "UTF-8"); } else { @@ -108,8 +108,8 @@ public void process(HttpServletResponse response) throws Exception { if (Helper.isEmpty(geometryFormat) || !geometryFormat.equals("geojson")) { rreq.setGeometryFormat("geojson"); } - RouteResult result = RoutingProfileManager.getInstance().computeRoute(rreq); - gpx = new GlobalResponseProcessor(rreq, new RouteResult[]{result}).toGPX(); + RouteResult[] result = RoutingProfileManager.getInstance().computeRoute(rreq); + gpx = new GlobalResponseProcessor(rreq, result).toGPX(); //gpx = GpxResponseWriter.toGPX(rreq, new RouteResult[]{result}); if (gpx != null) { ServletUtility.write(response, gpx); From 3a28ad467cf43f1f7cd7af9215a4b493f940d017 Mon Sep 17 00:00:00 2001 From: takb Date: Mon, 28 Jan 2019 16:17:52 +0100 Subject: [PATCH 02/24] Added unit and API tests, weight/share factor parameters, improved error handling --- CHANGELOG.md | 1 + .../ors/services/routing/ResultTest.java | 26 +++++++++++++++ .../ors/routing/RouteResultBuilder.java | 4 --- .../ors/routing/RouteSearchParameters.java | 33 +++++++++++++++++++ .../heigit/ors/routing/RoutingProfile.java | 6 ++-- .../ors/routing/RoutingProfileManager.java | 4 +++ .../routing/RouteSearchParametersTest.java | 11 ++++++- 7 files changed, 77 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e98f456371..53bf34240a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added - Added support for ISO 3166-1 Alpha-2 / Alpha-3 codes for routing directions option avoid_countries (Issue #195) +- Added support for GH alternative_route algorithm (Issue #377) ### Fixed ### Changed - Updated rural speed limit in France to be 80km/h (Issue #355) diff --git a/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/ResultTest.java b/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/ResultTest.java index 16c0d6d890..e3d6222923 100644 --- a/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/ResultTest.java +++ b/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/ResultTest.java @@ -54,6 +54,9 @@ public ResultTest() { addParameter("preference", "fastest"); addParameter("bikeProfile", "cycling-regular"); addParameter("carProfile", "driving-car"); + + // query for testing the alternative routes algorithm + addParameter("coordinatesAR", "8.680401,49.437436|8.746362,49.414191"); } @Test @@ -1475,4 +1478,27 @@ public void testAccessRestrictionsWarnings() { .body("routes[0].extras.roadaccessrestrictions.values[1][2]", is(32)) .statusCode(200); } + + @Test + public void testAlternativeRoutes() { + + given() + .param("coordinates", getParameter("coordinatesAR")) + .param("instructions", "true") + .param("preference", getParameter("preference")) + .param("profile", getParameter("carProfile")) + .param("options", "{\"alternative_routes\": 2}") + .when().log().ifValidationFails() + .get(getEndPointName()) + .then() + .assertThat() + .body("any { it.key == 'routes' }", is(true)) + .body("routes.size()", is(2)) + .body("routes[0].summary.distance", is(8178.2f)) + .body("routes[0].summary.duration", is(1087.3f)) + .body("routes[1].summary.distance", is(10670.8f)) + .body("routes[1].summary.duration", is(1414)) + .statusCode(200); + } } + diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteResultBuilder.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteResultBuilder.java index 241ee7ae20..fb2fd3cfb2 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RouteResultBuilder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteResultBuilder.java @@ -57,11 +57,7 @@ public RouteResultBuilder() public RouteResult[] createRouteResults(List routes, RoutingRequest request, List extras) throws Exception { if (routes.isEmpty()) return new RouteResult[]{new RouteResult(request.getExtraInfo())}; - if (routes.size() > 1) { - if (request.getSearchParameters().getAlternativeRoutes() > 1) { - throw new InternalServerException(RoutingErrorCodes.INVALID_PARAMETER_VALUE, "Alternative routes algorithm does not support more than two way points"); - } return new RouteResult[]{createRouteResult(routes, request, extras)}; } return createRouteResultSet(routes.get(0), request, extras); diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java index 4db103dab7..9651660533 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java @@ -65,7 +65,10 @@ public class RouteSearchParameters { private int[] _avoidCountries = null; private BordersExtractor.Avoid _avoidBorders = BordersExtractor.Avoid.NONE; +// TAKB: parameters weight factor and share factor seem to be ignored by the algorithm, further testing required. private int _alternativeRoutes = -1; + private double _alternativeRoutesWeightFactor = 1.4; + private double _alternativeRoutesShareFactor = 0.6; private String _options; @@ -176,6 +179,22 @@ public void setAlternativeRoutes(int _alternativeRoutes) { this._alternativeRoutes = _alternativeRoutes; } + public double getAlternativeRoutesWeightFactor() { + return _alternativeRoutesWeightFactor; + } + + public void set_alternativeRoutesWeightFactor(double _alternativeRoutesWeightFactor) { + this._alternativeRoutesWeightFactor = _alternativeRoutesWeightFactor; + } + + public double getAlternativeRoutesShareFactor() { + return _alternativeRoutesShareFactor; + } + + public void set_alternativeRoutesShareFactor(double _alternativeRoutesShareFactor) { + this._alternativeRoutesShareFactor = _alternativeRoutesShareFactor; + } + public String getOptions() { return _options; } @@ -414,6 +433,20 @@ else if (jProfileParams.has("maximum_gradient")) } catch (Exception ex) { throw new ParameterValueException(RoutingErrorCodes.INVALID_PARAMETER_FORMAT, "alternative_routes", json.getString("alternative_routes")); } + if (json.has("alternative_routes_weight_factor")) { + try { + _alternativeRoutesWeightFactor = json.getDouble("alternative_routes_weight_factor"); + } catch (Exception ex) { + throw new ParameterValueException(RoutingErrorCodes.INVALID_PARAMETER_FORMAT, "alternative_routes_weight_factor", json.getString("alternative_routes_weight_factor")); + } + } + if (json.has("alternative_routes_share_factor")) { + try { + _alternativeRoutesShareFactor = json.getDouble("alternative_routes_share_factor"); + } catch (Exception ex) { + throw new ParameterValueException(RoutingErrorCodes.INVALID_PARAMETER_FORMAT, "alternative_routes_share_factor", json.getString("alternative_routes_share_factor")); + } + } } } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java index 4e67a706b6..be65dd1629 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java @@ -919,9 +919,9 @@ else if (bearings[1] == null) if (searchParams.getAlternativeRoutes() > 0) { req.setAlgorithm("alternative_route"); req.getHints().put("alternative_route.max_paths", searchParams.getAlternativeRoutes()); -// TAKB: TODO more testing required to find out if we can tweak here to remove irregular alternative paths -// req.getHints().put("alternative_route.max_weight_factor", 1.4); -// req.getHints().put("alternative_route.max_share_factor", 0.6); + req.getHints().put("alternative_route.max_weight_factor", searchParams.getAlternativeRoutesWeightFactor()); + req.getHints().put("alternative_route.max_share_factor", searchParams.getAlternativeRoutesShareFactor()); +// TAKB: contraction hierarchies have to be disabled for alternative routes until GH pulls https://github.com/graphhopper/graphhopper/pull/1524 and we update our fork. req.getHints().put("ch.disable", true); } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java index 8e525b8082..7dc4eb5bf7 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java @@ -370,6 +370,10 @@ public RouteResult[] computeRoute(RoutingRequest req) throws Exception { WayPointBearing[] bearings = (req.getContinueStraight() || searchParams.getBearings() != null) ? new WayPointBearing[2] : null; double[] radiuses = searchParams.getMaximumRadiuses() != null ? new double[2] : null; + if (req.getSearchParameters().getAlternativeRoutes() > 1 && coords.length > 2) { + throw new InternalServerException(RoutingErrorCodes.INVALID_PARAMETER_VALUE, "Alternative routes algorithm does not support more than two way points."); + } + for (int i = 1; i <= nSegments; ++i) { c1 = coords[i]; diff --git a/openrouteservice/src/test/java/heigit/ors/routing/RouteSearchParametersTest.java b/openrouteservice/src/test/java/heigit/ors/routing/RouteSearchParametersTest.java index bd41bf1275..782c559ae4 100644 --- a/openrouteservice/src/test/java/heigit/ors/routing/RouteSearchParametersTest.java +++ b/openrouteservice/src/test/java/heigit/ors/routing/RouteSearchParametersTest.java @@ -249,4 +249,13 @@ public void setBearings() { routeSearchParameters.setBearings(new WayPointBearing[]{}); Assert.assertArrayEquals(new WayPointBearing[]{}, routeSearchParameters.getBearings()); } -} \ No newline at end of file + + @Test + public void alternativeRoutesParams() throws Exception { + RouteSearchParameters routeSearchParameters = new RouteSearchParameters(); + routeSearchParameters.setOptions("{\"alternative_routes\": 2, \"alternative_routes_weight_factor\": 3.3, \"alternative_routes_share_factor\": 4.4}}"); + Assert.assertEquals(2, routeSearchParameters.getAlternativeRoutes()); + Assert.assertEquals(3.3, routeSearchParameters.getAlternativeRoutesWeightFactor(), 0.0); + Assert.assertEquals(4.4, routeSearchParameters.getAlternativeRoutesShareFactor(), 0.0); + } +} From 1f0299b58d3ba4fa0a7c7e2a8ecdda39d4864911 Mon Sep 17 00:00:00 2001 From: takb Date: Wed, 23 Jan 2019 12:15:51 +0100 Subject: [PATCH 03/24] added search option alternative_routes, added RouteResult processing for GHResponse with multiple paths, minor refactoring in RouteResultBuilder and RoutingRequestProcessor --- .../main/java/heigit/ors/routing/RouteSearchParameters.java | 4 +++- .../src/main/java/heigit/ors/routing/RoutingProfile.java | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java index 9651660533..41b20e364b 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java @@ -65,7 +65,6 @@ public class RouteSearchParameters { private int[] _avoidCountries = null; private BordersExtractor.Avoid _avoidBorders = BordersExtractor.Avoid.NONE; -// TAKB: parameters weight factor and share factor seem to be ignored by the algorithm, further testing required. private int _alternativeRoutes = -1; private double _alternativeRoutesWeightFactor = 1.4; private double _alternativeRoutesShareFactor = 0.6; @@ -433,6 +432,7 @@ else if (jProfileParams.has("maximum_gradient")) } catch (Exception ex) { throw new ParameterValueException(RoutingErrorCodes.INVALID_PARAMETER_FORMAT, "alternative_routes", json.getString("alternative_routes")); } +<<<<<<< HEAD if (json.has("alternative_routes_weight_factor")) { try { _alternativeRoutesWeightFactor = json.getDouble("alternative_routes_weight_factor"); @@ -447,6 +447,8 @@ else if (jProfileParams.has("maximum_gradient")) throw new ParameterValueException(RoutingErrorCodes.INVALID_PARAMETER_FORMAT, "alternative_routes_share_factor", json.getString("alternative_routes_share_factor")); } } +======= +>>>>>>> added search option alternative_routes, added RouteResult processing for GHResponse with multiple paths, minor refactoring in RouteResultBuilder and RoutingRequestProcessor } } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java index be65dd1629..a39253cdf1 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java @@ -921,7 +921,6 @@ else if (bearings[1] == null) req.getHints().put("alternative_route.max_paths", searchParams.getAlternativeRoutes()); req.getHints().put("alternative_route.max_weight_factor", searchParams.getAlternativeRoutesWeightFactor()); req.getHints().put("alternative_route.max_share_factor", searchParams.getAlternativeRoutesShareFactor()); -// TAKB: contraction hierarchies have to be disabled for alternative routes until GH pulls https://github.com/graphhopper/graphhopper/pull/1524 and we update our fork. req.getHints().put("ch.disable", true); } From e125391658cf4b0073a802d486058adcd8e29802 Mon Sep 17 00:00:00 2001 From: takb Date: Mon, 28 Jan 2019 16:17:52 +0100 Subject: [PATCH 04/24] Added unit and API tests, weight/share factor parameters, improved error handling --- .../main/java/heigit/ors/routing/RouteSearchParameters.java | 4 +--- .../src/main/java/heigit/ors/routing/RoutingProfile.java | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java index 41b20e364b..9651660533 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java @@ -65,6 +65,7 @@ public class RouteSearchParameters { private int[] _avoidCountries = null; private BordersExtractor.Avoid _avoidBorders = BordersExtractor.Avoid.NONE; +// TAKB: parameters weight factor and share factor seem to be ignored by the algorithm, further testing required. private int _alternativeRoutes = -1; private double _alternativeRoutesWeightFactor = 1.4; private double _alternativeRoutesShareFactor = 0.6; @@ -432,7 +433,6 @@ else if (jProfileParams.has("maximum_gradient")) } catch (Exception ex) { throw new ParameterValueException(RoutingErrorCodes.INVALID_PARAMETER_FORMAT, "alternative_routes", json.getString("alternative_routes")); } -<<<<<<< HEAD if (json.has("alternative_routes_weight_factor")) { try { _alternativeRoutesWeightFactor = json.getDouble("alternative_routes_weight_factor"); @@ -447,8 +447,6 @@ else if (jProfileParams.has("maximum_gradient")) throw new ParameterValueException(RoutingErrorCodes.INVALID_PARAMETER_FORMAT, "alternative_routes_share_factor", json.getString("alternative_routes_share_factor")); } } -======= ->>>>>>> added search option alternative_routes, added RouteResult processing for GHResponse with multiple paths, minor refactoring in RouteResultBuilder and RoutingRequestProcessor } } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java index a39253cdf1..be65dd1629 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java @@ -921,6 +921,7 @@ else if (bearings[1] == null) req.getHints().put("alternative_route.max_paths", searchParams.getAlternativeRoutes()); req.getHints().put("alternative_route.max_weight_factor", searchParams.getAlternativeRoutesWeightFactor()); req.getHints().put("alternative_route.max_share_factor", searchParams.getAlternativeRoutesShareFactor()); +// TAKB: contraction hierarchies have to be disabled for alternative routes until GH pulls https://github.com/graphhopper/graphhopper/pull/1524 and we update our fork. req.getHints().put("ch.disable", true); } From 0d3821d78b39a39386ef47f40cfcb057cc0bcc57 Mon Sep 17 00:00:00 2001 From: takb Date: Wed, 23 Jan 2019 12:15:51 +0100 Subject: [PATCH 05/24] added search option alternative_routes, added RouteResult processing for GHResponse with multiple paths, minor refactoring in RouteResultBuilder and RoutingRequestProcessor --- .../main/java/heigit/ors/routing/RouteSearchParameters.java | 4 +++- .../src/main/java/heigit/ors/routing/RoutingProfile.java | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java index 9651660533..df1e273174 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java @@ -65,7 +65,6 @@ public class RouteSearchParameters { private int[] _avoidCountries = null; private BordersExtractor.Avoid _avoidBorders = BordersExtractor.Avoid.NONE; -// TAKB: parameters weight factor and share factor seem to be ignored by the algorithm, further testing required. private int _alternativeRoutes = -1; private double _alternativeRoutesWeightFactor = 1.4; private double _alternativeRoutesShareFactor = 0.6; @@ -433,6 +432,7 @@ else if (jProfileParams.has("maximum_gradient")) } catch (Exception ex) { throw new ParameterValueException(RoutingErrorCodes.INVALID_PARAMETER_FORMAT, "alternative_routes", json.getString("alternative_routes")); } +<<<<<<< HEAD if (json.has("alternative_routes_weight_factor")) { try { _alternativeRoutesWeightFactor = json.getDouble("alternative_routes_weight_factor"); @@ -447,6 +447,8 @@ else if (jProfileParams.has("maximum_gradient")) throw new ParameterValueException(RoutingErrorCodes.INVALID_PARAMETER_FORMAT, "alternative_routes_share_factor", json.getString("alternative_routes_share_factor")); } } +======= +>>>>>>> d7887276... added search option alternative_routes, added RouteResult processing for GHResponse with multiple paths, minor refactoring in RouteResultBuilder and RoutingRequestProcessor } } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java index be65dd1629..a39253cdf1 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java @@ -921,7 +921,6 @@ else if (bearings[1] == null) req.getHints().put("alternative_route.max_paths", searchParams.getAlternativeRoutes()); req.getHints().put("alternative_route.max_weight_factor", searchParams.getAlternativeRoutesWeightFactor()); req.getHints().put("alternative_route.max_share_factor", searchParams.getAlternativeRoutesShareFactor()); -// TAKB: contraction hierarchies have to be disabled for alternative routes until GH pulls https://github.com/graphhopper/graphhopper/pull/1524 and we update our fork. req.getHints().put("ch.disable", true); } From 5e8b62574655c468329e91a4e61a56ac1485830b Mon Sep 17 00:00:00 2001 From: takb Date: Mon, 28 Jan 2019 16:17:52 +0100 Subject: [PATCH 06/24] Added unit and API tests, weight/share factor parameters, improved error handling --- .../main/java/heigit/ors/routing/RouteSearchParameters.java | 4 +--- .../src/main/java/heigit/ors/routing/RoutingProfile.java | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java index df1e273174..9651660533 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java @@ -65,6 +65,7 @@ public class RouteSearchParameters { private int[] _avoidCountries = null; private BordersExtractor.Avoid _avoidBorders = BordersExtractor.Avoid.NONE; +// TAKB: parameters weight factor and share factor seem to be ignored by the algorithm, further testing required. private int _alternativeRoutes = -1; private double _alternativeRoutesWeightFactor = 1.4; private double _alternativeRoutesShareFactor = 0.6; @@ -432,7 +433,6 @@ else if (jProfileParams.has("maximum_gradient")) } catch (Exception ex) { throw new ParameterValueException(RoutingErrorCodes.INVALID_PARAMETER_FORMAT, "alternative_routes", json.getString("alternative_routes")); } -<<<<<<< HEAD if (json.has("alternative_routes_weight_factor")) { try { _alternativeRoutesWeightFactor = json.getDouble("alternative_routes_weight_factor"); @@ -447,8 +447,6 @@ else if (jProfileParams.has("maximum_gradient")) throw new ParameterValueException(RoutingErrorCodes.INVALID_PARAMETER_FORMAT, "alternative_routes_share_factor", json.getString("alternative_routes_share_factor")); } } -======= ->>>>>>> d7887276... added search option alternative_routes, added RouteResult processing for GHResponse with multiple paths, minor refactoring in RouteResultBuilder and RoutingRequestProcessor } } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java index a39253cdf1..be65dd1629 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java @@ -921,6 +921,7 @@ else if (bearings[1] == null) req.getHints().put("alternative_route.max_paths", searchParams.getAlternativeRoutes()); req.getHints().put("alternative_route.max_weight_factor", searchParams.getAlternativeRoutesWeightFactor()); req.getHints().put("alternative_route.max_share_factor", searchParams.getAlternativeRoutesShareFactor()); +// TAKB: contraction hierarchies have to be disabled for alternative routes until GH pulls https://github.com/graphhopper/graphhopper/pull/1524 and we update our fork. req.getHints().put("ch.disable", true); } From 31b63f2432777a4af9bf9015f397a6b3ff5a86e7 Mon Sep 17 00:00:00 2001 From: takb Date: Wed, 23 Jan 2019 12:15:51 +0100 Subject: [PATCH 07/24] added search option alternative_routes, added RouteResult processing for GHResponse with multiple paths, minor refactoring in RouteResultBuilder and RoutingRequestProcessor --- .../java/heigit/ors/routing/RouteSearchParameters.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java index 9651660533..6e4405822e 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java @@ -65,10 +65,14 @@ public class RouteSearchParameters { private int[] _avoidCountries = null; private BordersExtractor.Avoid _avoidBorders = BordersExtractor.Avoid.NONE; +<<<<<<< HEAD // TAKB: parameters weight factor and share factor seem to be ignored by the algorithm, further testing required. private int _alternativeRoutes = -1; private double _alternativeRoutesWeightFactor = 1.4; private double _alternativeRoutesShareFactor = 0.6; +======= + private int _alternativeRoutes = -1; +>>>>>>> 6c967b42... added search option alternative_routes, added RouteResult processing for GHResponse with multiple paths, minor refactoring in RouteResultBuilder and RoutingRequestProcessor private String _options; @@ -179,6 +183,7 @@ public void setAlternativeRoutes(int _alternativeRoutes) { this._alternativeRoutes = _alternativeRoutes; } +<<<<<<< HEAD public double getAlternativeRoutesWeightFactor() { return _alternativeRoutesWeightFactor; } @@ -195,6 +200,8 @@ public void set_alternativeRoutesShareFactor(double _alternativeRoutesShareFacto this._alternativeRoutesShareFactor = _alternativeRoutesShareFactor; } +======= +>>>>>>> 6c967b42... added search option alternative_routes, added RouteResult processing for GHResponse with multiple paths, minor refactoring in RouteResultBuilder and RoutingRequestProcessor public String getOptions() { return _options; } From cd2d0f20bae71b03e2cc897605cdced42b97ea14 Mon Sep 17 00:00:00 2001 From: takb Date: Mon, 28 Jan 2019 16:17:52 +0100 Subject: [PATCH 08/24] Added unit and API tests, weight/share factor parameters, improved error handling --- .../java/heigit/ors/routing/RouteSearchParameters.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java index 6e4405822e..84258a1586 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java @@ -65,14 +65,9 @@ public class RouteSearchParameters { private int[] _avoidCountries = null; private BordersExtractor.Avoid _avoidBorders = BordersExtractor.Avoid.NONE; -<<<<<<< HEAD -// TAKB: parameters weight factor and share factor seem to be ignored by the algorithm, further testing required. private int _alternativeRoutes = -1; private double _alternativeRoutesWeightFactor = 1.4; private double _alternativeRoutesShareFactor = 0.6; -======= - private int _alternativeRoutes = -1; ->>>>>>> 6c967b42... added search option alternative_routes, added RouteResult processing for GHResponse with multiple paths, minor refactoring in RouteResultBuilder and RoutingRequestProcessor private String _options; @@ -183,7 +178,6 @@ public void setAlternativeRoutes(int _alternativeRoutes) { this._alternativeRoutes = _alternativeRoutes; } -<<<<<<< HEAD public double getAlternativeRoutesWeightFactor() { return _alternativeRoutesWeightFactor; } @@ -200,8 +194,6 @@ public void set_alternativeRoutesShareFactor(double _alternativeRoutesShareFacto this._alternativeRoutesShareFactor = _alternativeRoutesShareFactor; } -======= ->>>>>>> 6c967b42... added search option alternative_routes, added RouteResult processing for GHResponse with multiple paths, minor refactoring in RouteResultBuilder and RoutingRequestProcessor public String getOptions() { return _options; } From e06134b441726998113fe770f0cab260ceba0bf6 Mon Sep 17 00:00:00 2001 From: takb Date: Mon, 28 Jan 2019 16:17:52 +0100 Subject: [PATCH 09/24] Added unit and API tests, weight/share factor parameters, improved error handling --- .../src/main/java/heigit/ors/routing/RouteSearchParameters.java | 1 + 1 file changed, 1 insertion(+) diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java index 84258a1586..9651660533 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java @@ -65,6 +65,7 @@ public class RouteSearchParameters { private int[] _avoidCountries = null; private BordersExtractor.Avoid _avoidBorders = BordersExtractor.Avoid.NONE; +// TAKB: parameters weight factor and share factor seem to be ignored by the algorithm, further testing required. private int _alternativeRoutes = -1; private double _alternativeRoutesWeightFactor = 1.4; private double _alternativeRoutesShareFactor = 0.6; From 58c5941f2bebb8539cae1b085fa9a8875ab26357 Mon Sep 17 00:00:00 2001 From: Adam Rousell Date: Mon, 21 Jan 2019 10:26:22 +0100 Subject: [PATCH 10/24] Update pom.xml for opengeo repo and newest ORS-GH (#398) --- CHANGELOG.md | 1 + openrouteservice/pom.xml | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53bf34240a..5f2e765bee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed - Updated rural speed limit in France to be 80km/h (Issue #355) - Modified smoothing and buffer distances for small isochrones, aswell as other fixes for smaller isochrones (Issue #382) +- Updated pom to use correct opengeo repo and reordered so this is the last in the list, and use latest ORS-Graphhopper library (Issue #398) ### Deprecated ## [4.7.2] - 2018-12-10 diff --git a/openrouteservice/pom.xml b/openrouteservice/pom.xml index f6db26712d..d6674bb7e8 100644 --- a/openrouteservice/pom.xml +++ b/openrouteservice/pom.xml @@ -171,19 +171,6 @@ Java.net repository http://download.java.net/maven/2 - - osgeo - Open Source Geospatial Foundation Repository - http://download.osgeo.org/webdav/geotools/ - - - - true - - opengeo - OpenGeo Maven Repository - http://repo.opengeo.org - bintray-nitram509-jbrotli bintray @@ -193,6 +180,19 @@ jitpack.io https://jitpack.io + + osgeo + Open Source Geospatial Foundation Repository + http://download.osgeo.org/webdav/geotools/ + + + + true + + opengeo + OpenGeo Maven Repository + http://repo.boundlessgeo.com/main + @@ -273,13 +273,13 @@ com.github.GIScience.graphhopper graphhopper-core - v0.10.1-8 + v0.10.1.12 com.github.GIScience.graphhopper graphhopper-reader-osm - v0.10.1-8 + v0.10.1.12 From 460427e2ae59ad4d77243c0497b8c3a2618a5126 Mon Sep 17 00:00:00 2001 From: nilsnolde Date: Wed, 16 Jan 2019 18:40:28 +0300 Subject: [PATCH 11/24] [feat] enable geometry_simplify API parameter --- .../ors/services/routing/ParamsTest.java | 29 +++++++++++++++++++ .../ors/services/routing/ResultTest.java | 26 ++++++++++++++++- .../services/routing/RoutingErrorCodes.java | 1 + openrouteservice/pom.xml | 19 ++++++++++-- .../IncompatibleParametersException.java | 27 +++++++++++++++++ .../heigit/ors/routing/RoutingErrorCodes.java | 1 + .../heigit/ors/routing/RoutingProfile.java | 4 ++- .../ors/routing/RoutingProfileManager.java | 7 ++--- .../heigit/ors/routing/RoutingRequest.java | 5 ++++ .../RoutingRequestParser.java | 11 ++++++- 10 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 openrouteservice/src/main/java/heigit/ors/exceptions/IncompatibleParametersException.java diff --git a/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/ParamsTest.java b/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/ParamsTest.java index 8fcec9ff9b..14a3b305b9 100644 --- a/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/ParamsTest.java +++ b/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/ParamsTest.java @@ -754,4 +754,33 @@ public void expectSuppressedWarnings() { .body("routes[0].containsKey('warnings')", is(false)) .statusCode(200); } + + @Test + public void expectSimplifyGeometry() { + given() + .param("coordinates", getParameter("coordinatesShort")) + .param("profile", getParameter("carProfile")) + .param("geometry_simplify", "true") + .when() + .get(getEndPointName()) + .then() + .assertThat() + .body("any { it.key == 'routes' }", is(true)) + .statusCode(200); + }; + + @Test + public void expectIncompatibleParameters() { + given() + .param("coordinates", getParameter("coordinatesShort")) + .param("profile", getParameter("carProfile")) + .param("geometry_simplify", "true") + .param("extra_info", getParameter("extra_info")) + .when() + .get(getEndPointName()) + .then() + .assertThat() + .body("error.code", is(RoutingErrorCodes.INCOMPATIBLE_PARAMETERS)) + .statusCode(400); + }; } diff --git a/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/ResultTest.java b/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/ResultTest.java index e3d6222923..6b314998ac 100644 --- a/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/ResultTest.java +++ b/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/ResultTest.java @@ -1481,7 +1481,6 @@ public void testAccessRestrictionsWarnings() { @Test public void testAlternativeRoutes() { - given() .param("coordinates", getParameter("coordinatesAR")) .param("instructions", "true") @@ -1500,5 +1499,30 @@ public void testAlternativeRoutes() { .body("routes[1].summary.duration", is(1414)) .statusCode(200); } + + @Test + public void testSimplifyHasLessWayPoints() { + given() + .param("coordinates", getParameter("coordinatesShort")) + .param("profile", "driving-car") + .param("format", "geojson") + .when() + .get(getEndPointName()) + .then() + .assertThat() + .body("features[0].geometry.coordinates.size()", is(75)) + .statusCode(200); + given() + .param("coordinates", getParameter("coordinatesShort")) + .param("profile", "driving-car") + .param("format", "geojson") + .param("geometry_simplify", "true") + .when() + .get(getEndPointName()) + .then() + .assertThat() + .body("features[0].geometry.coordinates.size()", is(34)) + .statusCode(200); + } } diff --git a/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/RoutingErrorCodes.java b/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/RoutingErrorCodes.java index 952ae030d0..c46c6c1e6c 100644 --- a/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/RoutingErrorCodes.java +++ b/openrouteservice-api-tests/src/test/java/heigit/ors/services/routing/RoutingErrorCodes.java @@ -39,5 +39,6 @@ public class RoutingErrorCodes { public static int EMPTY_ELEMENT = 2008; public static int ROUTE_NOT_FOUND = 2009; public static int POINT_NOT_FOUND = 2010; + public static int INCOMPATIBLE_PARAMETERS = 2011; public static int UNKNOWN = 2099; } diff --git a/openrouteservice/pom.xml b/openrouteservice/pom.xml index d6674bb7e8..f24508d9a0 100644 --- a/openrouteservice/pom.xml +++ b/openrouteservice/pom.xml @@ -172,6 +172,23 @@ http://download.java.net/maven/2 +<<<<<<< HEAD +======= + osgeo + Open Source Geospatial Foundation Repository + http://download.osgeo.org/webdav/geotools/ + + + + true + never + + opengeo + OpenGeo Maven Repository + http://repo.opengeo.org + + +>>>>>>> [feat] enable geometry_simplify API parameter bintray-nitram509-jbrotli bintray http://dl.bintray.com/nitram509/jbrotli @@ -269,7 +286,6 @@ 3.0.3 - com.github.GIScience.graphhopper graphhopper-core @@ -282,7 +298,6 @@ v0.10.1.12 - + +- [Contribution Guidelines](#contribution-guidelines) + - [Issues](#issues) + - [Technical issues](#technical-issues) + - [Routing issues](#routing-issues) + - [Feature requests](#feature-requests) + - [Pull Requests](#pull-requests) + - [Pull request guidelines](#pull-request-guidelines) + - [Contributing code](#contributing-code) + + + **Firstly, thanks for using the ORS and contributing to making it better for everyone.** OpenRouteService has been around for over ten years, and as such it has seen many changes and adoption of new methodologies and techniques, as well as the coming and going of multiple developers. To try and keep the OpenRouteService codebase clean and stable, there are a few guidelines that we try to follow. -###Creating issues -When creating an issue on GitHub, please complete as many of the following steps as possible to ensure that we can better locate the problem: -* Provide a description of what should happen and what does happen -* If the problem is with an API request, provide the URL that you used (ommitting your API key) -* If the problem is related to geometry, provide a screenshot of the route -We aim to do a minor update at the end of every month which will add any bug fixes to the live ORS. +## Issues + +We accept technical issues, routing issues and feature requests. Common questions should be asked at [ask.openrouteservice.org](https://ask.openrouteservice.org). + +Please search for issues before creating [a new one](https://github.com/GIScience/openrouteservice/issues/new). + +### Technical issues + +If you encounter a bug, please make sure to be as descriptive as possible, i.e.: + +- operating system (in case of self-hosting) +- request URL (incl. parameters if POST) +- expected outcome +- actual outcome (e.g. JSON output) +- fenced code around the bug, if known + +### Routing issues + +If you encounter weird or unexpected behavior during routing, please make sure to rule out expected behavior based on road attributes from e.g. [openstreetmap.org](https://openstreetmap.org/query), such as unexpected one-way streets or access restrictions. Find an overview of our tagging filters for all transportation profiles in our [wiki](https://github.com/GIScience/openrouteservice/wiki/Tag-Filtering). + +Information to include: + +- request URL (incl. parameters if POST) +- expected outcome +- actual outcome (e.g. JSON output) +- screenshots where applicable (e.g. from our [maps](https://maps.openrouteservice.org)) -###Creating Pull Requests -When creating pull requests, ensure that you address each item in the checklist before submitting. When an item is not applicable, leave it blank or better yet, use a pait of ~ on each side of the item to show that it is not applicable. -**Only create pull requests against the development branch!** +### Feature requests + +Here you can be creative, but still descriptive. Make sure to describe the current behavior, your desired behavior and **to give actual use cases**. That makes it whole easier for us to prioritize. + +## Pull Requests + +We :heart: pull requests! We aspire to make our commit history cleaner and more sustainable, benefiting our contributors and us maintainers. + +### Pull request guidelines + +We'd like all pull requests to adhere to the following rules: + +- a PR has to **close an issue**. If there is none yet for yours, please [create one](https://github.com/GIScience/openrouteservice/issues/new) +- branch off [developemnt](https://github.com/GIScience/openrouteservice/tree/development) +- name your branch according to `<[hotfix/bugfix/feat/algo]>/-`, e.g. `[feat]/#381-simplify_geometry` +- if you introduce new functions/classes, write unit or API tests +- **limit the number of commits to a minimum**, i.e. use [`git commit --amend [--no-edit]`](https://www.atlassian.com/git/tutorials/rewriting-history#git-commit--amend) +- use meaningful commit messages, e.g. `commit -m "[feat] include geometry_simplify in API and core code"` +- if your branch needs an update from its base branch, use [`rebase`](https://blog.algolia.com/master-git-rebase/#rebasing-on-the-base-branch), e.g. + +``` +git checkout my-new-feat +git rebase master +``` + +Be extra careful using `rebase` commands when collaborating on a branch with other people. + +**Don't merge** `development` branch into your feature branch. + +### Contributing code + +For a short explanation on how to setup, deploy and test **openrouteservice** locally for development, see our [wiki entry](https://soon.coming). -###Contributing code Though there are no concrete rules for code that is contributed, we have a few general styles that should be adopted: -* Always make your code easy to read - methods, variables and classes should all have sensible names that tell you what they are for -* Comments should be used to explain something that needs some background and for JDocs descriptions. They should *NEVER* be used to comment out blocks of code! In general, following the principle of proper naming for variables and methods, your code should be self explanitory and so not need an abundance of comments to explain it. -* Try to make your code extendable with OO techniques (i.e. interfaces) where possible -* Write unit tests -* If your code adds new functionality to the API, make sure to write corresponding API-Tests in the openrouteservice-api-tests subproject. -* Try to keep methods short - it is is almost always better to have multiple short methods that do one thing each rather than one goliath of a method that tries to do everything. -* Keep an eye out for an elusive yet mischievous digital llama hiding in the code - reports say that he appears every now and then and changes a double to a float, just to make things difficult... but then again, maybe a developer created this rumour to cover up their mistakes... no one knows for sure \ No newline at end of file + +- **Descriptive names** for variables, methods and classes +- **Minimal in-line comments**: code should be self-explanatory for the most part. **Never** use comments to comment out blocks of code +- **Use JDoc** docstrings to provide background for methods and classes +- **Unit tests!!** +- **API test** when adding API functionality in the corresponding [`openrouteservice-api-tests`](https://github.com/GIScience/openrouteservice/tree/master/openrouteservice-api-tests) subproject +- Keep **methods modular**, rather short and singular functionality than 100s line of code From b1b0f5b5e4995f3afba3cc937280de464b597ee0 Mon Sep 17 00:00:00 2001 From: nilsnolde Date: Wed, 16 Jan 2019 12:32:32 +0300 Subject: [PATCH 16/24] add git stash to rebase instructions [ci skip] --- CONTRIBUTE.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md index 59ecac89fa..06ee29a5dc 100644 --- a/CONTRIBUTE.md +++ b/CONTRIBUTE.md @@ -50,7 +50,7 @@ Here you can be creative, but still descriptive. Make sure to describe the curre ## Pull Requests -We :heart: pull requests! We aspire to make our commit history cleaner and more sustainable, benefiting our contributors and us maintainers. +We :heart: pull requests! We also aspire to make our commit history cleaner and more sustainable, benefiting our contributors and us maintainers. ### Pull request guidelines @@ -66,7 +66,9 @@ We'd like all pull requests to adhere to the following rules: ``` git checkout my-new-feat -git rebase master +git stash +git rebase development +git stash pop ``` Be extra careful using `rebase` commands when collaborating on a branch with other people. @@ -80,8 +82,8 @@ For a short explanation on how to setup, deploy and test **openrouteservice** lo Though there are no concrete rules for code that is contributed, we have a few general styles that should be adopted: - **Descriptive names** for variables, methods and classes -- **Minimal in-line comments**: code should be self-explanatory for the most part. **Never** use comments to comment out blocks of code -- **Use JDoc** docstrings to provide background for methods and classes +- **Minimal in-line comments**: code should be self-explanatory. **Never** use comments to comment out blocks of code +- **Use JDoc** docstrings to provide context for methods and classes - **Unit tests!!** - **API test** when adding API functionality in the corresponding [`openrouteservice-api-tests`](https://github.com/GIScience/openrouteservice/tree/master/openrouteservice-api-tests) subproject - Keep **methods modular**, rather short and singular functionality than 100s line of code From 5e2b49af22af21b65b1c88d2f6e502917b877e10 Mon Sep 17 00:00:00 2001 From: nilsnolde Date: Fri, 18 Jan 2019 13:37:03 +0300 Subject: [PATCH 17/24] fix PR template to rebase, fix typo --- CONTRIBUTE.md | 2 +- PULL_REQUEST_TEMPLATE.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md index 06ee29a5dc..a94b14d00b 100644 --- a/CONTRIBUTE.md +++ b/CONTRIBUTE.md @@ -86,4 +86,4 @@ Though there are no concrete rules for code that is contributed, we have a few g - **Use JDoc** docstrings to provide context for methods and classes - **Unit tests!!** - **API test** when adding API functionality in the corresponding [`openrouteservice-api-tests`](https://github.com/GIScience/openrouteservice/tree/master/openrouteservice-api-tests) subproject -- Keep **methods modular**, rather short and singular functionality than 100s line of code +- Keep **methods modular**: rather short and singular functionality than 100s line of code diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index f3daf54148..0c70047563 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ ### Pull Request Checklist -- [ ] 1. I have merged the latest version of the development branch into my feature branch and all conflicts have been resolved. +- [ ] 1. I have [**rebased**](https://github.com/GIScience/openrouteservice/blob/master/CONTRIBUTE.md#pull-request-guidelines) the latest version of the development branch into my feature branch and all conflicts have been resolved. - [ ] 2. I have added information about the change/addition to functionality to the CHANGELOG.md file under the [Unreleased] heading. - [ ] 3. I have documented my code using JDocs tags. - [ ] 4. I have removed unnecessary commented out code, imports and System.out.println statements. @@ -17,10 +17,10 @@ Fixes # . ### Information about the changes - Key functionality added: -- Reason for change: +- Reason for change: ### Examples and reasons for differences between live ORS routes and those generated from this pull request -- +- ### Required changes to app.config (if applicable) -- +- From 3cea644e8f4800bf31a675cf2c1786bdfe8e05dc Mon Sep 17 00:00:00 2001 From: nilsnolde Date: Sat, 19 Jan 2019 12:33:08 +0300 Subject: [PATCH 18/24] fixed typo for real;) --- CONTRIBUTE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md index a94b14d00b..7d1b0239e1 100644 --- a/CONTRIBUTE.md +++ b/CONTRIBUTE.md @@ -57,7 +57,7 @@ We :heart: pull requests! We also aspire to make our commit history cleaner and We'd like all pull requests to adhere to the following rules: - a PR has to **close an issue**. If there is none yet for yours, please [create one](https://github.com/GIScience/openrouteservice/issues/new) -- branch off [developemnt](https://github.com/GIScience/openrouteservice/tree/development) +- branch off [development](https://github.com/GIScience/openrouteservice/tree/development) - name your branch according to `<[hotfix/bugfix/feat/algo]>/-`, e.g. `[feat]/#381-simplify_geometry` - if you introduce new functions/classes, write unit or API tests - **limit the number of commits to a minimum**, i.e. use [`git commit --amend [--no-edit]`](https://www.atlassian.com/git/tutorials/rewriting-history#git-commit--amend) From 6211bffcfe152ec3d1e194779871c25ab9f14ada Mon Sep 17 00:00:00 2001 From: nilsnolde Date: Mon, 21 Jan 2019 09:29:50 +0300 Subject: [PATCH 19/24] adapt README links --- README.md | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 228e413b4a..7ea6b89e44 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Openrouteservice -- [master](https://github.com/GIScience/openrouteservice) [![Build Status](https://travis-ci.org/GIScience/openrouteservice.svg?branch=master)](https://travis-ci.org/GIScience/openrouteservice) -- [development](https://github.com/GIScience/openrouteservice/tree/development) [![Build Status](https://travis-ci.org/GIScience/openrouteservice.svg?branch=development)](https://travis-ci.org/GIScience/openrouteservice) +       [master](https://github.com/GIScience/openrouteservice)        [development](https://github.com/GIScience/openrouteservice/tree/development) +[![Build Status](https://travis-ci.org/GIScience/openrouteservice.svg?branch=master)](https://travis-ci.org/GIScience/openrouteservice) [![Build Status](https://travis-ci.org/GIScience/openrouteservice.svg?branch=development)](https://travis-ci.org/GIScience/openrouteservice) The **openrouteservice API** provides global spatial services by consuming user-generated and collaboratively collected free geographic data directly from [OpenStreetMap](http://www.openstreetmap.org). It is highly customizable, performant and written in Java. @@ -12,11 +12,12 @@ The following services are available via a RESTful interface served by Tomcat. To play around with openrouteservice you may use our [demonstration server](https://maps.openrouteservice.org) which comes with both the backend and a [frontend](https://github.com/GIScience/openrouteservice-app). Or simply sign up for an [API key](https://openrouteservice.org) and fire your requests against the API directly. -Please note that openrouteservice uses a forked and edited version of [graphhopper 0.9](https://github.com/GIScience/graphhopper) which can be found [here](https://github.com/GIScience/graphhopper). +Please note that openrouteservice uses a forked and edited version of [graphhopper 0.10](https://github.com/GIScience/graphhopper) which can be found [here](https://github.com/GIScience/graphhopper). [![ors client accessibility](https://user-images.githubusercontent.com/23240110/30385487-9eac96b8-98a7-11e7-9357-afd4df8fccdf.png)](https://openrouteservice.org/reach) **Note** + - Our geocoding API is a separate service running the stack built around [**Pelias**](https://github.com/pelias/pelias). - Our locations/API is another service which we have coined **openpoiservice** which can be found [here](https://github.com/GIScience/openpoiservice). @@ -29,13 +30,7 @@ Please note that openrouteservice uses a forked and edited version of [graphhopp We appreciate any kind of contribution - bug reports, new feature suggestion or improving our translations are greatly appreciated. Feel free to create an [issue](https://github.com/GIScience/openrouteservice/issues) and label it accordingly. If your issue regards the openrouteservice web-app please use the [corresponding repository](https://github.com/GIScience/openrouteservice-app/issues). -If you want to do contribute your improvements, please follow these steps: - - 1. [Fork the openrouteservice project](https://help.github.com/articles/fork-a-repo) - - 2. Create a branch for the improvement from the development branch on your fork and add your contributions there. - - 3. Create a [pull request](https://help.github.com/articles/using-pull-requests) to our development branch, so we can review your changes before applying them. Please write your pull request description similar to [this](http://api.coala.io/en/latest/Developers/Writing_Good_Commits.html) standard. Also please make sure to reference your pull request to the corresponding issue, for changes regarding multiple issues please create different pullrequests using different branches in your fork. +If you want to contribute your improvements, please follow the steps outlined in [our CONTRIBUTION guidelines](./CONTRIBUTE.md) ## Installation @@ -63,7 +58,7 @@ After you have packaged openrouteservice, there are two options for running it. 1. Install Tomcat 8 using `sudo apt-get install tomcat8`. 2. If you want to use system settings (i.e. Java heap size) other than the default, then you need to add these to the `/usr/share/tomcat8/bin/setenv.sh` file. If the file is not present, then you can create it. The settings generally used on our servers are similar to: - + ```bash JAVA_OPTS="-server -XX:TargetSurvivorRatio=75 -XX:SurvivorRatio=64 -XX:MaxTenuringThreshold=3 -XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:ParallelGCThreads=4 -Xms114g -Xmx114g -XX:MaxMetaspaceSize=50m" CATALINA_OPTS="(here we set settings for JMX monitoring)" @@ -96,7 +91,7 @@ After obtaining your key you can try out the different endpoints instantly and s ## Questions -For questions please use our [Google Groups Forum](https://groups.google.com/forum/#!forum/openrouteservice) and we will respond to you shortly or add a GitHub issue if it is of technical nature. +For questions please use our [community forum](https://ask.openrouteservice.org). ## Translations From 279a781c464a285a2125c7bdffafa9a9488c7efa Mon Sep 17 00:00:00 2001 From: Nils Date: Mon, 21 Jan 2019 11:01:30 +0300 Subject: [PATCH 20/24] add ../ to data paths so we can just copy the config to WEB-INF and use it without changing paths manually --- .../conf/app.config.test | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/openrouteservice-api-tests/conf/app.config.test b/openrouteservice-api-tests/conf/app.config.test index b38cccd490..ad14ef64c9 100644 --- a/openrouteservice-api-tests/conf/app.config.test +++ b/openrouteservice-api-tests/conf/app.config.test @@ -111,7 +111,7 @@ routing: { enabled: true, mode: "normal", - sources: ["openrouteservice-api-tests/data/heidelberg.osm.gz"], + sources: ["../openrouteservice-api-tests/data/heidelberg.osm.gz"], init_threads: 1, attribution: "openrouteservice.org, OpenStreetMap contributors, tmc - BASt", distance_approximation: true, @@ -122,7 +122,7 @@ graphs_root_path: "graphs", elevation_provider: multi, elevation_cache_clear: false, - elevation_cache_path: "openrouteservice-api-tests/data/elevation", + elevation_cache_path: "../openrouteservice-api-tests/data/elevation", instructions: true, maximum_distance: 100000, maximum_segment_distance_with_dynamic_weights: 50000, @@ -206,9 +206,9 @@ WaySurfaceType: {}, Tollways: {}, Borders: { - boundaries: "openrouteservice-api-tests/data/borders/borders.geojson", - ids: "openrouteservice-api-tests/data/borders/ids.csv", - openborders: "openrouteservice-api-tests/data/borders/openborders.csv" + boundaries: "../openrouteservice-api-tests/data/borders/borders.geojson", + ids: "../openrouteservice-api-tests/data/borders/ids.csv", + openborders: "../openrouteservice-api-tests/data/borders/openborders.csv" }, RoadAccessRestrictions: { use_for_warnings: true @@ -266,9 +266,9 @@ WaySurfaceType: {}, Tollways: {}, Borders: { - boundaries: "openrouteservice-api-tests/data/borders/borders.geojson", - ids: "openrouteservice-api-tests/data/borders/ids.csv", - openborders: "openrouteservice-api-tests/data/borders/openborders.csv" + boundaries: "../openrouteservice-api-tests/data/borders/borders.geojson", + ids: "../openrouteservice-api-tests/data/borders/ids.csv", + openborders: "../openrouteservice-api-tests/data/borders/openborders.csv" } } traffic: false @@ -335,10 +335,10 @@ elevation: true, ext_storages: { GreenIndex: { - filepath: "openrouteservice-api-tests/data/green_streets_hd.csv" + filepath: "../openrouteservice-api-tests/data/green_streets_hd.csv" }, NoiseIndex: { - filepath: "openrouteservice-api-tests/data/noise_data_hd.csv" + filepath: "../openrouteservice-api-tests/data/noise_data_hd.csv" }, WayCategory: {}, WaySurfaceType: {}, @@ -354,10 +354,10 @@ elevation: true, ext_storages: { GreenIndex: { - filepath: "openrouteservice-api-tests/data/green_streets_hd.csv" + filepath: "../openrouteservice-api-tests/data/green_streets_hd.csv" }, NoiseIndex: { - filepath: "openrouteservice-api-tests/data/noise_data_hd.csv" + filepath: "../openrouteservice-api-tests/data/noise_data_hd.csv" }, WayCategory: {}, WaySurfaceType: {}, @@ -408,4 +408,4 @@ stdout: true } } -} \ No newline at end of file +} From c2946e139be4adb53955688ef794d2b5b311df6b Mon Sep 17 00:00:00 2001 From: Nils Date: Mon, 21 Jan 2019 11:21:31 +0300 Subject: [PATCH 21/24] update wiki entry for code contribution --- CONTRIBUTE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md index 7d1b0239e1..775ebb11d2 100644 --- a/CONTRIBUTE.md +++ b/CONTRIBUTE.md @@ -77,7 +77,7 @@ Be extra careful using `rebase` commands when collaborating on a branch with oth ### Contributing code -For a short explanation on how to setup, deploy and test **openrouteservice** locally for development, see our [wiki entry](https://soon.coming). +For a short explanation on how to setup, deploy and test **openrouteservice** locally for development, see our [wiki entry](https://github.com/GIScience/openrouteservice/wiki/Contributing-Code). Though there are no concrete rules for code that is contributed, we have a few general styles that should be adopted: From 7967dde892c4a900dbef7690e394939a488a5ab1 Mon Sep 17 00:00:00 2001 From: Nils Date: Mon, 21 Jan 2019 12:19:51 +0300 Subject: [PATCH 22/24] revert changing data paths --- .../conf/app.config.test | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/openrouteservice-api-tests/conf/app.config.test b/openrouteservice-api-tests/conf/app.config.test index ad14ef64c9..86a7f35411 100644 --- a/openrouteservice-api-tests/conf/app.config.test +++ b/openrouteservice-api-tests/conf/app.config.test @@ -111,7 +111,7 @@ routing: { enabled: true, mode: "normal", - sources: ["../openrouteservice-api-tests/data/heidelberg.osm.gz"], + sources: ["openrouteservice-api-tests/data/heidelberg.osm.gz"], init_threads: 1, attribution: "openrouteservice.org, OpenStreetMap contributors, tmc - BASt", distance_approximation: true, @@ -122,7 +122,7 @@ graphs_root_path: "graphs", elevation_provider: multi, elevation_cache_clear: false, - elevation_cache_path: "../openrouteservice-api-tests/data/elevation", + elevation_cache_path: "openrouteservice-api-tests/data/elevation", instructions: true, maximum_distance: 100000, maximum_segment_distance_with_dynamic_weights: 50000, @@ -206,9 +206,9 @@ WaySurfaceType: {}, Tollways: {}, Borders: { - boundaries: "../openrouteservice-api-tests/data/borders/borders.geojson", - ids: "../openrouteservice-api-tests/data/borders/ids.csv", - openborders: "../openrouteservice-api-tests/data/borders/openborders.csv" + boundaries: "openrouteservice-api-tests/data/borders/borders.geojson", + ids: "openrouteservice-api-tests/data/borders/ids.csv", + openborders: "openrouteservice-api-tests/data/borders/openborders.csv" }, RoadAccessRestrictions: { use_for_warnings: true @@ -266,9 +266,9 @@ WaySurfaceType: {}, Tollways: {}, Borders: { - boundaries: "../openrouteservice-api-tests/data/borders/borders.geojson", - ids: "../openrouteservice-api-tests/data/borders/ids.csv", - openborders: "../openrouteservice-api-tests/data/borders/openborders.csv" + boundaries: "openrouteservice-api-tests/data/borders/borders.geojson", + ids: "openrouteservice-api-tests/data/borders/ids.csv", + openborders: "openrouteservice-api-tests/data/borders/openborders.csv" } } traffic: false @@ -335,10 +335,10 @@ elevation: true, ext_storages: { GreenIndex: { - filepath: "../openrouteservice-api-tests/data/green_streets_hd.csv" + filepath: "openrouteservice-api-tests/data/green_streets_hd.csv" }, NoiseIndex: { - filepath: "../openrouteservice-api-tests/data/noise_data_hd.csv" + filepath: "openrouteservice-api-tests/data/noise_data_hd.csv" }, WayCategory: {}, WaySurfaceType: {}, @@ -354,10 +354,10 @@ elevation: true, ext_storages: { GreenIndex: { - filepath: "../openrouteservice-api-tests/data/green_streets_hd.csv" + filepath: "openrouteservice-api-tests/data/green_streets_hd.csv" }, NoiseIndex: { - filepath: "../openrouteservice-api-tests/data/noise_data_hd.csv" + filepath: "openrouteservice-api-tests/data/noise_data_hd.csv" }, WayCategory: {}, WaySurfaceType: {}, From 3d0fe615827970f0c004c6ad109ff0bea9ee11ee Mon Sep 17 00:00:00 2001 From: Adam Rousell Date: Tue, 22 Jan 2019 09:43:42 +0100 Subject: [PATCH 23/24] Added the /directions endpoint for the routing service --- CHANGELOG.md | 1 + openrouteservice/WebContent/WEB-INF/web.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5b13e3f42c..1044a37958 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Updated rural speed limit in France to be 80km/h (Issue #355) - Modified smoothing and buffer distances for small isochrones, aswell as other fixes for smaller isochrones (Issue #382) - Updated pom to use correct opengeo repo and reordered so this is the last in the list, and use latest ORS-Graphhopper library (Issue #398) +- Added /directions as an endpoint for routing (Issue #384) ### Deprecated ## [4.7.2] - 2018-12-10 diff --git a/openrouteservice/WebContent/WEB-INF/web.xml b/openrouteservice/WebContent/WEB-INF/web.xml index 425c42a6ab..50b8ace288 100644 --- a/openrouteservice/WebContent/WEB-INF/web.xml +++ b/openrouteservice/WebContent/WEB-INF/web.xml @@ -10,6 +10,7 @@ routing /routes + /directions From 909d33c2444aabd49b40ae8c39e3d2c59caab0df Mon Sep 17 00:00:00 2001 From: Adam Rousell Date: Fri, 1 Feb 2019 14:27:31 +0100 Subject: [PATCH 24/24] Added check to the matrix service that checks if the points are out of bounds of the graph --- CHANGELOG.md | 1 + .../ors/services/matrix/MatrixErrorCodes.java | 1 + .../matrix/ParametersValidationTest.java | 15 +++++ .../exceptions/PointNotFoundException.java | 4 ++ .../heigit/ors/matrix/MatrixErrorCodes.java | 1 + .../matrix/MatrixSearchContextBuilder.java | 62 +++++++++++++++++-- .../heigit/ors/routing/RoutingProfile.java | 4 ++ 7 files changed, 83 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1044a37958..fa42c8ba31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - Added support for ISO 3166-1 Alpha-2 / Alpha-3 codes for routing directions option avoid_countries (Issue #195) - Added support for GH alternative_route algorithm (Issue #377) +- Added check on matrix service to make sure that the requested locations are within the bounding area of the graph (Issue #408) ### Fixed - Fixed `geometry_simplify` parameter, which had no effect before. `geometry_simplify` is incompatible with `extra_info` (#381) ### Changed diff --git a/openrouteservice-api-tests/src/test/java/heigit/ors/services/matrix/MatrixErrorCodes.java b/openrouteservice-api-tests/src/test/java/heigit/ors/services/matrix/MatrixErrorCodes.java index 12d7904992..9351366013 100644 --- a/openrouteservice-api-tests/src/test/java/heigit/ors/services/matrix/MatrixErrorCodes.java +++ b/openrouteservice-api-tests/src/test/java/heigit/ors/services/matrix/MatrixErrorCodes.java @@ -37,5 +37,6 @@ public class MatrixErrorCodes { public static int EXPORT_HANDLER_ERROR = 6006; public static int UNSUPPORTED_EXPORT_FORMAT = 6007; public static int EMPTY_ELEMENT = 6008; + public static int POINT_NOT_FOUND = 6010; public static int UNKNOWN = 6099; } diff --git a/openrouteservice-api-tests/src/test/java/heigit/ors/services/matrix/ParametersValidationTest.java b/openrouteservice-api-tests/src/test/java/heigit/ors/services/matrix/ParametersValidationTest.java index 27fd5a02f8..c8818f7aa8 100644 --- a/openrouteservice-api-tests/src/test/java/heigit/ors/services/matrix/ParametersValidationTest.java +++ b/openrouteservice-api-tests/src/test/java/heigit/ors/services/matrix/ParametersValidationTest.java @@ -375,4 +375,19 @@ public void resolveLocationsFormatTest() { .body("error.code", is(MatrixErrorCodes.INVALID_PARAMETER_FORMAT)) .statusCode(400); } + + @Test + public void pointOutOfBoundsTest() { + given() + .param("profile", "driving-car") + .param("locations", "9.0,48.7|9.0,49.1") + .param("sources", "all") + .param("destinations", "all") + .when() + .get(getEndPointName()) + .then() + .assertThat() + .body("error.code", is(MatrixErrorCodes.POINT_NOT_FOUND)) + .statusCode(404); + } } diff --git a/openrouteservice/src/main/java/heigit/ors/exceptions/PointNotFoundException.java b/openrouteservice/src/main/java/heigit/ors/exceptions/PointNotFoundException.java index 4860b15ccc..6797897dcc 100644 --- a/openrouteservice/src/main/java/heigit/ors/exceptions/PointNotFoundException.java +++ b/openrouteservice/src/main/java/heigit/ors/exceptions/PointNotFoundException.java @@ -8,4 +8,8 @@ public class PointNotFoundException extends StatusCodeException { public PointNotFoundException(String message) { super(StatusCode.NOT_FOUND, RoutingErrorCodes.POINT_NOT_FOUND, message); } + + public PointNotFoundException(String message, int errorCode) { + super(StatusCode.NOT_FOUND, errorCode, message); + } } diff --git a/openrouteservice/src/main/java/heigit/ors/matrix/MatrixErrorCodes.java b/openrouteservice/src/main/java/heigit/ors/matrix/MatrixErrorCodes.java index 7964a1504a..135aff2070 100644 --- a/openrouteservice/src/main/java/heigit/ors/matrix/MatrixErrorCodes.java +++ b/openrouteservice/src/main/java/heigit/ors/matrix/MatrixErrorCodes.java @@ -35,5 +35,6 @@ public class MatrixErrorCodes { public static int EXPORT_HANDLER_ERROR = 6006; public static int UNSUPPORTED_EXPORT_FORMAT = 6007; public static int EMPTY_ELEMENT = 6008; + public static int POINT_NOT_FOUND = 6010; public static int UNKNOWN = 6099; } diff --git a/openrouteservice/src/main/java/heigit/ors/matrix/MatrixSearchContextBuilder.java b/openrouteservice/src/main/java/heigit/ors/matrix/MatrixSearchContextBuilder.java index ccbd12eb09..c15bd17afe 100644 --- a/openrouteservice/src/main/java/heigit/ors/matrix/MatrixSearchContextBuilder.java +++ b/openrouteservice/src/main/java/heigit/ors/matrix/MatrixSearchContextBuilder.java @@ -18,13 +18,12 @@ import com.graphhopper.storage.Graph; import com.graphhopper.storage.index.LocationIndex; import com.graphhopper.storage.index.QueryResult; +import com.graphhopper.util.shapes.BBox; import com.graphhopper.util.shapes.GHPoint3D; import com.vividsolutions.jts.geom.Coordinate; +import heigit.ors.exceptions.PointNotFoundException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class MatrixSearchContextBuilder { private Map _locationCache; @@ -52,7 +51,9 @@ public MatrixSearchContext create(Graph graph, Coordinate[] sources, Coordinate[ _locationCache = new HashMap(); else _locationCache.clear(); - + + checkBounds(graph.getBounds(), sources, destinations); + QueryGraph queryGraph = new QueryGraph(graph); List queryResults = new ArrayList(sources.length + destinations.length); @@ -66,6 +67,57 @@ public MatrixSearchContext create(Graph graph, Coordinate[] sources, Coordinate[ return new MatrixSearchContext(queryGraph, mlSources, mlDestinations); } + + private void checkBounds(BBox bounds, Coordinate[] sources, Coordinate[] destinations) throws PointNotFoundException { + String[] messages = new String[2]; + messages[0] = constructPointOutOfBoundsMessage("Source", bounds, sources); + messages[1] = constructPointOutOfBoundsMessage("Destination", bounds, destinations); + + String exceptionMessage = messages[0]; + if (!exceptionMessage.isEmpty() && !messages[1].isEmpty()) + exceptionMessage += ". "; + exceptionMessage += messages[1]; + + if (!exceptionMessage.isEmpty()) + throw new PointNotFoundException(exceptionMessage, MatrixErrorCodes.POINT_NOT_FOUND); + } + + private String constructPointOutOfBoundsMessage(String pointsType, BBox bounds, Coordinate[] coords) { + int[] pointIds = pointIdsOutOfBounds(bounds, coords); + String message = ""; + + if (pointIds.length > 0) { + String idString = Arrays.toString(pointIds); + String coordsString = ""; + for (int id : pointIds) { + coordsString = coordsString + coords[id].y + "," + coords[id].x + "; "; + } + if (coordsString.length() > 1) { + coordsString = coordsString.substring(0, coordsString.length() - 2); + } + + message = pointsType + " point(s) " + idString + " out of bounds: " + coordsString; + } + + return message; + } + + private int[] pointIdsOutOfBounds(BBox bounds, Coordinate[] coords) { + List ids = new ArrayList(); + for (int i=0; i queryResults, double maxSearchRadius) { diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java index ae676e3c74..6061462282 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java @@ -34,6 +34,8 @@ import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import heigit.ors.exceptions.InternalServerException; +import heigit.ors.exceptions.PointNotFoundException; +import heigit.ors.exceptions.StatusCodeException; import heigit.ors.isochrones.*; import heigit.ors.isochrones.statistics.StatisticsProvider; import heigit.ors.isochrones.statistics.StatisticsProviderConfiguration; @@ -564,6 +566,8 @@ public MatrixResult computeMatrix(MatrixRequest req) throws Exception { mtxResult = alg.compute(mtxSearchCntx.getSources(), mtxSearchCntx.getDestinations(), req.getMetrics()); } catch (Exception ex) { LOGGER.error(ex); + if (ex instanceof StatusCodeException) + throw ex; throw new InternalServerException(MatrixErrorCodes.UNKNOWN, "Unable to compute a distance/duration matrix."); }