diff --git a/.travis.yml b/.travis.yml index bc079cb642..4bad499c36 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,9 +24,8 @@ jobs: script: - cp ${TRAVIS_BUILD_DIR}/openrouteservice-api-tests/conf/app.config.test ${TRAVIS_BUILD_DIR}/openrouteservice/src/main/resources/app.config - mvn -f ${TRAVIS_BUILD_DIR}/openrouteservice/pom.xml install -B - - nohup mvn -f ${TRAVIS_BUILD_DIR}/openrouteservice/pom.xml tomcat7:run & + - mvn -f ${TRAVIS_BUILD_DIR}/openrouteservice/pom.xml tomcat7:run -B & - travis_wait 15 sleep 15m - - tail -n2000 nohup.out - curl http://127.0.0.1:8082/openrouteservice-5.0/health - mvn -f ${TRAVIS_BUILD_DIR}/openrouteservice-api-tests/pom.xml test diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bd9dc8af8..7881da6050 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,29 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed ### Deprecated +## [5.0.2] - 2019-07-29 +### Added +- 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) +- Fixed the wrong gpx header for api v2 (#496) +- Make sure external storages contain entries for all edge IDs (#535) +- Check if BordersStorage exists before calling it in AvoidBordersCoreEdgeFilter +- Take into account shortcut direction in LM selection weighting (#550) +- Updated Matrix api v2 response to correctly display sources (#560) +- Check for null pointer in LM selection weighting (#550) +- Use commas rather than pipes for weighting options in app.config.sample (#564) +- Update point references when point is not found for routing (#567) +### Changed +- Moved walking and hiking flag encoders to the ORS core system (#440) +- Remove route optimization code (#499) +- Reduced distance for neighbourhood point search in isochrones when small isochrones are generated (#494) +- Removed obsolete storages (#536) +- Refactor fallback to preprocessing-independent algorithm for certain routing request params +- Removed some landmark sets as default from app.config.sample +### Deprecated + ## [5.0.1] - 2019-04-08 ### Added - CALT routing algorithm - Not for production (Issue #433) diff --git a/openrouteservice-api-tests/src/test/java/heigit/ors/services/isochrones/ResultTest.java b/openrouteservice-api-tests/src/test/java/heigit/ors/services/isochrones/ResultTest.java index 2dccc62db4..a19ff685b5 100644 --- a/openrouteservice-api-tests/src/test/java/heigit/ors/services/isochrones/ResultTest.java +++ b/openrouteservice-api-tests/src/test/java/heigit/ors/services/isochrones/ResultTest.java @@ -117,7 +117,7 @@ public void testReachfactorAndArea() { .body("any { it.key == 'type' }", is(true)) .body("any { it.key == 'features' }", is(true)) .body("features[0].properties.area", is(both(greaterThan(6110000f)).and(lessThan(6120000f)))) - .body("features[0].properties.reachfactor", is(0.1752f)) + .body("features[0].properties.reachfactor", is(0.7007f)) .statusCode(200); } @@ -136,7 +136,7 @@ public void testReachfactorAndAreaAreaUnitsM() { .body("any { it.key == 'type' }", is(true)) .body("any { it.key == 'features' }", is(true)) .body("features[0].properties.area", is(both(greaterThan(6110000f)).and(lessThan(6120000f)))) - .body("features[0].properties.reachfactor", is(0.1752f)) + .body("features[0].properties.reachfactor", is(0.7007f)) .statusCode(200); } @@ -155,7 +155,7 @@ public void testReachfactorAndAreaAreaUnitsKM() { .body("any { it.key == 'type' }", is(true)) .body("any { it.key == 'features' }", is(true)) .body("features[0].properties.area", is(both(greaterThan(6.11f)).and(lessThan(6.12f)))) - .body("features[0].properties.reachfactor", is(0.1752f)) + .body("features[0].properties.reachfactor", is(0.7007f)) .statusCode(200); } @@ -194,7 +194,7 @@ public void testReachfactorAndAreaAreaUnitsMI() { .body("any { it.key == 'type' }", is(true)) .body("any { it.key == 'features' }", is(true)) .body("features[0].properties.area", is(both(greaterThan(2.36f)).and(lessThan(2.37f)))) - .body("features[0].properties.reachfactor", is(0.1752f)) + .body("features[0].properties.reachfactor", is(0.7007f)) .statusCode(200); } diff --git a/openrouteservice-api-tests/src/test/java/heigit/ors/services/optimization/ParametersValidationTest.java b/openrouteservice-api-tests/src/test/java/heigit/ors/services/optimization/ParametersValidationTest.java deleted file mode 100644 index e0c6d8a176..0000000000 --- a/openrouteservice-api-tests/src/test/java/heigit/ors/services/optimization/ParametersValidationTest.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * 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.services.optimization; - -import static io.restassured.RestAssured.*; -import static org.hamcrest.Matchers.*; - -import org.junit.Test; - -import heigit.ors.services.common.EndPointAnnotation; -import heigit.ors.services.common.ServiceTest; - -@EndPointAnnotation(name="optimized_routes") -public class ParametersValidationTest extends ServiceTest { - - public ParametersValidationTest() { - } - - @Test - public void profileWrongValueTest() { - given() - .param("profile", "driving-car2") - .param("locations", "8.5,48.7|8.6,49.1") - .when() - .get(getEndPointName()) - .then() - .assertThat() - .body("error.code", is(703)) - .statusCode(400); - } - - @Test - public void missingProfileFormatTest() { - given() - .param("profile2", "driving-car") - .param("locations", "8.5,48.7|8.6,49.1") - .when() - .get(getEndPointName()) - .then() - .assertThat() - .body("error.code", is(701)) - .statusCode(400); - } - - @Test - public void locationsEmptyTest() { - given() - .param("profile", "driving-car") - .param("locations", "") - .when() - .get(getEndPointName()) - .then() - .assertThat() - .body("error.code", is(701)) - .statusCode(400); - } - - @Test - public void locationsFormatTest() { - given() - .param("profile", "driving-car") - .param("locations", "8.5,48.7|8.6,49.1b") - .when() - .get(getEndPointName()) - .then() - .assertThat() - .body("error.code", is(702)) - .statusCode(400); - } - - @Test - public void sourceFormatTest() { - given() - .param("profile", "driving-car") - .param("locations", "8.5,48.7|8.6,49.1") - .param("source", "any2") - .param("destination", "any") - .when() - .get(getEndPointName()) - .then() - .assertThat() - .body("error.code", is(702)) - .statusCode(400); - } - - @Test - public void destinationFormatTest() { - given() - .param("profile", "driving-car") - .param("locations", "8.5,48.7|8.6,49.1") - .param("source", 0) - .param("destination", "any2") - .when() - .get(getEndPointName()) - .then() - .assertThat() - .body("error.code", is(702)) - .statusCode(400); - } - - @Test - public void sourceOutOfRangeTest() { - given() - .param("profile", "driving-car") - .param("locations", "8.5,48.7|8.6,49.1") - .param("source", 5) - .param("destination", "any") - .when() - .get(getEndPointName()) - .then() - .assertThat() - .body("error.code", is(703)) - .statusCode(400); - } - - @Test - public void destinationOutOfRangeTest() { - given() - .param("profile", "driving-car") - .param("locations", "8.5,48.7|8.6,49.1") - .param("source", 0) - .param("destination", 3) - .when() - .get(getEndPointName()) - .then() - .assertThat() - .body("error.code", is(703)) - .statusCode(400); - } - - @Test - public void roudTripFormatTest() { - given() - .param("profile", "driving-car") - .param("locations", "8.5,48.7|8.6,49.1") - .param("source", "any") - .param("destination", "any") - .param("roundtrip", "trues") - .when() - .get(getEndPointName()) - .then() - .assertThat() - .body("error.code", is(702)) - .statusCode(400); - } - - @Test - public void metricFormatTest() { - given() - .param("profile", "driving-car") - .param("locations", "8.5,48.7|8.6,49.1") - .param("source", "any") - .param("destination", "any") - .param("roundtrip", "true") - .param("metric", "distance_") - .when() - .get(getEndPointName()) - .then() - .assertThat() - .body("error.code", is(703)) - .statusCode(400); - } - - @Test - public void unitsFormatTest() { - given() - .param("profile", "driving-car") - .param("locations", "8.5,48.7|8.6,49.1") - .param("source", "any") - .param("destination", "any") - .param("roundtrip", "true") - .param("metric", "distance") - .param("units", "kml") - .when() - .get(getEndPointName()) - .then() - .assertThat() - .body("error.code", is(703)) - .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 7387b6626c..80b12520c5 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 @@ -26,9 +26,15 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; +import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; import java.io.IOException; import java.io.StringReader; @@ -64,6 +70,8 @@ public void testGpxExport() throws IOException, SAXException, ParserConfiguratio .contentType("application/xml;charset=UTF-8") .statusCode(200); testGpxConsistency(response, true); + testGpxSchema(response); + Response response_without_instructions = given() .param("coordinates", getParameter("coordinatesShort")) .param("preference", getParameter("preference")) @@ -77,6 +85,7 @@ public void testGpxExport() throws IOException, SAXException, ParserConfiguratio .contentType("application/xml;charset=UTF-8") .statusCode(200); testGpxConsistency(response_without_instructions, false); + testGpxSchema(response); } /** @@ -286,7 +295,7 @@ private void testGpxConsistency(Response response, boolean instructions) throws case "descent": rteExtensionsDescent = true; break; - case "avgSpeed": + case "avgspeed": rteExtensionsAvgSpeed = true; break; case "bounds": @@ -364,6 +373,136 @@ private void testGpxConsistency(Response response, boolean instructions) throws Assert.assertTrue(gpxExtensions); } + /** + * Validates the gpx against the ors xsd schema. + */ + private void testGpxSchema(Response response) throws IOException, SAXException { + SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + String xsdSchema = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + Schema schema = factory.newSchema(new StreamSource(new StringReader(xsdSchema))); + Validator validator = schema.newValidator(); + Source xmlSource = new StreamSource(new StringReader(response.body().asString())); + validator.validate(xmlSource); + } + /** * The function validates the whole GeoJson export except segments. * Segments hold the instructions and are not necessary for our valid GeoJson-export. diff --git a/openrouteservice-api-tests/src/test/java/heigit/ors/v2/services/isochrones/ResultTest.java b/openrouteservice-api-tests/src/test/java/heigit/ors/v2/services/isochrones/ResultTest.java index fa6ec3015c..0070a080ba 100644 --- a/openrouteservice-api-tests/src/test/java/heigit/ors/v2/services/isochrones/ResultTest.java +++ b/openrouteservice-api-tests/src/test/java/heigit/ors/v2/services/isochrones/ResultTest.java @@ -219,7 +219,7 @@ public void testReachfactorAndArea() { .body("any { it.key == 'type' }", is(true)) .body("any { it.key == 'features' }", is(true)) .body("features[0].properties.area", is(both(greaterThan(6110000f)).and(lessThan(6120000f)))) - .body("features[0].properties.reachfactor", is(0.1752f)) + .body("features[0].properties.reachfactor", is(0.7007f)) .statusCode(200); } @@ -245,7 +245,7 @@ public void testReachfactorAndAreaAreaUnitsM() { .body("any { it.key == 'type' }", is(true)) .body("any { it.key == 'features' }", is(true)) .body("features[0].properties.area", is(both(greaterThan(6110000f)).and(lessThan(6120000f)))) - .body("features[0].properties.reachfactor", is(0.1752f)) + .body("features[0].properties.reachfactor", is(0.7007f)) .statusCode(200); } @@ -271,7 +271,7 @@ public void testReachfactorAndAreaAreaUnitsKM() { .body("any { it.key == 'type' }", is(true)) .body("any { it.key == 'features' }", is(true)) .body("features[0].properties.area", is(both(greaterThan(6.11f)).and(lessThan(6.12f)))) - .body("features[0].properties.reachfactor", is(0.1752f)) + .body("features[0].properties.reachfactor", is(0.7007f)) .statusCode(200); } @@ -324,7 +324,7 @@ public void testReachfactorAndAreaAreaUnitsMI() { .body("any { it.key == 'type' }", is(true)) .body("any { it.key == 'features' }", is(true)) .body("features[0].properties.area", is(both(greaterThan(2.36f)).and(lessThan(2.37f)))) - .body("features[0].properties.reachfactor", is(0.1752f)) + .body("features[0].properties.reachfactor", is(0.7007f)) .statusCode(200); } diff --git a/openrouteservice-api-tests/src/test/java/heigit/ors/v2/services/matrix/ResultTest.java b/openrouteservice-api-tests/src/test/java/heigit/ors/v2/services/matrix/ResultTest.java index dd67a875f3..feed7525d2 100644 --- a/openrouteservice-api-tests/src/test/java/heigit/ors/v2/services/matrix/ResultTest.java +++ b/openrouteservice-api-tests/src/test/java/heigit/ors/v2/services/matrix/ResultTest.java @@ -63,6 +63,30 @@ public ResultTest() { locationsLong.put(coord3); addParameter("locationsLong", locationsLong); + JSONArray locations5 = new JSONArray(); + coord1 = new JSONArray(); + coord1.put(8.684682); + coord1.put(49.401961); + locations5.put(coord1); + coord2 = new JSONArray(); + coord2.put(8.690518); + coord2.put(49.405326); + locations5.put(coord2); + coord3 = new JSONArray(); + coord3.put(8.690915); + coord3.put(49.430117); + locations5.put(coord3); + coord4 = new JSONArray(); + coord4.put(8.68834); + coord4.put(49.427758); + locations5.put(coord4); + JSONArray coord5 = new JSONArray(); + coord5.put(8.687525); + coord5.put(49.405437); + locations5.put(coord5); + + addParameter("locations5", locations5); + // Fake array to test maximum exceedings JSONArray maximumLocations = HelperFunctions.fakeJSONLocations(MatrixServiceSettings.getMaximumRoutes(false) + 1); addParameter("maximumLocations", maximumLocations); @@ -794,4 +818,34 @@ public void testDefinedDestinations() { .body("durations[2][1]", is(0.0f)) .statusCode(200); } + + @Test + public void testDefinedSourcesAndDestinations() { + + JSONObject body = new JSONObject(); + + body.put("locations", getParameter("locations5")); + body.put("sources", new JSONArray(new int[] {0,1})); + body.put("destinations", new JSONArray(new int[] {2,3,4})); + + given() + .header("Accept", "application/json") + .header("Content-Type", "application/json") + .pathParam("profile", getParameter("carProfile")) + .body(body.toString()) + .when().log().ifValidationFails() + .post(getEndPointPath() + "/{profile}/json") + .then().log().ifValidationFails() + .assertThat() + .body("any { it.key == 'destinations' }", is(true)) + .body("any { it.key == 'sources' }", is(true)) + .body("destinations.size()", is(3)) + .body("sources.size()", is(2)) + .body("destinations[0].snapped_distance", is(4.18f)) + .body("destinations[1].snapped_distance", is(2.42f)) + .body("destinations[2].snapped_distance", is(7.11f)) + .body("sources[0].snapped_distance", is(8.98f)) + .body("sources[1].snapped_distance", is(7.87f)) + .statusCode(200); + } } diff --git a/openrouteservice-api-tests/src/test/java/heigit/ors/v2/services/routing/ResultTest.java b/openrouteservice-api-tests/src/test/java/heigit/ors/v2/services/routing/ResultTest.java index dd21ae62b1..bd2214e136 100644 --- a/openrouteservice-api-tests/src/test/java/heigit/ors/v2/services/routing/ResultTest.java +++ b/openrouteservice-api-tests/src/test/java/heigit/ors/v2/services/routing/ResultTest.java @@ -28,15 +28,22 @@ import org.xml.sax.SAXException; import javax.imageio.metadata.IIOMetadataNode; +import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; 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; @@ -76,6 +83,7 @@ public ResultTest() { extraInfo.put("surface"); extraInfo.put("suitability"); extraInfo.put("steepness"); + extraInfo.put("countryinfo"); addParameter("extra_info", extraInfo); addParameter("preference", "fastest"); @@ -129,6 +137,7 @@ public void testGpxExport() throws IOException, SAXException, ParserConfiguratio .contentType("application/gpx+xml;charset=UTF-8") .statusCode(200); testGpxConsistency(response, true); + testGpxSchema(response); testGpxGeometry(response); body.put("instructions", false); @@ -146,6 +155,7 @@ public void testGpxExport() throws IOException, SAXException, ParserConfiguratio .contentType("application/gpx+xml;charset=UTF-8") .statusCode(200); testGpxConsistency(response_without_instructions, false); + testGpxSchema(response); testGpxGeometry(response_without_instructions); } @@ -468,6 +478,137 @@ private void testGpxConsistency(Response response, boolean instructions) throws Assert.assertTrue(gpxExtensions); } + + /** + * Validates the gpx against the ors xsd schema. + */ + private void testGpxSchema(Response response) throws IOException, SAXException { + SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + String xsdSchema = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n"; + Schema schema = factory.newSchema(new StreamSource(new StringReader(xsdSchema))); + Validator validator = schema.newValidator(); + Source xmlSource = new StreamSource(new StringReader(response.body().asString())); + validator.validate(xmlSource); + } + /** * The function validates the whole GeoJson export except segments. * Segments hold the instructions and are not necessary for our valid GeoJson-export. @@ -737,7 +878,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}") @@ -748,6 +889,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); } @@ -2368,6 +2510,171 @@ public void testRouteMergeInstructionsWithoutGeometry() { .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("\\|"); diff --git a/openrouteservice/pom.xml b/openrouteservice/pom.xml index c82cf2c83a..d373a69a0c 100644 --- a/openrouteservice/pom.xml +++ b/openrouteservice/pom.xml @@ -30,7 +30,7 @@ 4.0.0 heigit.ors openrouteservice - 5.0.1 + 5.0.2 war openrouteservice openrouteservice.org diff --git a/openrouteservice/src/main/java/heigit/ors/api/requests/common/APIEnums.java b/openrouteservice/src/main/java/heigit/ors/api/requests/common/APIEnums.java index 8d314675f6..9058d6ab83 100644 --- a/openrouteservice/src/main/java/heigit/ors/api/requests/common/APIEnums.java +++ b/openrouteservice/src/main/java/heigit/ors/api/requests/common/APIEnums.java @@ -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; diff --git a/openrouteservice/src/main/java/heigit/ors/api/requests/routing/RouteRequestHandler.java b/openrouteservice/src/main/java/heigit/ors/api/requests/routing/RouteRequestHandler.java index 05434d5d3b..3e040da109 100644 --- a/openrouteservice/src/main/java/heigit/ors/api/requests/routing/RouteRequestHandler.java +++ b/openrouteservice/src/main/java/heigit/ors/api/requests/routing/RouteRequestHandler.java @@ -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; @@ -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())); diff --git a/openrouteservice/src/main/java/heigit/ors/api/responses/matrix/JSONMatrixResponseObjects/JSONBasedIndividualMatrixResponse.java b/openrouteservice/src/main/java/heigit/ors/api/responses/matrix/JSONMatrixResponseObjects/JSONBasedIndividualMatrixResponse.java index 97a278225d..f1b8febf5b 100644 --- a/openrouteservice/src/main/java/heigit/ors/api/responses/matrix/JSONMatrixResponseObjects/JSONBasedIndividualMatrixResponse.java +++ b/openrouteservice/src/main/java/heigit/ors/api/responses/matrix/JSONMatrixResponseObjects/JSONBasedIndividualMatrixResponse.java @@ -44,7 +44,7 @@ List constructDestinations(MatrixResult matrixResult) { List constructSources(MatrixResult matrixResult) { List sources = new ArrayList<>(); - for (ResolvedLocation location : matrixResult.getDestinations()) { + for (ResolvedLocation location : matrixResult.getSources()) { if (location != null) sources.add(new JSON2DSources(location, includeResolveLocations)); else diff --git a/openrouteservice/src/main/java/heigit/ors/api/responses/routing/GPXRouteResponseObjects/GPXRouteResponse.java b/openrouteservice/src/main/java/heigit/ors/api/responses/routing/GPXRouteResponseObjects/GPXRouteResponse.java index 7db69e3c71..7847bc30be 100644 --- a/openrouteservice/src/main/java/heigit/ors/api/responses/routing/GPXRouteResponseObjects/GPXRouteResponse.java +++ b/openrouteservice/src/main/java/heigit/ors/api/responses/routing/GPXRouteResponseObjects/GPXRouteResponse.java @@ -38,6 +38,9 @@ public class GPXRouteResponse extends RouteResponse { @XmlAttribute(name = "creator") private String gpxCreator = "openrouteservice"; + @XmlAttribute(name = "xmlns") + private String xmlnsLink = "https://raw.githubusercontent.com/GIScience/openrouteservice-schema/master/gpx/v2/ors-gpx.xsd"; + @XmlElement(name = "metadata") private GPXMetadata metadata; diff --git a/openrouteservice/src/main/java/heigit/ors/globalResponseProcessor/gpx/GpxResponseWriter.java b/openrouteservice/src/main/java/heigit/ors/globalResponseProcessor/gpx/GpxResponseWriter.java index 04175488ec..986e63d0b2 100644 --- a/openrouteservice/src/main/java/heigit/ors/globalResponseProcessor/gpx/GpxResponseWriter.java +++ b/openrouteservice/src/main/java/heigit/ors/globalResponseProcessor/gpx/GpxResponseWriter.java @@ -169,7 +169,7 @@ public static String toGPX(RoutingRequest rreq, RouteResult[] routeResults) thro RteTypeExtensions rteTypeExtensions = new RteTypeExtensions(); RouteSummary route_summary = route.getSummary(); rteTypeExtensions.setAscent(route_summary.getAscent()); - rteTypeExtensions.setAvgSpeed(route_summary.getAverageSpeed()); + rteTypeExtensions.setAvgspeed(route_summary.getAverageSpeed()); rteTypeExtensions.setDescent(route_summary.getDescent()); rteTypeExtensions.setDistance(route_summary.getDistance()); rteTypeExtensions.setDuration(route_summary.getDuration()); diff --git a/openrouteservice/src/main/java/heigit/ors/globalResponseProcessor/gpx/beans/BoundsType.java b/openrouteservice/src/main/java/heigit/ors/globalResponseProcessor/gpx/beans/BoundsType.java index 3c2c265651..fa8dbb6170 100644 --- a/openrouteservice/src/main/java/heigit/ors/globalResponseProcessor/gpx/beans/BoundsType.java +++ b/openrouteservice/src/main/java/heigit/ors/globalResponseProcessor/gpx/beans/BoundsType.java @@ -45,10 +45,10 @@ * * * - * - * - * - * + * + * + * + * * * * @@ -61,13 +61,13 @@ @XmlType(name = "boundsType") public class BoundsType { - @XmlAttribute(name = "minlat", required = true) + @XmlAttribute(name = "minLat", required = true) protected BigDecimal minlat; - @XmlAttribute(name = "minlon", required = true) + @XmlAttribute(name = "minLon", required = true) protected BigDecimal minlon; - @XmlAttribute(name = "maxlat", required = true) + @XmlAttribute(name = "maxLat", required = true) protected BigDecimal maxlat; - @XmlAttribute(name = "maxlon", required = true) + @XmlAttribute(name = "maxLon", required = true) protected BigDecimal maxlon; /** diff --git a/openrouteservice/src/main/java/heigit/ors/globalResponseProcessor/gpx/beans/RteTypeExtensions.java b/openrouteservice/src/main/java/heigit/ors/globalResponseProcessor/gpx/beans/RteTypeExtensions.java index dcdc9c6ef1..87999b3b2f 100644 --- a/openrouteservice/src/main/java/heigit/ors/globalResponseProcessor/gpx/beans/RteTypeExtensions.java +++ b/openrouteservice/src/main/java/heigit/ors/globalResponseProcessor/gpx/beans/RteTypeExtensions.java @@ -44,7 +44,7 @@ "distanceActual", "ascent", "descent", - "avgSpeed", + "avgspeed", "bounds" // always add new variables here! and below }) @@ -56,7 +56,7 @@ public class RteTypeExtensions extends ExtensionsType { private double distanceActual; private double ascent; private double descent; - private double avgSpeed; + private double avgspeed; private BoundsType bounds; @@ -156,17 +156,17 @@ public void setDescent(double descent) { * * @return avgspeed as double */ - public double getAvgSpeed() { - return avgSpeed; + public double getAvgspeed() { + return avgspeed; } /** * Sets the value of the avgspeed property * - * @param avgSpeed needs a double as input + * @param avgspeed needs a double as input */ - public void setAvgSpeed(double avgSpeed) { - this.avgSpeed = avgSpeed; + public void setAvgspeed(double avgspeed) { + this.avgspeed = avgspeed; } /** diff --git a/openrouteservice/src/main/java/heigit/ors/isochrones/Isochrone.java b/openrouteservice/src/main/java/heigit/ors/isochrones/Isochrone.java index fe0b191660..edcc87e2ee 100644 --- a/openrouteservice/src/main/java/heigit/ors/isochrones/Isochrone.java +++ b/openrouteservice/src/main/java/heigit/ors/isochrones/Isochrone.java @@ -30,14 +30,14 @@ public class Isochrone { private boolean hasArea = false; private boolean hasReachfactor = false; private double reachfactor; - private double maxRadius; + private double meanRadius; private Envelope envelope; private List _attributes; - public Isochrone(Geometry geometry, double value, double maxRadius) { + public Isochrone(Geometry geometry, double value, double meanRadius) { this.geometry = geometry; this.value = value; - this.maxRadius = maxRadius; + this.meanRadius = meanRadius; } public Geometry getGeometry() { @@ -48,21 +48,21 @@ public double getValue() { return value; } - public double getMaxRadius(String units) { + public double getMeanRadius(String units) { if (units != null) { switch (units) { case "m": - return maxRadius; + return meanRadius; case "mi": - return UnitsConverter.MetersToMiles(maxRadius); + return UnitsConverter.MetersToMiles(meanRadius); case "km": - return UnitsConverter.MetersToKilometers(maxRadius); + return UnitsConverter.MetersToKilometers(meanRadius); } } // return default meter - return maxRadius; + return meanRadius; } public double calcArea(String units) throws Exception { @@ -110,7 +110,7 @@ public boolean hasArea() { public double calcReachfactor(String units) throws Exception { - double r = getMaxRadius(units); + double r = getMeanRadius(units); double maxArea = Math.PI * r * r; hasReachfactor = true; diff --git a/openrouteservice/src/main/java/heigit/ors/isochrones/builders/concaveballs/ConcaveBallsIsochroneMapBuilder.java b/openrouteservice/src/main/java/heigit/ors/isochrones/builders/concaveballs/ConcaveBallsIsochroneMapBuilder.java index 629802af21..a6d11bd0a5 100644 --- a/openrouteservice/src/main/java/heigit/ors/isochrones/builders/concaveballs/ConcaveBallsIsochroneMapBuilder.java +++ b/openrouteservice/src/main/java/heigit/ors/isochrones/builders/concaveballs/ConcaveBallsIsochroneMapBuilder.java @@ -16,9 +16,7 @@ import com.carrotsearch.hppc.IntObjectMap; import com.carrotsearch.hppc.cursors.IntObjectCursor; import com.graphhopper.coll.GHIntObjectHashMap; -import com.graphhopper.routing.util.AbstractFlagEncoder; -import com.graphhopper.routing.util.FootFlagEncoder; -import com.graphhopper.routing.util.HikeFlagEncoder; +import com.graphhopper.routing.util.*; import com.graphhopper.storage.GraphHopperStorage; import com.graphhopper.storage.NodeAccess; import com.graphhopper.storage.SPTEntry; @@ -34,7 +32,8 @@ import heigit.ors.isochrones.builders.AbstractIsochroneMapBuilder; import heigit.ors.routing.RouteSearchContext; import heigit.ors.routing.graphhopper.extensions.AccessibilityMap; -import heigit.ors.routing.graphhopper.extensions.flagencoders.WheelchairFlagEncoder; +import heigit.ors.routing.graphhopper.extensions.flagencoders.*; +import heigit.ors.routing.graphhopper.extensions.flagencoders.FootFlagEncoder; import heigit.ors.util.GeomUtility; import org.apache.log4j.Logger; import org.opensphere.geometry.algorithm.ConcaveHull; @@ -87,6 +86,10 @@ public IsochroneMap compute(IsochroneSearchParameters parameters) throws Excepti maxSpeed = WheelchairFlagEncoder.MEAN_SPEED; } + double meanSpeed = maxSpeed; + if (_searchContext.getEncoder() instanceof ORSAbstractFlagEncoder) { + meanSpeed = ((ORSAbstractFlagEncoder) _searchContext.getEncoder()).getMeanSpeed(); + } AccessibilityMap edgeMap = GraphEdgeMapFinder.findEdgeMap(_searchContext, parameters); @@ -127,6 +130,8 @@ public IsochroneMap compute(IsochroneSearchParameters parameters) throws Excepti int nRanges = parameters.getRanges().length; double metersPerSecond = maxSpeed / 3.6; + // only needed for reachfactor property + double meanMetersPerSecond = meanSpeed / 3.6; double prevCost = 0; for (int i = 0; i < nRanges; i++) { @@ -145,12 +150,15 @@ public IsochroneMap compute(IsochroneSearchParameters parameters) throws Excepti } double maxRadius = 0; + double meanRadius = 0; switch (isochroneType) { case Distance: maxRadius = isoValue; + meanRadius = isoValue; break; case Time: maxRadius = metersPerSecond * isoValue; + meanRadius = meanMetersPerSecond * isoValue; isochronesDifference = metersPerSecond * isochronesDifference; break; } @@ -167,7 +175,7 @@ public IsochroneMap compute(IsochroneSearchParameters parameters) throws Excepti sw.start(); } - addIsochrone(isochroneMap, points, isoValue, maxRadius, smoothingFactor); + addIsochrone(isochroneMap, points, isoValue, maxRadius, meanRadius, smoothingFactor); if (LOGGER.isDebugEnabled()) @@ -214,7 +222,7 @@ private double convertSmoothingFactorToDistance(float smoothingFactor, double ma return maxLength; } - private void addIsochrone(IsochroneMap isochroneMap, GeometryCollection points, double isoValue, double maxRadius, float smoothingFactor) + private void addIsochrone(IsochroneMap isochroneMap, GeometryCollection points, double isoValue, double maxRadius, double meanRadius, float smoothingFactor) { if (points.isEmpty()) return; @@ -233,7 +241,7 @@ private void addIsochrone(IsochroneMap isochroneMap, GeometryCollection points, copyConvexHullPoints(poly); - isochroneMap.addIsochrone(new Isochrone(poly, isoValue, maxRadius)); + isochroneMap.addIsochrone(new Isochrone(poly, isoValue, meanRadius)); } private void markDeadEndEdges(AccessibilityMap edgeMap) @@ -358,7 +366,9 @@ private GeometryCollection buildIsochrone(AccessibilityMap edgeMap, List= maxCost) { // This checks for dead end edges, but we need to include those in small areas to provide realistic // results - if (goalEdge.edge == -2 && isochronesDifference > 1000) + if (goalEdge.edge == -2 && !useHighDetail) { //addPoint(points, qtree, nodeAccess.getLon(nodeId), nodeAccess.getLat(nodeId), true); } diff --git a/openrouteservice/src/main/java/heigit/ors/optimization/OptimizationErrorCodes.java b/openrouteservice/src/main/java/heigit/ors/optimization/OptimizationErrorCodes.java deleted file mode 100644 index d3a0bfaea2..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/optimization/OptimizationErrorCodes.java +++ /dev/null @@ -1,23 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.optimization; - -public class OptimizationErrorCodes { - public static int INVALID_JSON_FORMAT = 700; - public static int MISSING_PARAMETER = 701; - public static int INVALID_PARAMETER_FORMAT = 702; - public static int INVALID_PARAMETER_VALUE = 703; - public static int PARAMETER_VALUE_EXCEEDS_MAXIMUM = 704; - public static int UNKNOWN = 799; -} diff --git a/openrouteservice/src/main/java/heigit/ors/optimization/RouteOptimizationRequest.java b/openrouteservice/src/main/java/heigit/ors/optimization/RouteOptimizationRequest.java deleted file mode 100644 index 822989cc61..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/optimization/RouteOptimizationRequest.java +++ /dev/null @@ -1,210 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.optimization; - -import com.vividsolutions.jts.geom.Coordinate; - -import heigit.ors.common.DistanceUnit; -import heigit.ors.matrix.MatrixMetricsType; -import heigit.ors.matrix.MatrixRequest; -import heigit.ors.routing.RouteInstructionsFormat; -import heigit.ors.routing.RoutingRequest; -import heigit.ors.services.ServiceRequest; - -public class RouteOptimizationRequest extends ServiceRequest { - private int _profileType; - private Coordinate[] _locations; - private int _sourceIndex; - private int _destinationIndex; - private int _metric = MatrixMetricsType.Duration; - private boolean _roundTrip = false; - private DistanceUnit _units = DistanceUnit.Meters; - - private String _language = "en"; - private String _geometryFormat = "encodedpolyline"; - private RouteInstructionsFormat _instructionsFormat = RouteInstructionsFormat.TEXT; - private Boolean _includeInstructions = true; - private Boolean _includeElevation = false; - private Boolean _includeGeometry = true; - private Boolean _simplifyGeometry = false; - //private double[] _searchRadii; - - public RouteOptimizationRequest() - { - - } - - public int getProfileType() { - return _profileType; - } - - public void setProfileType(int profileType) { - _profileType = profileType; - } - - public Coordinate[] getLocations() - { - return _locations; - } - - public void setLocations(Coordinate[] locations) - { - _locations = locations; - } - - public int getLocationsCount() - { - return _locations == null ? 0: _locations.length; - } - - public boolean isRoundTrip() { - return _roundTrip; - } - - public void setRoundTrip(boolean roundTrip) { - _roundTrip = roundTrip; - } - - public int getMetric() { - return _metric; - } - - public void setMetric(int metric) { - _metric = metric; - } - - public int getSourceIndex() { - return _sourceIndex; - } - - public void setSourceIndex(int sourceIndex) { - _sourceIndex = sourceIndex; - } - - public int getDestinationIndex() { - return _destinationIndex; - } - - public void setDestinationIndex(int destinationIndex) { - _destinationIndex = destinationIndex; - } - - public DistanceUnit getUnits() { - return _units; - } - - public void setUnits(DistanceUnit units) { - _units = units; - } - - public String getGeometryFormat() { - return _geometryFormat; - } - - public void setGeometryFormat(String geometryFormat) { - _geometryFormat = geometryFormat; - } - - public String getLanguage() { - return _language; - } - - public void setLanguage(String language) { - _language = language; - } - - public RouteInstructionsFormat getInstructionsFormat() { - return _instructionsFormat; - } - - public void setInstructionsFormat(RouteInstructionsFormat instructionsFormat) { - _instructionsFormat = instructionsFormat; - } - - public Boolean getIncludeInstructions() { - return _includeInstructions; - } - - public void setIncludeInstructions(Boolean includeInstructions) { - _includeInstructions = includeInstructions; - } - - public Boolean getIncludeElevation() { - return _includeElevation; - } - - public void setIncludeElevation(Boolean includeElevation) { - _includeElevation = includeElevation; - } - - public Boolean getIncludeGeometry() { - return _includeGeometry; - } - - public void setIncludeGeometry(Boolean includeGeometry) { - this._includeGeometry = includeGeometry; - } - - public Boolean getSimplifyGeometry() { - return _simplifyGeometry; - } - - public void setSimplifyGeometry(Boolean simplifyGeometry) { - this._simplifyGeometry = simplifyGeometry; - } - - public RoutingRequest createRoutingRequest(int[] wayPoints) - { - RoutingRequest req = new RoutingRequest(); - //req.setCoordinates(_coordinates); - req.setGeometryFormat(_geometryFormat); - - return req; - } - - public MatrixRequest createMatrixRequest() - { - MatrixRequest mtxReq = new MatrixRequest(); - mtxReq.setProfileType(_profileType); - mtxReq.setMetrics(_metric); - mtxReq.setUnits(_units); - - if (_sourceIndex == -1) - { - mtxReq.setSources(_locations); - mtxReq.setDestinations(_locations); - } - else - { - mtxReq.setSources(new Coordinate[] { _locations[_sourceIndex] }); - - int nLocations = _locations.length; - Coordinate[] destinations = new Coordinate[nLocations - 1]; - - int j = 0; - for (int i = 0; i < nLocations; ++i) - { - if (i != _sourceIndex) - { - destinations[j] = _locations[i]; - ++j; - } - } - mtxReq.setDestinations(destinations); - } - - return mtxReq; - } - -} diff --git a/openrouteservice/src/main/java/heigit/ors/optimization/RouteOptimizationResult.java b/openrouteservice/src/main/java/heigit/ors/optimization/RouteOptimizationResult.java deleted file mode 100644 index 7360718348..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/optimization/RouteOptimizationResult.java +++ /dev/null @@ -1,42 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.optimization; - -import heigit.ors.routing.RouteResult; - -public class RouteOptimizationResult { - private RouteResult _routeResult; - private int[] _waypoints; - - public RouteOptimizationResult() - { - - } - - public RouteResult getRouteResult() { - return _routeResult; - } - - public void setRouteResult(RouteResult routeResult) { - _routeResult = routeResult; - } - - public int[] getWayPoints() { - return _waypoints; - } - - public void setWayPoints(int[] waypoints) { - _waypoints = waypoints; - } -} diff --git a/openrouteservice/src/main/java/heigit/ors/optimization/solvers/OptimizationProblemSolver.java b/openrouteservice/src/main/java/heigit/ors/optimization/solvers/OptimizationProblemSolver.java deleted file mode 100644 index 37b8720266..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/optimization/solvers/OptimizationProblemSolver.java +++ /dev/null @@ -1,23 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.optimization.solvers; - -import java.util.Map; - -public interface OptimizationProblemSolver { - - public void init(Map options); - - public OptimizationSolution solve(); -} diff --git a/openrouteservice/src/main/java/heigit/ors/optimization/solvers/OptimizationProblemSolverFactory.java b/openrouteservice/src/main/java/heigit/ors/optimization/solvers/OptimizationProblemSolverFactory.java deleted file mode 100644 index 641493fa1b..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/optimization/solvers/OptimizationProblemSolverFactory.java +++ /dev/null @@ -1,36 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.optimization.solvers; - -import java.util.Map; - -import heigit.ors.optimization.solvers.simulatedannealing.SimulatedAnnealingSolver; - -public class OptimizationProblemSolverFactory { - public static OptimizationProblemSolver createSolver(String name, Map opts) - { - OptimizationProblemSolver solver = null; - - switch(name.toLowerCase()) - { - case "simulatedannealing": - solver = new SimulatedAnnealingSolver(); - break; - } - - solver.init(opts); - - return solver; - } -} diff --git a/openrouteservice/src/main/java/heigit/ors/optimization/solvers/OptimizationSolution.java b/openrouteservice/src/main/java/heigit/ors/optimization/solvers/OptimizationSolution.java deleted file mode 100644 index 558fa74b97..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/optimization/solvers/OptimizationSolution.java +++ /dev/null @@ -1,23 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.optimization.solvers; - -public class OptimizationSolution { - private boolean _isValid = false; - - public boolean isValid() - { - return _isValid; - } -} diff --git a/openrouteservice/src/main/java/heigit/ors/optimization/solvers/simulatedannealing/SimulatedAnnealingSolver.java b/openrouteservice/src/main/java/heigit/ors/optimization/solvers/simulatedannealing/SimulatedAnnealingSolver.java deleted file mode 100644 index 38acdcaeb9..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/optimization/solvers/simulatedannealing/SimulatedAnnealingSolver.java +++ /dev/null @@ -1,34 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.optimization.solvers.simulatedannealing; - -import java.util.Map; - -import heigit.ors.optimization.solvers.OptimizationProblemSolver; -import heigit.ors.optimization.solvers.OptimizationSolution; - -public class SimulatedAnnealingSolver implements OptimizationProblemSolver { - - @Override - public OptimizationSolution solve() { - // TODO Auto-generated method stub - return null; - } - - @Override - public void init(Map options) { - // TODO Auto-generated method stub - - } -} diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteExtraInfoFlag.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteExtraInfoFlag.java index 52d3b99168..ca24e16855 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RouteExtraInfoFlag.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteExtraInfoFlag.java @@ -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; @@ -78,6 +79,9 @@ public static int getFromString(String value) { case "roadaccessrestrictions": res |= RoadAccessRestrictions; break; + case "countryinfo": + res |= CountryInfo; + break; } } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java index 9d460cb067..05495be207 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RouteSearchParameters.java @@ -429,4 +429,12 @@ public boolean requiresDynamicWeights() { || isProfileTypeDriving() && getConsiderTraffic() ; } + + /** + * Check if the request is compatible with preprocessed graphs + */ + public boolean requiresFallbackAlgorithm() { + return hasAvoidAreas() + || (getProfileParameters() != null && getProfileParameters().hasWeightings()); + } } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java index ac2b665e5b..9c984757d8 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfile.java @@ -16,45 +16,66 @@ 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.optimization.OptimizationErrorCodes; -import heigit.ors.optimization.RouteOptimizationRequest; -import heigit.ors.optimization.RouteOptimizationResult; -import heigit.ors.optimization.solvers.OptimizationProblemSolver; -import heigit.ors.optimization.solvers.OptimizationProblemSolverFactory; -import heigit.ors.optimization.solvers.OptimizationSolution; 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; import heigit.ors.services.matrix.MatrixServiceSettings; -import heigit.ors.services.optimization.OptimizationServiceSettings; import heigit.ors.util.DebugUtility; import heigit.ors.util.RuntimeUtility; import heigit.ors.util.StringUtility; @@ -67,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. @@ -157,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(); @@ -510,45 +544,6 @@ public MatrixResult computeMatrix(MatrixRequest req) throws Exception { return mtxResult; } - public RouteOptimizationResult computeOptimizedRoutes(RouteOptimizationRequest req) throws Exception { - RouteOptimizationResult optResult = null; - - MatrixResult mtxResult = null; - - try { - MatrixRequest mtxReq = req.createMatrixRequest(); - mtxResult = computeMatrix(mtxReq); - } catch (Exception ex) { - LOGGER.error(ex); - throw new InternalServerException(OptimizationErrorCodes.UNKNOWN, "Unable to compute an optimized route."); - } - - OptimizationProblemSolver solver = OptimizationProblemSolverFactory.createSolver(OptimizationServiceSettings.getSolverName(), OptimizationServiceSettings.getSolverOptions()); - - if (solver == null) - throw new Exception("Unable to create an algorithm to distance/duration matrix."); - - OptimizationSolution solution = null; - - try { - float[] costs = mtxResult.getTable(req.getMetric()); - costs[0] = 0; // TODO - - solution = solver.solve(); - } catch (Exception ex) { - LOGGER.error(ex); - - throw new InternalServerException(OptimizationErrorCodes.UNKNOWN, "Optimization problem solver threw an exception."); - } - - if (!solution.isValid()) - throw new InternalServerException(OptimizationErrorCodes.UNKNOWN, "Optimization problem solver was unable to find an appropriate solution."); - - optResult = new RouteOptimizationResult(); - - return optResult; - } - private RouteSearchContext createSearchContext(RouteSearchParameters searchParams, RouteSearchMode mode, EdgeFilter customEdgeFilter) throws Exception { PMap props = new PMap(); @@ -588,13 +583,8 @@ private RouteSearchContext createSearchContext(RouteSearchParameters searchParam if (RoutingProfileType.isHeavyVehicle(profileType) && searchParams.hasParameters(VehicleParameters.class)) { VehicleParameters vehicleParams = (VehicleParameters) profileParams; - if (vehicleParams.hasAttributes()) { - - if (profileType == RoutingProfileType.DRIVING_HGV) - edgeFilters.add(new HeavyVehicleEdgeFilter(flagEncoder, searchParams.getVehicleType(), vehicleParams, gs)); - else if (profileType == RoutingProfileType.DRIVING_EMERGENCY) - edgeFilters.add(new EmergencyVehicleEdgeFilter(vehicleParams, gs)); - } + if (vehicleParams.hasAttributes() && profileType == RoutingProfileType.DRIVING_HGV) + edgeFilters.add(new HeavyVehicleEdgeFilter(flagEncoder, searchParams.getVehicleType(), vehicleParams, gs)); } } @@ -796,8 +786,8 @@ else if (bearings[1] == null) } } } - //cannot use CH or CoreALT with avoid areas. Need to fallback to ALT with beeline approximator or Dijkstra - if(props.getBool("avoid_areas", false)){ + //cannot use CH or CoreALT with requests where the weighting of non-predefined edges might change + if(searchParams.requiresFallbackAlgorithm()) { req.setAlgorithm("astarbi"); req.getHints().put("lm.disable", false); req.getHints().put("core.disable", true); @@ -926,9 +916,12 @@ public IsochroneMap buildIsochrone(IsochroneSearchParameters parameters) throws } - if (parameters.hasAttribute("reachfactor") && parameters.getRangeType() == TravelRangeType.Time) { + if (parameters.hasAttribute("reachfactor")) { double reachfactor = isochrone.calcReachfactor(units); + // reach factor could be > 1, which would confuse people + reachfactor = (reachfactor > 1) ? 1 : reachfactor; + isochrone.setReachfactor(reachfactor); } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java index 3923fb41a4..663d21b515 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java @@ -30,9 +30,6 @@ import heigit.ors.matrix.MatrixErrorCodes; import heigit.ors.matrix.MatrixRequest; import heigit.ors.matrix.MatrixResult; -import heigit.ors.optimization.OptimizationErrorCodes; -import heigit.ors.optimization.RouteOptimizationRequest; -import heigit.ors.optimization.RouteOptimizationResult; import heigit.ors.routing.configuration.RouteProfileConfiguration; import heigit.ors.routing.configuration.RoutingManagerConfiguration; import heigit.ors.routing.pathprocessors.ElevationSmoothPathProcessor; @@ -49,7 +46,12 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; -import java.util.concurrent.*; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorCompletionService; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; public class RoutingProfileManager { private static final Logger LOGGER = Logger.getLogger(RoutingProfileManager.class.getName()); @@ -343,8 +345,10 @@ public RouteResult computeRoute(RoutingRequest req) throws Exception { RoutingProfile rp = getRouteProfile(req, false); RouteSearchParameters searchParams = req.getSearchParameters(); PathProcessor pathProcessor = null; - - pathProcessor = new ExtraInfoProcessor(rp.getGraphhopper(), req); + if (req.getIncludeCountryInfo()) + pathProcessor = new ExtraInfoProcessor(rp.getGraphhopper(), req, rp.getGraphhopper().getGeneralCbReader()); + else + pathProcessor = new ExtraInfoProcessor(rp.getGraphhopper(), req); Coordinate[] coords = req.getCoordinates(); Coordinate c0 = coords[0]; @@ -418,7 +422,21 @@ public RouteResult computeRoute(RoutingRequest req) throws Exception { for(Throwable error: gr.getErrors()) { if(!StringUtility.isEmpty(message)) message = message + "; "; - message = message + error.getMessage(); + if (error instanceof com.graphhopper.util.exceptions.PointNotFoundException) { + com.graphhopper.util.exceptions.PointNotFoundException pointNotFoundException = (com.graphhopper.util.exceptions.PointNotFoundException) error; + int pointReference = (i-1) + pointNotFoundException.getPointIndex(); + + Coordinate pointCoordinate = (pointNotFoundException.getPointIndex() == 0) ? c0 : c1; + double pointRadius = radiuses[pointNotFoundException.getPointIndex()]; + + message = message + String.format("Could not find point %d: %s within a radius of %.1f meters.", + pointReference, + FormatUtility.formatCoordinate(pointCoordinate), + pointRadius); + + } else { + message = message + error.getMessage(); + } } throw new PointNotFoundException(message); } else { @@ -513,7 +531,7 @@ public RoutingProfile getRouteProfile(RoutingRequest req, boolean oneToMany) thr RouteSearchParameters searchParams = req.getSearchParameters(); int profileType = searchParams.getProfileType(); - boolean hasAvoidAreas = searchParams.hasAvoidAreas(); + boolean fallbackAlgorithm = searchParams.requiresFallbackAlgorithm(); boolean dynamicWeights = searchParams.requiresDynamicWeights(); RoutingProfile rp = _routeProfiles.getRouteProfile(profileType, !dynamicWeights); @@ -529,7 +547,7 @@ public RoutingProfile getRouteProfile(RoutingRequest req, boolean oneToMany) thr if (config.getMaximumDistance() > 0 || (dynamicWeights && config.getMaximumDistanceDynamicWeights() > 0) || config.getMaximumWayPoints() > 0 - || (hasAvoidAreas && config.getMaximumDistanceAvoidAreas() > 0)) { + || (fallbackAlgorithm && config.getMaximumDistanceAvoidAreas() > 0)) { Coordinate[] coords = req.getCoordinates(); int nCoords = coords.length; if (config.getMaximumWayPoints() > 0) { @@ -539,7 +557,7 @@ public RoutingProfile getRouteProfile(RoutingRequest req, boolean oneToMany) thr if (config.getMaximumDistance() > 0 || (dynamicWeights && config.getMaximumDistanceDynamicWeights() > 0) - || (hasAvoidAreas && config.getMaximumDistanceAvoidAreas() > 0)) { + || (fallbackAlgorithm && config.getMaximumDistanceAvoidAreas() > 0)) { double longestSegmentDist = 0.0; DistanceCalc distCalc = Helper.DIST_EARTH; @@ -577,8 +595,8 @@ public RoutingProfile getRouteProfile(RoutingRequest req, boolean oneToMany) thr if (dynamicWeights && config.getMaximumDistanceDynamicWeights() > 0 && totalDist > config.getMaximumDistanceDynamicWeights()) throw new ServerLimitExceededException(RoutingErrorCodes.REQUEST_EXCEEDS_SERVER_LIMIT, "By dynamic weighting, the approximated distance of a route segment must not be greater than " + Double.toString(config.getMaximumDistanceDynamicWeights()) + " meters."); - if (hasAvoidAreas && config.getMaximumDistanceAvoidAreas() > 0 && totalDist > config.getMaximumDistanceAvoidAreas()) - throw new ServerLimitExceededException(RoutingErrorCodes.REQUEST_EXCEEDS_SERVER_LIMIT, "With areas to avoid, the approximated route distance must not be greater than " + Double.toString(config.getMaximumDistanceAvoidAreas()) + " meters."); + if (fallbackAlgorithm && config.getMaximumDistanceAvoidAreas() > 0 && totalDist > config.getMaximumDistanceAvoidAreas()) + throw new ServerLimitExceededException(RoutingErrorCodes.REQUEST_EXCEEDS_SERVER_LIMIT, "With these options, the approximated route distance must not be greater than " + Double.toString(config.getMaximumDistanceAvoidAreas()) + " meters."); } } @@ -609,12 +627,4 @@ public MatrixResult computeMatrix(MatrixRequest req) throws Exception { return rp.computeMatrix(req); } - public RouteOptimizationResult computeOptimizedRoutes(RouteOptimizationRequest req) throws Exception { - RoutingProfile rp = _routeProfiles.getRouteProfile(req.getProfileType(), true); - - if (rp == null) - throw new InternalServerException(OptimizationErrorCodes.UNKNOWN, "Unable to find an appropriate routing profile."); - - return rp.computeOptimizedRoutes(req); - } } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileType.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileType.java index 853a83b97f..214cdd8274 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileType.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileType.java @@ -21,9 +21,9 @@ public class RoutingProfileType { // DRIVING STUFF public static final int DRIVING_CAR = 1; public static final int DRIVING_HGV = 2; - public static final int DRIVING_EMERGENCY = 3; + public static final int DRIVING_EMERGENCY = 3; // not supported public static final int DRIVING_CAROFFROAD = 4; // not supported - public static final int DRIVING_SEGWAY = 5; // not supported + public static final int DRIVING_SEGWAY = 5; // not implemented public static final int DRIVING_ELECTRIC_CAR = 6; public static final int DRIVING_MOTORCYCLE = 7; public static final int DRIVING_TRAFFIC = 8; @@ -260,10 +260,10 @@ public static String getEncoderName(int routePref) { case RoutingProfileType.FOOT_WALKING: - return FlagEncoderNames.GH_FOOT; + return FlagEncoderNames.PEDESTRIAN_ORS; case RoutingProfileType.FOOT_HIKING: - return FlagEncoderNames.GH_HIKE; + return FlagEncoderNames.HIKING_ORS; case RoutingProfileType.WHEELCHAIR: diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingRequest.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingRequest.java index 045e67489d..87614e16c6 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingRequest.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingRequest.java @@ -43,6 +43,7 @@ public class RoutingRequest extends ServiceRequest private boolean _continueStraight = false; private Boolean _suppressWarnings = false; private List _skipSegments = new ArrayList<>(); + private boolean _includeCountryInfo = false; public RoutingRequest() { @@ -213,4 +214,12 @@ public List getSkipSegments() { public void setSkipSegments(List skipSegments) { _skipSegments = skipSegments; } + + public boolean getIncludeCountryInfo() { + return _includeCountryInfo; + } + + public void setIncludeCountryInfo(boolean includeCountryInfo) { + this._includeCountryInfo = includeCountryInfo; + } } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSDefaultFlagEncoderFactory.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSDefaultFlagEncoderFactory.java index 7d20d4123a..7204ad614d 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSDefaultFlagEncoderFactory.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSDefaultFlagEncoderFactory.java @@ -81,6 +81,12 @@ public FlagEncoder createFlagEncoder(String name, PMap configuration) { case FlagEncoderNames.WHEELCHAIR: return new heigit.ors.routing.graphhopper.extensions.flagencoders.WheelchairFlagEncoder(configuration); + + case FlagEncoderNames.PEDESTRIAN_ORS: + return new heigit.ors.routing.graphhopper.extensions.flagencoders.PedestrianFlagEncoder(configuration); + + case FlagEncoderNames.HIKING_ORS: + return new heigit.ors.routing.graphhopper.extensions.flagencoders.HikingFlagEncoder(configuration); } } } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSGraphHopper.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSGraphHopper.java index 91d6e6ae52..6253b7d2e9 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSGraphHopper.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSGraphHopper.java @@ -46,6 +46,7 @@ import heigit.ors.routing.graphhopper.extensions.edgefilters.core.AvoidFeaturesCoreEdgeFilter; import heigit.ors.routing.graphhopper.extensions.edgefilters.core.HeavyVehicleCoreEdgeFilter; import heigit.ors.routing.graphhopper.extensions.edgefilters.core.WheelchairCoreEdgeFilter; +import heigit.ors.routing.graphhopper.extensions.reader.borders.CountryBordersReader; import heigit.ors.routing.graphhopper.extensions.util.ORSParameters; import heigit.ors.routing.graphhopper.extensions.util.ORSParameters.Core; import heigit.ors.util.CoordTools; @@ -65,6 +66,7 @@ public class ORSGraphHopper extends GraphHopper { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private GraphProcessContext _procCntx; + private CountryBordersReader _generalCbReader; private HashMap> osmId2EdgeIds; // one osm id can correspond to multiple edges private HashMap tmcEdges; @@ -624,4 +626,14 @@ protected void loadOrPrepareCoreLM() { ghStorage.getProperties().put(ORSParameters.CoreLandmark.PREPARE + "done", true); } } + + public CountryBordersReader getGeneralCbReader() { + return _generalCbReader; + } + + public void setGeneralCbReader(CountryBordersReader _generalCbReader) { + this._generalCbReader = _generalCbReader; + } + + } \ No newline at end of file diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSOSMReader.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSOSMReader.java index 21e2940628..1fab1b88b2 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSOSMReader.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/ORSOSMReader.java @@ -20,7 +20,7 @@ import com.graphhopper.storage.GraphHopperStorage; import com.graphhopper.util.EdgeIteratorState; import com.graphhopper.util.Helper; -import com.vividsolutions.jts.geom.*; +import com.vividsolutions.jts.geom.Coordinate; import heigit.ors.routing.RoutingProfile; import heigit.ors.routing.graphhopper.extensions.reader.osmfeatureprocessors.OSMFeatureFilter; import heigit.ors.routing.graphhopper.extensions.reader.osmfeatureprocessors.WheelchairWayFilter; @@ -31,9 +31,13 @@ import org.apache.log4j.Logger; import java.io.InvalidObjectException; -import java.util.*; - +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; +import java.util.Set; public class ORSOSMReader extends OSMReader { diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/OSMTags.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/OSMTags.java new file mode 100644 index 0000000000..266f69e396 --- /dev/null +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/OSMTags.java @@ -0,0 +1,35 @@ +/* + * This file is part of Openrouteservice. + * + * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, see . + */ + +package heigit.ors.routing.graphhopper.extensions; + +public class OSMTags { + private OSMTags() { } + + public static class Keys { + public static final String HIGHWAY = "highway"; + public static final String SIDEWALK = "sidewalk"; + public static final String ROUTE = "route"; + public static final String FOOT = "foot"; + public static final String SAC_SCALE = "sac_scale"; + public static final String FORD = "ford"; + public static final String MOTOR_ROAD = "motorroad"; + public static final String JUNCTION = "junction"; + public static final String RAILWAY = "railway"; + public static final String MAN_MADE = "man_made"; + public static final String TUNNEL = "tunnel"; + public static final String BICYCLE = "bicycle"; + } +} diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/core/CoreLandmarkStorage.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/core/CoreLandmarkStorage.java index bfde7d74d7..6dae0955cc 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/core/CoreLandmarkStorage.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/core/CoreLandmarkStorage.java @@ -118,7 +118,7 @@ public double calcWeight(EdgeIteratorState edge, boolean reverse, int prevOrNext if (res >= Double.MAX_VALUE) return Double.POSITIVE_INFINITY; - expandEdge(tmp, false); + expandEdge(tmp); return count; } @@ -151,7 +151,7 @@ public String toString() { this.subnetworkStorage = new SubnetworkStorage(dir, "landmarks_core_" + name); } - private void expandEdge(CHEdgeIteratorState mainEdgeState, boolean reverse) { + private void expandEdge(CHEdgeIteratorState mainEdgeState) { if (!mainEdgeState.isShortcut()) { count += 1; return; @@ -161,22 +161,23 @@ private void expandEdge(CHEdgeIteratorState mainEdgeState, boolean reverse) { int skippedEdge2 = mainEdgeState.getSkippedEdge2(); int from = mainEdgeState.getBaseNode(), to = mainEdgeState.getAdjNode(); - - - CHEdgeIteratorState iter = core.getEdgeIteratorState(skippedEdge1, from); - boolean empty = iter == null; - if (empty) - iter = core.getEdgeIteratorState(skippedEdge2, from); - - expandEdge(iter, true); - - if (empty) - iter = core.getEdgeIteratorState(skippedEdge1, to); - else - iter = core.getEdgeIteratorState(skippedEdge2, to); - - expandEdge(iter, false); - + //TODO: This is an adaptation of the Path4CH expansion algo. The original algo does not properly apply to our core + // and therefore produces NPEs sometimes. For now this is fixed by a brute force algo that just tries to expand all edges and checks for null every time + CHEdgeIteratorState iter = core.getEdgeIteratorState(skippedEdge1, from); + if (iter != null) { + expandEdge(iter); + iter = core.getEdgeIteratorState(skippedEdge2, to); + if(iter != null) + expandEdge(iter); + } + else { + iter = core.getEdgeIteratorState(skippedEdge1, to); + if (iter != null) + expandEdge(iter); + iter = core.getEdgeIteratorState(skippedEdge2, from); + if (iter != null) + expandEdge(iter); + } } /** diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/AccessRestrictionsEdgeFilter.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/AccessRestrictionsEdgeFilter.java deleted file mode 100644 index 97271e2ad7..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/AccessRestrictionsEdgeFilter.java +++ /dev/null @@ -1,69 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.routing.graphhopper.extensions.edgefilters; - -import com.graphhopper.coll.GHIntArrayList; -import com.graphhopper.routing.EdgeIteratorStateHelper; -import com.graphhopper.routing.util.EdgeFilter; -import com.graphhopper.routing.util.FlagEncoder; -import com.graphhopper.storage.GraphStorage; -import com.graphhopper.util.EdgeIteratorState; -import heigit.ors.routing.RoutingProfileType; -import heigit.ors.routing.graphhopper.extensions.AccessRestrictionType; -import heigit.ors.routing.graphhopper.extensions.storages.AccessRestrictionsGraphStorage; -import heigit.ors.routing.graphhopper.extensions.storages.GraphStorageUtils; - -import java.util.List; - -public class AccessRestrictionsEdgeFilter implements EdgeFilter { - private int _vehicleType= 0; - private AccessRestrictionsGraphStorage _gsRestrictions; - private GHIntArrayList _allowedEdges; - private byte[] _buffer = new byte[2]; - - public AccessRestrictionsEdgeFilter(FlagEncoder encoder, GraphStorage graphStorage, List allowedEdges) { - - if (allowedEdges != null) - { - _allowedEdges = new GHIntArrayList(allowedEdges.size()); - for (Integer v : allowedEdges) - _allowedEdges.add(v); - } - - // motorcar = 0 - // motorcycle = 1 - // bicycle = 2 - // foot = 3 - int routePref = RoutingProfileType.getFromEncoderName(encoder.toString()); - - if (RoutingProfileType.isDriving(routePref) && routePref == RoutingProfileType.DRIVING_MOTORCYCLE) - _vehicleType = 1; - else if (RoutingProfileType.isDriving(routePref)) - _vehicleType = 0; - else if (RoutingProfileType.isCycling(routePref)) - _vehicleType = 2; - else if (RoutingProfileType.isWalking(routePref)) - _vehicleType = 3; - - _gsRestrictions = GraphStorageUtils.getGraphExtension(graphStorage, AccessRestrictionsGraphStorage.class); - } - - @Override - public final boolean accept(EdgeIteratorState iter) { - - return _gsRestrictions.getEdgeValue(EdgeIteratorStateHelper.getOriginalEdge(iter), _vehicleType, _buffer) == AccessRestrictionType.None || _allowedEdges == null || _allowedEdges.contains(EdgeIteratorStateHelper.getOriginalEdge(iter)); - - } - -} diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/AvoidBordersEdgeFilter.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/AvoidBordersEdgeFilter.java index 54f663b04b..6055bed63e 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/AvoidBordersEdgeFilter.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/AvoidBordersEdgeFilter.java @@ -25,6 +25,7 @@ public class AvoidBordersEdgeFilter implements EdgeFilter { private BordersExtractor.Avoid _avoidBorders = BordersExtractor.Avoid.NONE; private boolean _avoidCountries = false; + private boolean isStorageBuilt; private BordersExtractor _bordersExtractor; @@ -45,7 +46,8 @@ public AvoidBordersEdgeFilter(RouteSearchParameters searchParams, GraphStorage g */ private void init(RouteSearchParameters searchParams, BordersGraphStorage extBorders) { // Init the graph storage - if(extBorders != null) { + isStorageBuilt = extBorders != null; + if(isStorageBuilt) { int[] avoidCountries; if(searchParams.hasAvoidCountries()) avoidCountries = searchParams.getAvoidCountries(); @@ -71,6 +73,8 @@ private void init(RouteSearchParameters searchParams, BordersGraphStorage extBor */ @Override public final boolean accept(EdgeIteratorState iter) { + if(!isStorageBuilt) + return true; if (_avoidBorders != BordersExtractor.Avoid.NONE) { // We have been told to avoid some form of border diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/EmergencyVehicleEdgeFilter.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/EmergencyVehicleEdgeFilter.java deleted file mode 100644 index 288e886863..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/EmergencyVehicleEdgeFilter.java +++ /dev/null @@ -1,113 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.routing.graphhopper.extensions.edgefilters; - -import com.graphhopper.routing.EdgeIteratorStateHelper; -import com.graphhopper.routing.util.EdgeFilter; -import com.graphhopper.storage.GraphStorage; -import com.graphhopper.util.EdgeIteratorState; -import heigit.ors.routing.graphhopper.extensions.VehicleDimensionRestrictions; -import heigit.ors.routing.graphhopper.extensions.storages.EmergencyVehicleAttributesGraphStorage; -import heigit.ors.routing.graphhopper.extensions.storages.GraphStorageUtils; -import heigit.ors.routing.parameters.VehicleParameters; - -import java.util.ArrayList; - -public class EmergencyVehicleEdgeFilter implements EdgeFilter { - - private EmergencyVehicleAttributesGraphStorage gsAttributes; - private float[] restrictionValues; - private double[] retValues; - private Integer[] indexValues; - private int restCount; - private byte[] buffer; - - public EmergencyVehicleEdgeFilter(VehicleParameters vehicleParams, GraphStorage graphStorage) { - float[] vehicleAttrs = new float[VehicleDimensionRestrictions.Count]; - - vehicleAttrs[VehicleDimensionRestrictions.MaxHeight] = (float)vehicleParams.getHeight(); - vehicleAttrs[VehicleDimensionRestrictions.MaxWidth] = (float)vehicleParams.getWidth(); - vehicleAttrs[VehicleDimensionRestrictions.MaxWeight] = (float)vehicleParams.getWeight(); - vehicleAttrs[VehicleDimensionRestrictions.MaxLength] = (float)vehicleParams.getLength(); - vehicleAttrs[VehicleDimensionRestrictions.MaxAxleLoad] = (float)vehicleParams.getAxleload(); - - ArrayList idx = new ArrayList(); - - for (int i = 0; i < VehicleDimensionRestrictions.Count; i++) { - float value = vehicleAttrs[i]; - if (value > 0) { - idx.add(i); - } - } - - retValues = new double[5]; - Integer[] indexValues = idx.toArray(new Integer[idx.size()]); - - this.restrictionValues = vehicleAttrs; - this.restCount = indexValues == null ? 0 : indexValues.length; - this.indexValues = indexValues; - - this.buffer = new byte[2]; - - this.gsAttributes = GraphStorageUtils.getGraphExtension(graphStorage, EmergencyVehicleAttributesGraphStorage.class); - } - - @Override - public boolean accept(EdgeIteratorState iter) { - int edgeId = EdgeIteratorStateHelper.getOriginalEdge(iter); - - if (restCount != 0 && gsAttributes != null) { - if (restCount == 1) { - double value = gsAttributes.getEdgeRestrictionValue(edgeId, indexValues[0]); - if (value > 0 && value < restrictionValues[0]) - return false; - else - return true; - } else { - if (gsAttributes.getEdgeRestrictionValues(edgeId, retValues)) - { - double value = retValues[0]; - if (value > 0.0f && value < restrictionValues[0]) - return false; - - value = retValues[1]; - if (value > 0.0f && value < restrictionValues[1]) - return false; - - if (restCount >= 3) { - value = retValues[2]; - if (value > 0.0f && value < restrictionValues[2]) - return false; - } - - if (restCount >= 4) { - value = retValues[3]; - if (value > 0.0f && value < restrictionValues[3]) - return false; - } - - if (restCount == 5) { - value = retValues[4]; - if (value > 0.0f && value < restrictionValues[4]) - return false; - } - } - } - } - - return true; - - } - -} diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/core/AvoidBordersCoreEdgeFilter.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/core/AvoidBordersCoreEdgeFilter.java index 4ad45c098a..f2d9ba47fe 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/core/AvoidBordersCoreEdgeFilter.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/edgefilters/core/AvoidBordersCoreEdgeFilter.java @@ -24,16 +24,19 @@ public class AvoidBordersCoreEdgeFilter implements EdgeFilter { private BordersGraphStorage storage; private int[] avoidCountries; private boolean isAvoidCountries = false; + private boolean isStorageBuilt; //Used to avoid all borders public AvoidBordersCoreEdgeFilter(GraphStorage graphStorage) { this.storage = GraphStorageUtils.getGraphExtension(graphStorage, BordersGraphStorage.class); + isStorageBuilt = storage != null; } //Used to specify multiple countries to avoid (For a specific LM set) public AvoidBordersCoreEdgeFilter(GraphStorage graphStorage, int[] avoidCountries) { this.storage = GraphStorageUtils.getGraphExtension(graphStorage, BordersGraphStorage.class); this.avoidCountries = avoidCountries; if(avoidCountries.length > 0) isAvoidCountries = true; + isStorageBuilt = storage != null; } public int[] getAvoidCountries(){ @@ -46,17 +49,16 @@ public int[] getAvoidCountries(){ */ @Override public final boolean accept(EdgeIteratorState iter) { + //If there is no borders storage, we accept everything + if(!isStorageBuilt) return true; //If a specific country was given, just check if its one of the country borders if(iter instanceof CHEdgeIterator) if(((CHEdgeIterator)iter).isShortcut()) return true; if(isAvoidCountries) return !restrictedCountry(iter.getEdge()); //else check if there is ANY border - if (storage == null) { - return true; - } else { - return storage.getEdgeValue(iter.getEdge(), BordersGraphStorage.Property.TYPE) == BordersGraphStorage.NO_BORDER; - } + return storage.getEdgeValue(iter.getEdge(), BordersGraphStorage.Property.TYPE) == BordersGraphStorage.NO_BORDER; + } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/CarFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/CarFlagEncoder.java index ad3f91b1a4..39cd4508d4 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/CarFlagEncoder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/CarFlagEncoder.java @@ -35,7 +35,7 @@ * @author Peter Karich * @author Nop */ -public class CarFlagEncoder extends ORSAbstractFlagEncoder { +public class CarFlagEncoder extends VehicleFlagEncoder { private static Logger LOGGER = Logger.getLogger(CarFlagEncoder.class); @@ -54,6 +54,9 @@ public class CarFlagEncoder extends ORSAbstractFlagEncoder { // Take into account acceleration calculations when determining travel speed protected boolean useAcceleration = false; + // Mean speed for isochrone reach_factor + private static final int MEAN_SPEED = 100; + public CarFlagEncoder() { this(5, 5, 0); } @@ -184,6 +187,10 @@ public CarFlagEncoder(int speedBits, double speedFactor, int maxTurnCosts) { init(); } + public double getMeanSpeed() { + return MEAN_SPEED; + } + @Override public int getVersion() { return 1; 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 fccd005a92..3835693ce5 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 @@ -22,8 +22,9 @@ import java.util.*; -public class EmergencyFlagEncoder extends ORSAbstractFlagEncoder +public class EmergencyFlagEncoder extends VehicleFlagEncoder { + private final static double MEAN_SPEED = 80; protected final HashSet forwardKeys = new HashSet(5); protected final HashSet backwardKeys = new HashSet(5); protected final HashSet noValues = new HashSet(5); @@ -50,6 +51,8 @@ public EmergencyFlagEncoder() this(5, 5, 0); } + public double getMeanSpeed() { return MEAN_SPEED; } + public EmergencyFlagEncoder(PMap properties) { this(properties.getInt("speed_bits", 5), diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/FlagEncoderNames.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/FlagEncoderNames.java index f944c9ae6f..ad5615a178 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/FlagEncoderNames.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/FlagEncoderNames.java @@ -19,6 +19,9 @@ public interface FlagEncoderNames { public static final String MTB_ORS = "mtb-ors"; public static final String BIKE_ELECTRO = "electrobike"; + public static final String PEDESTRIAN_ORS = "pedestrian-ors"; + public static final String HIKING_ORS = "hiking-ors"; + public static final String GH_CAR = "car"; public static final String GH_CAR4WD = "car4wd"; diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/FootFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/FootFlagEncoder.java new file mode 100644 index 0000000000..14fff05c60 --- /dev/null +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/FootFlagEncoder.java @@ -0,0 +1,475 @@ +/* + * This file is part of Openrouteservice. + * + * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, see . + */ + +package heigit.ors.routing.graphhopper.extensions.flagencoders; + +import com.graphhopper.reader.ReaderRelation; +import com.graphhopper.reader.ReaderWay; +import com.graphhopper.routing.util.EncodedDoubleValue; +import com.graphhopper.routing.util.EncodedValue; +import com.graphhopper.routing.util.PriorityCode; +import com.graphhopper.routing.weighting.PriorityWeighting; +import heigit.ors.routing.graphhopper.extensions.OSMTags; + +import java.util.*; + +import static com.graphhopper.routing.util.PriorityCode.*; + +/** + * This code has been adapted from the original GraphHopper FootFlagEncoder found at + * https://github.com/graphhopper/graphhopper/blob/master/core/src/main/java/com/graphhopper/routing/util/FootFlagEncoder.java + * + * @author Adam Rousell + * @author Peter Karich + */ +public abstract class FootFlagEncoder extends ORSAbstractFlagEncoder { + static final int SLOW_SPEED = 2; + private static final int MEAN_SPEED = 5; + static final int FERRY_SPEED = 15; + + private final Set safeHighwayTags = new HashSet<>(); + private final Set allowedHighwayTags = new HashSet<>(); + private final Set avoidHighwayTags = new HashSet<>(); + + Set preferredWayTags = new HashSet<>(); + + private final Set avoidUnlessSidewalkTags = new HashSet<>(); + + Set suitableSacScales = new HashSet<>(); + // convert network tag of hiking routes into a way route code + final Map hikingNetworkToCode = new HashMap<>(); + Set usableSidewalkValues = new HashSet<>(5); + Set noSidewalkValues = new HashSet<>(5); + + protected EncodedValue priorityWayEncoder; + protected EncodedValue relationCodeEncoder; + + FootFlagEncoder(int speedBits, double speedFactor) { + super(speedBits, speedFactor, 0); + restrictions.addAll(Arrays.asList("foot", "access")); + + restrictedValues.addAll(Arrays.asList( + "private", + "no", + "restricted", + "military", + "emergency" + )); + + intendedValues.addAll(Arrays.asList( + "yes", + "designated", + "official", + "permissive" + )); + + noSidewalkValues.addAll(Arrays.asList( + "no", + "none", + "separate", + "separate" + )); + + usableSidewalkValues.addAll(Arrays.asList( + "yes", + "both", + "left", + "right" + )); + + setBlockByDefault(false); + potentialBarriers.add("gate"); + + safeHighwayTags.addAll(Arrays.asList( + "footway", + "path", + "steps", + "pedestrian", + "living_street", + "track", + "residential", + "service" + )); + + avoidHighwayTags.addAll(Arrays.asList( + "secondary", + "secondary_link", + "tertiary", + "tertiary_link" + )); + + avoidUnlessSidewalkTags.addAll(Arrays.asList( + "trunk", + "trunk_link", + "primary", + "primary_link" + )); + + allowedHighwayTags.addAll(safeHighwayTags); + allowedHighwayTags.addAll(avoidHighwayTags); + allowedHighwayTags.addAll(avoidUnlessSidewalkTags); + allowedHighwayTags.addAll(Arrays.asList( + "cycleway", + "unclassified", + "road" + )); + + hikingNetworkToCode.put("iwn", UNCHANGED.getValue()); + hikingNetworkToCode.put("nwn", UNCHANGED.getValue()); + hikingNetworkToCode.put("rwn", UNCHANGED.getValue()); + hikingNetworkToCode.put("lwn", UNCHANGED.getValue()); + + maxPossibleSpeed = FERRY_SPEED; + + init(); + } + + public double getMeanSpeed() { + return MEAN_SPEED; + } + + @Override + public int defineWayBits(int index, int shift) { + // first two bits are reserved for route handling in superclass + shift = super.defineWayBits(index, shift); + // larger value required - ferries are faster than pedestrians + speedEncoder = new EncodedDoubleValue("Speed", shift, speedBits, speedFactor, MEAN_SPEED, maxPossibleSpeed); + shift += speedEncoder.getBits(); + + priorityWayEncoder = new EncodedValue("PreferWay", shift, 3, 1, 0, 7); + shift += priorityWayEncoder.getBits(); + return shift; + } + + @Override + public int defineRelationBits(int index, int shift) { + relationCodeEncoder = new EncodedValue("RelationCode", shift, 3, 1, 0, 7); + return shift + relationCodeEncoder.getBits(); + } + + /** + * Foot flag encoder does not provide any turn cost / restrictions + */ + @Override + public int defineTurnBits(int index, int shift) { + return shift; + } + + /** + * Foot flag encoder does not provide any turn cost / restrictions + *

