Skip to content

Commit

Permalink
feature-#349 list traversal countries
Browse files Browse the repository at this point in the history
  • Loading branch information
Julian Psotta committed May 21, 2019
1 parent 37235c6 commit d9ebc23
Show file tree
Hide file tree
Showing 15 changed files with 440 additions and 87 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Makes docker and docker-compose deployment of openrouteservice more customizable (Issue #434)
- Add the possibility to predefine standard maximum search radii in general and for each used profile in the config file (Issue #418)
- Added a gpx schema validator into the api-tests, testing all gpx outputs while fixing the bug from (#496)
- Added information for countries a route traverses (#349)
### Fixed
- isochrone reachfactor gives now more realistic results (#325)
- v2 isochrones now respects max_locations in app.config (#482)
Expand Down
Expand Up @@ -43,6 +43,7 @@
import java.util.List;

import static io.restassured.RestAssured.given;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.is;

Expand Down Expand Up @@ -82,6 +83,7 @@ public ResultTest() {
extraInfo.put("surface");
extraInfo.put("suitability");
extraInfo.put("steepness");
extraInfo.put("countryinfo");
addParameter("extra_info", extraInfo);

addParameter("preference", "fastest");
Expand Down Expand Up @@ -838,7 +840,7 @@ public void testExtras() {
given()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.pathParam("profile", getParameter("bikeProfile"))
.pathParam("profile", getParameter("carProfile"))
.body(body.toString())
.when()
.post(getEndPointPath() + "/{profile}")
Expand All @@ -849,6 +851,7 @@ public void testExtras() {
.body("routes[0].extras.containsKey('surface')", is(true))
.body("routes[0].extras.containsKey('suitability')", is(true))
.body("routes[0].extras.containsKey('steepness')", is(true))
.body("routes[0].extras.containsKey('countryinfo')", is(true))
.statusCode(200);
}

Expand Down Expand Up @@ -2407,6 +2410,171 @@ public void testPreferQuiet() {
.statusCode(200);
}

@Test
public void testCountryTraversalNoBorderCrossing(){
JSONObject body = new JSONObject();
JSONArray noBorderCrossing = new JSONArray();
JSONArray coord = new JSONArray();
coord.put(8.692256212234497);
coord.put(49.405004518240005);
noBorderCrossing.put(coord);
coord = new JSONArray();
coord.put(8.689970970153809);
coord.put(49.40532565875338);
noBorderCrossing.put(coord);
body.put("coordinates", noBorderCrossing);
JSONArray extraInfo = new JSONArray();
extraInfo.put("countryinfo");
body.put("extra_info", extraInfo);

// No border crossing
given()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.pathParam("profile", getParameter("carProfile"))
.body(body.toString())
.when()
.post(getEndPointPath() + "/{profile}/json")
.then().log().ifValidationFails()
.assertThat()
.body("any { it.key == 'routes' }", is(true))
.body("routes[0].containsKey('extras')", is(true))
.body("routes[0].extras.containsKey('countryinfo')", is(true))
.body("routes[0].extras.countryinfo.containsKey('values')", is(true))
.body("routes[0].extras.countryinfo.containsKey('summary')", is(true))
.body("routes[0].extras.countryinfo.values[0][0]", is(0))
.body("routes[0].extras.countryinfo.values[0][1]", is(2))
.body("routes[0].extras.countryinfo.values[0][2]", is(4))
.body("routes[0].extras.countryinfo.summary[0].value", is(4.0f))
.body("routes[0].extras.countryinfo.summary[0].distance", is(169.2f))
.body("routes[0].extras.countryinfo.summary[0].amount", is(100.0f))
.statusCode(200);
}

@Test
public void testCountryTraversalOuterBorder() {
JSONObject body = new JSONObject();
JSONArray outerBorder = new JSONArray();
JSONArray coord = new JSONArray();
coord.put(8.688002);
coord.put(49.392946);
outerBorder.put(coord);
coord = new JSONArray();
coord.put(8.687809);
coord.put(49.39472);
outerBorder.put(coord);
body.put("coordinates", outerBorder);
JSONArray extraInfo = new JSONArray();
extraInfo.put("countryinfo");
body.put("extra_info", extraInfo);

// Outside of any borders
given()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.pathParam("profile", getParameter("carProfile"))
.body(body.toString())
.when()
.post(getEndPointPath() + "/{profile}/json")
.then().log().ifValidationFails()
.assertThat()
.body("any { it.key == 'routes' }", is(true))
.body("routes[0].containsKey('extras')", is(true))
.body("routes[0].extras.containsKey('countryinfo')", is(true))
.body("routes[0].extras.countryinfo.containsKey('values')", is(true))
.body("routes[0].extras.countryinfo.containsKey('summary')", is(true))
.body("routes[0].extras.countryinfo.values", empty())
.statusCode(200);
}

@Test
public void testCoutryTraversalCloseToBorder() {
JSONObject body = new JSONObject();
JSONArray closeToBorder = new JSONArray();
JSONArray coord = new JSONArray();
coord.put(8.685869872570038);
coord.put(49.402674441283786);
closeToBorder.put(coord);
coord = new JSONArray();
coord.put(8.687363862991333);
coord.put(49.4027128404518);
closeToBorder.put(coord);
body.put("coordinates", closeToBorder);
JSONArray extraInfo = new JSONArray();
extraInfo.put("countryinfo");
body.put("extra_info", extraInfo);

// Close to a border crossing
given()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.pathParam("profile", getParameter("carProfile"))
.body(body.toString())
.when()
.post(getEndPointPath() + "/{profile}/json")
.then().log().ifValidationFails()
.assertThat()
.body("any { it.key == 'routes' }", is(true))
.body("routes[0].containsKey('extras')", is(true))
.body("routes[0].extras.containsKey('countryinfo')", is(true))
.body("routes[0].extras.countryinfo.containsKey('values')", is(true))
.body("routes[0].extras.countryinfo.containsKey('summary')", is(true))
.body("routes[0].extras.countryinfo.values[0][0]", is(0))
.body("routes[0].extras.countryinfo.values[0][1]", is(2))
.body("routes[0].extras.countryinfo.values[0][2]", is(3))
.body("routes[0].extras.countryinfo.summary[0].value", is(3.0f))
.body("routes[0].extras.countryinfo.summary[0].distance", is(108.0f))
.body("routes[0].extras.countryinfo.summary[0].amount", is(100.0f))
.statusCode(200);
}

@Test
public void testCountryTraversalWithBorderCrossing() {
JSONObject body = new JSONObject();
JSONArray borderCrossing = new JSONArray();
JSONArray coord = new JSONArray();
coord.put(8.685046434402466);
coord.put(49.40267269586634);
borderCrossing.put(coord);
coord = new JSONArray();
coord.put(8.687556982040405);
coord.put(49.40271458586781);
borderCrossing.put(coord);
body.put("coordinates", borderCrossing);
JSONArray extraInfo = new JSONArray();
extraInfo.put("countryinfo");
body.put("extra_info", extraInfo);

// With Border crossing
given()
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.pathParam("profile", getParameter("carProfile"))
.body(body.toString())
.when()
.post(getEndPointPath() + "/{profile}/json")
.then().log().ifValidationFails()
.assertThat()
.body("any { it.key == 'routes' }", is(true))
.body("routes[0].containsKey('extras')", is(true))
.body("routes[0].extras.containsKey('countryinfo')", is(true))
.body("routes[0].extras.countryinfo.containsKey('values')", is(true))
.body("routes[0].extras.countryinfo.containsKey('summary')", is(true))
.body("routes[0].extras.countryinfo.values[0][0]", is(0))
.body("routes[0].extras.countryinfo.values[0][1]", is(2))
.body("routes[0].extras.countryinfo.values[0][2]", is(2))
.body("routes[0].extras.countryinfo.summary[0].value", is(2.0f))
.body("routes[0].extras.countryinfo.summary[0].distance", is(150.4f))
.body("routes[0].extras.countryinfo.summary[0].amount", is(82.88f))
.body("routes[0].extras.countryinfo.values[1][0]", is(2))
.body("routes[0].extras.countryinfo.values[1][1]", is(3))
.body("routes[0].extras.countryinfo.values[1][2]", is(3))
.body("routes[0].extras.countryinfo.summary[1].value", is(3.0f))
.body("routes[0].extras.countryinfo.summary[1].distance", is(31.1f))
.body("routes[0].extras.countryinfo.summary[1].amount", is(17.12f))
.statusCode(200);
}

private JSONArray constructCoords(String coordString) {
JSONArray coordinates = new JSONArray();
String[] coordPairs = coordString.split("\\|");
Expand Down
Expand Up @@ -63,7 +63,8 @@ public enum ExtraInfo {
TOLLWAYS("tollways"),
TRAIL_DIFFICULTY("traildifficulty"),
OSM_ID("osmid"),
ROAD_ACCESS_RESTRICTIONS("roadaccessrestrictions");
ROAD_ACCESS_RESTRICTIONS("roadaccessrestrictions"),
COUNTRY_INFO("countryinfo");

private final String value;

Expand Down
Expand Up @@ -23,10 +23,26 @@
import heigit.ors.api.requests.common.GenericHandler;
import heigit.ors.common.DistanceUnit;
import heigit.ors.common.StatusCode;
import heigit.ors.exceptions.*;
import heigit.ors.exceptions.EmptyElementException;
import heigit.ors.exceptions.IncompatibleParameterException;
import heigit.ors.exceptions.InternalServerException;
import heigit.ors.exceptions.ParameterOutOfRangeException;
import heigit.ors.exceptions.ParameterValueException;
import heigit.ors.exceptions.StatusCodeException;
import heigit.ors.exceptions.UnknownParameterValueException;
import heigit.ors.geojson.GeometryJSON;
import heigit.ors.localization.LocalizationManager;
import heigit.ors.routing.*;
import heigit.ors.routing.AvoidFeatureFlags;
import heigit.ors.routing.RouteExtraInfoFlag;
import heigit.ors.routing.RouteInstructionsFormat;
import heigit.ors.routing.RouteResult;
import heigit.ors.routing.RouteSearchParameters;
import heigit.ors.routing.RoutingErrorCodes;
import heigit.ors.routing.RoutingProfileManager;
import heigit.ors.routing.RoutingProfileType;
import heigit.ors.routing.RoutingRequest;
import heigit.ors.routing.WayPointBearing;
import heigit.ors.routing.WeightingMethod;
import heigit.ors.routing.graphhopper.extensions.reader.borders.CountryBordersReader;
import heigit.ors.routing.pathprocessors.BordersExtractor;
import heigit.ors.util.DistanceUnitUtil;
Expand Down Expand Up @@ -80,9 +96,14 @@ public RoutingRequest convertRouteRequest(RouteRequest request) throws StatusCo
if (request.hasAttributes())
routingRequest.setAttributes(convertAttributes(request.getAttributes()));

if (request.hasExtraInfo())
if (request.hasExtraInfo()){
routingRequest.setExtraInfo(convertExtraInfo(request.getExtraInfo()));

for (APIEnums.ExtraInfo extra: request.getExtraInfo()) {
if (extra.compareTo(APIEnums.ExtraInfo.COUNTRY_INFO) == 0) {
routingRequest.setIncludeCountryInfo(true);
}
}
}
if (request.hasLanguage())
routingRequest.setLanguage(convertLanguage(request.getLanguage()));

Expand Down
Expand Up @@ -28,6 +28,7 @@ public class RouteExtraInfoFlag {
public static final int TrailDifficulty = 512;
public static final int OsmId = 1024;
public static final int RoadAccessRestrictions = 2048;
public static final int CountryInfo = 4096;

public static boolean isSet(int extraInfo, int value) {
return (extraInfo & value) == value;
Expand Down Expand Up @@ -78,6 +79,9 @@ public static int getFromString(String value) {
case "roadaccessrestrictions":
res |= RoadAccessRestrictions;
break;
case "countryinfo":
res |= CountryInfo;
break;
}
}

Expand Down
Expand Up @@ -16,34 +16,62 @@
import com.graphhopper.GHRequest;
import com.graphhopper.GHResponse;
import com.graphhopper.GraphHopper;
import com.graphhopper.routing.util.*;
import com.graphhopper.routing.util.DefaultEdgeFilter;
import com.graphhopper.routing.util.EdgeFilter;
import com.graphhopper.routing.util.EncodingManager;
import com.graphhopper.routing.util.FlagEncoder;
import com.graphhopper.routing.util.HintsMap;
import com.graphhopper.routing.weighting.Weighting;
import com.graphhopper.storage.*;
import com.graphhopper.util.*;
import com.graphhopper.storage.CHGraph;
import com.graphhopper.storage.Graph;
import com.graphhopper.storage.GraphHopperStorage;
import com.graphhopper.storage.GraphStorage;
import com.graphhopper.storage.StorableProperties;
import com.graphhopper.util.CmdArgs;
import com.graphhopper.util.EdgeIteratorState;
import com.graphhopper.util.Helper;
import com.graphhopper.util.PMap;
import com.graphhopper.util.PointList;
import com.graphhopper.util.shapes.BBox;
import com.graphhopper.util.shapes.GHPoint;
import com.typesafe.config.Config;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import heigit.ors.common.TravelRangeType;
import heigit.ors.exceptions.InternalServerException;
import heigit.ors.exceptions.StatusCodeException;
import heigit.ors.isochrones.*;
import heigit.ors.isochrones.Isochrone;
import heigit.ors.isochrones.IsochroneMap;
import heigit.ors.isochrones.IsochroneMapBuilderFactory;
import heigit.ors.isochrones.IsochroneSearchParameters;
import heigit.ors.isochrones.IsochronesErrorCodes;
import heigit.ors.isochrones.statistics.StatisticsProvider;
import heigit.ors.isochrones.statistics.StatisticsProviderConfiguration;
import heigit.ors.isochrones.statistics.StatisticsProviderFactory;
import heigit.ors.mapmatching.MapMatcher;
import heigit.ors.mapmatching.RouteSegmentInfo;
import heigit.ors.mapmatching.hmm.HiddenMarkovMapMatcher;
import heigit.ors.matrix.*;
import heigit.ors.matrix.MatrixErrorCodes;
import heigit.ors.matrix.MatrixRequest;
import heigit.ors.matrix.MatrixResult;
import heigit.ors.matrix.MatrixSearchContext;
import heigit.ors.matrix.MatrixSearchContextBuilder;
import heigit.ors.matrix.algorithms.MatrixAlgorithm;
import heigit.ors.matrix.algorithms.MatrixAlgorithmFactory;
import heigit.ors.routing.configuration.RouteProfileConfiguration;
import heigit.ors.routing.graphhopper.extensions.*;
import heigit.ors.routing.graphhopper.extensions.GraphProcessContext;
import heigit.ors.routing.graphhopper.extensions.HeavyVehicleAttributes;
import heigit.ors.routing.graphhopper.extensions.ORSDefaultFlagEncoderFactory;
import heigit.ors.routing.graphhopper.extensions.ORSGraphHopper;
import heigit.ors.routing.graphhopper.extensions.ORSGraphStorageFactory;
import heigit.ors.routing.graphhopper.extensions.ORSWeightingFactory;
import heigit.ors.routing.graphhopper.extensions.edgefilters.*;
import heigit.ors.routing.graphhopper.extensions.storages.GraphStorageUtils;
import heigit.ors.routing.parameters.*;
import heigit.ors.routing.graphhopper.extensions.storages.builders.BordersGraphStorageBuilder;
import heigit.ors.routing.graphhopper.extensions.storages.builders.GraphStorageBuilder;
import heigit.ors.routing.parameters.ProfileParameters;
import heigit.ors.routing.parameters.VehicleParameters;
import heigit.ors.routing.parameters.WheelchairParameters;
import heigit.ors.routing.traffic.RealTrafficDataProvider;
import heigit.ors.routing.traffic.TrafficEdgeAnnotator;
import heigit.ors.services.isochrones.IsochronesServiceSettings;
Expand All @@ -60,7 +88,13 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
* This class generates {@link RoutingProfile} classes and is used by mostly all service classes e.g.
Expand Down Expand Up @@ -150,6 +184,13 @@ public static ORSGraphHopper initGraphHopper(String osmFile, RouteProfileConfigu

gh.importOrLoad();

// Set the general country builder object for general use
for (GraphStorageBuilder builder : gpc.getStorageBuilders()) {
if (builder.getName().equals(BordersGraphStorageBuilder.builderName)) {
gh.setGeneralCbReader(((BordersGraphStorageBuilder) builder).getCbReader());
}
}

if (LOGGER.isInfoEnabled()) {
EncodingManager encodingMgr = gh.getEncodingManager();
GraphHopperStorage ghStorage = gh.getGraphHopperStorage();
Expand Down

0 comments on commit d9ebc23

Please sign in to comment.