diff --git a/README.md b/README.md
index d6532cf42e..057b453b87 100644
--- a/README.md
+++ b/README.md
@@ -36,7 +36,7 @@ If you want to do contribute your improvements, please follow these steps:
## Installation
-We suggest using docker to install and launch OpenRouteService backend. In short, run the following command under the source code tree will get everything done.
+We suggest using docker to install and launch openrouteservice backend. In short, run the following command under the source code tree will get everything done.
```bash
cd docker && docker-compose up
@@ -46,8 +46,18 @@ For more details, check the [docker installation guide](docker/README.md).
## Usage
-Instructions on how to use the endpoints of the running tomcat container will follow soon.
+Openrouteservice offers a set of endpoints for different spatial purposes. They are served with the help of [Tomcat in a java servlet container](https://github.com/GIScience/openrouteservice/blob/master/openrouteservice/WebContent/WEB-INF/web.xml). By default you will be able to query the services with these addresses:
+- `http://localhost:8080/name_of_war_archive/routes`
+- `http://localhost:8080/name_of_war_archive/isochrones`
+- `http://localhost:8080/name_of_war_archive/matrix`
+
+Both `/locations` and `/geocoding` need additional setup steps for usage.
+- `http://localhost:8080/name_of_war_archive/locations` | You will have to set up a locations database, for this please refer to [openrouteservice-tools](https://github.com/GIScience/openrouteservice-tools).
+- `http://localhost:8080/name_of_war_archive/geocoding` | You can either use [Photon](https://github.com/komoot/photon), [Nominatim](https://github.com/openstreetmap/Nominatim) or [Pelias](https://github.com/pelias/pelias). One of these services must be installed in addition to the openrouteservice and configured in `app.config`.
+
+Please find a detailed description of the api architecture on https://app.swaggerhub.com/apis/OpenRouteService/ors-api/.
+
## API Documentation
For an easy and interactive way to test the api, visit our [documentation](https://app.swaggerhub.com/apis/openrouteservice/ors-api/) at swaggerhub. After obtaining your key you can try out the different endpoints instantly and start firing requests.
diff --git a/docker/README.md b/docker/README.md
index 8644d5101b..a8742a16ef 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -1,22 +1,22 @@
-# Install and Run OpenRouteService Backend via Docker
+# Install and run openrouteservice with docker
-It's possible and easy to install and launch the OpenRouteService backend service with Docker. Please note that the [Dockerfile](../Dockerfile) under the repository root directory is only for building the [WAR file](https://www.wikiwand.com/en/WAR_(file_format)).
+Installing the openrouteservice backend service with **Docker** is quite straightforward. Please note that the [Dockerfile](../Dockerfile) located in the repository root directory is merely for building the [WAR file](https://www.wikiwand.com/en/WAR_(file_format)).
## Short version
-run the following command within this `docker/` directory:
+Run the following command within this `docker/` directory:
```bash
-docker-compose up
+sudo docker-compose up -d
```
-It will:
+This will:
-1. build and test the OpenRouteService core from the local codebase with the `docker/conf/app.config.sample` as the config and the dataset for Heidelberg under `docker/data/` as sample data;
-2. generate the built `ors.war` file and expose it to `docker/build/` directory;
-3. launch the OpenRouteService backend service on port `8080`.
+1. Build and test the openrouteservice core from the local codebase with the `docker/conf/app.config.sample` as the config file and the OpenStreetMap dataset for Heidelberg under `docker/data/` as sample data.
+2. Generate the built `ors.war` file and expose it to `docker/build/` directory.
+3. Launch the openrouteservice service on port `8080` within a tomcat container.
-The service status is queryable via `http://localhost:8080/ors/health` endpoint. When the service is ready, go to `http://localhost:8080/ors/status` and it will show more detailed information. A URL for test can be `http://localhost:8080/ors/routes?profile=foot-walking&coordinates=8.676581,49.418204|8.692803,49.409465`. It should be able to provide the recommanded walking path in JSON format.
+By default the service status is queryable via the `http://localhost:8080/ors/health` endpoint. When the service is ready, you will be able to request `http://localhost:8080/ors/status` for further information on the running services. If you use the default dataset you will be able to request `http://localhost:8080/ors/routes?profile=foot-walking&coordinates=8.676581,49.418204|8.692803,49.409465` for test purposes.
## Long version
@@ -34,20 +34,20 @@ or
docker-compose up ors-build
```
-If everything goes fine, the built `ors.war` file can be found under the host directory, e.g. `/Users/user/build` in the above `docker run` command or `./build/` in the `docker-compose` command.
+If everything goes fine, the built `ors.war` archive can be found under the shared host directory, e.g. `/Users/user/build` for the above `docker run` command or `./build/` for the `docker-compose` command.
-### Run OpenRouteService
+### Run openrouteservice
-No matter whether the WAR file has been built or not, run
+No matter whether the WAR file has been built or not, simply run:
```bash
-docker-compose up
+sudo docker-compose up
```
-will get everything done with the sample Heidelberg dataset.
+will take care of all steps with the sample Heidelberg dataset.
-### Run with your own OSM dataset
+### Run with your own OpenStreetMap dataset
-Prepare the OSM dataset (formats support `.osm`, `.osm.gz`, `.osm.zip`, `.pbf`) in the `docker/data/` directory. Make your own `app.config` (check the sample with detailed comments [here](../openrouteservice/WebContent/WEB-INF/app.config.sample) for reference) and change the `APP_CONFIG` variable in `docker-compose.yml` to let it point to your customized `app.config`. Then, run `docker-compose up`.
+Prepare the OSM dataset (formats supported are `.osm`, `.osm.gz`, `.osm.zip` and `.pbf`) in the `docker/data/` directory. Adapt your own `app.config` (check the sample with detailed comments [here](../openrouteservice/WebContent/WEB-INF/app.config.sample) for reference) and change the `APP_CONFIG` variable in `docker-compose.yml` to let it point to your customized `app.config`. Then, run `docker-compose up`.
-It should be noticed that if your dataset is very big, please adjust the `-Xmx` parameter of `JAVA_OPTS` in `docker-compose.yml`. According to our experiences, it should be at least `180g` for the whole globe.
\ No newline at end of file
+It should be mentioned that if your dataset is very large, please adjust the `-Xmx` parameter of `JAVA_OPTS` in `docker-compose.yml`. According to our experience, this should be at least `180g` for the whole globe if you are planning to use 3 or more modes of transport.
diff --git a/openrouteservice-api-tests/src/test/java/heigit/ors/services/locations/ResultsValidationTest.java b/openrouteservice-api-tests/src/test/java/heigit/ors/services/locations/ResultsValidationTest.java
index 7451469953..5e590ab713 100644
--- a/openrouteservice-api-tests/src/test/java/heigit/ors/services/locations/ResultsValidationTest.java
+++ b/openrouteservice-api-tests/src/test/java/heigit/ors/services/locations/ResultsValidationTest.java
@@ -73,7 +73,7 @@ public void bboxSearchFilterTest() {
Assert.assertEquals(jResponse.getJSONArray("features").length(), 8);
}
- @Test
+ /**@Test
public void pointSearchWithoutNameFilterTest() {
Response response = given()
.param("request", "pois")
@@ -95,9 +95,9 @@ public void pointSearchWithoutNameFilterTest() {
Assert.assertEquals(true, jBbox.getDouble(1) == 49.377332);
Assert.assertEquals(true, jBbox.getDouble(2) == 8.710422);
Assert.assertEquals(true, jBbox.getDouble(3) == 49.454217);
- }
+ }*/
- @Test
+ /**@Test
public void pointSearchWithNameFilterTest() {
Response response = given()
.param("request", "pois")
@@ -113,9 +113,9 @@ public void pointSearchWithNameFilterTest() {
JSONObject jResponse = new JSONObject(response.body().asString());
Assert.assertEquals(jResponse.getJSONArray("features").length(), 9);
- }
+ }*/
- @Test
+ /**@Test
public void linestringSearchWithNameFilterTest() {
Response response = given()
.param("request", "pois")
@@ -130,7 +130,7 @@ public void linestringSearchWithNameFilterTest() {
Assert.assertEquals(response.getStatusCode(), 200);
JSONObject jResponse = new JSONObject(response.body().asString());
Assert.assertEquals(jResponse.getJSONArray("features").length(), 2);
- }
+ }*/
@Test
public void detailsTest() {
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 44b122c4e6..d31b46c602 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
@@ -103,7 +103,7 @@ public void testSummary() {
.body("routes[0].containsKey('segments')", is(true))
.body("routes[0].segments.size()", is(2))
.body("routes[0].summary.distance", is(14132.5f))
- .body("routes[0].summary.duration", is(3815.6f))
+ .body("routes[0].summary.duration", is(4115.6f))
.body("routes[0].summary.ascent", is(349.4f))
.body("routes[0].summary.descent", is(340))
.statusCode(200);
@@ -127,7 +127,7 @@ public void testSegmentDistances() {
.body("routes[0].segments[0].distance", is(7199.4f))
.body("routes[0].segments[0].duration", is(2597.4f))
.body("routes[0].segments[1].distance", is(6933.1f))
- .body("routes[0].segments[1].duration", is(1218.2f))
+ .body("routes[0].segments[1].duration", is(1518.2f))
.statusCode(200);
}
@@ -408,6 +408,7 @@ public void testTollwaysExtraDetails() {
.param("instructions", "true")
.param("preference", "fastest")
.param("profile", "driving-hgv")
+ .param("continue_straight", "false")
.param("options", "{\"profile_params\":{\"width\":\"2\",\"height\":\"2\",\"weight\":\"14\"},\"vehicle_type\":\"hgv\"}")
.param("extra_info", "suitability|tollways")
.when()
diff --git a/openrouteservice/WebContent/WEB-INF/app.config.sample b/openrouteservice/WebContent/WEB-INF/app.config.sample
index 3ee877b2ae..032a3de2b1 100644
--- a/openrouteservice/WebContent/WEB-INF/app.config.sample
+++ b/openrouteservice/WebContent/WEB-INF/app.config.sample
@@ -1,66 +1,88 @@
{
ors {
- # The topmost element for parameterization of ORS end-points such as Routing, Geocoding, Isochrones, etc.
+ # The topmost element for parameterization of the ORS end-points such as Routing, Geocoding, Isochrones, etc.
services: {
- # An end-point used to shorten links.
+ # ********************************************************************************************************************
+ # An end-point used to shorten links.
+ # ********************************************************************************************************************
shortenlink: {
- # Enables or disables (true/false) the end-point. Default value is true.
+ # Enables or disables (true/false) the end-point. Default value is true.
enabled: true,
user_name: YOUR_USER,
user_password: YOUR_PASSWORD,
api_key: YOUR_API_KEY,
}
+ # ********************************************************************************************************************
# Accessibility API end-point parameters
# NOTE: not ready for production yet.
+ # ********************************************************************************************************************
accessibility: {
- # Enables or disables (true/false) the end-point. Default value is true.
- enabled: true,
- maximum_range_distance: 120000,
- maximum_range_time: 3600,
- maximum_locations: 2,
- route_details_allowed: true,
- attribution: "openrouteservice.org, OpenStreetMap contributors"
- }
+ # Enables or disables (true/false) the end-point. Default value is true.
+ enabled: true,
+ # Possible values for maximum_range_distance and maximum_range_time are an integer or a list of values specifically defined for each profile.
+ maximum_range_distance:
+ [
+ { profiles: "any", value: 50000 }
+ { profiles: "driving-car, driving-hgv", value: 100000 }
+ ],
+ maximum_range_time:
+ [
+ { profiles: "any", value: 18000 }
+ { profiles: "driving-car, driving-hgv", value: 3600 }
+ ],
+ maximum_locations: 2,
+ route_details_allowed: true,
+ attribution: "openrouteservice.org, OpenStreetMap contributors"
+ }
+ # ********************************************************************************************************************
# Matrix API end-point parameters
- matrix: {
- # Enables or disables (true/false) the end-point. Default value is true.
- enabled: true,
+ # ********************************************************************************************************************
+ matrix: {
+ # Enables or disables (true/false) the end-point. Default value is true.
+ enabled: true,
# Maximum dimension of the result matrix. In other words, the maximum possible length of a row or a column in the matrix.
# Default value is 100.
- maximum_locations: 100,
+ maximum_locations: 100,
# Maximum allowed distance between the requested coordinate and a point on the nearest road. The value is measured in meters.
- maximum_search_radius: 5000,
+ maximum_search_radius: 5000,
# Maximum allowed number of visited nodes in shortest path computation. This threshold is applied only for Dijkstra algorithm.
- maximum_visited_nodes: 100000,
+ maximum_visited_nodes: 100000,
# Specifies whether the name of a neares street to the location can be resolved or not. Default value is true.
- allow_resolve_locations: true,
- attribution: "openrouteservice.org, OpenStreetMap contributors"
- }
+ allow_resolve_locations: true,
+ attribution: "openrouteservice.org, OpenStreetMap contributors"
+ }
+ # ********************************************************************************************************************
# Optimization API end-point parameters
- # NOTE: not ready for production yet.
- optimization: {
- # Enables or disables (true/false) the end-point. Default value is true.
- enabled: true,
- maximum_locations: 200,
- solver_name: "default",
- solver_options:
- {
- }
- attribution: "openrouteservice.org, OpenStreetMap contributors"
- }
+ # NOTE: not implemented yet.
+ # ********************************************************************************************************************
+ optimization: {
+ # Enables or disables (true/false) the end-point. Default value is true.
+ enabled: true,
+ maximum_locations: 200,
+ solver_name: "default",
+ solver_options:
+ {
+ },
+ attribution: "openrouteservice.org, OpenStreetMap contributors"
+ }
+ # ********************************************************************************************************************
# MapMatching API end-point parameters
# NOTE: not implemented yet.
- mapmatching: {
- # Enables or disables (true/false) the end-point. Default value is true.
- enabled: true,
- maximum_locations: 100,
- maximum_search_radius: 200,
- maximum_visited_nodes: 10000,
- attribution: "openrouteservice.org, OpenStreetMap contributors"
- }
+ # ********************************************************************************************************************
+ mapmatching: {
+ # Enables or disables (true/false) the end-point. Default value is true.
+ enabled: true,
+ maximum_locations: 100,
+ maximum_search_radius: 200,
+ maximum_visited_nodes: 10000,
+ attribution: "openrouteservice.org, OpenStreetMap contributors"
+ }
+ # ********************************************************************************************************************
# Isochrones API end-point parameters
+ # ********************************************************************************************************************
isochrones: {
- # Enables or disables (true/false) the end-point.
+ # Enables or disables (true/false) the end-point. Default value is true.
+ enabled: true,
# Possible values for maximum_range_distance and maximum_range_time are an integer or a list of values specifically defined for each profile.
maximum_range_distance:
[
@@ -72,26 +94,41 @@
{ profiles: "any", value: 18000 }
{ profiles: "driving-car, driving-hgv", value: 3600 }
],
+ # Maximum number of intervals/isochrones computed for each location.
maximum_intervals: 10,
+ # Maximum number of locations in one request.
maximum_locations: 2,
+ # Speficies whether area computation by setting "attributes=area" is allowed or not.
allow_compute_area: true,
attribution: "openrouteservice.org, OpenStreetMap contributors"
}
+ # ********************************************************************************************************************
# Geocoding API end-point parameters
+ # ********************************************************************************************************************
geocoding: {
# Enables or disables (true/false) the end-point. Default value is true.
- geocoder_name: pelias,
- geocoding_url: "http://YOUR_ADDRESS/v1/search",
- reverse_geocoding_url: "http://YOUR_ADDRESS/v1/reverse",
- response_limit: 20,
- user_agent: OpenRouteService,
- attribution: "openrouteservice.org, OpenStreetMap contributors"
- }
+ enabled: true,
+ # The name of a geocoder. Possible values are nomimatim, pelias or photon.
+ geocoder_name: pelias,
+ # URL for forward geocoding.
+ geocoding_url: "http://YOUR_ADDRESS/v1/search",
+ # URL for reverse geocoding.
+ reverse_geocoding_url: "http://YOUR_ADDRESS/v1/reverse",
+ # The maximum allowed number of returned results.
+ response_limit: 20,
+ # Sets the value of the User-agent HTTP header sent to a backend.
+ user_agent: OpenRouteService,
+ attribution: "openrouteservice.org, OpenStreetMap contributors"
+ }
+ # ********************************************************************************************************************
# Locations API end-point parameters
+ # ********************************************************************************************************************
locations: {
# Enables or disables (true/false) the end-point. Default value is true.
enabled: true,
+ # Defines the provider name of the Locations API backend. Possible values are postgreql, memsql (not finished).
provider_name: postgresql,
+ # Connection parameters of the provider.
provider_parameters: {
host: "YOUR_HOST",
port: 5432,
@@ -100,89 +137,106 @@
password : "YOUR_PASSWORD",
table_name : "YOUR_TABLE"
},
+ # The maximum allowed number of returned results.
response_limit: 1000,
+ # The maximum allowed number of categories specifed in a request.
maximum_categories: 5,
- # maximum allowed length of a linestring, measured in meters
+ # The maximum allowed length of a linestring, measured in meters.
maximum_feature_length: 10000000,
- # maximum allowed area of a polygon, measured in square meters
+ # The maximum allowed area of a polygon, measured in square meters
maximum_feature_area: -1,
- # maximum allowed search radius
+ # The maximum allowed search radius, measured in meters.
maximum_search_radius_for_points: 50000,
maximum_search_radius_for_linestrings: 2000,
maximum_search_radius_for_polygons: 1000,
attribution: "openrouteservice.org, OpenStreetMap contributors"
}
+ # ********************************************************************************************************************
# Routing API end-point parameters
+ # ********************************************************************************************************************
routing: {
# Enables or disables (true/false) the end-point. Default value is true.
enabled: true,
mode: "normal",
+ # The path to an OpenStreetMap data file.
sources: ["openrouteservice/src/main/files/heidelberg.osm.gz"],
+ # The number of threads used to initialize (build/load) graphs. Higher numbers requires more RAM.
init_threads: 2,
attribution: "openrouteservice.org, OpenStreetMap contributors",
+ # Defines a set of routing profiles.
profiles: {
+ # Defines a list of active routing profiles. The element name XXX must correspond to a notation "profile-XXX", which is used in the following sections.
active: ["vehicles", "bike", "bike2", "pedestrian"],
+ # Set parameters that is applied to every profile by default.
default_params: {
+ # The number of bytes used for FlagEncoders.
encoder_flags_size: 8,
+ # The root path to a directory for storing graphs.
graphs_root_path: "graphs",
+ # The name of an elevation provider. Possible values are cgiar and srtm.
elevation_provider: cgiar,
+ # The path to a directory in which SRTM tiles will be stored.
elevation_cache_path: "cgiar_provider",
- instructions: true,
- maximum_distance: 100000,
- maximum_segment_distance_with_dynamic_weights: 50000,
- maximum_waypoints: 50,
-
- preparation:
- {
- min_network_size: 200,
- min_one_way_network_size: 200,
+ # Specifies whether way names will be stored during the import or not.
+ instructions: true,
+ # The maximum allowed total distance of a route.
+ maximum_distance: 100000,
+ # The maximum allowed distance between two way points when dynamic weights are used.
+ maximum_segment_distance_with_dynamic_weights: 50000,
+ # The maximum number of way points in a request.
+ maximum_waypoints: 50,
+
+ # The parameters for the pre-processing stage.
+ preparation: {
+ min_network_size: 200,
+ min_one_way_network_size: 200,
- methods:
- {
- lm:
- {
- enabled: true,
- threads: 1,
- weightings: "fastest|shortest",
- landmarks: 16
- }
+ methods: {
+ # Landmarks
+ lm: {
+ # Enables or disables landmarks features.
+ enabled: true,
+ # The number of threads used to compute landmarks.
+ threads: 1,
+ # A pipe (|) separated list of weightings used for Landmarks.
+ weightings: "fastest|shortest",
+ # The number of landmarks.
+ landmarks: 16
}
}
- execution:
- {
- methods:
- {
- lm:
- {
- disabling_allowed: true,
- active_landmarks: 8
- }
+ }
+ # The parameters for the execution stage.
+ execution: {
+ methods: {
+ lm: {
+ disabling_allowed: true,
+ active_landmarks: 8
}
}
+ }
},
+ # ====================================================================================================================
+ # Vehicle profiles
+ # ====================================================================================================================
profile-vehicles: {
profiles: "driving-car,driving-hgv,driving-motorcycle",
parameters: {
- encoder_flags_size: 8,
- encoder_options : "turn_costs=true|block_fords=false,turn_costs=true|block_fords=false,turn_costs=true|block_fords=false",
- maximum_distance: 100000,
- elevation: true,
- # parameters for the pre-processing stage
- preparation:
- {
- min_network_size: 200,
- min_one_way_network_size: 200,
-
- methods:
- {
- ch:
- {
+ encoder_flags_size: 8,
+ # List of options used by FlagEncoders.
+ encoder_options : "turn_costs=true|block_fords=false,turn_costs=true|block_fords=false,turn_costs=true|block_fords=false",
+ maximum_distance: 100000,
+ elevation: true,
+ preparation: {
+ min_network_size: 200,
+ min_one_way_network_size: 200,
+
+ methods: {
+ ch: {
enabled: true,
threads: 1,
weightings: "fastest"
},
- lm:
- {
+ lm: {
enabled: true,
threads: 1,
weightings: "fastest|shortest",
@@ -190,79 +244,84 @@
}
}
}
- # parameters for pre-processing the execution stage
- execution:
- {
- methods:
- {
- # Contraction hierachies
- ch:
- {
+ execution: {
+ methods: {
+ # Contraction hierachies
+ ch: {
disabling_allowed: true
},
# Landmarks
- lm:
- {
+ lm: {
disabling_allowed: true,
active_landmarks: 8
}
}
}
- ext_storages: {
- WayCategory: { },
- HeavyVehicle: {
+ # The list of custom storages that store additional attribtues for graph edges.
+ ext_storages: {
+ WayCategory: { },
+ HeavyVehicle: {
restrictions: true
- },
+ },
WaySurfaceType: { }
- }
+ }
# Traffic feature is not ready for production.
- traffic: false
- }
+ traffic: false
+ }
}
+ # ====================================================================================================================
+ # Cycling profiles
+ # ====================================================================================================================
profile-bike: {
profiles: "cycling-regular, cycling-mountain, cycling-road",
parameters: {
- # extent: [5.866240, 15.042050, 47.270210, 55.058140], #
- encoder_options :"consider_elevation=true|turn_costs=true|block_fords=false,consider_elevation=true|turn_costs=true|block_fords=false,consider_elevation=true|turn_costs=true|block_fords=false",
- elevation: true,
- ext_storages: {
- WayCategory: { },
+ # extent: [5.866240, 15.042050, 47.270210, 55.058140], #
+ encoder_options :"consider_elevation=true|turn_costs=true|block_fords=false,consider_elevation=true|turn_costs=true|block_fords=false,consider_elevation=true|turn_costs=true|block_fords=false",
+ elevation: true,
+ ext_storages: {
+ WayCategory: { },
WaySurfaceType: { },
HillIndex: { },
TrailDifficulty: { }
- }
+ }
}
}
+ # ====================================================================================================================
+ # Cycling profiles
+ # ====================================================================================================================
profile-bike2: {
profiles: "cycling-safe,cycling-tour, cycling-electric",
parameters: {
- encoder_options: "consider_elevation=true|turn_costs=true|block_fords=false,consider_elevation=true|turn_costs=true|block_fords=false,consider_elevation=true|turn_costs=true|block_fords=false",
- elevation: true,
- ext_storages: {
- WayCategory: { },
+ encoder_options: "consider_elevation=true|turn_costs=true|block_fords=false,consider_elevation=true|turn_costs=true|block_fords=false,consider_elevation=true|turn_costs=true|block_fords=false",
+ elevation: true,
+ ext_storages: {
+ WayCategory: { },
WaySurfaceType: { },
HillIndex: { },
TrailDifficulty: { }
- }
+ }
}
}
+ # ====================================================================================================================
+ # Walking profiles
+ # ====================================================================================================================
profile-pedestrian: {
profiles: "foot-walking,foot-hiking",
parameters: {
- encoder_options: "block_fords=false,block_fords=false",
- elevation: true,
- ext_storages: {
- #GreenIndex: {
- # filepath: "PATH/TO/THE_GREEN_INDEX_CSV_FILE"
- #},
- #NoiseIndex: {
- # filepath: "PATH/TO/THE_NOISE_INDEX_CSV_FILE"
- #},
- WayCategory: { },
+ encoder_options: "block_fords=false,block_fords=false",
+ elevation: true,
+ ext_storages: {
+ #GreenIndex: {
+ # filepath: "PATH/TO/THE_GREEN_INDEX_CSV_FILE"
+ #},
+ #NoiseIndex: {
+ # filepath: "PATH/TO/THE_NOISE_INDEX_CSV_FILE"
+ #},
+ WayCategory: { },
WaySurfaceType: { },
HillIndex: { },
TrailDifficulty: { }
- }
+ }
}
}
}
@@ -282,10 +341,15 @@
}
}
}
+ # Logging configuration
logging: {
+ # Enables or disables logging. Default value is true.
enabled: true,
+ # The path to a file containing logging parameters.
level_file: "DEBUG_LOGGING.properties",
+ # The path to a directory to which logs will be written.
location: "./logs",
+ # Enables/disables writing logs to STDOUT.
stdout: true
}
}
diff --git a/openrouteservice/docs/services/isochrones/eurostat/age_groups_mappings.txt b/openrouteservice/docs/services/isochrones/eurostat/age_groups_mappings.txt
new file mode 100644
index 0000000000..3790aca6ed
--- /dev/null
+++ b/openrouteservice/docs/services/isochrones/eurostat/age_groups_mappings.txt
@@ -0,0 +1,63 @@
+"t_a-total":"pop_total",
+"t_a-lt5":"pop_lt5",
+"t_a-5_9":"pop_5-9",
+"t_a-10_14":"pop_10-14",
+"t_a-15_19":"pop_15-19",
+"t_a-20_24":"pop_20-24",
+"t_a-25_29":"pop_25-29",
+"t_a-30_34":"pop_30-34",
+"t_a-35_39":"pop_35-39",
+"t_a-40_44":"pop_40-44",
+"t_a-45_49":"pop_45-49",
+"t_a-50_54":"pop_50-54",
+"t_a-55_59":"pop_55-59",
+"t_a-60_64":"pop_60-64",
+"t_a-65_69":"pop_65-69",
+"t_a-70_74":"pop_70-74",
+"t_a-75_79":"pop_75-79",
+"t_a-80_84":"pop_80-84",
+"t_a-85_89":"pop_85-89",
+"t_a-ge85":"pop_ge85",
+"t_a-ge90":"pop_ge90",
+"m_a-total":"pop_male_total",
+"m_a-lt5":"pop_male_lt5",
+"m_a-5_9":"pop_male_5-9",
+"m_a-10_14":"pop_male_10-14",
+"m_a-15_19":"pop_male_15-19",
+"m_a-20_24":"pop_male_20-24",
+"m_a-25_29":"pop_male_25-29",
+"m_a-30_34":"pop_male_30-34",
+"m_a-35_39":"pop_male_35-39",
+"m_a-40_44":"pop_male_40-44",
+"m_a-45_49":"pop_male_45-49",
+"m_a-50_54":"pop_male_50-54",
+"m_a-55_59":"pop_male_55-59",
+"m_a-60_64":"pop_male_60-64",
+"m_a-65_69":"pop_male_65-69",
+"m_a-70_74":"pop_male_70-74",
+"m_a-75_79":"pop_male_75-79",
+"m_a-80_84":"pop_male_80-84",
+"m_a-85_89":"pop_male_85-89",
+"m_a-ge85":"pop_male_ge85",
+"m_a-ge90":"pop_male_ge90",
+"f_a-total":"pop_female_total",
+"f_a-lt5":"pop_female_lt5",
+"f_a-5_9":"pop_female_5-9",
+"f_a-10_14":"pop_female_10-14",
+"f_a-15_19":"pop_female_15-19",
+"f_a-20_24":"pop_female_20-24",
+"f_a-25_29":"pop_female_25-29",
+"f_a-30_34":"pop_female_30-34",
+"f_a-35_39":"pop_female_35-39",
+"f_a-40_44":"pop_female_40-44",
+"f_a-45_49":"pop_female_45-49",
+"f_a-50_54":"pop_female_50-54",
+"f_a-55_59":"pop_female_55-59",
+"f_a-60_64":"pop_female_60-64",
+"f_a-65_69":"pop_female_65-69",
+"f_a-70_74":"pop_female_70-74",
+"f_a-75_79":"pop_female_75-79",
+"f_a-80_84":"pop_female_80-84",
+"f_a-85_89":"pop_female_85-89",
+"f_a-ge85":"pop_female_ge85",
+"f_a-ge90":"pop_female_ge90"
diff --git a/openrouteservice/docs/services/isochrones/eurostat/example_query.sql b/openrouteservice/docs/services/isochrones/eurostat/example_query.sql
new file mode 100644
index 0000000000..bb6bd1eac1
--- /dev/null
+++ b/openrouteservice/docs/services/isochrones/eurostat/example_query.sql
@@ -0,0 +1,12 @@
+SELECT Round(SUM(c.ratio * c.%%column_name%%))
+FROM (
+ SELECT St_area(St_intersection(a.geog,poly)) / St_area(a.geog) ratio,
+ a.*
+ FROM geostat_grd_2016_ageclasses_nuts a,
+ %%wkb_geom%%
+ WHERE a.gid IN
+ (
+ SELECT a.gid
+ FROM geostat_grd_2016_ageclasses_nuts a,
+ %%wkb_geom%%
+ WHERE st_intersects (a.geog, poly))) AS c;
diff --git a/openrouteservice/pom.xml b/openrouteservice/pom.xml
index b89822df0c..179ec9f5c6 100644
--- a/openrouteservice/pom.xml
+++ b/openrouteservice/pom.xml
@@ -5,14 +5,14 @@
4.0.0
heigit.ors
openrouteservice
- 4.2.2
+ 4.3.0
war
OpenRouteService
openrouteservice.org
2017
- GitLab
- https://gitlab.gistools.geog.uni-heidelberg.de/giscience/openrouteservice/core/issues
+ GitHub
+ https://github.com/GIScience/openrouteservice/issues
UTF-8
@@ -178,12 +178,12 @@
3.0.3
-
+
com.github.GIScience
graphhopper
- v0.9.2
+ v0.9.3
-
+
com.typesafe
config
diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteResultBuilder.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteResultBuilder.java
index 8218ad60e8..b475efc82e 100644
--- a/openrouteservice/src/main/java/heigit/ors/routing/RouteResultBuilder.java
+++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteResultBuilder.java
@@ -196,6 +196,10 @@ public RouteResult createRouteResult(List routes, RoutingRequest req
RoundaboutInstruction raInstr = (RoundaboutInstruction)instr;
step.setExitNumber(raInstr.getExitNumber());
instrText = instrTranslator.getRoundabout(raInstr.getExitNumber(), roadName);
+ if (raInstr.getRoundaboutExitBearings() != null)
+ {
+ step.setRoundaboutExitBearings(raInstr.getRoundaboutExitBearings());
+ }
}
else
{
diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteStep.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteStep.java
index abf85a0948..e98cb12168 100644
--- a/openrouteservice/src/main/java/heigit/ors/routing/RouteStep.java
+++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteStep.java
@@ -32,6 +32,7 @@ public class RouteStep
private int _type;
private int[] _wayPoints;
private RouteStepManeuver _maneuver;
+ private int[] _roundaboutExitBearings;
public double getDuration() {
return _duration;
@@ -112,4 +113,12 @@ public RouteStepManeuver getManeuver() {
public void setManeuver(RouteStepManeuver maneuver) {
_maneuver = maneuver;
}
+
+ public int[] getRoundaboutExitBearings() {
+ return _roundaboutExitBearings;
+ }
+
+ public void setRoundaboutExitBearings(int[] roundaboutExitBearings) {
+ _roundaboutExitBearings = roundaboutExitBearings;
+ }
}
diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java
index f79bb88517..7542436b78 100644
--- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java
+++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java
@@ -84,7 +84,6 @@
import com.graphhopper.reader.dem.ElevationProvider;
import com.graphhopper.routing.util.DefaultEdgeFilter;
import com.graphhopper.routing.util.EdgeFilter;
-import com.graphhopper.routing.util.EdgeFilterSequence;
import com.graphhopper.routing.util.EncodingManager;
import com.graphhopper.routing.util.FlagEncoder;
import com.graphhopper.routing.util.HintsMap;
@@ -767,7 +766,7 @@ public boolean canProcessRequest(double totalDistance, double longestSegmentDist
return totalDistance <= maxDistance && wayPoints <= maxWayPoints;
}
- public GHResponse computeRoute(double lat0, double lon0, double lat1, double lon1, boolean directedSegment, RouteSearchParameters searchParams, EdgeFilter customEdgeFilter, boolean simplifyGeometry, RouteProcessContext routeProcCntx)
+ public GHResponse computeRoute(double lat0, double lon0, double lat1, double lon1, double heading, boolean directedSegment, RouteSearchParameters searchParams, EdgeFilter customEdgeFilter, boolean simplifyGeometry, RouteProcessContext routeProcCntx)
throws Exception {
GHResponse resp = null;
@@ -782,12 +781,17 @@ public GHResponse computeRoute(double lat0, double lon0, double lat1, double lon
RouteSearchContext searchCntx = createSearchContext(searchParams, RouteSearchMode.Routing, customEdgeFilter);
boolean flexibleMode = searchParams.getFlexibleMode();
- GHRequest req = new GHRequest(new GHPoint(lat0, lon0), new GHPoint(lat1, lon1));
+ GHRequest req = null;
+ if (heading == Double.MIN_VALUE)
+ req = new GHRequest(new GHPoint(lat0, lon0), new GHPoint(lat1, lon1));
+ else
+ req = new GHRequest(new GHPoint(lat0, lon0), new GHPoint(lat1, lon1), heading, Double.NaN);
+
req.setVehicle(searchCntx.getEncoder().toString());
req.setMaxSpeed(searchParams.getMaximumSpeed());
req.setSimplifyGeometry(simplifyGeometry);
req.setAlgorithm("dijkstrabi");
-
+
PMap props = searchCntx.getProperties();
if (props != null && props.size() > 0)
req.getHints().merge(props);
@@ -826,7 +830,7 @@ else if (weightingMethod == WeightingMethod.RECOMMENDED)
flexibleMode = true;
}
-
+
if (RoutingProfileType.isDriving(profileType) && RealTrafficDataProvider.getInstance().isInitialized())
req.setEdgeAnnotator(new TrafficEdgeAnnotator(mGraphHopper.getGraphHopperStorage()));
@@ -849,6 +853,13 @@ else if (weightingMethod == WeightingMethod.RECOMMENDED)
req.getHints().put("ch.disable", true);
}
+ if (profileType == RoutingProfileType.DRIVING_EMERGENCY)
+ {
+ req.getHints().put("custom_weightings", true);
+ req.getHints().put("weighting_#acceleration#", true);
+ req.getHints().put("lm.disable", true); // REMOVE
+ }
+
if (_astarEpsilon != null)
req.getHints().put("astarbi.epsilon", _astarEpsilon);
if (_astarApproximation != null)
diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java
index de8b08eae7..fabfa18723 100644
--- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java
+++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java
@@ -66,6 +66,7 @@
import com.graphhopper.storage.RAMDataAccess;
import com.graphhopper.util.DistanceCalc;
import com.graphhopper.util.Helper;
+import com.graphhopper.util.PointList;
import com.vividsolutions.jts.geom.Coordinate;
public class RoutingProfileManager {
@@ -289,9 +290,9 @@ public List computeRoutes(RoutingRequest req, boolean invertFlow, b
Coordinate c1 = coords[i];
GHResponse gr = null;
if (invertFlow)
- gr = rp.computeRoute(c0.y, c0.x, c1.y, c1.x, false, searchParams, customEdgeFilter, req.getSimplifyGeometry(), routeProcCntx);
+ gr = rp.computeRoute(c0.y, c0.x, c1.y, c1.x, 0.0, false, searchParams, customEdgeFilter, req.getSimplifyGeometry(), routeProcCntx);
else
- gr = rp.computeRoute(c1.y, c1.x, c0.y, c0.x, false, searchParams, customEdgeFilter, req.getSimplifyGeometry(), routeProcCntx);
+ gr = rp.computeRoute(c1.y, c1.x, c0.y, c0.x, 0.0, false, searchParams, customEdgeFilter, req.getSimplifyGeometry(), routeProcCntx);
//if (gr.hasErrors())
// throw new InternalServerException(RoutingErrorCodes.UNKNOWN, String.format("Unable to find a route between points %d (%s) and %d (%s)", i, FormatUtility.formatCoordinate(c0), i + 1, FormatUtility.formatCoordinate(c1)));
@@ -345,7 +346,8 @@ public RouteResult computeRoute(RoutingRequest req) throws Exception
int nSegments = coords.length - 1;
RouteProcessContext routeProcCntx = new RouteProcessContext(pathProcessor);
EdgeFilter customEdgeFilter = rp.createAccessRestrictionFilter(coords);
-
+ GHResponse prevResp = null;
+
for(int i = 1; i <= nSegments; ++i)
{
c1 = coords[i];
@@ -353,11 +355,16 @@ public RouteResult computeRoute(RoutingRequest req) throws Exception
if (pathProcessor != null)
pathProcessor.setSegmentIndex(i - 1, nSegments);
- GHResponse gr = rp.computeRoute(c0.y, c0.x, c1.y, c1.x, c0.z == 1.0, searchParams, customEdgeFilter, req.getSimplifyGeometry(), routeProcCntx);
-
+ double heading = Double.MIN_VALUE;
+ if (i > 1 && req.getContinueStraight())
+ heading = getHeadingDirection(prevResp);
+
+ GHResponse gr = rp.computeRoute(c0.y, c0.x, c1.y, c1.x, heading, c0.z == 1.0, searchParams, customEdgeFilter, req.getSimplifyGeometry(), routeProcCntx);
+
if (gr.hasErrors())
throw new InternalServerException(RoutingErrorCodes.UNKNOWN, String.format("Unable to find a route between points %d (%s) and %d (%s)", i, FormatUtility.formatCoordinate(c0), i + 1, FormatUtility.formatCoordinate(c1)));
+ prevResp = gr;
routes.add(gr);
c0 = c1;
}
@@ -365,6 +372,22 @@ public RouteResult computeRoute(RoutingRequest req) throws Exception
return new RouteResultBuilder().createRouteResult(routes, req, (pathProcessor != null && (pathProcessor instanceof ExtraInfoProcessor)) ? ((ExtraInfoProcessor)pathProcessor).getExtras(): null);
}
+ private double getHeadingDirection(GHResponse resp)
+ {
+ PointList points = resp.getBest().getPoints();
+ int nPoints = points.size();
+ if (nPoints > 1)
+ {
+ double lon1 = points.getLon(nPoints - 2);
+ double lat1 = points.getLat(nPoints - 2);
+ double lon2 = points.getLon(nPoints - 1);
+ double lat2 = points.getLat(nPoints - 1);
+ return Helper.ANGLE_CALC.calcAzimuth(lat1, lon1, lat2, lon2);
+ }
+ else
+ return 0;
+ }
+
public RoutingProfile getRouteProfile(RoutingRequest req, boolean oneToMany) throws Exception {
RouteSearchParameters searchParams = req.getSearchParameters();
int profileType = searchParams.getProfileType();
diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingRequest.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingRequest.java
index 4aedb47083..5cdb0972fe 100644
--- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingRequest.java
+++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingRequest.java
@@ -37,10 +37,12 @@ public class RoutingRequest extends ServiceRequest
private Boolean _includeElevation = false;
private Boolean _includeGeometry = true;
private Boolean _includeManeuvers = false;
+ private boolean _includeRoundaboutExits = false;
private Boolean _simplifyGeometry = false;
private String[] _attributes = null;
private int _extraInfo;
private int _locationIndex = -1;
+ private boolean _continueStraight = true;
public RoutingRequest()
{
@@ -179,4 +181,20 @@ public Boolean getIncludeManeuvers() {
public void setIncludeManeuvers(Boolean includeManeuvers) {
_includeManeuvers = includeManeuvers;
}
+
+ public boolean getContinueStraight() {
+ return _continueStraight;
+ }
+
+ public void setContinueStraight(boolean continueStraight) {
+ _continueStraight = continueStraight;
+ }
+
+ public boolean getIncludeRoundaboutExits() {
+ return _includeRoundaboutExits;
+ }
+
+ public void setIncludeRoundaboutExits(boolean includeRoundaboutExits) {
+ _includeRoundaboutExits = includeRoundaboutExits;
+ }
}
diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSWeightingFactory.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSWeightingFactory.java
index 2764eb9846..5ad24d2aec 100644
--- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSWeightingFactory.java
+++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSWeightingFactory.java
@@ -156,6 +156,9 @@ else if ("recommended".equalsIgnoreCase(strWeighting))
case "quiet":
softWeightings.add(new QuietWeighting(encoder, getWeightingProps(weightingName, map), graphStorage));
break;
+ case "acceleration":
+ softWeightings.add(new AccelerationWeighting(encoder, getWeightingProps(weightingName, map), graphStorage));
+ break;
}
}
diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/EdgeFilterSequence.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/EdgeFilterSequence.java
new file mode 100644
index 0000000000..0dea1415cf
--- /dev/null
+++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/EdgeFilterSequence.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to GIScience Research Group, Heidelberg University (GIScience)
+ *
+ * http://www.giscience.uni-hd.de
+ * http://www.heigit.org
+ *
+ * under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright
+ * ownership. The GIScience licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package heigit.ors.routing.graphhopper.extensions.edgefilters;
+
+import java.util.ArrayList;
+
+import com.graphhopper.routing.util.EdgeFilter;
+import com.graphhopper.util.EdgeIteratorState;
+
+public class EdgeFilterSequence implements EdgeFilter {
+
+ private ArrayList edgeFilters;
+ private int filtersCount;
+
+ /**
+ * Creates an edges filter which accepts both direction of the specified
+ * vehicle.
+ */
+ public EdgeFilterSequence(ArrayList edgeFilters) {
+ this.edgeFilters = edgeFilters;
+ this.filtersCount = edgeFilters.size();
+ }
+
+ public void addFilter(EdgeFilter e) {
+ edgeFilters.add(e);
+ filtersCount++;
+ }
+
+ public EdgeFilter getEdgeFilter(Class> type)
+ {
+ for (int i = 0; i < filtersCount; i++) {
+ if (type.isAssignableFrom(edgeFilters.get(i).getClass()))
+ return edgeFilters.get(i);
+ }
+
+ return null;
+ }
+
+ public boolean containsEdgeFilter(Class> type)
+ {
+ for (int i = 0; i < filtersCount; i++) {
+ if (type.isAssignableFrom(edgeFilters.get(i).getClass()))
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override
+ public final boolean accept(EdgeIteratorState iter) {
+ for (int i = 0; i < filtersCount; i++) {
+ if (!edgeFilters.get(i).accept(iter))
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "EdgeFilter Sequence :" + filtersCount;
+ }
+}
diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/EmergencyFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/EmergencyFlagEncoder.java
index c16e1e84ce..a781681340 100644
--- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/EmergencyFlagEncoder.java
+++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/EmergencyFlagEncoder.java
@@ -258,7 +258,9 @@ public double getMaxSpeed(ReaderWay way ) // runge
if (backSpeed >= 0 && (maxSpeed < 0 || backSpeed < maxSpeed))
maxSpeed = backSpeed;
*/
- String maxspeedTag = way.getTag("maxspeed");
+ String maxspeedTag = way.getTag("maxspeed:hgv");
+ if (Helper.isEmpty(maxspeedTag))
+ maxspeedTag = way.getTag("maxspeed");
double maxSpeed = parseSpeed(maxspeedTag);
if (bCheckMaxSpeed)
diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/weighting/AccelerationWeighting.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/weighting/AccelerationWeighting.java
new file mode 100644
index 0000000000..3c1d58903d
--- /dev/null
+++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/weighting/AccelerationWeighting.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to GIScience Research Group, Heidelberg University (GIScience)
+ *
+ * http://www.giscience.uni-hd.de
+ * http://www.heigit.org
+ *
+ * under one or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information regarding copyright
+ * ownership. The GIScience licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package heigit.ors.routing.graphhopper.extensions.weighting;
+
+import com.graphhopper.routing.util.FlagEncoder;
+import com.graphhopper.routing.weighting.FastestWeighting;
+import com.graphhopper.storage.GraphHopperStorage;
+import com.graphhopper.storage.GraphStorage;
+import com.graphhopper.util.AngleCalc;
+import com.graphhopper.util.EdgeIteratorState;
+import com.graphhopper.util.PMap;
+import com.graphhopper.util.PointList;
+
+public class AccelerationWeighting extends FastestWeighting {
+ private GraphHopperStorage _ghStorage;
+ private AngleCalc _angleCalc = new AngleCalc();
+ private long _maxEdges;
+
+ public AccelerationWeighting(FlagEncoder encoder, PMap map, GraphStorage graphStorage) {
+ super(encoder, map);
+ _ghStorage = (GraphHopperStorage)graphStorage;
+ _maxEdges= _ghStorage.getEdges();
+ }
+
+ private double getTurnAngle(PointList currEdgeGeom, PointList prevEdgeGeom)
+ {
+ if (currEdgeGeom.size() >= 1 && prevEdgeGeom.size() >= 1)
+ {
+ int locIndex = prevEdgeGeom.size() - 1;
+ double lon0 = prevEdgeGeom.getLon(locIndex - 1);
+ double lat0 = prevEdgeGeom.getLat(locIndex - 1);
+ double lon1 = prevEdgeGeom.getLon(locIndex);
+ double lat1 = prevEdgeGeom.getLat(locIndex);
+
+ double bearingBefore = Math.round(_angleCalc.calcAzimuth(lat0, lon0, lat1, lon1));
+
+ double lon2 = currEdgeGeom.getLon(1);
+ double lat2 = currEdgeGeom.getLat(1);
+
+ double bearingAfter = (int)Math.round(_angleCalc.calcAzimuth(lat1, lon1, lat2, lon2));
+ //bearingAfter = _angleCalc.alignOrientation(bearingBefore, bearingAfter);
+ double res = Math.abs(bearingBefore - bearingAfter);
+ if (res > 180)
+ {
+ res = 360 - res;
+ return res;
+ }
+
+ return res;
+ }
+
+ return 0.0;
+ }
+
+ @Override
+ public double calcWeight(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId) {
+ if (prevOrNextEdgeId == -1 || edgeState.getEdge() >= _maxEdges || prevOrNextEdgeId >= _maxEdges)
+ {
+ //TODO
+ return 1.0;
+ }
+
+ PointList currEdgeGeom, prevEdgeGeom;
+ if (reverse)
+ {
+ prevEdgeGeom = _ghStorage.getEdgeIteratorState(edgeState.getEdge(), edgeState.getBaseNode()).fetchWayGeometry(3);
+ currEdgeGeom = _ghStorage.getEdgeIteratorState(prevOrNextEdgeId, edgeState.getBaseNode()).detach(true).fetchWayGeometry(3);
+ }
+ else
+ {
+ currEdgeGeom = _ghStorage.getEdgeIteratorState(edgeState.getEdge(), edgeState.getAdjNode()).fetchWayGeometry(3);
+ prevEdgeGeom = _ghStorage.getEdgeIteratorState(prevOrNextEdgeId, edgeState.getBaseNode()).fetchWayGeometry(3);
+ }
+
+ double turnAngle = getTurnAngle(currEdgeGeom, prevEdgeGeom);
+
+ if (isFullTurn(turnAngle))
+ {
+ // TODO
+ return 1.1;
+ }
+
+ return 1.0;
+ }
+
+ private boolean isFullTurn(double angle)
+ {
+ return angle > 50 && angle <= 140;
+ }
+
+ @Override
+ public long calcMillis(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId) {
+ if (prevOrNextEdgeId == -1 || edgeState.getEdge() >= _maxEdges || prevOrNextEdgeId >= _maxEdges)
+ {
+ // compute acceleration for departure and finish edges.
+ return (long)(0);
+ }
+
+ PointList currEdgeGeom, prevEdgeGeom;
+ if (reverse)
+ {
+ prevEdgeGeom = _ghStorage.getEdgeIteratorState(edgeState.getEdge(), edgeState.getBaseNode()).fetchWayGeometry(3);
+ currEdgeGeom = _ghStorage.getEdgeIteratorState(prevOrNextEdgeId, edgeState.getBaseNode()).detach(true).fetchWayGeometry(3);
+ }
+ else
+ {
+ currEdgeGeom = _ghStorage.getEdgeIteratorState(edgeState.getEdge(), edgeState.getAdjNode()).fetchWayGeometry(3);
+ prevEdgeGeom = _ghStorage.getEdgeIteratorState(prevOrNextEdgeId, edgeState.getBaseNode()).fetchWayGeometry(3);
+ }
+
+ double turnAngle = getTurnAngle(currEdgeGeom, prevEdgeGeom);
+
+ if (isFullTurn(turnAngle))
+ {
+ /*double speed = 1000*edgeState.getDistance()/weight * SPEED_CONV;
+ double distAfter = currEdgeGeom.calcDistance(Helper.DIST_EARTH);
+
+ // compute acceleration influence only for a segment after the turn.
+ int totalSeconds = (int)(weight/1000) + 100;
+ int accelTime = 0;
+ double accelDist = 0.0;
+
+ for (int i= 0; i < totalSeconds; ++i)
+ {
+ double currSpeed = (i + 1)* 2.5*0.3048;
+
+ accelTime = i + 1;
+ accelDist += currSpeed;
+
+ if (currSpeed >= speed/SPEED_CONV)
+ break;
+ if (accelDist > distAfter)
+ break;
+ }
+
+ accelTime *= 1000;
+ long fullSpeedTime = 0;
+ if (accelDist < distAfter)
+ {
+ fullSpeedTime = (long)((distAfter - accelDist)/speed * SPEED_CONV);
+ }
+
+ return (long)(-weight + accelTime + fullSpeedTime);*/
+
+ return (long)0;// 10 seconds for every turn
+ }
+
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/weighting/AdditionWeighting.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/weighting/AdditionWeighting.java
index eee50399f4..20017379d0 100644
--- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/weighting/AdditionWeighting.java
+++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/weighting/AdditionWeighting.java
@@ -51,6 +51,8 @@ else if (count == 5)
public abstract class WeightCalc
{
public abstract double calcWeight(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId);
+
+ public abstract long calcMillis(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId);
}
public class OneWeightCalc extends WeightCalc
@@ -66,6 +68,11 @@ public double calcWeight(EdgeIteratorState edgeState, boolean reverse, int prevO
{
return _weighting.calcWeight(edgeState, reverse, prevOrNextEdgeId);
}
+
+ public long calcMillis(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId)
+ {
+ return _weighting.calcMillis(edgeState, reverse, prevOrNextEdgeId);
+ }
}
public class TwoWeightCalc extends OneWeightCalc
@@ -82,6 +89,11 @@ public double calcWeight(EdgeIteratorState edgeState, boolean reverse, int prevO
{
return super.calcWeight(edgeState, reverse, prevOrNextEdgeId) + _weighting.calcWeight(edgeState, reverse, prevOrNextEdgeId);
}
+
+ public long calcMillis(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId)
+ {
+ return super.calcMillis(edgeState, reverse, prevOrNextEdgeId) + _weighting.calcMillis(edgeState, reverse, prevOrNextEdgeId);
+ }
}
public class ThreeWeightCalc extends TwoWeightCalc
@@ -98,6 +110,11 @@ public double calcWeight(EdgeIteratorState edgeState, boolean reverse, int prevO
{
return super.calcWeight(edgeState, reverse, prevOrNextEdgeId) + _weighting.calcWeight(edgeState, reverse, prevOrNextEdgeId);
}
+
+ public long calcMillis(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId)
+ {
+ return super.calcMillis(edgeState, reverse, prevOrNextEdgeId) + _weighting.calcMillis(edgeState, reverse, prevOrNextEdgeId);
+ }
}
public class FourWeightCalc extends ThreeWeightCalc
@@ -114,6 +131,11 @@ public double calcWeight(EdgeIteratorState edgeState, boolean reverse, int prevO
{
return super.calcWeight(edgeState, reverse, prevOrNextEdgeId) + _weighting.calcWeight(edgeState, reverse, prevOrNextEdgeId);
}
+
+ public long calcMillis(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId)
+ {
+ return super.calcMillis(edgeState, reverse, prevOrNextEdgeId) + _weighting.calcMillis(edgeState, reverse, prevOrNextEdgeId);
+ }
}
public class FiveWeightCalc extends FourWeightCalc
@@ -130,6 +152,11 @@ public double calcWeight(EdgeIteratorState edgeState, boolean reverse, int prevO
{
return super.calcWeight(edgeState, reverse, prevOrNextEdgeId) + _weighting.calcWeight(edgeState, reverse, prevOrNextEdgeId);
}
+
+ public long calcMillis(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId)
+ {
+ return super.calcMillis(edgeState, reverse, prevOrNextEdgeId) + _weighting.calcMillis(edgeState, reverse, prevOrNextEdgeId);
+ }
}
@Override
@@ -142,6 +169,11 @@ public double calcWeight(EdgeIteratorState edgeState, boolean reverse, int prevO
public double getMinWeight(double distance) {
return 0;
}
+
+ @Override
+ public long calcMillis(EdgeIteratorState edgeState, boolean reverse, int prevOrNextEdgeId) {
+ return _superWeighting.calcMillis(edgeState, reverse, prevOrNextEdgeId) + _weightCalc.calcMillis(edgeState, reverse, prevOrNextEdgeId);
+ }
@Override
public String getName() {
diff --git a/openrouteservice/src/main/java/heigit/ors/services/accessibility/AccessibilityServiceSettings.java b/openrouteservice/src/main/java/heigit/ors/services/accessibility/AccessibilityServiceSettings.java
index a973589ab5..9d749b1b24 100644
--- a/openrouteservice/src/main/java/heigit/ors/services/accessibility/AccessibilityServiceSettings.java
+++ b/openrouteservice/src/main/java/heigit/ors/services/accessibility/AccessibilityServiceSettings.java
@@ -20,14 +20,23 @@
*/
package heigit.ors.services.accessibility;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.typesafe.config.ConfigObject;
+
import heigit.ors.common.TravelRangeType;
import heigit.ors.config.AppConfig;
+import heigit.ors.routing.RoutingProfileType;
public class AccessibilityServiceSettings
{
private static int maximumLocations = 1;
private static int maximumRangeDistance = 100000; // in meters
+ private static Map profileMaxRangeDistances;
private static int maximumRangeTime = 3600; // in seconds
+ private static Map profileMaxRangeTimes;
private static boolean routeDetailsAllowed = false;
private static int responseLimit = 50;
private static String attribution = "";
@@ -44,9 +53,30 @@ public class AccessibilityServiceSettings
value = AppConfig.Global().getServiceParameter("accessibility", "maximum_range_distance");
if (value != null)
maximumRangeDistance = Integer.parseInt(value);
+ else
+ {
+ List extends ConfigObject> params = AppConfig.Global().getObjectList("accessibility", "maximum_range_distance");
+ if (params != null)
+ {
+ profileMaxRangeDistances = getParameters(params);
+ if (profileMaxRangeDistances.containsKey(-1))
+ maximumRangeDistance = profileMaxRangeDistances.get(-1);
+ }
+ }
+
value = AppConfig.Global().getServiceParameter("accessibility", "maximum_range_time");
if (value != null)
maximumRangeTime = Integer.parseInt(value);
+ else
+ {
+ List extends ConfigObject> params = AppConfig.Global().getObjectList("accessibility", "maximum_range_time");
+ if (params != null)
+ {
+ profileMaxRangeTimes = getParameters(params);
+ if (profileMaxRangeTimes.containsKey(-1))
+ maximumRangeTime = profileMaxRangeTimes.get(-1);
+ }
+ }
value = AppConfig.Global().getServiceParameter("accessibility", "route_details_allowed");
if (value != null)
routeDetailsAllowed = Boolean.parseBoolean(value);
@@ -58,6 +88,28 @@ public class AccessibilityServiceSettings
attribution = value;
}
+ private static Map getParameters(List extends ConfigObject> params)
+ {
+ Map result = new HashMap();
+
+ for(ConfigObject cfgObj : params)
+ {
+ if (cfgObj.containsKey("profiles") && cfgObj.containsKey("value"))
+ {
+ String[] profiles = cfgObj.toConfig().getString("profiles").split(",");
+ for (String profileStr : profiles)
+ {
+ profileStr = profileStr.trim();
+ Integer profile = ("any".equalsIgnoreCase(profileStr)) ? -1 : RoutingProfileType.getFromString(profileStr);
+ if (profile != RoutingProfileType.UNKNOWN)
+ result.put(profile, cfgObj.toConfig().getInt("value"));
+ }
+ }
+ }
+
+ return result;
+ }
+
public static Boolean getEnabled() {
return enabled;
}
@@ -70,16 +122,30 @@ public static int getMaximumLocations() {
return maximumLocations;
}
- public static int getMaximumRange(TravelRangeType range) {
+ public static int getMaximumRange(int profileType, TravelRangeType range) {
+ Integer res = 0;
+
switch(range)
{
case Distance:
- return maximumRangeDistance;
+ res = maximumRangeDistance;
+
+ if (profileMaxRangeDistances != null && profileMaxRangeDistances.containsKey(profileType))
+ {
+ res = profileMaxRangeDistances.get(profileType);
+ }
+ break;
case Time:
- return maximumRangeTime;
+ res = maximumRangeTime;
+
+ if (profileMaxRangeTimes != null && profileMaxRangeTimes.containsKey(profileType))
+ {
+ res = profileMaxRangeTimes.get(profileType);
+ }
+ break;
}
- return 0;
+ return res;
}
public static boolean getRouteDetailsAllowed()
diff --git a/openrouteservice/src/main/java/heigit/ors/services/accessibility/requestprocessors/json/JsonAccessibilityRequestProcessor.java b/openrouteservice/src/main/java/heigit/ors/services/accessibility/requestprocessors/json/JsonAccessibilityRequestProcessor.java
index 18ade402e1..40a1ce6fe5 100644
--- a/openrouteservice/src/main/java/heigit/ors/services/accessibility/requestprocessors/json/JsonAccessibilityRequestProcessor.java
+++ b/openrouteservice/src/main/java/heigit/ors/services/accessibility/requestprocessors/json/JsonAccessibilityRequestProcessor.java
@@ -36,9 +36,12 @@
import com.vividsolutions.jts.geom.Geometry;
import heigit.ors.accessibility.AccessibilityAnalyzer;
+import heigit.ors.accessibility.AccessibilityErrorCodes;
import heigit.ors.accessibility.AccessibilityRequest;
import heigit.ors.accessibility.AccessibilityResult;
import heigit.ors.common.StatusCode;
+import heigit.ors.common.TravellerInfo;
+import heigit.ors.exceptions.ParameterOutOfRangeException;
import heigit.ors.exceptions.StatusCodeException;
import heigit.ors.geojson.GeometryJSON;
import heigit.ors.services.accessibility.AccessibilityServiceSettings;
@@ -77,6 +80,20 @@ public void process(HttpServletResponse response) throws Exception
if (req == null)
throw new StatusCodeException(StatusCode.BAD_REQUEST, "AccessibilityRequest object is null.");
+
+ List travellers = req.getTravellers();
+
+ if (travellers.size() > AccessibilityServiceSettings.getMaximumLocations())
+ throw new ParameterOutOfRangeException(AccessibilityErrorCodes.PARAMETER_VALUE_EXCEEDS_MAXIMUM, "locations", Integer.toString(travellers.size()), Integer.toString(AccessibilityServiceSettings.getMaximumLocations()));
+
+ for (int i = 0;i < travellers.size(); ++i){
+ TravellerInfo traveller = travellers.get(i);
+ int maxAllowedRange = AccessibilityServiceSettings.getMaximumRange(traveller.getRouteSearchParameters().getProfileType(), traveller.getRangeType());
+ double maxRange = traveller.getMaximumRange();
+ if (maxRange > maxAllowedRange)
+ throw new ParameterOutOfRangeException(AccessibilityErrorCodes.PARAMETER_VALUE_EXCEEDS_MAXIMUM, "range", Integer.toString(maxAllowedRange), Double.toString(maxRange));
+ }
+
AccessibilityResult accesibilityResult = AccessibilityAnalyzer.computeAccessibility(req);
diff --git a/openrouteservice/src/main/java/heigit/ors/services/routing/requestprocessors/json/JsonRoutingRequestParser.java b/openrouteservice/src/main/java/heigit/ors/services/routing/requestprocessors/json/JsonRoutingRequestParser.java
index 2be7d258ce..464d92861e 100644
--- a/openrouteservice/src/main/java/heigit/ors/services/routing/requestprocessors/json/JsonRoutingRequestParser.java
+++ b/openrouteservice/src/main/java/heigit/ors/services/routing/requestprocessors/json/JsonRoutingRequestParser.java
@@ -141,6 +141,14 @@ public static RoutingRequest parseFromRequestParams(HttpServletRequest request)
value = request.getParameter("elevation");
if (!Helper.isEmpty(value))
req.setIncludeElevation(Boolean.parseBoolean(value));
+
+ value = request.getParameter("continue_straight");
+ if (!Helper.isEmpty(value))
+ req.setContinueStraight(Boolean.parseBoolean(value));
+
+ value = request.getParameter("roundabout_exits");
+ if (!Helper.isEmpty(value))
+ req.setIncludeRoundaboutExits(Boolean.parseBoolean(value));
value = request.getParameter("instructions_format");
if (!Helper.isEmpty(value))
diff --git a/openrouteservice/src/main/java/heigit/ors/services/routing/requestprocessors/json/JsonRoutingResponseWriter.java b/openrouteservice/src/main/java/heigit/ors/services/routing/requestprocessors/json/JsonRoutingResponseWriter.java
index 9dc55b1ebd..fd37272e58 100644
--- a/openrouteservice/src/main/java/heigit/ors/services/routing/requestprocessors/json/JsonRoutingResponseWriter.java
+++ b/openrouteservice/src/main/java/heigit/ors/services/routing/requestprocessors/json/JsonRoutingResponseWriter.java
@@ -233,6 +233,11 @@ public static JSONArray toJsonArray(RoutingRequest request, RouteResult[] routeR
jStep.put("maneuver", jManeuver);
}
}
+
+ if (request.getIncludeRoundaboutExits() && step.getRoundaboutExitBearings() != null)
+ {
+ jStep.put("exit_bearings", new JSONArray(step.getRoundaboutExitBearings()));
+ }
// add mode: driving, cycling, etc.
diff --git a/openrouteservice/src/main/java/heigit/ors/servlet/filters/CompressionFilter.java b/openrouteservice/src/main/java/heigit/ors/servlet/filters/CompressionFilter.java
index a881845d43..9dae1c964a 100644
--- a/openrouteservice/src/main/java/heigit/ors/servlet/filters/CompressionFilter.java
+++ b/openrouteservice/src/main/java/heigit/ors/servlet/filters/CompressionFilter.java
@@ -42,13 +42,16 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
String acceptEncoding = request.getHeader("accept-encoding");
if (acceptEncoding != null) {
- if (acceptEncoding.indexOf(ContentEncodingType.BROTLI) != -1) {
+ /* Commented out as jBrotli library crashes the server.
+ * Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
+ *J 4868 org.meteogroup.jbrotli.BrotliStreamCompressor.freeNativeResources()I
+ * if (acceptEncoding.indexOf(ContentEncodingType.BROTLI) != -1) {
BrotliResponseWrapper wrappedResponse = new BrotliResponseWrapper(response);
chain.doFilter(req, wrappedResponse);
wrappedResponse.finishResponse();
return;
}
- else if(acceptEncoding.indexOf(ContentEncodingType.GZIP) != -1) {
+ else*/ if(acceptEncoding.indexOf(ContentEncodingType.GZIP) != -1) {
GZIPResponseWrapper wrappedResponse = new GZIPResponseWrapper(response);
chain.doFilter(req, wrappedResponse);
wrappedResponse.finishResponse();
diff --git a/openrouteservice/src/main/java/heigit/ors/util/PolylineEncoder.java b/openrouteservice/src/main/java/heigit/ors/util/PolylineEncoder.java
index fa41174aef..5086e78dfe 100644
--- a/openrouteservice/src/main/java/heigit/ors/util/PolylineEncoder.java
+++ b/openrouteservice/src/main/java/heigit/ors/util/PolylineEncoder.java
@@ -52,7 +52,7 @@ public static String encode(final Coordinate[] coords, boolean includeElevation,
return buffer.toString();
}
-
+
private static void encode(long v, StringBuffer buffer) {
v = v < 0 ? ~(v << 1) : v << 1;