+ * + * @return false + */ + @Override + public boolean isTurnRestricted(long flag) { + return false; + } + + /** + * Foot flag encoder does not provide any turn cost / restrictions + *

+ * + * @return 0 + */ + @Override + public double getTurnCost(long flag) { + return 0; + } + + @Override + public long getTurnFlags(boolean restricted, double costs) { + return 0; + } + + @Override + public long handleRelationTags(ReaderRelation relation, long oldRelationFlags) { + int code = 0; + if (relation.hasTag(OSMTags.Keys.ROUTE, "hiking") || relation.hasTag(OSMTags.Keys.ROUTE, "foot")) { + Integer val = hikingNetworkToCode.get(relation.getTag("network")); + if (val != null) + code = val; + else + code = hikingNetworkToCode.get("lwn"); + } else if (relation.hasTag(OSMTags.Keys.ROUTE, "ferry")) { + code = PriorityCode.AVOID_IF_POSSIBLE.getValue(); + } + + int oldCode = (int) relationCodeEncoder.getValue(oldRelationFlags); + if (oldCode < code) + return relationCodeEncoder.setValue(0, code); + return oldRelationFlags; + } + + @Override + public long handleWayTags(ReaderWay way, long allowed, long relationFlags) { + if (!isAccept(allowed)) + return 0; + + long flags = 0; + if (!isFerry(allowed)) { + String sacScale = way.getTag(OSMTags.Keys.SAC_SCALE); + if (sacScale != null && !"hiking".equals(sacScale)) { + flags = speedEncoder.setDoubleValue(flags, SLOW_SPEED); + } else { + flags = speedEncoder.setDoubleValue(flags, MEAN_SPEED); + } + flags |= directionBitMask; + + boolean isRoundabout = way.hasTag(OSMTags.Keys.JUNCTION, "roundabout") || way.hasTag(OSMTags.Keys.JUNCTION, "circular"); + if (isRoundabout) + flags = setBool(flags, K_ROUNDABOUT, true); + + } else { + double ferrySpeed = getFerrySpeed(way); + flags = setSpeed(flags, ferrySpeed); + flags |= directionBitMask; + } + + int priorityFromRelation = 0; + if (relationFlags != 0) + priorityFromRelation = (int) relationCodeEncoder.getValue(relationFlags); + + flags = priorityWayEncoder.setValue(flags, handlePriority(way, priorityFromRelation)); + + return flags; + } + + @Override + public double getDouble(long flags, int key) { + if (key == PriorityWeighting.KEY) + return (double) priorityWayEncoder.getValue(flags) / BEST.getValue(); + else + return super.getDouble(flags, key); + } + + @Override + public long acceptWay(ReaderWay way) { + String highwayValue = way.getTag(OSMTags.Keys.HIGHWAY); + + if (highwayValue == null) + return handleNonHighways(way); + + if (hasTooDifficultSacScale(way)) + return 0; + + // no need to evaluate ferries or fords - already included here + if (way.hasTag(OSMTags.Keys.FOOT, intendedValues)) + return acceptBit; + + // check access restrictions + if (way.hasTag(restrictions, restrictedValues) && !getConditionalTagInspector().isRestrictedWayConditionallyPermitted(way)) + return 0; + + if (way.hasTag(OSMTags.Keys.SIDEWALK, usableSidewalkValues)) + return acceptBit; + + if (!allowedHighwayTags.contains(highwayValue)) + return 0; + + if (way.hasTag(OSMTags.Keys.MOTOR_ROAD, "yes")) + return 0; + + // do not get our feet wet, "yes" is already included above + if (isBlockFords() && (way.hasTag(OSMTags.Keys.HIGHWAY, "ford") || way.hasTag(OSMTags.Keys.FORD))) + return 0; + + if (getConditionalTagInspector().isPermittedWayConditionallyRestricted(way)) + return 0; + + return acceptBit; + } + + /** + * Method which generates the acceptance flag for ways that are not seen as being highways (such as ferry routes) + * + * @param way The way that is to be assessed + * @return The acceptance flag for the way + */ + private long handleNonHighways(ReaderWay way) { + long acceptPotentially = 0; + + if (way.hasTag(OSMTags.Keys.ROUTE, ferries)) { + String footTag = way.getTag(OSMTags.Keys.FOOT); + if (footTag == null || "yes".equals(footTag)) + acceptPotentially = acceptBit | ferryBit; + } + + // special case not for all acceptedRailways, only platform + if (way.hasTag(OSMTags.Keys.RAILWAY, "platform")) + acceptPotentially = acceptBit; + + if (way.hasTag(OSMTags.Keys.MAN_MADE, "pier")) + acceptPotentially = acceptBit; + + if (acceptPotentially != 0) { + if (way.hasTag(restrictions, restrictedValues) && !getConditionalTagInspector().isRestrictedWayConditionallyPermitted(way)) + return 0; + return acceptPotentially; + } + + return 0; + } + + /** + * Determine if the way is seen as being too difficult based on any sac_scale tags and the information provided in + * the setup of the object (suitableSacScales) + * + * @param way The way to be assessed + * @return Whether the way is too difficult or not + */ + private boolean hasTooDifficultSacScale(ReaderWay way) { + String sacScale = way.getTag(OSMTags.Keys.SAC_SCALE); + return sacScale != null && !suitableSacScales.contains(sacScale); + } + + /** + * Assign priorities based on relations and values stored against the way. This is the top level method that calls + * other priority assessment methods + * + * @param way The way to be assessed + * @param priorityFromRelation The priority obtained from any relations + * @return The overall priority value for the way + */ + private int handlePriority(ReaderWay way, int priorityFromRelation) { + TreeMap weightToPrioMap = new TreeMap<>(); + if (priorityFromRelation == 0) + weightToPrioMap.put(0d, UNCHANGED.getValue()); + else + weightToPrioMap.put(110d, priorityFromRelation); + + assignPriorities(way, weightToPrioMap); + + // pick priority with biggest order value + return weightToPrioMap.lastEntry().getValue(); + } + + /** + * @param weightToPrioMap associate a weight with every priority. This sorted map allows + * subclasses to 'insert' more important priorities as well as overwrite determined priorities. + */ + private void assignPriorities(ReaderWay way, TreeMap weightToPrioMap) { + if (way.hasTag(OSMTags.Keys.FOOT, "designated")) + weightToPrioMap.put(100d, PREFER.getValue()); + + assignSafeHighwayPriority(way, weightToPrioMap); + + assignAvoidHighwayPriority(way, weightToPrioMap); + + assignAvoidUnlessSidewalkPresentPriority(way, weightToPrioMap); + + assignBicycleWayPriority(way, weightToPrioMap); + + } + + /** + * Update the weight priority map based on values relating to highway types that are identified as being "safe" or + * with low speeds + * + * @param way The way containing the tag information + * @param weightToPrioMap The priority weight map that will have the weightings updated + */ + void assignSafeHighwayPriority(ReaderWay way, TreeMap weightToPrioMap) { + String highway = way.getTag(OSMTags.Keys.HIGHWAY); + double maxSpeed = getMaxSpeed(way); + + if (safeHighwayTags.contains(highway) || maxSpeed > 0 && maxSpeed <= 20) { + if (preferredWayTags.contains(highway)) + weightToPrioMap.put(40d, VERY_NICE.getValue()); + else { + weightToPrioMap.put(40d, PREFER.getValue()); + } + assignTunnelPriority(way, weightToPrioMap); + } + } + + /** + * Update the weight priority map based on tunnel information + * + * @param way The way containing the tag information + * @param weightToPrioMap The priority weight map that will have the weightings updated + */ + void assignTunnelPriority(ReaderWay way, TreeMap weightToPrioMap) { + if (way.hasTag(OSMTags.Keys.TUNNEL, intendedValues)) { + if (way.hasTag(OSMTags.Keys.SIDEWALK, noSidewalkValues)) + weightToPrioMap.put(40d, AVOID_IF_POSSIBLE.getValue()); + else + weightToPrioMap.put(40d, UNCHANGED.getValue()); + } + } + + /** + * Update the weight priority map based on values relating to avoiding highways + * + * @param way The way containing the tag information + * @param weightToPrioMap The priority weight map that will have the weightings updated + */ + private void assignAvoidHighwayPriority(ReaderWay way, TreeMap weightToPrioMap) { + String highway = way.getTag(OSMTags.Keys.HIGHWAY); + double maxSpeed = getMaxSpeed(way); + + if ((maxSpeed > 50 || avoidHighwayTags.contains(highway)) + && !way.hasTag(OSMTags.Keys.SIDEWALK, usableSidewalkValues)) { + weightToPrioMap.put(45d, REACH_DEST.getValue()); + } + } + + /** + * Mark the way as to be avoided if there is no sidewalk present on highway types identified as needing a sidewalk + * to be traversed + * + * @param way The way containing the tag information + * @param weightToPrioMap The priority weight map that will have the weightings updated + */ + private void assignAvoidUnlessSidewalkPresentPriority(ReaderWay way, TreeMap weightToPrioMap) { + String highway = way.getTag(OSMTags.Keys.HIGHWAY); + if (avoidUnlessSidewalkTags.contains(highway) && !way.hasTag(OSMTags.Keys.SIDEWALK, usableSidewalkValues)) + weightToPrioMap.put(45d, AVOID_AT_ALL_COSTS.getValue()); + } + + /** + * Update the weight priority map based on values relating to bicycle ways. + * + * @param way The way containing the tag information + * @param weightToPrioMap The priority weight map that will have the weightings updated + */ + private void assignBicycleWayPriority(ReaderWay way, TreeMap weightToPrioMap) { + if (way.hasTag(OSMTags.Keys.BICYCLE, "official") || way.hasTag(OSMTags.Keys.BICYCLE, "designated")) + weightToPrioMap.put(44d, AVOID_IF_POSSIBLE.getValue()); + } + + @Override + public boolean supports(Class feature) { + if (super.supports(feature)) { + return true; + } + + return PriorityWeighting.class.isAssignableFrom(feature); + } + + /* + * This method is a current hack, to allow ferries to be actually faster than our current storable maxSpeed. + */ + @Override + public double getSpeed(long flags) { + double speed = super.getSpeed(flags); + if (speed == getMaxSpeed()) { + // We cannot be sure if it was a long or a short trip + return SHORT_TRIP_FERRY_SPEED; + } + + return speed; + } +} diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/HeavyVehicleFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/HeavyVehicleFlagEncoder.java index f9e154dfb1..188737d808 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/HeavyVehicleFlagEncoder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/HeavyVehicleFlagEncoder.java @@ -27,7 +27,7 @@ import static com.graphhopper.routing.util.PriorityCode.BEST; import static com.graphhopper.routing.util.PriorityCode.UNCHANGED; -public class HeavyVehicleFlagEncoder extends ORSAbstractFlagEncoder +public class HeavyVehicleFlagEncoder extends VehicleFlagEncoder { protected final HashSet forwardKeys = new HashSet(5); protected final HashSet backwardKeys = new HashSet(5); @@ -37,6 +37,7 @@ public class HeavyVehicleFlagEncoder extends ORSAbstractFlagEncoder protected boolean useAcceleration = false; protected int maxTrackGradeLevel = 3; + private static final int MEAN_SPEED = 70; /** * A map which associates string to speed. Get some impression: @@ -186,6 +187,10 @@ public HeavyVehicleFlagEncoder( int speedBits, double speedFactor, int maxTurnCo init(); } + + public double getMeanSpeed() { + return MEAN_SPEED; + } public double getDefaultMaxSpeed() { diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/HikingFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/HikingFlagEncoder.java new file mode 100644 index 0000000000..883a3254fc --- /dev/null +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/HikingFlagEncoder.java @@ -0,0 +1,66 @@ +/* + * This file is part of Openrouteservice. + * + * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, see . + */ + +package heigit.ors.routing.graphhopper.extensions.flagencoders; + +import com.graphhopper.util.PMap; + +import java.util.Arrays; + +import static com.graphhopper.routing.util.PriorityCode.BEST; +import static com.graphhopper.routing.util.PriorityCode.VERY_NICE; + +public class HikingFlagEncoder extends FootFlagEncoder { + public HikingFlagEncoder(PMap properties) { + this((int) properties.getLong("speedBits", 4), + properties.getDouble("speedFactor", 1)); + this.properties = properties; + this.setBlockFords(properties.getBool("block_fords", false)); + } + + private HikingFlagEncoder(int speedBits, double speedFactor) { + super(speedBits, speedFactor); + + hikingNetworkToCode.put("iwn", BEST.getValue()); + hikingNetworkToCode.put("nwn", BEST.getValue()); + hikingNetworkToCode.put("rwn", VERY_NICE.getValue()); + hikingNetworkToCode.put("lwn", VERY_NICE.getValue()); + + suitableSacScales.addAll(Arrays.asList( + "hiking", + "mountain_hiking", + "demanding_mountain_hiking", + "alpine_hiking" + )); + + preferredWayTags.addAll(Arrays.asList( + "track", + "path", + "footway" + )); + + init(); + } + + @Override + public int getVersion() { + return 3; + } + + @Override + public String toString() { + return FlagEncoderNames.HIKING_ORS; + } +} diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/ORSAbstractFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/ORSAbstractFlagEncoder.java index e790d964ae..1cd92adb89 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/ORSAbstractFlagEncoder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/ORSAbstractFlagEncoder.java @@ -15,199 +15,176 @@ import com.graphhopper.reader.ReaderWay; import com.graphhopper.routing.util.AbstractFlagEncoder; +import com.graphhopper.routing.util.EncodedDoubleValue; +import com.graphhopper.util.BitUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public abstract class ORSAbstractFlagEncoder extends AbstractFlagEncoder { + private final static Logger logger = LoggerFactory.getLogger(ORSAbstractFlagEncoder.class); - private final double ACCELERATION_SPEED_CUTOFF_MAX = 80.0; - private final double ACCELERATION_SPEED_CUTOFF_MIN = 20.0; - protected SpeedLimitHandler _speedLimitHandler; - - private double accelerationModifier = 0.0; + protected boolean considerElevation = false; + protected EncodedDoubleValue reverseSpeedEncoder; + protected boolean blockByDefault = true; protected ORSAbstractFlagEncoder(int speedBits, double speedFactor, int maxTurnCosts) { super(speedBits, speedFactor, maxTurnCosts); } - double addResedentialPenalty(double baseSpeed, ReaderWay way) { - if (baseSpeed == 0) - return 0; - double speed = baseSpeed; - - if(way.hasTag("highway","residential")) { - double estDist = way.getTag("estimated_distance", Double.MAX_VALUE); - // take into account number of nodes to get an average distance between nodes - double interimDistance = estDist; - int interimNodes = way.getNodes().size() - 2; - if(interimNodes > 0) { - interimDistance = estDist/(interimNodes+1); - } - if(interimDistance < 100) { - speed = speed * 0.5; - } - //Don't go below 2.5 because it will be stored as 0 later - if(speed < 5) - speed = 5; - } - - return speed; + public void setConsiderElevation(boolean considerElevation) { + this.considerElevation = considerElevation; } - double averageSecondsTo100KmpH() { return 10; } - - /** - * Returns how many seconds it is assumed that this vehicle would reach 100 km/h taking into acocunt the acceleration modifier - * - * @return - */ - double secondsTo100KmpH() { - return averageSecondsTo100KmpH() + (accelerationModifier * averageSecondsTo100KmpH()); - } - - /** - * Returns the acceleration in KM per hour per second. - * - * @return - */ - double accelerationKmpHpS() { - return 100.0 / secondsTo100KmpH(); - } - - /** - * Adjust the maximum speed taking into account supposed acceleration on the segment. The method looks at acceleration - * along the way (assuming starting from 0km/h) and then uses the length to travel and the supposed maximum speed - * to determine an average speed for travelling along the whole segment. - * - * @param distance How long the segment to travel along is - * @param maximumSpeedInKmph The maximum speed that a vehicle can travel along this segment (usually the speed limit) - * @return - */ - double adjustSpeedForAcceleration(double distance, double maximumSpeedInKmph) { - // We only want to perform the adjustment if the road is a slower speed - main roads shouldnt be affected as much due to less junctions and changes in direction - if(maximumSpeedInKmph < ACCELERATION_SPEED_CUTOFF_MAX) { - if (distance <= 0) { - return maximumSpeedInKmph; - } - - // slower roads can be assumed to have slower acceleration... - - double normalisedSpeed = maximumSpeedInKmph; - if(normalisedSpeed < ACCELERATION_SPEED_CUTOFF_MIN) - normalisedSpeed = ACCELERATION_SPEED_CUTOFF_MIN; + public abstract double getMeanSpeed(); - normalisedSpeed = (normalisedSpeed -ACCELERATION_SPEED_CUTOFF_MIN) / (ACCELERATION_SPEED_CUTOFF_MAX-ACCELERATION_SPEED_CUTOFF_MIN); - - accelerationModifier = Math.pow(0.01, normalisedSpeed); - - double timeToMaxSpeed = durationToMaxSpeed(0, maximumSpeedInKmph); - - // We need to calculate how much distance is travelled in acceleration/deceleration phases - double accelerationDistance = distanceTravelledInDuration(0, maximumSpeedInKmph, timeToMaxSpeed); - - double distanceAtMaxSpeed = distance - (accelerationDistance * 2); // Double the distance because of deceleration aswell - - double averageSpeed; + @Override + public long reverseFlags(long flags) { + flags = super.reverseFlags(flags); + if (considerElevation) { + // swap speeds + double temp = reverseSpeedEncoder.getDoubleValue(flags); + flags = setReverseSpeed(flags, speedEncoder.getDoubleValue(flags)); + flags = setSpeed(flags, temp); + } + return flags; + } - if (distanceAtMaxSpeed < 0) { - averageSpeed = convertMpsToKmph(distance / (durationToTravelDistance(0, maximumSpeedInKmph, distance / 2) * 2)); + @Override + protected long setLowSpeed(long flags, double speed, boolean reverse) { + if (considerElevation) { + if (reverse) { + return setBool(reverseSpeedEncoder.setDoubleValue(flags, 0), K_BACKWARD, false); } else { - double timeAtMaxSpeed = distanceAtMaxSpeed / convertKmphToMps(maximumSpeedInKmph); - double averageSpeedMps = distance / (timeToMaxSpeed*2 + timeAtMaxSpeed); - - averageSpeed = convertMpsToKmph(averageSpeedMps); + return setBool(speedEncoder.setDoubleValue(flags, 0), K_FORWARD, false); } - - return averageSpeed; - } else { - return maximumSpeedInKmph; } + return super.setLowSpeed(flags, speed, reverse); } - /** - * How many seconds does it take to reach maximum speed based on initial speed and acceleration. - * - * @param initialSpeedInKmph How fast the vehicle is travelling at the start of the calculation - * @param maxSpeedInKmph The target speed to be reached - * @return How long it takes to reach the speed in seconds - */ - private double durationToMaxSpeed(double initialSpeedInKmph, double maxSpeedInKmph) { - return (maxSpeedInKmph - initialSpeedInKmph) / accelerationKmpHpS(); + @Override + public long flagsDefault(boolean forward, boolean backward) { + long flags = super.flagsDefault(forward, backward); + if (considerElevation && backward) { + flags = reverseSpeedEncoder.setDefaultValue(flags); + } + return flags; } - /** - * How long in seconds does it take to reach the intended distance based on the initial travelling speed and the - * maximum speed that can be travelled. - * - * @param initialSpeedInKmph The speed of the vehicle when starting the calculation - * @param maxSpeedInKmph The maximum speed the vehicle can travel at - * @param distanceInM The target distance to be travelled - * @return How long it takes in seconds to reach the target distance - */ - private double durationToTravelDistance(double initialSpeedInKmph, double maxSpeedInKmph, double distanceInM) { - double secondsTravelled = 0; - double distanceTravelled = 0; - - double currentSpeed = initialSpeedInKmph; - - while(currentSpeed < maxSpeedInKmph && distanceTravelled < distanceInM) { - currentSpeed += accelerationKmpHpS(); - secondsTravelled += 1; - distanceTravelled += convertKmphToMps(currentSpeed); + @Override + public long setReverseSpeed(long flags, double speed) { + if (considerElevation) { + // taken from GH Bike2WeightFlagEncoder.setReverseSpeed(...) + if (speed < 0 || Double.isNaN(speed)) { + throw new IllegalArgumentException("Speed cannot be negative: " + speed + ", flags:" + BitUtil.LITTLE.toBitString(flags)); + } + if (speed < speedEncoder.getFactor() / 2) { + return setLowSpeed(flags, speed, true); + } + if (speed > getMaxSpeed()) { + speed = getMaxSpeed(); + } + return reverseSpeedEncoder.setDoubleValue(flags, speed); + } else { + return setSpeed(flags, speed); } + } - double distanceRemaining = distanceInM - distanceTravelled; + @Override + public double getReverseSpeed(long flags) { + if (considerElevation) { + return reverseSpeedEncoder.getDoubleValue(flags); + } + return getSpeed(flags); + } - if(distanceRemaining > 0) { - secondsTravelled += (distanceRemaining / convertKmphToMps(maxSpeedInKmph)); + @Override + public long setProperties(double speed, boolean forward, boolean backward) { + long flags = super.setAccess(setSpeed(0, speed), forward, backward); + if (considerElevation && backward) { + flags = setReverseSpeed(flags, speed); } + return flags; + } - return secondsTravelled; + @Override + public double getMaxSpeed(ReaderWay way) { + return super.getMaxSpeed(way); } - /** - * How far can the vehicle travel in the specified time frame - * - * @param initialSpeedInKmph The starting speed of the vehicle - * @param maxSpeedInKmph The maximum travel speed - * @param duration How long is the vehicle travelling for - * @return The distance in metres that the vehicle travels in the specified time - */ - private double distanceTravelledInDuration(double initialSpeedInKmph, double maxSpeedInKmph, double duration) { - double secondsTravelled = 0; - double distanceTravelled = 0; - double currentSpeed = initialSpeedInKmph; - - while(currentSpeed < maxSpeedInKmph && secondsTravelled < duration) { - currentSpeed += accelerationKmpHpS(); - secondsTravelled += 1; - distanceTravelled += convertKmphToMps(currentSpeed); - } + @Override + protected double getFerrySpeed(ReaderWay way) { + return getFerrySpeed(way, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE); + } - double secondsRemaining = duration - secondsTravelled; + protected double getFerrySpeed(ReaderWay way, double unknownSpeed, double shortTripsSpeed, double longTripsSpeed) { + // taken from GH AbstractFlagEncoder.getFerrySpeed(...), + long duration = 0; - if(secondsRemaining > 0 ) { - distanceTravelled += (secondsRemaining * convertKmphToMps(maxSpeedInKmph)); + try { + // During the reader process we have converted the duration value into a artificial tag called "duration:seconds". + duration = Long.parseLong(way.getTag("duration:seconds")); + } catch (Exception ex) { } + // seconds to hours + double durationInHours = duration / 60d / 60d; + // Check if our graphhopper specific artificially created estimated_distance way tag is present + Number estimatedLength = way.getTag("estimated_distance", null); + if (durationInHours > 0) + try { + if (estimatedLength != null) { + double estimatedLengthInKm = estimatedLength.doubleValue() / 1000; + // If duration AND distance is available we can calculate the speed more precisely + // and set both speed to the same value. Factor 1.4 slower because of waiting time! + double calculatedTripSpeed = estimatedLengthInKm / durationInHours / 1.4; + // Plausibility check especially for the case of wrongly used PxM format with the intention to + // specify the duration in minutes, but actually using months + if (calculatedTripSpeed > 0.01d) { + if (calculatedTripSpeed > getMaxSpeed()) { + return getMaxSpeed(); + } + // If the speed is lower than the speed we can store, we have to set it to the minSpeed, but > 0 + if (Math.round(calculatedTripSpeed) < speedEncoder.getFactor() / 2) { + return speedEncoder.getFactor() / 2; + } + + return Math.round(calculatedTripSpeed); + } else { + long lastId = way.getNodes().isEmpty() ? -1 : way.getNodes().get(way.getNodes().size() - 1); + long firstId = way.getNodes().isEmpty() ? -1 : way.getNodes().get(0); + if (firstId != lastId) + logger.warn("Unrealistic long duration ignored in way with way ID=" + way.getId() + " : Duration tag value=" + + way.getTag("duration") + " (=" + Math.round(duration / 60d) + " minutes)"); + durationInHours = 0; + } + } + } catch (Exception ex) { + } - return distanceTravelled; + if (durationInHours == 0) { + if(estimatedLength != null && estimatedLength.doubleValue() <= 300) + return speedEncoder.getFactor() / 2; + if(Integer.MIN_VALUE == unknownSpeed) + return UNKNOWN_DURATION_FERRY_SPEED; + return unknownSpeed; + } else if (durationInHours > 1) { + // lengthy ferries should be faster than short trip ferry + if(Integer.MIN_VALUE == longTripsSpeed) + return LONG_TRIP_FERRY_SPEED; + return longTripsSpeed; + } else { + if(Integer.MIN_VALUE == shortTripsSpeed) + return SHORT_TRIP_FERRY_SPEED; + return shortTripsSpeed; + } } - /** - * Convert kilometres per hour to metres per second - * - * @param speedInKmph The speed to be converted in km per hour - * @return The speed in metres per second - */ - private double convertKmphToMps(double speedInKmph) { - return (speedInKmph * 1000) / 3600; + @Override + public void setBlockByDefault(boolean blockByDefault) { + super.setBlockByDefault(blockByDefault); + this.blockByDefault = blockByDefault; } - /** - * Convert metres per second to kilometres per hour - * - * @param speedInMps The speed in metres per second - * @return The speed in kilometres per hour - */ - private double convertMpsToKmph(double speedInMps) { - return (3600 * speedInMps) / 1000; + public boolean isBlockByDefault() { + return this.blockByDefault; } } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/PedestrianFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/PedestrianFlagEncoder.java new file mode 100644 index 0000000000..24f24d2c72 --- /dev/null +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/PedestrianFlagEncoder.java @@ -0,0 +1,47 @@ +/* + * This file is part of Openrouteservice. + * + * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, see . + */ + +package heigit.ors.routing.graphhopper.extensions.flagencoders; + +import com.graphhopper.util.PMap; + +public class PedestrianFlagEncoder extends FootFlagEncoder { + + public PedestrianFlagEncoder(PMap properties) { + this((int) properties.getLong("speedBits", 4), + properties.getDouble("speedFactor", 1)); + this.properties = properties; + this.setBlockFords(properties.getBool("block_fords", true)); + } + + private PedestrianFlagEncoder(int speedBits, double speedFactor) { + super(speedBits, speedFactor); + + suitableSacScales.add("hiking"); + + init(); + } + + @Override + + public int getVersion() { + return 4; + } + + @Override + public String toString() { + return FlagEncoderNames.PEDESTRIAN_ORS; + } +} diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/VehicleFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/VehicleFlagEncoder.java new file mode 100644 index 0000000000..9c1ad08236 --- /dev/null +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/VehicleFlagEncoder.java @@ -0,0 +1,213 @@ +/* + * This file is part of Openrouteservice. + * + * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, see . + */ + +package heigit.ors.routing.graphhopper.extensions.flagencoders; + +import com.graphhopper.reader.ReaderWay; + +public abstract class VehicleFlagEncoder extends ORSAbstractFlagEncoder { + private final double ACCELERATION_SPEED_CUTOFF_MAX = 80.0; + private final double ACCELERATION_SPEED_CUTOFF_MIN = 20.0; + protected SpeedLimitHandler _speedLimitHandler; + + private double accelerationModifier = 0.0; + + VehicleFlagEncoder(int speedBits, double speedFactor, int maxTurnCosts) { + super(speedBits, speedFactor, maxTurnCosts); + } + + double addResedentialPenalty(double baseSpeed, ReaderWay way) { + if (baseSpeed == 0) + return 0; + double speed = baseSpeed; + + if(way.hasTag("highway","residential")) { + double estDist = way.getTag("estimated_distance", Double.MAX_VALUE); + // take into account number of nodes to get an average distance between nodes + double interimDistance = estDist; + int interimNodes = way.getNodes().size() - 2; + if(interimNodes > 0) { + interimDistance = estDist/(interimNodes+1); + } + if(interimDistance < 100) { + speed = speed * 0.5; + } + //Don't go below 2.5 because it will be stored as 0 later + if(speed < 5) + speed = 5; + } + + return speed; + } + + double averageSecondsTo100KmpH() { return 10; } + + /** + * Returns how many seconds it is assumed that this vehicle would reach 100 km/h taking into acocunt the acceleration modifier + * + * @return + */ + double secondsTo100KmpH() { + return averageSecondsTo100KmpH() + (accelerationModifier * averageSecondsTo100KmpH()); + } + + /** + * Returns the acceleration in KM per hour per second. + * + * @return + */ + double accelerationKmpHpS() { + return 100.0 / secondsTo100KmpH(); + } + + /** + * Adjust the maximum speed taking into account supposed acceleration on the segment. The method looks at acceleration + * along the way (assuming starting from 0km/h) and then uses the length to travel and the supposed maximum speed + * to determine an average speed for travelling along the whole segment. + * + * @param distance How long the segment to travel along is + * @param maximumSpeedInKmph The maximum speed that a vehicle can travel along this segment (usually the speed limit) + * @return + */ + double adjustSpeedForAcceleration(double distance, double maximumSpeedInKmph) { + // We only want to perform the adjustment if the road is a slower speed - main roads shouldnt be affected as much due to less junctions and changes in direction + if(maximumSpeedInKmph < ACCELERATION_SPEED_CUTOFF_MAX) { + if (distance <= 0) { + return maximumSpeedInKmph; + } + + // slower roads can be assumed to have slower acceleration... + + double normalisedSpeed = maximumSpeedInKmph; + if(normalisedSpeed < ACCELERATION_SPEED_CUTOFF_MIN) + normalisedSpeed = ACCELERATION_SPEED_CUTOFF_MIN; + + normalisedSpeed = (normalisedSpeed -ACCELERATION_SPEED_CUTOFF_MIN) / (ACCELERATION_SPEED_CUTOFF_MAX-ACCELERATION_SPEED_CUTOFF_MIN); + + accelerationModifier = Math.pow(0.01, normalisedSpeed); + + double timeToMaxSpeed = durationToMaxSpeed(0, maximumSpeedInKmph); + + // We need to calculate how much distance is travelled in acceleration/deceleration phases + double accelerationDistance = distanceTravelledInDuration(0, maximumSpeedInKmph, timeToMaxSpeed); + + double distanceAtMaxSpeed = distance - (accelerationDistance * 2); // Double the distance because of deceleration aswell + + double averageSpeed; + + if (distanceAtMaxSpeed < 0) { + averageSpeed = convertMpsToKmph(distance / (durationToTravelDistance(0, maximumSpeedInKmph, distance / 2) * 2)); + } else { + double timeAtMaxSpeed = distanceAtMaxSpeed / convertKmphToMps(maximumSpeedInKmph); + double averageSpeedMps = distance / (timeToMaxSpeed*2 + timeAtMaxSpeed); + + averageSpeed = convertMpsToKmph(averageSpeedMps); + } + + return averageSpeed; + } else { + return maximumSpeedInKmph; + } + } + + /** + * How many seconds does it take to reach maximum speed based on initial speed and acceleration. + * + * @param initialSpeedInKmph How fast the vehicle is travelling at the start of the calculation + * @param maxSpeedInKmph The target speed to be reached + * @return How long it takes to reach the speed in seconds + */ + private double durationToMaxSpeed(double initialSpeedInKmph, double maxSpeedInKmph) { + return (maxSpeedInKmph - initialSpeedInKmph) / accelerationKmpHpS(); + } + + /** + * How long in seconds does it take to reach the intended distance based on the initial travelling speed and the + * maximum speed that can be travelled. + * + * @param initialSpeedInKmph The speed of the vehicle when starting the calculation + * @param maxSpeedInKmph The maximum speed the vehicle can travel at + * @param distanceInM The target distance to be travelled + * @return How long it takes in seconds to reach the target distance + */ + private double durationToTravelDistance(double initialSpeedInKmph, double maxSpeedInKmph, double distanceInM) { + double secondsTravelled = 0; + double distanceTravelled = 0; + + double currentSpeed = initialSpeedInKmph; + + while(currentSpeed < maxSpeedInKmph && distanceTravelled < distanceInM) { + currentSpeed += accelerationKmpHpS(); + secondsTravelled += 1; + distanceTravelled += convertKmphToMps(currentSpeed); + } + + double distanceRemaining = distanceInM - distanceTravelled; + + if(distanceRemaining > 0) { + secondsTravelled += (distanceRemaining / convertKmphToMps(maxSpeedInKmph)); + } + + return secondsTravelled; + } + + /** + * How far can the vehicle travel in the specified time frame + * + * @param initialSpeedInKmph The starting speed of the vehicle + * @param maxSpeedInKmph The maximum travel speed + * @param duration How long is the vehicle travelling for + * @return The distance in metres that the vehicle travels in the specified time + */ + private double distanceTravelledInDuration(double initialSpeedInKmph, double maxSpeedInKmph, double duration) { + double secondsTravelled = 0; + double distanceTravelled = 0; + double currentSpeed = initialSpeedInKmph; + + while(currentSpeed < maxSpeedInKmph && secondsTravelled < duration) { + currentSpeed += accelerationKmpHpS(); + secondsTravelled += 1; + distanceTravelled += convertKmphToMps(currentSpeed); + } + + double secondsRemaining = duration - secondsTravelled; + + if(secondsRemaining > 0 ) { + distanceTravelled += (secondsRemaining * convertKmphToMps(maxSpeedInKmph)); + } + + return distanceTravelled; + } + + /** + * Convert kilometres per hour to metres per second + * + * @param speedInKmph The speed to be converted in km per hour + * @return The speed in metres per second + */ + private double convertKmphToMps(double speedInKmph) { + return (speedInKmph * 1000) / 3600; + } + + /** + * Convert metres per second to kilometres per hour + * + * @param speedInMps The speed in metres per second + * @return The speed in kilometres per hour + */ + private double convertMpsToKmph(double speedInMps) { + return (3600 * speedInMps) / 1000; + } +} diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/WheelchairFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/WheelchairFlagEncoder.java index e4a4deb182..4c6aa018ba 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/WheelchairFlagEncoder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/WheelchairFlagEncoder.java @@ -16,7 +16,6 @@ import com.graphhopper.reader.ReaderNode; import com.graphhopper.reader.ReaderRelation; import com.graphhopper.reader.ReaderWay; -import com.graphhopper.routing.util.AbstractFlagEncoder; import com.graphhopper.routing.util.EncodedDoubleValue; import com.graphhopper.routing.util.EncodedValue; import com.graphhopper.routing.util.PriorityCode; @@ -28,54 +27,43 @@ import static com.graphhopper.routing.util.PriorityCode.*; -public class WheelchairFlagEncoder extends AbstractFlagEncoder -{ - static final int SLOW_SPEED = 2; +public class WheelchairFlagEncoder extends FootFlagEncoder { public static final int MEAN_SPEED = 4; - static final int FERRY_SPEED = 10; static final int MAX_SPEED = 15; - private EncodedValue priorityWayEncoder; - private EncodedValue relationCodeEncoder; - - private final Set usableSidewalkValues = new HashSet(); - private final Set noSidewalkValues = new HashSet(); - // convert network tag of hiking routes into a way route code - private final Map hikingNetworkToCode = new HashMap(); - - protected HashSet acceptedPublicTransport = new HashSet(5); + protected Set acceptedPublicTransport = new HashSet<>(5); /** * Fully suitable for wheelchair users */ - private final Set fullyWheelchairAccessibleHighways = new HashSet(); + private final Set fullyWheelchairAccessibleHighways = new HashSet<>(); /** * Suitable for wheelchair users. However highways falling into this category that explicitly indicate a sidewalk is available will be prefered */ - private final Set assumedWheelchairAccessibleHighways = new HashSet(); + private final Set assumedWheelchairAccessibleHighways = new HashSet<>(); /** * Highways that fall into this category will only be considered if further information about surface/smoothness is available */ - private final Set limitedWheelchairAccessibleHighways = new HashSet(); + private final Set limitedWheelchairAccessibleHighways = new HashSet<>(); /** * Highways that fall into this category will only be considered if further information about surface/smoothness is available */ - private final Set restrictedWheelchairHighways = new HashSet(); + private final Set restrictedWheelchairHighways = new HashSet<>(); /** * Highways that fall into this category cannot be accessed by Wheelchair users (e.g. steps) */ - private final Set nonWheelchairAccessibleHighways = new HashSet(); + private final Set nonWheelchairAccessibleHighways = new HashSet<>(); /** * Barriers (nodes) that are not accessible. Routes that would these nodes are not possible. */ - private HashSet inaccessibleBarriers = new HashSet(5); + private Set inaccessibleBarriers = new HashSet<>(5); - private final Set accessibilityRelatedAttributes = new HashSet(); + private final Set accessibilityRelatedAttributes = new HashSet<>(); public WheelchairFlagEncoder(PMap configuration) { @@ -93,34 +81,12 @@ public WheelchairFlagEncoder() public WheelchairFlagEncoder( int speedBits, double speedFactor ) { - super(speedBits, speedFactor, 0); + super(speedBits, speedFactor); // test for the following restriction keys - restrictions.addAll(Arrays.asList("foot", "access", "wheelchair")); - - // for nodes: these values make the node impassable for any value of restrictions - // for ways: these values make the way impassable for any value of restrictions - restrictedValues.add("private"); - restrictedValues.add("no"); - restrictedValues.add("restricted"); - - intendedValues.add("yes"); - intendedValues.add("designated"); - intendedValues.add("official"); - intendedValues.add("permissive"); - // TODO: include limited here or not? maybe make this is an parameter, selectable via client UI? + restrictions.add("wheelchair"); + intendedValues.add("limited"); - usableSidewalkValues.add("yes"); - usableSidewalkValues.add("both"); - usableSidewalkValues.add("left"); - usableSidewalkValues.add("right"); - - noSidewalkValues.add("no"); - noSidewalkValues.add("none"); - noSidewalkValues.add("separate"); - noSidewalkValues.add("seperate"); - noSidewalkValues.add("detached"); - // http://wiki.openstreetmap.org/wiki/Key:barrier // http://taginfo.openstreetmap.org/keys/?key=barrier#values @@ -204,36 +170,19 @@ public WheelchairFlagEncoder( int speedBits, double speedFactor ) accessibilityRelatedAttributes.add("incline"); accessibilityRelatedAttributes.add("sloped_curb"); accessibilityRelatedAttributes.add("sloped_kerb"); - - // prefer international, national, regional or local hiking routes - hikingNetworkToCode.put("iwn", BEST.getValue()); - hikingNetworkToCode.put("nwn", BEST.getValue()); - hikingNetworkToCode.put("rwn", VERY_NICE.getValue()); - hikingNetworkToCode.put("lwn", VERY_NICE.getValue()); init(); } + + public double getMeanSpeed() { + return MEAN_SPEED; + } public double getDefaultMaxSpeed() { return 4; } - @Override - public int defineWayBits( int index, int shift ) - { - // first 3 bits are reserved for route handling in superclass - shift = super.defineWayBits(index, shift); - // larger value required - ferries are faster than pedestrians (4 bits) - speedEncoder = new EncodedDoubleValue("Speed", shift, speedBits, speedFactor, MEAN_SPEED, MAX_SPEED); - shift += speedEncoder.getBits(); - - priorityWayEncoder = new EncodedValue("PreferWay", shift, 3, 1, 0, 7); - shift += priorityWayEncoder.getBits(); - - return shift; - } - @Override public int defineNodeBits(int index, int shift) { shift = super.defineNodeBits(index, shift); @@ -286,49 +235,6 @@ public long setNonSidewalkSpeed(long flags) // return adaptSpeed(flags, 1d); } - @Override - public int defineRelationBits( int index, int shift ) - { - relationCodeEncoder = new EncodedValue("RelationCode", shift, 3, 1, 0, 7); - return shift + relationCodeEncoder.getBits(); - } - - /** - * Wheelchair flag encoder does not provide any turn cost / restrictions - */ - @Override - public int defineTurnBits( int index, int shift ) - { - return shift; - } - - /** - * Wheelchair flag encoder does not provide any turn cost / restrictions - *

- * @return false - */ - @Override - public boolean isTurnRestricted( long flag ) - { - return false; - } - - /** - * Foot flag encoder does not provide any turn cost / restrictions - *

- * @return 0 - */ - @Override - public double getTurnCost( long flag ) - { - return 0; - } - - @Override - public long getTurnFlags( boolean restricted, double costs ) - { - return 0; - } /** * Some ways are okay but not separate for pedestrians. @@ -679,26 +585,6 @@ public void applyWayTags(ReaderWay way, EdgeIteratorState edge ) } */ } - - - - - - @Override - public double getDouble(long flags, int key) - { - switch (key) - { - case PriorityWeighting.KEY: - double prio = priorityWayEncoder.getValue(flags); - if (prio == 0) - return (double) UNCHANGED.getValue() / (double) BEST.getValue(); - - return prio / (double) BEST.getValue(); - default: - return super.getDouble(flags, key); - } - } @Override // currently unused @@ -830,8 +716,6 @@ else if (way.hasTag("foot", intendedValues) || way.hasTag("bicycle", "designated int sum = positiveFeatures - negativeFeatures; - // System.out.println("WheelchairFlagEncoder.collect(), sum="+sum+", wayId="+way.getId()); - if (sum <= -6) weightToPrioMap.put(2d, AVOID_AT_ALL_COSTS.getValue()); else if (sum >= -5 && sum <= -3) weightToPrioMap.put(2d, REACH_DEST.getValue()); else if (sum >= -2 && sum <= -1) weightToPrioMap.put(2d, AVOID_IF_POSSIBLE.getValue()); @@ -840,16 +724,6 @@ else if (way.hasTag("foot", intendedValues) || way.hasTag("bicycle", "designated else if (sum >= 3 && sum <= 5) weightToPrioMap.put(2d, VERY_NICE.getValue()); else if (sum >= 6) weightToPrioMap.put(2d, BEST.getValue()); } - - - @Override - public boolean supports( Class feature ) - { - if (super.supports(feature)) - return true; - - return PriorityWeighting.class.isAssignableFrom(feature); - } @Override public String toString() @@ -861,6 +735,4 @@ public String toString() public int getVersion() { return 2; } - - } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/CommonBikeFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/CommonBikeFlagEncoder.java index 881ee1efb2..7ce565480e 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/CommonBikeFlagEncoder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/CommonBikeFlagEncoder.java @@ -22,6 +22,7 @@ import com.graphhopper.routing.util.*; import com.graphhopper.routing.weighting.PriorityWeighting; import com.graphhopper.util.*; +import heigit.ors.routing.graphhopper.extensions.flagencoders.ORSAbstractFlagEncoder; import org.apache.log4j.Logger; import java.util.*; @@ -37,7 +38,7 @@ * @author Nop * @author ratrun */ -abstract public class CommonBikeFlagEncoder extends AbstractFlagEncoder { +abstract public class CommonBikeFlagEncoder extends ORSAbstractFlagEncoder { /** * Reports whether this edge is unpaved. */ @@ -246,7 +247,7 @@ public int defineWayBits(int index, int shift) { shift += priorityWayEncoder.getBits(); // MARQ24 MOD START - if (isConsiderElevation()) { + if (considerElevation) { reverseSpeedEncoder = new EncodedDoubleValue("Reverse Speed", shift, speedBits, speedFactor, getHighwaySpeed("cycleway").speed, maxPossibleSpeed); shift += reverseSpeedEncoder.getBits(); } @@ -1044,7 +1045,7 @@ public String toString(){ @Override public void applyWayTags(ReaderWay way, EdgeIteratorState edge) { // MARQ24 MOD START - if (isConsiderElevation()) { + if (considerElevation) { // MARQ24 MOD END PointList pl = edge.fetchWayGeometry(3); if (!pl.is3D()) diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/ElectroBikeFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/ElectroBikeFlagEncoder.java index 2bdcde716d..280ede980e 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/ElectroBikeFlagEncoder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/ElectroBikeFlagEncoder.java @@ -18,7 +18,8 @@ public class ElectroBikeFlagEncoder extends CommonBikeFlagEncoder { - + private static final int MEAN_SPEED = 20; + public ElectroBikeFlagEncoder() { this(4, 2, 0, false); @@ -129,6 +130,10 @@ public ElectroBikeFlagEncoder( int speedBits, double speedFactor, int maxTurnCos this.init(); } + public double getMeanSpeed() { + return MEAN_SPEED; + } + @Override public int getVersion() { diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/MountainBikeFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/MountainBikeFlagEncoder.java index fd519f1dc8..530efa25a2 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/MountainBikeFlagEncoder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/MountainBikeFlagEncoder.java @@ -34,6 +34,8 @@ * @author Peter Karich */ public class MountainBikeFlagEncoder extends CommonBikeFlagEncoder { + private static final int MEAN_SPEED = 14; + public MountainBikeFlagEncoder() { // MARQ24 MOD START //this(4, 2, 0); @@ -151,6 +153,10 @@ public MountainBikeFlagEncoder(int speedBits, double speedFactor, int maxTurnCos init(); } + public double getMeanSpeed() { + return MEAN_SPEED; + } + @Override public int getVersion() { return 2; diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/RegularBikeFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/RegularBikeFlagEncoder.java index d2e98d7ace..a2e4eb5fc2 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/RegularBikeFlagEncoder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/RegularBikeFlagEncoder.java @@ -29,6 +29,8 @@ * @author Peter Karich */ public class RegularBikeFlagEncoder extends CommonBikeFlagEncoder { + private static final int MEAN_SPEED = 15; + public RegularBikeFlagEncoder() { // MARQ24 MOD START //this(4, 2, 0); @@ -86,6 +88,10 @@ public RegularBikeFlagEncoder(int speedBits, double speedFactor, int maxTurnCost init(); } + public double getMeanSpeed() { + return MEAN_SPEED; + } + @Override public int getVersion() { return 2; diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/RoadBikeFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/RoadBikeFlagEncoder.java index 0b19150bdc..6c214800d7 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/RoadBikeFlagEncoder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/bike/RoadBikeFlagEncoder.java @@ -34,6 +34,8 @@ * @author Peter Karich */ public class RoadBikeFlagEncoder extends CommonBikeFlagEncoder { + private static final int MEAN_SPEED = 25; + public RoadBikeFlagEncoder() { // MARQ24 MOD START //this(4, 2, 0); @@ -196,6 +198,10 @@ public RoadBikeFlagEncoder(int speedBits, double speedFactor, int maxTurnCosts, this.init(); } + public double getMeanSpeed() { + return MEAN_SPEED; + } + @Override public int getVersion() { return 2; diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/currentlynotinuse/ExGhORSCarFlagEncoder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/currentlynotinuse/ExGhORSCarFlagEncoder.java index a1afbdba01..15294c2910 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/currentlynotinuse/ExGhORSCarFlagEncoder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/flagencoders/currentlynotinuse/ExGhORSCarFlagEncoder.java @@ -23,6 +23,7 @@ import com.graphhopper.routing.util.EncodedDoubleValue; import com.graphhopper.util.Helper; import com.graphhopper.util.PMap; +import heigit.ors.routing.graphhopper.extensions.flagencoders.ORSAbstractFlagEncoder; import java.util.*; @@ -33,7 +34,8 @@ * @author Peter Karich * @author Nop */ -public class ExGhORSCarFlagEncoder extends AbstractFlagEncoder { +public class ExGhORSCarFlagEncoder extends ORSAbstractFlagEncoder { + private final static double MEAN_SPEED = 100; protected final Map trackTypeSpeedMap = new HashMap(); protected final Set badSurfaceSpeedMap = new HashSet(); @@ -57,6 +59,8 @@ public ExGhORSCarFlagEncoder() { this(5, 5, 0); } + public double getMeanSpeed() { return MEAN_SPEED; } + public ExGhORSCarFlagEncoder(PMap properties) { this((int) properties.getLong("speed_bits", 5), properties.getDouble("speed_factor", 5), diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/reader/borders/CountryBordersReader.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/reader/borders/CountryBordersReader.java index b550a63ce4..6baefcb97e 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/reader/borders/CountryBordersReader.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/reader/borders/CountryBordersReader.java @@ -15,7 +15,6 @@ import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; -import com.vividsolutions.jts.geom.Point; import heigit.ors.geojson.GeometryJSON; import heigit.ors.util.CSVUtility; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/AccessRestrictionsGraphStorage.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/AccessRestrictionsGraphStorage.java deleted file mode 100644 index 58e99db32b..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/AccessRestrictionsGraphStorage.java +++ /dev/null @@ -1,212 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.routing.graphhopper.extensions.storages; - -import com.graphhopper.storage.DataAccess; -import com.graphhopper.storage.Directory; -import com.graphhopper.storage.Graph; -import com.graphhopper.storage.GraphExtension; - -import heigit.ors.routing.RoutingProfileType; - -public class AccessRestrictionsGraphStorage implements GraphExtension { - /* pointer for no entry */ - protected final int NO_ENTRY = -1; - protected final int EF_RESTRICTIONS; - - protected DataAccess edges; - protected int edgeEntryIndex = 0; - protected int edgeEntryBytes; - protected int edgesCount; - private byte[] byteValues; - private boolean _hasMotorVehicles = false; - private boolean _hasNonMotorVehicles = false; - - public AccessRestrictionsGraphStorage(int[] profileTypes) - { - for (int i = 0; i < profileTypes.length; i++) - { - int rp = profileTypes[i]; - if (RoutingProfileType.isCycling(rp) || RoutingProfileType.isWalking(rp) ) - _hasNonMotorVehicles = true; - else if (RoutingProfileType.isDriving(rp)) - _hasMotorVehicles = true; - } - - // we allocate 1 or 2 bytes for 4 profiles (motorcar, motorcycle, bicycle, foot), each profile might occupy maximum 4 bits - EF_RESTRICTIONS = nextBlockEntryIndex (_hasMotorVehicles && _hasNonMotorVehicles ? 2 : 1); - - edgeEntryBytes = edgeEntryIndex; - edgesCount = 0; - byteValues = new byte[2]; - } - - public void init(Graph graph, Directory dir) { - if (edgesCount > 0) - throw new AssertionError("The ext_access_restrictions storage must be initialized only once."); - - this.edges = dir.find("ext_access_restrictions"); - } - - protected final int nextBlockEntryIndex(int size) { - int res = edgeEntryIndex; - edgeEntryIndex += size; - return res; - } - - public void setSegmentSize(int bytes) { - edges.setSegmentSize(bytes); - } - - public GraphExtension create(long initBytes) { - edges.create((long) initBytes * edgeEntryBytes); - return this; - } - - public void flush() { - edges.setHeader(0, edgeEntryBytes); - edges.setHeader(1 * 4, edgesCount); - edges.flush(); - } - - public void close() { - edges.close(); - } - - public long getCapacity() { - return edges.getCapacity(); - } - - public int entries() { - return edgesCount; - } - - public boolean loadExisting() { - if (!edges.loadExisting()) - throw new IllegalStateException("Unable to load storage 'ext_access_restrictions'. corrupt file or directory? "); - - edgeEntryBytes = edges.getHeader(0); - edgesCount = edges.getHeader(4); - return true; - } - - void ensureEdgesIndex(int edgeIndex) { - edges.ensureCapacity(((long) edgeIndex + 1) * edgeEntryBytes); - } - - public void setEdgeValue(int edgeId, int[] restrictions) { - edgesCount++; - ensureEdgesIndex(edgeId); - - long edgePointer = (long) edgeId * edgeEntryBytes; - - if (restrictions != null) - { - if (_hasMotorVehicles && _hasNonMotorVehicles) - { - byteValues[0] = (byte)(restrictions[0] << 4 | (0x0F & restrictions[1])); - byteValues[1] = (byte)(restrictions[2] << 4 | (0x0F & restrictions[3])); - edges.setBytes(edgePointer + EF_RESTRICTIONS, byteValues, 2); - } - else - { - if (_hasMotorVehicles) - byteValues[0] = (byte)(restrictions[0] << 4 | (0x0F & restrictions[1])); - else - byteValues[0] = (byte)(restrictions[2] << 4 | (0x0F & restrictions[3])); - - edges.setBytes(edgePointer + EF_RESTRICTIONS, byteValues, 1); - } - } - } - - //vehicleType can take the following values - // motorcar = 0 - // motorcycle = 1 - // bicycle = 2 - // foot = 3 - public int getEdgeValue(int edgeId, int vehicleType, byte[] buffer) { - long edgeBase = (long) edgeId * edgeEntryBytes; - - if (vehicleType == 0 || vehicleType == 1) - { - edges.getBytes(edgeBase + EF_RESTRICTIONS, buffer, 1); - - byte value = buffer[0]; - if (value != 0) - { - if (vehicleType == 1) - return value & 0xF; - else - return (value >> 4) & 0xF; - } - } - else - { - if (_hasMotorVehicles) - edges.getBytes(edgeBase + EF_RESTRICTIONS + 1, buffer, 1); - else - edges.getBytes(edgeBase + EF_RESTRICTIONS, buffer, 1); - - byte value = buffer[0]; - if (value != 0) - { - if (vehicleType == 2) - return value & 0xF; - else - return (value >> 4) & 0xF; - } - } - - return 0; - } - - public boolean isRequireNodeField() { - return true; - } - - public boolean isRequireEdgeField() { - // we require the additional field in the graph to point to the first - // entry in the node table - return true; - } - - public int getDefaultNodeFieldValue() { - return -1; - // throw new UnsupportedOperationException("Not supported by this storage"); - } - - public int getDefaultEdgeFieldValue() { - return -1; - } - - public GraphExtension copyTo(GraphExtension clonedStorage) { - if (!(clonedStorage instanceof AccessRestrictionsGraphStorage)) { - throw new IllegalStateException("the extended storage to clone must be the same"); - } - - AccessRestrictionsGraphStorage clonedTC = (AccessRestrictionsGraphStorage) clonedStorage; - - edges.copyTo(clonedTC.edges); - clonedTC.edgesCount = edgesCount; - - return clonedStorage; - } - - @Override - public boolean isClosed() { - // TODO Auto-generated method stub - return false; - } -} diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/BordersGraphStorage.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/BordersGraphStorage.java index da65ef4fec..9093232d0f 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/BordersGraphStorage.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/BordersGraphStorage.java @@ -1,15 +1,15 @@ /* This file is part of Openrouteservice. * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 + * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, see . */ package heigit.ors.routing.graphhopper.extensions.storages; @@ -19,11 +19,15 @@ import com.graphhopper.storage.GraphExtension; import com.graphhopper.storage.RAMDirectory; +import org.apache.log4j.Logger; + /** * Graph storage class for the Border Restriction routing */ public class BordersGraphStorage implements GraphExtension { - public enum Property { TYPE, START, END }; + private static final Logger LOGGER = Logger.getLogger(BordersGraphStorage.class.getName()); + + public enum Property { TYPE, START, END} /* pointer for no entry */ protected final int NO_ENTRY = -1; private final int EF_BORDER = 0; // byte location of border type @@ -40,7 +44,6 @@ public enum Property { TYPE, START, END }; private int edgesCount; // number of edges with custom values public BordersGraphStorage() { - //EF_BORDER = 0; int edgeEntryIndex = 0; edgeEntryBytes = edgeEntryIndex + 6; // item uses 3 short values which are 2 bytes length each @@ -52,11 +55,10 @@ public BordersGraphStorage() { * * This method takes the internal ID of the edge and adds the information obtained from the Borders CSV file to it * so that the values can be taken into account when generating a route. - * - * @param edgeId Internal ID of the graph edge - * @param borderType Level of border crossing (0 - No border, 1 - controlled border, 2 - open border= - * @param start ID of the country that the edge starts in - * @param end ID of the country that the edge ends in + * @param edgeId Internal ID of the graph edge + * @param borderType Level of border crossing (0 - No border, 1 - controlled border, 2 - open border= + * @param start ID of the country that the edge starts in + * @param end ID of the country that the edge ends in */ public void setEdgeValue(int edgeId, short borderType, short start, short end) { edgesCount++; @@ -74,24 +76,22 @@ public void setEdgeValue(int edgeId, short borderType, short start, short end) { /** * Get the specified custom value of the edge that was assigned to it in the setValueEdge method

- * + *

* The method takes an identifier to the edge and then gets the requested value for the edge from the storage * - * @param edgeId Internal ID of the edge to get values for - * @param prop The property of the edge to get (TYPE - border type (0,1,2), START - the ID of the country - * the edge starts in, END - the ID of the country the edge ends in. - * @return The value of the requested property + * @param edgeId Internal ID of the edge to get values for + * @param prop The property of the edge to get (TYPE - border type (0,1,2), START - the ID of the country + * the edge starts in, END - the ID of the country the edge ends in. + * @return The value of the requested property */ public short getEdgeValue(int edgeId, Property prop) { long edgePointer = (long) edgeId * edgeEntryBytes; - short border = 0, start = 0, end = 0; - border = orsEdges.getShort(edgePointer + EF_BORDER); - start = orsEdges.getShort(edgePointer + EF_START); - end = orsEdges.getShort(edgePointer + EF_END); + short border = orsEdges.getShort(edgePointer + EF_BORDER); + short start = orsEdges.getShort(edgePointer + EF_START); + short end = orsEdges.getShort(edgePointer + EF_END); switch (prop) { case TYPE: - return border; case START: return start; diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/EmergencyVehicleAttributesGraphStorage.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/EmergencyVehicleAttributesGraphStorage.java deleted file mode 100644 index 7565b50193..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/EmergencyVehicleAttributesGraphStorage.java +++ /dev/null @@ -1,41 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.routing.graphhopper.extensions.storages; - -import com.graphhopper.storage.Directory; -import com.graphhopper.storage.Graph; - -public class EmergencyVehicleAttributesGraphStorage extends HeavyVehicleAttributesGraphStorage { - public EmergencyVehicleAttributesGraphStorage(boolean includeRestrictions) { - super(includeRestrictions); - - } - - /* pointer for no entry */ - public void init(Graph graph, Directory dir) { - if (edgesCount > 0) - throw new AssertionError("The ext_emergency storage must be initialized only once."); - - this.orsEdges = dir.find("ext_emergency"); - } - - public boolean loadExisting() { - if (!orsEdges.loadExisting()) - throw new IllegalStateException("Unable to load storage 'ext_emergency'. corrupt file or directory? "); - - edgeEntryBytes = orsEdges.getHeader(0); - edgesCount = orsEdges.getHeader(4); - return true; - } -} diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/HeavyVehicleAttributesGraphStorage.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/HeavyVehicleAttributesGraphStorage.java index a3b19ac522..c192c3e708 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/HeavyVehicleAttributesGraphStorage.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/HeavyVehicleAttributesGraphStorage.java @@ -113,7 +113,7 @@ public void setEdgeValue(int edgeId, int vehicleType, int heavyVehicleDestinatio throw new IllegalStateException("EF_RESTRICTION is not supported."); for (int i = 0; i < VehicleDimensionRestrictions.Count; i++) { - short shortValue = restrictionValues == null ? 0 : (short) (restrictionValues[i] * factor); + short shortValue = (short) (restrictionValues[i] * factor); orsEdges.setShort(edgePointer + EF_RESTRICTIONS + i * EF_RESTRICTION_BYTES, shortValue); } } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/RoadAccessRestrictionsGraphStorage.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/RoadAccessRestrictionsGraphStorage.java index fefd86d185..c78c45c552 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/RoadAccessRestrictionsGraphStorage.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/RoadAccessRestrictionsGraphStorage.java @@ -138,11 +138,11 @@ public int getDefaultEdgeFieldValue() { } public GraphExtension copyTo(GraphExtension clonedStorage) { - if (!(clonedStorage instanceof AccessRestrictionsGraphStorage)) { + if (!(clonedStorage instanceof RoadAccessRestrictionsGraphStorage)) { throw new IllegalStateException("the extended storage to clone must be the same"); } - AccessRestrictionsGraphStorage clonedTC = (AccessRestrictionsGraphStorage) clonedStorage; + RoadAccessRestrictionsGraphStorage clonedTC = (RoadAccessRestrictionsGraphStorage) clonedStorage; edges.copyTo(clonedTC.edges); clonedTC.edgesCount = edgesCount; diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/AccessRestrictionsGraphStorageBuilder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/AccessRestrictionsGraphStorageBuilder.java deleted file mode 100644 index 76a76bdbc3..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/AccessRestrictionsGraphStorageBuilder.java +++ /dev/null @@ -1,189 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.routing.graphhopper.extensions.storages.builders; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import com.graphhopper.GraphHopper; -import com.graphhopper.reader.ReaderWay; -import com.graphhopper.routing.util.EncodingManager; -import com.graphhopper.routing.util.FlagEncoder; -import com.graphhopper.storage.GraphExtension; -import com.graphhopper.util.EdgeIteratorState; - -import heigit.ors.routing.RoutingProfileType; -import heigit.ors.routing.graphhopper.extensions.AccessRestrictionType; -import heigit.ors.routing.graphhopper.extensions.storages.AccessRestrictionsGraphStorage; - -public class AccessRestrictionsGraphStorageBuilder extends AbstractGraphStorageBuilder -{ - private AccessRestrictionsGraphStorage _storage; - private boolean _hasRestrictions = false; - private int[] _restrictions = new int[4]; - private List _accessRestrictedTags = new ArrayList(5); - private List _motorCarTags = new ArrayList(5); - private List _motorCycleTags = new ArrayList(5); - private Set _restrictedValues = new HashSet(5); - private Set _permissiveValues = new HashSet(5); - - public AccessRestrictionsGraphStorageBuilder() - { - _accessRestrictedTags.addAll(Arrays.asList("motorcar", "motor_vehicle", "vehicle", "access")); - _motorCarTags.addAll(Arrays.asList("motorcar", "motor_vehicle")); - _motorCycleTags.addAll(Arrays.asList("motorcycle", "motor_vehicle")); - - _restrictedValues.add("private"); - _restrictedValues.add("no"); - _restrictedValues.add("restricted"); - _restrictedValues.add("military"); - _restrictedValues.add("destination"); - _restrictedValues.add("customers"); - _restrictedValues.add("emergency"); - - _permissiveValues.add("yes"); - _permissiveValues.add("designated"); - _permissiveValues.add("official"); - _permissiveValues.add("permissive"); - } - - public GraphExtension init(GraphHopper graphhopper) throws Exception { - if (_storage != null) - throw new Exception("GraphStorageBuilder has been already initialized."); - - // extract profiles from GraphHopper instance - EncodingManager encMgr = graphhopper.getEncodingManager(); - List encoders = encMgr.fetchEdgeEncoders(); - int[] profileTypes = new int[encoders.size()]; - int i = 0; - for (FlagEncoder enc : encoders) - { - profileTypes[i] = RoutingProfileType.getFromEncoderName(enc.toString()); - i++; - } - - _storage = new AccessRestrictionsGraphStorage(profileTypes); - - return _storage; - } - - public void processWay(ReaderWay way) { - - if (_hasRestrictions) - { - _hasRestrictions = false; - - _restrictions[0] = 0; - _restrictions[1] = 0; - _restrictions[2] = 0; - _restrictions[3] = 0; - } - - if (way.hasTag(_accessRestrictedTags, _restrictedValues)) - { - _hasRestrictions = true; - - _restrictions[0] = isAccessAllowed(way, _motorCarTags) ? 0 : getRestrictionType(way, _motorCarTags); - _restrictions[1] = isAccessAllowed(way, _motorCycleTags) ? 0 : getRestrictionType(way, _motorCycleTags); - _restrictions[2] = isAccessAllowed(way, "bicycle") ? 0 : getRestrictionType(way, "bicycle"); - _restrictions[3] = isAccessAllowed(way, "foot") ? 0 : getRestrictionType(way, "foot"); - } - - if (!_hasRestrictions) - { - // way 316156033 - if (way.hasTag("foot", _permissiveValues) || way.hasTag("bicycle", _permissiveValues)) - { - _hasRestrictions = true; - - _restrictions[0] = !isAccessAllowed(way, _motorCarTags) ? 0 : getRestrictionType(way, _motorCarTags); - if (_restrictions[0] == 0) - _restrictions[0] = AccessRestrictionType.No; - _restrictions[1] = !isAccessAllowed(way, _motorCycleTags) ? 0 : getRestrictionType(way, _motorCycleTags); - if (_restrictions[1] == 0) - _restrictions[1] = AccessRestrictionType.No; - } - } - } - - private int getRestrictionType(ReaderWay way, List tags) - { - int res = 0; - - String tagValue = way.getTag("access"); - if (tagValue != null && tagValue.equals("customers")) - res |= AccessRestrictionType.Customers; - - if (tags != null) - { - for (String key : tags) - { - tagValue = way.getTag(key); - if (tagValue != null) - { - if (tagValue.equals("no")) - res |= AccessRestrictionType.No; - if (tagValue.equals("destination")) - res |= AccessRestrictionType.Destination; - } - } - } - - return res; - } - - private int getRestrictionType(ReaderWay way, String tag) - { - int res = 0; - - String tagValue = way.getTag("access"); - if (tagValue != null && tagValue.equals("customers")) - res |= AccessRestrictionType.Customers; - - tagValue = way.getTag(tag); - if (tagValue != null) - { - if (tagValue.equals("no")) - res |= AccessRestrictionType.No; - if (tagValue.equals("destination")) - res |= AccessRestrictionType.Destination; - } - - return res; - } - - private boolean isAccessAllowed(ReaderWay way, List tagNames) - { - return way.hasTag(tagNames, _permissiveValues); - } - - private boolean isAccessAllowed(ReaderWay way, String tagName) - { - return way.hasTag(tagName, _permissiveValues); - } - - public void processEdge(ReaderWay way, EdgeIteratorState edge) - { - if (_hasRestrictions) - _storage.setEdgeValue(edge.getEdge(), _restrictions); - } - - @Override - public String getName() { - return "AccessRestrictions"; - } -} diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/BordersGraphStorageBuilder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/BordersGraphStorageBuilder.java index 8b0df345ff..bb0897d7a9 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/BordersGraphStorageBuilder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/BordersGraphStorageBuilder.java @@ -1,15 +1,15 @@ /* This file is part of Openrouteservice. * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 + * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 * of the License, or (at your option) any later version. - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, see . */ package heigit.ors.routing.graphhopper.extensions.storages.builders; @@ -20,7 +20,6 @@ import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; -import com.vividsolutions.jts.geom.Point; import heigit.ors.exceptions.MissingConfigParameterException; import heigit.ors.routing.graphhopper.extensions.reader.borders.CountryBordersPolygon; import heigit.ors.routing.graphhopper.extensions.reader.borders.CountryBordersReader; @@ -44,6 +43,8 @@ public class BordersGraphStorageBuilder extends AbstractGraphStorageBuilder { private GeometryFactory gf; + public static String builderName = "Borders"; + public BordersGraphStorageBuilder() { gf = new GeometryFactory(); } @@ -119,13 +120,15 @@ public void processWay(ReaderWay way) { public void processWay(ReaderWay way, Coordinate[] coords, HashMap> nodeTags) { // Process the way using the geometry provided // if we don't have the reader object, then we can't do anything - if(cbReader != null) { + if (cbReader != null) { String[] countries = findBorderCrossing(coords); - // If we find that the length of countries is more than one, then it does cross a border if (countries.length > 1 && !countries[0].equals(countries[1])) { way.setTag("country1", countries[0]); way.setTag("country2", countries[1]); + } else if (countries.length == 1){ + way.setTag("country1", countries[0]); + way.setTag("country2", countries[0]); } } } @@ -139,35 +142,30 @@ public void processWay(ReaderWay way, Coordinate[] coords, HashMap. - */ -package heigit.ors.routing.graphhopper.extensions.storages.builders; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Map.Entry; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import com.graphhopper.GraphHopper; -import com.graphhopper.reader.ReaderWay; -import com.graphhopper.storage.GraphExtension; -import com.graphhopper.util.EdgeIteratorState; -import com.graphhopper.util.Helper; - -import heigit.ors.routing.graphhopper.extensions.HeavyVehicleAttributes; -import heigit.ors.routing.graphhopper.extensions.VehicleDimensionRestrictions; -import heigit.ors.routing.graphhopper.extensions.storages.EmergencyVehicleAttributesGraphStorage; - -public class EmergencyVehicleGraphStorageBuilder extends AbstractGraphStorageBuilder { - private boolean _includeRestrictions = true; - private EmergencyVehicleAttributesGraphStorage _storage; - private int _hgvType = 0; - private boolean _hasRestrictionValues; - private double[] _restrictionValues = new double[VehicleDimensionRestrictions.Count]; - private List _motorVehicleRestrictions = new ArrayList(5); - private Set _motorVehicleRestrictedValues = new HashSet(5); - private Pattern _patternHeight; - - public EmergencyVehicleGraphStorageBuilder() { - // _motorVehicleRestrictions.addAll(Arrays.asList("motorcar", "motor_vehicle", "vehicle", "access")); - - // _motorVehicleRestrictedValues.add("private"); - // _motorVehicleRestrictedValues.add("no"); - // _motorVehicleRestrictedValues.add("restricted"); - // _motorVehicleRestrictedValues.add("military"); - - //_patternHeight = Pattern.compile("(?:\\s*(\\d+)\\s*(?:feet|ft\\.|ft|'))?(?:(\\d+)\\s*(?:inches|in\\.|in|''|\"))?"); - _patternHeight = Pattern.compile("(?:\\s*(.*?)\\s*(?:feet|ft\\.|ft|'))?(?:\\s*(.*?)\\s*(?:inches|in\\.|in|''|\"))?"); - } - - public GraphExtension init(GraphHopper graphhopper) throws Exception { - if (_storage != null) - throw new Exception("GraphStorageBuilder has been already initialized."); - - if (_parameters != null) { - String value = _parameters.get("restrictions"); - if (!Helper.isEmpty(value)) - _includeRestrictions = Boolean.parseBoolean(value); - } - - _storage = new EmergencyVehicleAttributesGraphStorage(_includeRestrictions); - - return _storage; - } - - @Override - public void processWay(ReaderWay way) { - - _hgvType = 0; - - if (_hasRestrictionValues) { - _restrictionValues[0] = 0.0; - _restrictionValues[1] = 0.0; - _restrictionValues[2] = 0.0; - _restrictionValues[3] = 0.0; - _restrictionValues[4] = 0.0; - - _hasRestrictionValues = false; - } - - boolean hasHighway = way.hasTag("highway"); - if (hasHighway && way.hasTag(_motorVehicleRestrictions, _motorVehicleRestrictedValues)) {// set to 0 - _hgvType |= 0; - // _hgvType |= HeavyVehicleAttributes.BUS; - // _hgvType |= HeavyVehicleAttributes.AGRICULTURE; - // _hgvType |= HeavyVehicleAttributes.FORESTRY; - // _hgvType |= HeavyVehicleAttributes.DELIVERY; - // _hgvType |= HeavyVehicleAttributes.GOODS; - // _hgvType |= HeavyVehicleAttributes.HGV; - } - - java.util.Iterator> it = way.getProperties(); - - while (it.hasNext()) { - Map.Entry pairs = it.next(); - String key = pairs.getKey(); - String value = pairs.getValue().toString(); - - if (hasHighway) { - if (key.equals("highway")) { - if (value.equals("motorway") || value.equals("motorway_link")) { - } else if (value.equals("steps")) { - } else if ("track".equals(value)) { - String tracktype = way.getTag("tracktype"); - if (tracktype != null && ( - tracktype.equals("grade1") || tracktype.equals("grade2") || - tracktype.equals("grade3") || tracktype.equals("grade4") || - tracktype.equals("grade5")) - ) { - _hgvType |= HeavyVehicleAttributes.AGRICULTURE; - _hgvType |= HeavyVehicleAttributes.FORESTRY; - } - } - - } - /* - * todo borders - */ - else { - if (_includeRestrictions) { - int valueIndex = -1; - - if (key.equals("maxheight")) { - valueIndex = VehicleDimensionRestrictions.MaxHeight; - } else if (key.equals("maxweight")) { - valueIndex = VehicleDimensionRestrictions.MaxWeight; - } else if (key.equals("maxweight:hgv")) { - valueIndex = VehicleDimensionRestrictions.MaxWeight; - } else if (key.equals("maxwidth")) { - valueIndex = VehicleDimensionRestrictions.MaxWidth; - } else if (key.equals("maxlength")) { - valueIndex = VehicleDimensionRestrictions.MaxLength; - } else if (key.equals("maxlength:hgv")) { - valueIndex = VehicleDimensionRestrictions.MaxLength; - } else if (key.equals("maxaxleload")) { - valueIndex = VehicleDimensionRestrictions.MaxAxleLoad; - } - - if (valueIndex >= 0 && !("none".equals(value) || "default".equals(value))) { - if (valueIndex == VehicleDimensionRestrictions.MaxWeight || valueIndex == VehicleDimensionRestrictions.MaxAxleLoad) { - if (value.contains("t")) { - value = value.replace('t', ' '); - } else if (value.contains("lbs")) { - value = value.replace("lbs", " "); - value = Double.toString(Double.parseDouble(value) / 2204.622); - } - } else { - if (value.contains("m")) { - value = value.replace('m', ' '); - } else /*if (value.contains("'"))*/{ - // MARQ24: why the heck we only make use of our fancy RegEx for height - // parsing - IF the string contains a ' ?! - Matcher m = _patternHeight.matcher(value); - if (m.matches() && m.lookingAt()) { - double feet = Double.parseDouble(m.group(1)); - double inches = 0; - if (m.groupCount() > 1 && m.group(2) != null) { - inches = Double.parseDouble(m.group(2)); - } - // MARQ24: n feet * 0.3048 = feet 2 meter - ok fine... BUT - // x inches * 0.0254 * y feet - this does not make much sense to me... - // double newValue = feet * 0.3048 + inches * 0.0254 * feet; - double newValue = feet * 0.3048 + inches * 0.0254; - value = Double.toString(newValue); - } - } - } - - // MARQ24: FIXME: Here we can get a "NumberFormatException" and then the complete - // iterator will stop (no additional propertis of the way will be processed! - _restrictionValues[valueIndex] = Double.parseDouble(value); - _hasRestrictionValues = true; - } - } - - - // String hgvTag = getHeavyVehicleValue(key, "hgv", value); //key.equals("hgv") ? value : null; - // String goodsTag = getHeavyVehicleValue(key, "goods", value); // key.equals("goods") ? value : null; - // String busTag = getHeavyVehicleValue(key, "bus", value); //key.equals("bus") ? value : null; - // String agriculturalTag = getHeavyVehicleValue(key, "agricultural", value); //key.equals("agricultural") ? value : null; - // String forestryTag = getHeavyVehicleValue(key, "forestry", value); // key.equals("forestry") ? value : null; - // String deliveryTag = getHeavyVehicleValue(key, "delivery", value); //key.equals("delivery") ? value : null; - - // String accessTag = key.equals("access") ? value : null; - - // if (Helper.isEmpty(accessTag)) { - // if ("agricultural".equals(accessTag)) - // agriculturalTag = "yes"; - // else if ("forestry".equals(accessTag)) - // forestryTag = "yes"; - // else if ("bus".equals(accessTag)) - // busTag = "yes"; - // } - - // String motorVehicle = key.equals("motor_vehicle") ? value : null; - // if (motorVehicle == null) - // motorVehicle = key.equals("motorcar") ? value : null; - - // if (motorVehicle != null) { - // if ("agricultural".equals(motorVehicle)) - // agriculturalTag = "yes"; - // else if ("forestry".equals(motorVehicle)) - // forestryTag = "yes"; - // else if ("delivery".equals(motorVehicle)) - // deliveryTag = "yes"; - - // //if ("destination".equals(motorVehicle)) - // // heavyVehicleFlag |= HeavyVehicleAttributes.Destination; - // } - - // if (goodsTag != null) { - // if ("no".equals(goodsTag)) - // _hgvType |= HeavyVehicleAttributes.GOODS; - // else if ("yes".equals(busTag)) - // _hgvType &= ~HeavyVehicleAttributes.GOODS; - // else if ("destination".equals(goodsTag)) - // { - // _hgvType |= HeavyVehicleAttributes.GOODS; - // _hgvDestination |= HeavyVehicleAttributes.GOODS;//(1 << (HeavyVehicleAttributes.Goods >> 1)); - // } - // } - - // if (hgvTag != null) { - // if ("no".equals(hgvTag)) - // _hgvType |= HeavyVehicleAttributes.HGV; - // else if ("yes".equals(busTag)) - // _hgvType &= ~HeavyVehicleAttributes.HGV; - // else if ("destination".equals(hgvTag)) - // { - // _hgvType |= HeavyVehicleAttributes.HGV; - // _hgvDestination |= HeavyVehicleAttributes.HGV;// (1 << (HeavyVehicleAttributes.Hgv >> 1)); - // } - // } - - // if (busTag != null) { - // if ("no".equals(busTag)) - // _hgvType |= HeavyVehicleAttributes.BUS; - // else if ("yes".equals(busTag)) - // _hgvType &= ~HeavyVehicleAttributes.BUS; - // else if ("destination".equals(busTag)) - // { - // _hgvType |= HeavyVehicleAttributes.BUS; - // _hgvDestination |= HeavyVehicleAttributes.BUS; //(1 << (HeavyVehicleAttributes.Bus >> 1)); - // } - // } - - // if (agriculturalTag != null) { - // if ("no".equals(agriculturalTag)) - // _hgvType |= HeavyVehicleAttributes.AGRICULTURE; - // else if ("yes".equals(busTag)) - // _hgvType &= ~HeavyVehicleAttributes.AGRICULTURE; - // else if ("destination".equals(agriculturalTag)) - // { - // _hgvType |= HeavyVehicleAttributes.AGRICULTURE; - // _hgvDestination |= HeavyVehicleAttributes.AGRICULTURE;// (1 << (HeavyVehicleAttributes.Agricultural >> 1)); - // } - // } else - - // if (forestryTag != null) { - // if ("no".equals(forestryTag)) - // _hgvType |= HeavyVehicleAttributes.FORESTRY; - // else if ("yes".equals(busTag)) - // _hgvType &= ~HeavyVehicleAttributes.FORESTRY; - // else if ("destination".equals(forestryTag)) - // { - // _hgvType |= HeavyVehicleAttributes.FORESTRY; - // _hgvDestination |= HeavyVehicleAttributes.FORESTRY;//(1 << (HeavyVehicleAttributes.Forestry >> 1)); - // } - // } - - // if (deliveryTag != null) { - // if ("no".equals(deliveryTag)) - // _hgvType |= HeavyVehicleAttributes.DELIVERY; - // else if ("yes".equals(busTag)) - // _hgvType &= ~HeavyVehicleAttributes.DELIVERY; - // else if ("destination".equals(deliveryTag) || "delivery".equals(deliveryTag) ) - // { - // _hgvType |= HeavyVehicleAttributes.DELIVERY; - // _hgvDestination |= HeavyVehicleAttributes.DELIVERY; //(1 << (HeavyVehicleAttributes.Delivery >> 1)); - // } - // } - - // String hazmatTag = key.equals("hazmat") ? value : null; - // if ("no".equals(hazmatTag)) { - // _hgvType |= HeavyVehicleAttributes.HAZMAT; - // } - - // (access=no) + access:conditional=delivery @ - // (07:00-11:00); customer @ (07:00-17:00) - } - } - } - } - - @Override - public void processEdge(ReaderWay way, EdgeIteratorState edge) { - //if (_hgvType > HeavyVehicleAttributes.UNKNOWN || _hgvDestination > 0 || _hasRestrictionValues) - { - if (_hasRestrictionValues) - _storage.setEdgeValue(edge.getEdge(), _hgvType, 0, _restrictionValues); - else - _storage.setEdgeValue(edge.getEdge(), _hgvType, 0, null); - } - } - - @Override - public String getName() { - return "EmergencyVehicle"; - } -} diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/HeavyVehicleGraphStorageBuilder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/HeavyVehicleGraphStorageBuilder.java index f8b60ef9dc..16d46e4894 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/HeavyVehicleGraphStorageBuilder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/HeavyVehicleGraphStorageBuilder.java @@ -223,15 +223,8 @@ else if (key.equals("hazmat") && "no".equals(value)) { } } - public void processEdge(ReaderWay way, EdgeIteratorState edge) - { - if (_hgvType > HeavyVehicleAttributes.UNKNOWN || _hgvDestination > 0 || _hasRestrictionValues) - { - if (_hasRestrictionValues) - _storage.setEdgeValue(edge.getEdge(), _hgvType, _hgvDestination, _restrictionValues); - else - _storage.setEdgeValue(edge.getEdge(), _hgvType, _hgvDestination, null); - } + public void processEdge(ReaderWay way, EdgeIteratorState edge) { + _storage.setEdgeValue(edge.getEdge(), _hgvType, _hgvDestination, _restrictionValues); } private String getHeavyVehicleValue(String key, String hv, String value) { diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/RoadAccessRestrictionsGraphStorageBuilder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/RoadAccessRestrictionsGraphStorageBuilder.java index f023eb58e3..50625349b0 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/RoadAccessRestrictionsGraphStorageBuilder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/RoadAccessRestrictionsGraphStorageBuilder.java @@ -253,8 +253,7 @@ private boolean isAccessAllowed(ReaderWay way, String tagName) { } public void processEdge(ReaderWay way, EdgeIteratorState edge) { - if (hasRestrictions) - storage.setEdgeValue(edge.getEdge(), restrictions); + storage.setEdgeValue(edge.getEdge(), restrictions); } public final int getRestrictions() { diff --git a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/WayCategoryGraphStorageBuilder.java b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/WayCategoryGraphStorageBuilder.java index f91142cb42..6083533764 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/WayCategoryGraphStorageBuilder.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/graphhopper/extensions/storages/builders/WayCategoryGraphStorageBuilder.java @@ -79,11 +79,9 @@ else if (("ford".equals(key) && value.equals("yes"))) } } } - - public void processEdge(ReaderWay way, EdgeIteratorState edge) - { - if (_wayType > 0) - _storage.setEdgeValue(edge.getEdge(), _wayType); + + public void processEdge(ReaderWay way, EdgeIteratorState edge) { + _storage.setEdgeValue(edge.getEdge(), _wayType); } private boolean isFerryRoute(ReaderWay way) { diff --git a/openrouteservice/src/main/java/heigit/ors/routing/pathprocessors/ExtraInfoProcessor.java b/openrouteservice/src/main/java/heigit/ors/routing/pathprocessors/ExtraInfoProcessor.java index 0480db94f6..cdde23b938 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/pathprocessors/ExtraInfoProcessor.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/pathprocessors/ExtraInfoProcessor.java @@ -22,17 +22,36 @@ import com.graphhopper.storage.GraphExtension; import com.graphhopper.util.EdgeIteratorState; import com.graphhopper.util.PointList; -import heigit.ors.routing.*; +import com.vividsolutions.jts.geom.Coordinate; +import heigit.ors.routing.RouteExtraInfo; +import heigit.ors.routing.RouteExtraInfoFlag; +import heigit.ors.routing.RoutingProfileType; +import heigit.ors.routing.RoutingRequest; import heigit.ors.routing.graphhopper.extensions.ORSGraphHopper; -import heigit.ors.routing.graphhopper.extensions.storages.*; +import heigit.ors.routing.graphhopper.extensions.reader.borders.CountryBordersPolygon; +import heigit.ors.routing.graphhopper.extensions.reader.borders.CountryBordersReader; +import heigit.ors.routing.graphhopper.extensions.storages.BordersGraphStorage; +import heigit.ors.routing.graphhopper.extensions.storages.GraphStorageUtils; +import heigit.ors.routing.graphhopper.extensions.storages.GreenIndexGraphStorage; +import heigit.ors.routing.graphhopper.extensions.storages.HillIndexGraphStorage; +import heigit.ors.routing.graphhopper.extensions.storages.NoiseIndexGraphStorage; +import heigit.ors.routing.graphhopper.extensions.storages.OsmIdGraphStorage; +import heigit.ors.routing.graphhopper.extensions.storages.RoadAccessRestrictionsGraphStorage; +import heigit.ors.routing.graphhopper.extensions.storages.TollwaysGraphStorage; +import heigit.ors.routing.graphhopper.extensions.storages.TrailDifficultyScaleGraphStorage; +import heigit.ors.routing.graphhopper.extensions.storages.WarningGraphExtension; +import heigit.ors.routing.graphhopper.extensions.storages.WayCategoryGraphStorage; +import heigit.ors.routing.graphhopper.extensions.storages.WaySurfaceTypeGraphStorage; import heigit.ors.routing.util.ElevationSmoother; import heigit.ors.routing.util.extrainfobuilders.RouteExtraInfoBuilder; import heigit.ors.routing.util.extrainfobuilders.SimpleRouteExtraInfoBuilder; import heigit.ors.routing.util.extrainfobuilders.SteepnessExtraInfoBuilder; -import java.util.*; +import java.util.ArrayList; +import java.util.List; public class ExtraInfoProcessor extends PathProcessor { + private WaySurfaceTypeGraphStorage _extWaySurface; private WayCategoryGraphStorage _extWayCategory; private GreenIndexGraphStorage _extGreenIndex; @@ -42,7 +61,8 @@ public class ExtraInfoProcessor extends PathProcessor { private HillIndexGraphStorage _extHillIndex; private OsmIdGraphStorage _extOsmId; private RoadAccessRestrictionsGraphStorage _extRoadAccessRestrictions; - + private BordersGraphStorage _extCountryTraversalInfo; + private RouteExtraInfo _surfaceInfo; private RouteExtraInfoBuilder _surfaceInfoBuilder; @@ -80,6 +100,9 @@ public class ExtraInfoProcessor extends PathProcessor { private RouteExtraInfo _roadAccessRestrictionsInfo; private RouteExtraInfoBuilder _roadAccessRestrictionsBuilder; + private RouteExtraInfo _countryTraversalInfo; + private RouteExtraInfoBuilder _countryTraversalBuilder; + private List warningExtensions; private int _profileType = RoutingProfileType.UNKNOWN; @@ -88,6 +111,13 @@ public class ExtraInfoProcessor extends PathProcessor { private byte[] buffer; private boolean _lastSegment; + private CountryBordersReader cbreader; + + public ExtraInfoProcessor(ORSGraphHopper graphhopper, RoutingRequest req, CountryBordersReader cbReader) throws Exception { + this(graphhopper, req); + this.cbreader = cbReader; + } + public ExtraInfoProcessor(ORSGraphHopper graphHopper, RoutingRequest req) throws Exception { _profileType = req.getSearchParameters().getProfileType(); @@ -205,6 +235,13 @@ public ExtraInfoProcessor(ORSGraphHopper graphHopper, RoutingRequest req) throws _roadAccessRestrictionsBuilder = new SimpleRouteExtraInfoBuilder(_roadAccessRestrictionsInfo); } + if (includeExtraInfo(extraInfo, RouteExtraInfoFlag.CountryInfo)) { + _extCountryTraversalInfo = GraphStorageUtils.getGraphExtension(graphHopper.getGraphHopperStorage(), BordersGraphStorage.class); + if (_extCountryTraversalInfo != null) { + _countryTraversalInfo = new RouteExtraInfo("countryinfo", _extCountryTraversalInfo); + _countryTraversalBuilder = new SimpleRouteExtraInfoBuilder(_countryTraversalInfo); + } + } buffer = new byte[4]; } @@ -276,6 +313,8 @@ public List getExtras() extras.add(_osmIdInfo); if (_roadAccessRestrictionsInfo != null) extras.add(_roadAccessRestrictionsInfo); + if (_countryTraversalInfo != null) + extras.add(_countryTraversalInfo); return extras; } @@ -283,6 +322,25 @@ public List getExtras() public void processEdge(EdgeIteratorState edge, boolean isLastEdge, PointList geom) { double dist = edge.getDistance(); + // TODO Add extra info for crossed countries + if (_extCountryTraversalInfo != null && cbreader != null) { + short country1 = _extCountryTraversalInfo.getEdgeValue(EdgeIteratorStateHelper.getOriginalEdge(edge), BordersGraphStorage.Property.START); + short country2 = _extCountryTraversalInfo.getEdgeValue(EdgeIteratorStateHelper.getOriginalEdge(edge), BordersGraphStorage.Property.END); + // This check will correct the countries of an edge if the starting coordinate of the route lies in a different country than the start of the edge. + if (country1 != country2 && geom.getSize() > 0) { + Coordinate coordinate = new Coordinate(); + coordinate.x = geom.getLon(0); + coordinate.y = geom.getLat(0); + CountryBordersPolygon[] countries = cbreader.getCountry(coordinate); + if (countries.length >= 1) { + country1 = Short.parseShort(cbreader.getId(cbreader.getCountry(coordinate)[0].getName())); + } + } + if (_countryTraversalBuilder != null && country1 != 0) { + _countryTraversalBuilder.addSegment(country1, country1, geom, dist, isLastEdge && _lastSegment); + } + } + if (_extWaySurface != null && _wayTypeInfo != null || _surfaceInfo != null) { WaySurfaceDescription wsd = _extWaySurface.getEdgeValue(EdgeIteratorStateHelper.getOriginalEdge(edge), buffer); diff --git a/openrouteservice/src/main/java/heigit/ors/services/isochrones/requestprocessors/json/JsonIsochronesRequestProcessor.java b/openrouteservice/src/main/java/heigit/ors/services/isochrones/requestprocessors/json/JsonIsochronesRequestProcessor.java index 4f0dd429ff..70be13b293 100644 --- a/openrouteservice/src/main/java/heigit/ors/services/isochrones/requestprocessors/json/JsonIsochronesRequestProcessor.java +++ b/openrouteservice/src/main/java/heigit/ors/services/isochrones/requestprocessors/json/JsonIsochronesRequestProcessor.java @@ -163,7 +163,7 @@ private void writeResponse(HttpServletResponse response, IsochroneRequest reques //if (includeReachFactor && traveller.getRangeType() == TravelRangeType.Time) { - // double r = isoLine.getMaxRadius(units); + // double r = isoLine.getMeanRadius(units); // double maxArea = Math.PI * r * r; // jProperties.put("reachfactor", FormatUtility.roundToDecimals(area / maxArea, 4)); diff --git a/openrouteservice/src/main/java/heigit/ors/services/optimization/OptimizationServiceServlet.java b/openrouteservice/src/main/java/heigit/ors/services/optimization/OptimizationServiceServlet.java deleted file mode 100644 index 2086b20b1f..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/services/optimization/OptimizationServiceServlet.java +++ /dev/null @@ -1,66 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.services.optimization; - -import javax.servlet.*; -import javax.servlet.http.*; - -import heigit.ors.services.optimization.requestprocessors.OptimizationServiceRequestProcessorFactory; -import heigit.ors.servlet.http.AbstractHttpRequestProcessor; -import heigit.ors.servlet.http.BaseHttpServlet; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -@Deprecated -@RestController -@RequestMapping("/optimized_routes") -public class OptimizationServiceServlet extends BaseHttpServlet { - /** Serial Version UID */ - private static final long serialVersionUID = 19433489527745L; - - public void init() throws ServletException { - } - - public void destroy() { - - } - - @PostMapping - public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException { - try - { - AbstractHttpRequestProcessor reqProcessor = OptimizationServiceRequestProcessorFactory.createProcessor(request); - reqProcessor.process(response); - reqProcessor.destroy(); - } - catch (Exception ex) { - writeError(response, ex); - } - } - - @GetMapping - public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException { - try - { - AbstractHttpRequestProcessor reqProcessor = OptimizationServiceRequestProcessorFactory.createProcessor(request); - reqProcessor.process(response); - reqProcessor.destroy(); - } - catch (Exception ex) { - writeError(response, ex); - } - } -} diff --git a/openrouteservice/src/main/java/heigit/ors/services/optimization/OptimizationServiceSettings.java b/openrouteservice/src/main/java/heigit/ors/services/optimization/OptimizationServiceSettings.java deleted file mode 100644 index de558a171c..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/services/optimization/OptimizationServiceSettings.java +++ /dev/null @@ -1,85 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.services.optimization; - -import java.util.Map; - -import heigit.ors.config.AppConfig; - -public class OptimizationServiceSettings { - private static boolean enabled = true; - private static int maximumLocations = 100; - private static String solverName = "default"; - private static Map solverOptions; - private static String attribution = ""; - private static AppConfig _config; - - static - { - _config = AppConfig.Global(); - init(_config); - } - - public static void loadFromFile(String path) - { - _config = new AppConfig(path); - - init(_config); - } - - private static void init(AppConfig config) - { - String value = config.getServiceParameter("optimization", "enabled"); - if (value != null) - enabled = Boolean.parseBoolean(value); - - value = AppConfig.Global().getServiceParameter("optimization", "maximum_locations"); - if (value != null) - maximumLocations = Math.max(1, Integer.parseInt(value)); - - value = AppConfig.Global().getServiceParameter("optimization", "solver_name"); - if (value != null) - solverName = value; - - value = AppConfig.Global().getServiceParameter("optimization", "solver_options"); - if (value != null) - solverOptions = _config.getServiceParametersMap("optimization", "solver_options", false); - - value = config.getServiceParameter("optimization", "attribution"); - if (value != null) - attribution = value; - } - - public static boolean getEnabled() - { - return enabled; - } - - public static String getSolverName() { - return solverName; - } - - public static Map getSolverOptions() - { - return solverOptions; - } - - public static int getMaximumLocations() { - return maximumLocations; - } - - public static String getAttribution() { - return attribution; - } -} diff --git a/openrouteservice/src/main/java/heigit/ors/services/optimization/requestprocessors/OptimizationServiceRequestProcessorFactory.java b/openrouteservice/src/main/java/heigit/ors/services/optimization/requestprocessors/OptimizationServiceRequestProcessorFactory.java deleted file mode 100644 index 36d63450ab..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/services/optimization/requestprocessors/OptimizationServiceRequestProcessorFactory.java +++ /dev/null @@ -1,50 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.services.optimization.requestprocessors; - -import javax.servlet.http.HttpServletRequest; - -import heigit.ors.common.StatusCode; -import heigit.ors.exceptions.StatusCodeException; -import heigit.ors.exceptions.UnknownParameterValueException; -import heigit.ors.optimization.OptimizationErrorCodes; -import heigit.ors.routing.RoutingProfileManagerStatus; -import heigit.ors.services.matrix.MatrixServiceSettings; -import heigit.ors.services.optimization.OptimizationServiceSettings; -import heigit.ors.services.optimization.requestprocessors.json.JsonOptimizationRequestProcessor; -import heigit.ors.servlet.http.AbstractHttpRequestProcessor; - -import com.graphhopper.util.Helper; - -public class OptimizationServiceRequestProcessorFactory { - - public static AbstractHttpRequestProcessor createProcessor(HttpServletRequest request) throws Exception - { - if (!(OptimizationServiceSettings.getEnabled() && MatrixServiceSettings.getEnabled())) - throw new StatusCodeException(StatusCode.SERVICE_UNAVAILABLE, OptimizationErrorCodes.UNKNOWN, "Optimizaiton service is not enabled."); - - if (!RoutingProfileManagerStatus.isReady()) - throw new StatusCodeException(StatusCode.SERVICE_UNAVAILABLE, OptimizationErrorCodes.UNKNOWN, "Optimizaiton service is not ready yet."); - - String formatParam = request.getParameter("format"); - - if (Helper.isEmpty(formatParam)) - formatParam = "json"; - - if (formatParam.equalsIgnoreCase("json")) - return new JsonOptimizationRequestProcessor(request); - else - throw new UnknownParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_VALUE, "format", formatParam); - } -} diff --git a/openrouteservice/src/main/java/heigit/ors/services/optimization/requestprocessors/json/JsonOptimizationRequestParser.java b/openrouteservice/src/main/java/heigit/ors/services/optimization/requestprocessors/json/JsonOptimizationRequestParser.java deleted file mode 100644 index eec9f19ce2..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/services/optimization/requestprocessors/json/JsonOptimizationRequestParser.java +++ /dev/null @@ -1,255 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.services.optimization.requestprocessors.json; - -import java.io.InputStream; - -import javax.servlet.http.HttpServletRequest; - -import org.json.JSONObject; - -import com.graphhopper.util.Helper; -import com.vividsolutions.jts.geom.Coordinate; - -import heigit.ors.common.DistanceUnit; -import heigit.ors.common.StatusCode; -import heigit.ors.exceptions.MissingParameterException; -import heigit.ors.exceptions.ParameterValueException; -import heigit.ors.exceptions.StatusCodeException; -import heigit.ors.exceptions.UnknownParameterValueException; -import heigit.ors.localization.LocalizationManager; -import heigit.ors.matrix.MatrixMetricsType; -import heigit.ors.optimization.OptimizationErrorCodes; -import heigit.ors.optimization.RouteOptimizationRequest; -import heigit.ors.routing.RouteInstructionsFormat; -import heigit.ors.routing.RoutingProfileType; -import heigit.ors.util.CoordTools; -import heigit.ors.util.DistanceUnitUtil; -import heigit.ors.util.StreamUtility; - -public class JsonOptimizationRequestParser { - - public static RouteOptimizationRequest parseFromStream(InputStream stream) throws Exception - { - String body = StreamUtility.readStream(stream); - - if (Helper.isEmpty(body)) - throw new StatusCodeException(StatusCode.BAD_REQUEST, OptimizationErrorCodes.INVALID_JSON_FORMAT, "Unable to parse JSON document."); - - JSONObject json = null; - - try - { - json = new JSONObject(body); - } - catch(Exception ex) - { - throw new StatusCodeException(StatusCode.BAD_REQUEST, OptimizationErrorCodes.INVALID_JSON_FORMAT, "Unable to parse JSON document." + ex.getMessage()); - } - - RouteOptimizationRequest req = new RouteOptimizationRequest(); - - String value = json.optString("id"); - if (!Helper.isEmpty(value)) - req.setId(value); - - throw new Exception("POST REQUEST IS NOT SUPPORTED"); - -// return req; - } - - public static RouteOptimizationRequest parseFromRequestParams(HttpServletRequest request) throws Exception - { - RouteOptimizationRequest req = new RouteOptimizationRequest(); - - String value = request.getParameter("profile"); - if (!Helper.isEmpty(value)) - { - int profileType = RoutingProfileType.getFromString(value); - if (profileType == RoutingProfileType.UNKNOWN) - throw new UnknownParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_VALUE, "profile", value); - req.setProfileType(profileType); - } - else - { - throw new MissingParameterException(OptimizationErrorCodes.MISSING_PARAMETER, "profile"); - } - - Coordinate[] locations = null; - - value = request.getParameter("locations"); - if (!Helper.isEmpty(value)) - { - try - { - locations = CoordTools.parse(value, "\\|", false, false); - if (locations.length < 2) - throw new ParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_VALUE, "locations"); - - req.setLocations(locations); - } - catch(NumberFormatException nfex) - { - throw new ParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_FORMAT, "locations"); - } - } - else - { - throw new MissingParameterException(OptimizationErrorCodes.MISSING_PARAMETER, "locations"); - } - - value = request.getParameter("source"); - if (!Helper.isEmpty(value)) - { - int sourceIndex = 0; - - try - { - String paramSource = request.getParameter("source"); - if ("any".equalsIgnoreCase(paramSource)) - sourceIndex = -1; - else - sourceIndex = Integer.parseInt(paramSource); - } - catch(NumberFormatException ex) - { - throw new ParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_FORMAT, "source"); - } - - if (sourceIndex >= locations.length) - throw new ParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_VALUE, "source"); - - req.setSourceIndex(sourceIndex); - } - else - req.setSourceIndex(-1); - - value = request.getParameter("destination"); - if (!Helper.isEmpty(value)) - { - int destIndex = locations.length - 1; - - try - { - String paramSource = request.getParameter("destination"); - if ("any".equalsIgnoreCase(paramSource)) - destIndex = -1; - else - destIndex = Integer.parseInt(paramSource); - } - catch(NumberFormatException ex) - { - throw new ParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_FORMAT, "destination"); - } - - if (destIndex >= locations.length) - throw new ParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_VALUE, "destination"); - - req.setDestinationIndex(destIndex); - } - else - req.setDestinationIndex(-1); - - value = request.getParameter("roundtrip"); - if (!Helper.isEmpty(value)) - { - try - { - Boolean b = Boolean.parseBoolean(value); - if (!b && !value.equalsIgnoreCase("false")) - throw new ParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_FORMAT, "roundtrip"); - req.setRoundTrip(b); - } - catch(Exception ex) - { - throw new ParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_FORMAT, "roundtrip", value); - } - } - - if (req.isRoundTrip() && req.getDestinationIndex() > 0 && req.getSourceIndex() != req.getDestinationIndex()) - throw new ParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_VALUE, "destination"); - - value = request.getParameter("metric"); - if (!Helper.isEmpty(value)) - { - int metrics = MatrixMetricsType.getFromString(value); - - if (metrics == MatrixMetricsType.Unknown) - throw new ParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_VALUE, "metric", value); - - req.setMetric(metrics); - } - - value = request.getParameter("units"); - if (!Helper.isEmpty(value)) - { - DistanceUnit units = DistanceUnitUtil.getFromString(value, DistanceUnit.Unknown); - - if (units == DistanceUnit.Unknown) - throw new ParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_VALUE, "units", value); - - req.setUnits(units); - } - - value = request.getParameter("language"); - if (!Helper.isEmpty(value)) - { - if(!LocalizationManager.getInstance().isLanguageSupported(value)) - throw new StatusCodeException(StatusCode.BAD_REQUEST, OptimizationErrorCodes.INVALID_PARAMETER_VALUE, "Specified language '" + value + "' is not supported."); - - req.setLanguage(value); - } - - value = request.getParameter("geometry"); - if (!Helper.isEmpty(value)) - req.setIncludeGeometry(Boolean.parseBoolean(value)); - - value = request.getParameter("geometry_format"); - if (!Helper.isEmpty(value)) - { - if (!("geojson".equalsIgnoreCase(value) || "polyline".equalsIgnoreCase(value) || "encodedpolyline".equalsIgnoreCase(value))) - throw new UnknownParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_VALUE, "geometry_format", value); - - req.setGeometryFormat(value); - } - - value = request.getParameter("geometry_simplify"); - if (!Helper.isEmpty(value)) - req.setSimplifyGeometry(Boolean.parseBoolean(value)); - - value = request.getParameter("instructions"); - if (!Helper.isEmpty(value)) - req.setIncludeInstructions(Boolean.parseBoolean(value)); - - value = request.getParameter("elevation"); - if (!Helper.isEmpty(value)) - req.setIncludeElevation(Boolean.parseBoolean(value)); - - value = request.getParameter("instructions_format"); - if (!Helper.isEmpty(value)) - { - RouteInstructionsFormat instrFormat = RouteInstructionsFormat.fromString(value); - if (instrFormat == RouteInstructionsFormat.UNKNOWN) - throw new UnknownParameterValueException(OptimizationErrorCodes.INVALID_PARAMETER_VALUE, "instructions_format", value); - - req.setInstructionsFormat(instrFormat); - } - - value = request.getParameter("id"); - if (!Helper.isEmpty(value)) - req.setId(value); - - return req; - } -} diff --git a/openrouteservice/src/main/java/heigit/ors/services/optimization/requestprocessors/json/JsonOptimizationRequestProcessor.java b/openrouteservice/src/main/java/heigit/ors/services/optimization/requestprocessors/json/JsonOptimizationRequestProcessor.java deleted file mode 100644 index c3a88fc122..0000000000 --- a/openrouteservice/src/main/java/heigit/ors/services/optimization/requestprocessors/json/JsonOptimizationRequestProcessor.java +++ /dev/null @@ -1,128 +0,0 @@ -/* This file is part of Openrouteservice. - * - * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the - * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 - * of the License, or (at your option) any later version. - - * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - - * You should have received a copy of the GNU Lesser General Public License along with this library; - * if not, see . - */ -package heigit.ors.services.optimization.requestprocessors.json; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.json.JSONArray; -import org.json.JSONObject; - -import com.graphhopper.util.Helper; -import com.graphhopper.util.shapes.BBox; - -import heigit.ors.common.StatusCode; -import heigit.ors.config.AppConfig; -import heigit.ors.exceptions.ParameterOutOfRangeException; -import heigit.ors.exceptions.StatusCodeException; -import heigit.ors.geojson.GeometryJSON; -import heigit.ors.optimization.OptimizationErrorCodes; -import heigit.ors.optimization.RouteOptimizationRequest; -import heigit.ors.optimization.RouteOptimizationResult; -import heigit.ors.routing.RouteResult; -import heigit.ors.routing.RoutingProfileManager; -import heigit.ors.routing.RoutingProfileType; -import heigit.ors.routing.RoutingRequest; -import heigit.ors.services.optimization.OptimizationServiceSettings; -import heigit.ors.services.routing.requestprocessors.json.JsonRoutingResponseWriter; -import heigit.ors.servlet.http.AbstractHttpRequestProcessor; -import heigit.ors.servlet.util.ServletUtility; -import heigit.ors.util.AppInfo; -import heigit.ors.util.DistanceUnitUtil; -import heigit.ors.util.FileUtility; - - -public class JsonOptimizationRequestProcessor extends AbstractHttpRequestProcessor -{ - public JsonOptimizationRequestProcessor(HttpServletRequest request) throws Exception - { - super(request); - } - - @Override - public void process(HttpServletResponse response) throws Exception - { - String reqMethod = _request.getMethod(); - - RouteOptimizationRequest req = null; - - switch (reqMethod) - { - case "GET": - req = JsonOptimizationRequestParser.parseFromRequestParams(_request); - break; - case "POST": - req = JsonOptimizationRequestParser.parseFromStream(_request.getInputStream()); - break; - default: - throw new StatusCodeException(StatusCode.METHOD_NOT_ALLOWED); - } - - if (req == null) - throw new StatusCodeException(StatusCode.BAD_REQUEST, OptimizationErrorCodes.UNKNOWN, "RouteOptimizationRequest object is null."); - - if (OptimizationServiceSettings.getMaximumLocations() > 0 && req.getLocationsCount() > OptimizationServiceSettings.getMaximumLocations()) - throw new ParameterOutOfRangeException(OptimizationErrorCodes.PARAMETER_VALUE_EXCEEDS_MAXIMUM, "locations", Integer.toString(req.getLocationsCount()), Integer.toString(OptimizationServiceSettings.getMaximumLocations())); - - RouteOptimizationResult optResult = RoutingProfileManager.getInstance().computeOptimizedRoutes(req); - - writeResponse(response, req, optResult); - } - - private void writeResponse(HttpServletResponse response, RouteOptimizationRequest request, RouteOptimizationResult optResult) throws Exception - { - JSONObject jResp = new JSONObject(true); - - RoutingRequest reqRoute = request.createRoutingRequest(optResult.getWayPoints()); - - BBox bbox = new BBox(0, 0, 0, 0); - JSONArray jRoutes = JsonRoutingResponseWriter.toJsonArray(reqRoute, new RouteResult[] { optResult.getRouteResult() }, bbox); - jResp.put("routes", jRoutes); - - JSONArray jWayPoints = new JSONArray(); - jWayPoints.put(0, new JSONArray(optResult.getWayPoints())); - jResp.put("way_points", jWayPoints); - - if (bbox != null) - jResp.put("bbox", GeometryJSON.toJSON(bbox.minLon, bbox.minLat, bbox.maxLon, bbox.maxLat)); - - JSONObject jQuery = new JSONObject(); - - jQuery.put("profile", RoutingProfileType.getName(request.getProfileType())); - - if (request.getUnits() != null) - jQuery.put("units", DistanceUnitUtil.toString(request.getUnits())); - - /*if (request.getWeightingMethod() != null) - jQuery.put("preference", request.getWeightingMethod());*/ - - if (request.getId() != null) - jQuery.put("id", request.getId()); - - JSONObject jInfo = new JSONObject(true); - jInfo.put("service", "optimization"); - jInfo.put("engine", AppInfo.getEngineInfo()); - if (!Helper.isEmpty(OptimizationServiceSettings.getAttribution())) - jInfo.put("attribution", OptimizationServiceSettings.getAttribution()); - jInfo.put("timestamp", System.currentTimeMillis()); - - if (AppConfig.hasValidMD5Hash()) - jInfo.put("osm_file_md5_hash", AppConfig.getMD5Hash()); - - jInfo.put("query", jQuery); - jResp.put("info", jInfo); - - ServletUtility.write(response, jResp); - } -} diff --git a/openrouteservice/src/main/resources/META-INF/services/heigit.ors.routing.graphhopper.extensions.storages.builders.GraphStorageBuilder b/openrouteservice/src/main/resources/META-INF/services/heigit.ors.routing.graphhopper.extensions.storages.builders.GraphStorageBuilder index ef8b6d08fc..8f8fdcd311 100644 --- a/openrouteservice/src/main/resources/META-INF/services/heigit.ors.routing.graphhopper.extensions.storages.builders.GraphStorageBuilder +++ b/openrouteservice/src/main/resources/META-INF/services/heigit.ors.routing.graphhopper.extensions.storages.builders.GraphStorageBuilder @@ -5,8 +5,6 @@ heigit.ors.routing.graphhopper.extensions.storages.builders.HillIndexGraphStorag heigit.ors.routing.graphhopper.extensions.storages.builders.WheelchairGraphStorageBuilder heigit.ors.routing.graphhopper.extensions.storages.builders.GreenIndexGraphStorageBuilder heigit.ors.routing.graphhopper.extensions.storages.builders.NoiseIndexGraphStorageBuilder -heigit.ors.routing.graphhopper.extensions.storages.builders.EmergencyVehicleGraphStorageBuilder -heigit.ors.routing.graphhopper.extensions.storages.builders.AccessRestrictionsGraphStorageBuilder heigit.ors.routing.graphhopper.extensions.storages.builders.TollwaysGraphStorageBuilder heigit.ors.routing.graphhopper.extensions.storages.builders.TrailDifficultyScaleGraphStorageBuilder heigit.ors.routing.graphhopper.extensions.storages.builders.BordersGraphStorageBuilder diff --git a/openrouteservice/src/main/resources/app.config.sample b/openrouteservice/src/main/resources/app.config.sample index 96317ccd81..f3a7be00a3 100644 --- a/openrouteservice/src/main/resources/app.config.sample +++ b/openrouteservice/src/main/resources/app.config.sample @@ -70,7 +70,7 @@ "lm": { "enabled": true, "threads": 1, - "weightings": "fastest|shortest", + "weightings": "fastest,shortest", "landmarks": 16 } } @@ -105,15 +105,15 @@ "lm": { "enabled": false, "threads": 1, - "weightings": "fastest|shortest", + "weightings": "fastest,shortest", "landmarks": 16 }, "core": { "enabled": true, "threads": 1, - "weightings": "fastest|shortest", + "weightings": "fastest,shortest", "landmarks": 64, - "lmsets": "highways,tollways;highways;tollways;country_193;allow_all" + "lmsets": "highways;allow_all" } } }, @@ -162,15 +162,15 @@ "lm": { "enabled": true, "threads": 1, - "weightings": "fastest|shortest", + "weightings": "fastest,shortest", "landmarks": 16 }, "core": { "enabled": true, "threads": 1, - "weightings": "fastest|shortest", + "weightings": "fastest,shortest", "landmarks": 64, - "lmsets": "highways,tollways;highways;tollways;country_193;allow_all" + "lmsets": "highways;allow_all" } } }, diff --git a/openrouteservice/src/test/java/heigit/ors/api/requests/routing/APIEnumsTest.java b/openrouteservice/src/test/java/heigit/ors/api/requests/routing/APIEnumsTest.java index ae06757194..43a566f424 100644 --- a/openrouteservice/src/test/java/heigit/ors/api/requests/routing/APIEnumsTest.java +++ b/openrouteservice/src/test/java/heigit/ors/api/requests/routing/APIEnumsTest.java @@ -33,6 +33,7 @@ public void testExtraInfoEnumCreation() throws ParameterValueException { Assert.assertEquals(APIEnums.ExtraInfo.TOLLWAYS, APIEnums.ExtraInfo.forValue("tollways")); Assert.assertEquals(APIEnums.ExtraInfo.TRAIL_DIFFICULTY, APIEnums.ExtraInfo.forValue("traildifficulty")); Assert.assertEquals(APIEnums.ExtraInfo.OSM_ID, APIEnums.ExtraInfo.forValue("osmid")); + Assert.assertEquals(APIEnums.ExtraInfo.COUNTRY_INFO, APIEnums.ExtraInfo.forValue("countryinfo")); APIEnums.ExtraInfo.forValue("invalid"); } @@ -47,6 +48,7 @@ public void testExtraInfoEnumValue() { Assert.assertEquals("tollways", APIEnums.ExtraInfo.TOLLWAYS.toString()); Assert.assertEquals("traildifficulty", APIEnums.ExtraInfo.TRAIL_DIFFICULTY.toString()); Assert.assertEquals("osmid", APIEnums.ExtraInfo.OSM_ID.toString()); + Assert.assertEquals("countryinfo", APIEnums.ExtraInfo.COUNTRY_INFO.toString()); } @Test(expected = ParameterValueException.class) diff --git a/openrouteservice/src/test/java/heigit/ors/globalResponseProcessor/gpx/beans/XMLBuilderTest.java b/openrouteservice/src/test/java/heigit/ors/globalResponseProcessor/gpx/beans/XMLBuilderTest.java index 8dfc973d66..23d86076f6 100644 --- a/openrouteservice/src/test/java/heigit/ors/globalResponseProcessor/gpx/beans/XMLBuilderTest.java +++ b/openrouteservice/src/test/java/heigit/ors/globalResponseProcessor/gpx/beans/XMLBuilderTest.java @@ -56,7 +56,7 @@ public static void setUp() throws DatatypeConfigurationException { // set route Extensions RteTypeExtensions rteTypeExtensions = new RteTypeExtensions(); rteTypeExtensions.setAscent(0); - rteTypeExtensions.setAvgSpeed(0); + rteTypeExtensions.setAvgspeed(0); rteTypeExtensions.setDescent(0); rteTypeExtensions.setDistance(0); rteTypeExtensions.setDistanceActual(0); @@ -203,8 +203,8 @@ public void testBuild() throws JAXBException { " 0.0\n" + " 0.0\n" + " 0.0\n" + - " 0.0\n" + - " \n" + + " 0.0\n" + + " \n" + " \n" + " \n" + " \n" + diff --git a/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/flagencoders/HikingFlagEncoderTest.java b/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/flagencoders/HikingFlagEncoderTest.java new file mode 100644 index 0000000000..4c86ae1db6 --- /dev/null +++ b/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/flagencoders/HikingFlagEncoderTest.java @@ -0,0 +1,264 @@ +/* + * This file is part of Openrouteservice. + * + * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, see . + */ + +package heigit.ors.routing.graphhopper.extensions.flagencoders; + +import com.graphhopper.reader.ReaderRelation; +import com.graphhopper.reader.ReaderWay; +import com.graphhopper.routing.util.EncodingManager; +import com.graphhopper.routing.util.PriorityCode; +import com.graphhopper.util.PMap; +import heigit.ors.routing.graphhopper.extensions.ORSDefaultFlagEncoderFactory; +import org.junit.Before; +import org.junit.Test; + +import java.util.TreeMap; + +import static org.junit.Assert.*; + +public class HikingFlagEncoderTest { + private HikingFlagEncoder flagEncoder; + private ReaderWay way; + + public HikingFlagEncoderTest() { + PMap properties = new PMap(); + ORSDefaultFlagEncoderFactory encoderFactory = new ORSDefaultFlagEncoderFactory(); + flagEncoder = (HikingFlagEncoder)new EncodingManager(new ORSDefaultFlagEncoderFactory(), FlagEncoderNames.HIKING_ORS, 4).getEncoder(FlagEncoderNames.HIKING_ORS); + } + + @Before + public void initWay() { + way = new ReaderWay(1); + } + + private ReaderWay generateHikeWay() { + way.getTags().put("highway", "path"); + return way; + } + + private ReaderWay generateFerryWay() { + way.getTags().put("route", "ferry"); + return way; + } + + @Test + public void acceptDifficultSacScale() { + way = generateHikeWay(); + way.getTags().put("sac_scale", "alpine_hiking"); + + assertEquals(1, flagEncoder.acceptWay(way)); + } + + @Test + public void noTurnRestrictions() { + assertFalse(flagEncoder.isTurnRestricted(1)); + } + + @Test + public void noTurnCost() { + assertEquals(0, flagEncoder.getTurnCost(1), 0.0); + } + + @Test + public void allwaysNoTurnFlags() { + assertEquals(0.0, flagEncoder.getTurnFlags(false, 1.0), 0.0); + } + + @Test + public void handleRelationTags() { + ReaderRelation rel = new ReaderRelation(1); + rel.getTags().put("route", "hiking"); + + rel.getTags().put("network", "iwn"); + assertEquals(PriorityCode.BEST.getValue(), flagEncoder.handleRelationTags(rel, 0)); + rel.getTags().put("network", "nwn"); + assertEquals(PriorityCode.BEST.getValue(), flagEncoder.handleRelationTags(rel, 0)); + rel.getTags().put("network", "rwn"); + assertEquals(PriorityCode.VERY_NICE.getValue(), flagEncoder.handleRelationTags(rel, 0)); + rel.getTags().put("network", "lwn"); + assertEquals(PriorityCode.VERY_NICE.getValue(), flagEncoder.handleRelationTags(rel, 0)); + + rel.getTags().put("route","foot");rel.getTags().put("network", "iwn"); + assertEquals(PriorityCode.BEST.getValue(), flagEncoder.handleRelationTags(rel, 0)); + rel.getTags().put("network", "nwn"); + assertEquals(PriorityCode.BEST.getValue(), flagEncoder.handleRelationTags(rel, 0)); + rel.getTags().put("network", "rwn"); + assertEquals(PriorityCode.VERY_NICE.getValue(), flagEncoder.handleRelationTags(rel, 0)); + rel.getTags().put("network", "lwn"); + assertEquals(PriorityCode.VERY_NICE.getValue(), flagEncoder.handleRelationTags(rel, 0)); + + rel.getTags().put("network", "unknown"); + assertEquals(PriorityCode.VERY_NICE.getValue(), flagEncoder.handleRelationTags(rel, 0)); + + rel.getTags().put("route", "ferry"); + assertEquals(PriorityCode.AVOID_IF_POSSIBLE.getValue(), flagEncoder.handleRelationTags(rel, 0)); + + } + + @Test + public void testOldRelationValueMaintained() { + ReaderRelation rel = new ReaderRelation(1); + rel.getTags().put("route", "hiking"); + + rel.getTags().put("network", "rwn"); + assertEquals(7, flagEncoder.handleRelationTags(rel, 7)); + } + + @Test + public void testAddPriorityFromRelation() { + way = generateHikeWay(); + assertEquals(171, flagEncoder.handleWayTags(way, 1, 1)); + } + + @Test + public void testRejectWay() { + assertEquals(0, flagEncoder.handleWayTags(way, 0, 0)); + } + + @Test + public void testFerrySpeed() { + way = generateFerryWay(); + assertEquals(555, flagEncoder.handleWayTags(way, 3, 0)); + } + + @Test + public void testHikingFlags() { + way = generateHikeWay(); + assertEquals(811, flagEncoder.handleWayTags(way, 1, 0)); + + way.getTags().put("highway", "living_street"); + assertEquals(683, flagEncoder.handleWayTags(way, 1, 0)); + } + + @Test + public void testDifficultHikingFlags() { + way = generateHikeWay(); + way.getTags().put("sac_scale", "alpine_hiking"); + assertEquals(787, flagEncoder.handleWayTags(way, 1, 0)); + } + + @Test + public void testAvoidWaysWithoutSidewalks() { + way.getTags().put("highway", "primary"); + assertEquals(171, flagEncoder.handleWayTags(way, 1, 0)); + way.getTags().put("sidewalk", "both"); + assertEquals(555, flagEncoder.handleWayTags(way, 1, 0)); + way.getTags().put("sidewalk", "none"); + assertEquals(171, flagEncoder.handleWayTags(way, 1, 0)); + } + + @Test + public void testSafeHighwayPriorities() { + TreeMap priorityMap = new TreeMap<>(); + way.getTags().put("highway", "track"); + flagEncoder.assignSafeHighwayPriority(way, priorityMap); + assertEquals((Integer)PriorityCode.VERY_NICE.getValue(), priorityMap.lastEntry().getValue()); + priorityMap.clear(); + way.getTags().put("highway", "path"); + flagEncoder.assignSafeHighwayPriority(way, priorityMap); + assertEquals((Integer)PriorityCode.VERY_NICE.getValue(), priorityMap.lastEntry().getValue()); + priorityMap.clear(); + way.getTags().put("highway", "footway"); + flagEncoder.assignSafeHighwayPriority(way, priorityMap); + assertEquals((Integer)PriorityCode.VERY_NICE.getValue(), priorityMap.lastEntry().getValue()); + priorityMap.clear(); + + way.getTags().put("highway", "living_street"); + flagEncoder.assignSafeHighwayPriority(way, priorityMap); + assertEquals((Integer)PriorityCode.PREFER.getValue(), priorityMap.lastEntry().getValue()); + priorityMap.clear(); + } + + @Test + public void testAcceptWayFerry() { + way = generateFerryWay(); + assertEquals(3, flagEncoder.acceptWay(way)); + } + + @Test + public void testAcceptFootway() { + way = generateHikeWay(); + way.getTags().put("foot", "yes"); + assertEquals(1, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "designated"); + assertEquals(1, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "official"); + assertEquals(1, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "permissive"); + assertEquals(1, flagEncoder.acceptWay(way)); + } + + @Test + public void testRejectRestrictedFootway() { + way = generateHikeWay(); + way.getTags().put("foot", "no"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "private"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "restricted"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "military"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "emergency"); + assertEquals(0, flagEncoder.acceptWay(way)); + + way.removeTag("foot"); + way.getTags().put("access", "no"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("access", "private"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("access", "restricted"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("access", "military"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("access", "emergency"); + assertEquals(0, flagEncoder.acceptWay(way)); + } + + @Test + public void testAcceptSidewalks() { + way.getTags().put("highway", "secondary"); + way.getTags().put("sidewalk", "both"); + assertEquals(1, flagEncoder.acceptWay(way)); + way.getTags().put("sidewalk", "left"); + assertEquals(1, flagEncoder.acceptWay(way)); + way.getTags().put("sidewalk", "right"); + assertEquals(1, flagEncoder.acceptWay(way)); + way.getTags().put("sidewalk", "yes"); + assertEquals(1, flagEncoder.acceptWay(way)); + } + + @Test + public void testRejectMotorways() { + way.getTags().put("highway", "motorway"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("highway", "motorway_link"); + assertEquals(0, flagEncoder.acceptWay(way)); + } + + @Test + public void testRejectMotorRoad() { + way = generateHikeWay(); + way.getTags().put("motorroad", "yes"); + assertEquals(0, flagEncoder.acceptWay(way)); + } + + @Test + public void testDefaultFords() { + way = generateHikeWay(); + way.getTags().put("ford", "yes"); + assertEquals(1, flagEncoder.acceptWay(way)); + } +} diff --git a/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/flagencoders/PedestrianFlagEncoderTest.java b/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/flagencoders/PedestrianFlagEncoderTest.java new file mode 100644 index 0000000000..c2571b4b2f --- /dev/null +++ b/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/flagencoders/PedestrianFlagEncoderTest.java @@ -0,0 +1,289 @@ +/* + * This file is part of Openrouteservice. + * + * Openrouteservice is free software; you can redistribute it and/or modify it under the terms of the + * GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License along with this library; + * if not, see . + */ + +package heigit.ors.routing.graphhopper.extensions.flagencoders; + +import com.graphhopper.reader.ReaderRelation; +import com.graphhopper.reader.ReaderWay; +import com.graphhopper.routing.util.EncodingManager; +import com.graphhopper.routing.util.PriorityCode; +import com.graphhopper.routing.weighting.FastestWeighting; +import com.graphhopper.routing.weighting.PriorityWeighting; +import com.graphhopper.routing.weighting.TurnWeighting; +import com.graphhopper.util.PMap; +import heigit.ors.routing.graphhopper.extensions.ORSDefaultFlagEncoderFactory; +import org.junit.Before; +import org.junit.Test; + +import java.util.TreeMap; + +import static org.junit.Assert.*; + +public class PedestrianFlagEncoderTest { + private PedestrianFlagEncoder flagEncoder; + private ReaderWay way; + + public PedestrianFlagEncoderTest() { + flagEncoder = (PedestrianFlagEncoder)new EncodingManager(new ORSDefaultFlagEncoderFactory(), FlagEncoderNames.PEDESTRIAN_ORS, 4).getEncoder(FlagEncoderNames.PEDESTRIAN_ORS); + } + + @Before + public void initWay() { + way = new ReaderWay(1); + } + + private ReaderWay generatePedestrianWay() { + way.getTags().put("highway", "path"); + return way; + } + + private ReaderWay generateFerryWay() { + way.getTags().put("route", "ferry"); + way.getTags().put("estimated_distance", 20000); + way.getTags().put("duration:seconds", "1800"); + return way; + } + + @Test + public void rejectDifficultSacScale() { + way = generatePedestrianWay(); + way.getTags().put("sac_scale", "alpine_hiking"); + + assertEquals(0, flagEncoder.acceptWay(way)); + } + + @Test + public void noTurnRestrictions() { + assertFalse(flagEncoder.isTurnRestricted(1)); + } + + @Test + public void noTurnCost() { + assertEquals(0, flagEncoder.getTurnCost(1), 0.0); + } + + @Test + public void allwaysNoTurnFlags() { + assertEquals(0.0, flagEncoder.getTurnFlags(false, 1.0), 0.0); + } + + @Test + public void handleRelationTags() { + ReaderRelation rel = new ReaderRelation(1); + + rel.getTags().put("route", "ferry"); + assertEquals(PriorityCode.AVOID_IF_POSSIBLE.getValue(), flagEncoder.handleRelationTags(rel, 0)); + } + + @Test + public void testRejectWay() { + assertEquals(0, flagEncoder.handleWayTags(way, 0, 0)); + } + + @Test + public void testFerryFlags() { + way = generateFerryWay(); + assertEquals(635, flagEncoder.handleWayTags(way, 3, 0)); + } + + @Test + public void testPlatformFlags() { + way.getTags().put("railway", "platform"); + assertEquals(1, flagEncoder.acceptWay(way)); + + way.getTags().put("railway", "track"); + assertEquals(0, flagEncoder.acceptWay(way)); + } + + @Test + public void testPierFlags() { + way.getTags().put("man_made", "pier"); + assertEquals(1, flagEncoder.acceptWay(way)); + + way.getTags().put("man_made", "not_a_pier"); + assertEquals(0, flagEncoder.acceptWay(way)); + } + + @Test + public void testHikingFlags() { + way = generatePedestrianWay(); + way.getTags().put("sac_scale", "hiking"); + assertEquals(683, flagEncoder.handleWayTags(way, 1, 0)); + + way.getTags().put("highway", "living_street"); + assertEquals(683, flagEncoder.handleWayTags(way, 1, 0)); + } + + @Test + public void testDesignatedFootwayPriority() { + way.getTags().put("highway", "secondary"); + assertEquals(299, flagEncoder.handleWayTags(way, 1, 0)); + + way.getTags().put("foot", "designated"); + assertEquals(683, flagEncoder.handleWayTags(way, 1, 0)); + } + + @Test + public void testAvoidWaysWithoutSidewalks() { + way.getTags().put("highway", "primary"); + assertEquals(171, flagEncoder.handleWayTags(way, 1, 0)); + way.getTags().put("sidewalk", "both"); + assertEquals(555, flagEncoder.handleWayTags(way, 1, 0)); + way.getTags().put("sidewalk", "none"); + assertEquals(171, flagEncoder.handleWayTags(way, 1, 0)); + } + + @Test + public void testAcceptWayFerry() { + way = generateFerryWay(); + assertEquals(3, flagEncoder.acceptWay(way)); + } + + @Test + public void testAcceptFootway() { + way = generatePedestrianWay(); + way.getTags().put("foot", "yes"); + assertEquals(1, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "designated"); + assertEquals(1, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "official"); + assertEquals(1, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "permissive"); + assertEquals(1, flagEncoder.acceptWay(way)); + } + + @Test + public void testRejectRestrictedFootway() { + way = generatePedestrianWay(); + way.getTags().put("foot", "no"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "private"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "restricted"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "military"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("foot", "emergency"); + assertEquals(0, flagEncoder.acceptWay(way)); + + way.removeTag("foot"); + way.getTags().put("access", "no"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("access", "private"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("access", "restricted"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("access", "military"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("access", "emergency"); + assertEquals(0, flagEncoder.acceptWay(way)); + } + + @Test + public void testAcceptSidewalks() { + way.getTags().put("highway", "secondary"); + way.getTags().put("sidewalk", "both"); + assertEquals(1, flagEncoder.acceptWay(way)); + way.getTags().put("sidewalk", "left"); + assertEquals(1, flagEncoder.acceptWay(way)); + way.getTags().put("sidewalk", "right"); + assertEquals(1, flagEncoder.acceptWay(way)); + way.getTags().put("sidewalk", "yes"); + assertEquals(1, flagEncoder.acceptWay(way)); + } + + @Test + public void testRejectMotorways() { + way.getTags().put("highway", "motorway"); + assertEquals(0, flagEncoder.acceptWay(way)); + way.getTags().put("highway", "motorway_link"); + assertEquals(0, flagEncoder.acceptWay(way)); + } + + @Test + public void testRejectMotorRoad() { + way = generatePedestrianWay(); + way.getTags().put("motorroad", "yes"); + assertEquals(0, flagEncoder.acceptWay(way)); + } + + @Test + public void testDefaultFords() { + way = generatePedestrianWay(); + way.getTags().put("ford", "yes"); + assertEquals(0, flagEncoder.acceptWay(way)); + } + + @Test + public void testTunnelValues() { + TreeMap priorityMap = new TreeMap<>(); + way.getTags().put("highway", "residential"); + way.getTags().put("tunnel", "yes"); + way.getTags().put("sidewalk", "no"); + flagEncoder.assignSafeHighwayPriority(way, priorityMap); + assertEquals((Integer)PriorityCode.AVOID_IF_POSSIBLE.getValue(), priorityMap.lastEntry().getValue()); + + way.getTags().put("sidewalk", "both"); + flagEncoder.assignSafeHighwayPriority(way, priorityMap); + assertEquals((Integer)PriorityCode.UNCHANGED.getValue(), priorityMap.lastEntry().getValue()); + } + + @Test + public void testBicyclePathPriority(){ + way.getTags().put("highway", "path"); + assertEquals(683, flagEncoder.handleWayTags(way, 1, 0)); + way.getTags().put("bicycle", "official"); + assertEquals(427, flagEncoder.handleWayTags(way, 1, 0)); + way.getTags().put("bicycle", "designated"); + assertEquals(427, flagEncoder.handleWayTags(way, 1, 0)); + way.getTags().put("bicycle", "permissive"); + assertEquals(683, flagEncoder.handleWayTags(way, 1, 0)); + } + + @Test + public void testSpeed() { + assertEquals(5.0, flagEncoder.getSpeed(683), 0.0); + assertEquals(20.0, flagEncoder.getSpeed(635), 0.0); + } + + @Test + public void testSupports() { + assertTrue(flagEncoder.supports(PriorityWeighting.class)); + assertFalse(flagEncoder.supports(TurnWeighting.class)); + } + + @Test + public void getWeighting() { + assertEquals(0.714, flagEncoder.getDouble(683, PriorityWeighting.KEY), 0.001); + boolean throwsError = false; + try { + // Only priority weighting allowed + flagEncoder.getDouble(683, 1); + } catch (UnsupportedOperationException e) { + throwsError = true; + } + + assertTrue(throwsError); + } + + @Test + public void testRoundaboutFlag() { + way = generatePedestrianWay(); + way.getTags().put("junction", "roundabout"); + assertEquals(687, flagEncoder.handleWayTags(way, 1, 0)); + way.getTags().put("junction", "circular"); + assertEquals(687, flagEncoder.handleWayTags(way, 1, 0)); + } +} diff --git a/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/storages/builders/BordersGraphStorageBuilderTest.java b/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/storages/builders/BordersGraphStorageBuilderTest.java index 1fa0624f2a..ce25af551d 100644 --- a/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/storages/builders/BordersGraphStorageBuilderTest.java +++ b/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/storages/builders/BordersGraphStorageBuilderTest.java @@ -16,7 +16,6 @@ import com.graphhopper.reader.ReaderWay; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.GeometryFactory; -import com.vividsolutions.jts.geom.LineString; import heigit.ors.routing.graphhopper.extensions.reader.borders.CountryBordersHierarchy; import heigit.ors.routing.graphhopper.extensions.reader.borders.CountryBordersPolygon; import heigit.ors.routing.graphhopper.extensions.reader.borders.CountryBordersReader; @@ -118,8 +117,8 @@ public void TestProcessWay() { _builder.processWay(rw2, cs2, null); - Assert.assertFalse(rw2.hasTag("country1")); - Assert.assertFalse(rw2.hasTag("country2")); + Assert.assertEquals("c1", rw2.getTag("country1")); + Assert.assertEquals("c1", rw2.getTag("country2")); } /**