From 404a60d0f116eac4ea0193075690bcb54ed538da Mon Sep 17 00:00:00 2001 From: Julian Psotta Date: Wed, 8 May 2019 09:48:08 +0200 Subject: [PATCH] feature-#349 list traversal countries --- .../ors/api/requests/common/APIEnums.java | 3 +- .../ors/routing/RouteExtraInfoFlag.java | 3 + .../ors/routing/RoutingProfileManager.java | 1 + .../reader/borders/CountryBordersReader.java | 14 ++++ .../storages/BordersGraphStorage.java | 60 ++++++++++----- .../builders/BordersGraphStorageBuilder.java | 77 +++++++++++-------- .../pathprocessors/ExtraInfoProcessor.java | 45 ++++++++++- .../AvoidBordersEdgeFilterTest.java | 6 +- .../storages/BordersGraphStorageTest.java | 4 +- .../pathprocessors/BordersExtractorTest.java | 6 +- 10 files changed, 158 insertions(+), 61 deletions(-) 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/routing/RouteExtraInfoFlag.java b/openrouteservice/src/main/java/heigit/ors/routing/RouteExtraInfoFlag.java index 52d3b99168..bfab4708b1 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; @@ -77,6 +78,8 @@ public static int getFromString(String value) { break; case "roadaccessrestrictions": res |= RoadAccessRestrictions; + case "countryinfo": + res |= CountryInfo; break; } } diff --git a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java index ab3d1894c5..4e358677a1 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/RoutingProfileManager.java @@ -32,6 +32,7 @@ import heigit.ors.matrix.MatrixResult; import heigit.ors.routing.configuration.RouteProfileConfiguration; import heigit.ors.routing.configuration.RoutingManagerConfiguration; +import heigit.ors.routing.graphhopper.extensions.reader.borders.CountryBordersReader; import heigit.ors.routing.pathprocessors.ElevationSmoothPathProcessor; import heigit.ors.routing.pathprocessors.ExtraInfoProcessor; import heigit.ors.routing.traffic.RealTrafficDataProvider; 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..9c5d5cf9b3 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 @@ -13,6 +13,8 @@ */ package heigit.ors.routing.graphhopper.extensions.reader.borders; +import com.graphhopper.util.PointList; +import com.graphhopper.util.shapes.GHPoint3D; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Point; @@ -381,6 +383,18 @@ public static int getCountryIdByISOCode(String code) { return currentInstance != null ? currentInstance.isoCodes.getOrDefault(code.toUpperCase(), 0) : 0; } + public static CountryBordersPolygon[] getCountriesByPointList(PointList pointList) { + CountryBordersPolygon[] countries = new CountryBordersPolygon[0]; + for (GHPoint3D point : + pointList) { + Coordinate coordinate = new Coordinate(point.lon, point.lat); + CountryBordersPolygon[] countries2 = currentInstance.getCandidateCountry(coordinate); + CountryBordersPolygon[] countries23 = currentInstance.getCandidateCountry(coordinate); + + } + return countries; + } + /** * Read information from the id csv. This includes a unique identifier, the local name of the country and the * English name of the country. Optionally reads ISO codes from column 4 and 5 (expecting them to contain the 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..0a4fd63a02 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,16 +19,22 @@ 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, COUNTRY1, COUNTRY2} /* pointer for no entry */ protected final int NO_ENTRY = -1; private final int EF_BORDER = 0; // byte location of border type private final int EF_START = 2; // byte location of the start country id private final int EF_END = 4; // byte location of the end country id + private final int EF_COUNTRY_1 = 8; // byte location of the first country id + private final int EF_COUNTRY_2 = 16; // byte location of the second country id // border types public static final short NO_BORDER = 0; @@ -40,7 +46,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,13 +57,14 @@ 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 + * @param country1 + * @param country2 */ - public void setEdgeValue(int edgeId, short borderType, short start, short end) { + public void setEdgeValue(int edgeId, short borderType, short start, short end, short country1, short country2) { edgesCount++; ensureEdgesIndex(edgeId); @@ -68,35 +74,47 @@ public void setEdgeValue(int edgeId, short borderType, short start, short end) { orsEdges.setShort(edgePointer + EF_BORDER, borderType); orsEdges.setShort(edgePointer + EF_START, start); orsEdges.setShort(edgePointer + EF_END, end); + orsEdges.setShort(edgePointer + EF_COUNTRY_1, country1); + orsEdges.setShort(edgePointer + EF_COUNTRY_2, country2); } private void ensureEdgesIndex(int edgeId) { orsEdges.ensureCapacity(((long) edgeId + 1) * edgeEntryBytes); } /** * 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) { + // TODO maybe implement a second function that accesses only the country data long edgePointer = (long) edgeId * edgeEntryBytes; - short border = 0, start = 0, end = 0; + short border; + short start; + short end; + short country1; + short country2; border = orsEdges.getShort(edgePointer + EF_BORDER); start = orsEdges.getShort(edgePointer + EF_START); end = orsEdges.getShort(edgePointer + EF_END); + country1 = orsEdges.getShort(edgePointer + EF_COUNTRY_1); + country2 = orsEdges.getShort(edgePointer + EF_COUNTRY_2); switch (prop) { case TYPE: - return border; case START: return start; case END: return end; + case COUNTRY1: + return country1; + case COUNTRY2: + return country2; default: return 0; } 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..b086f3ecc2 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 @@ -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; @@ -126,6 +125,10 @@ public void processWay(ReaderWay way, Coordinate[] coords, HashMap 1 && !countries[0].equals(countries[1])) { way.setTag("country1", countries[0]); way.setTag("country2", countries[1]); + } else if (countries.length == 1 && !countries[0].isEmpty()) { + way.setTag("country1", countries[0]); + } else if (countries.length == 1 && countries[0].isEmpty()){ + way.setTag("country2", countries[1]); } } } @@ -139,35 +142,46 @@ public void processWay(ReaderWay way, Coordinate[] coords, HashMap 2){ +// countries = countries; +// } // Now we have a list of all the countries that the nodes are in - if this is more than one it is likely it is // crossing a border, but not certain as in some disputed areas, countries overlap and so it may not cross any // border. 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..ed0294d399 100644 --- a/openrouteservice/src/main/java/heigit/ors/routing/pathprocessors/ExtraInfoProcessor.java +++ b/openrouteservice/src/main/java/heigit/ors/routing/pathprocessors/ExtraInfoProcessor.java @@ -29,10 +29,13 @@ import heigit.ors.routing.util.extrainfobuilders.RouteExtraInfoBuilder; import heigit.ors.routing.util.extrainfobuilders.SimpleRouteExtraInfoBuilder; import heigit.ors.routing.util.extrainfobuilders.SteepnessExtraInfoBuilder; +import org.apache.log4j.Logger; import java.util.*; public class ExtraInfoProcessor extends PathProcessor { + private static final Logger LOGGER = Logger.getLogger(BordersGraphStorage.class.getName()); + private WaySurfaceTypeGraphStorage _extWaySurface; private WayCategoryGraphStorage _extWayCategory; private GreenIndexGraphStorage _extGreenIndex; @@ -42,7 +45,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 +84,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; @@ -204,7 +211,14 @@ public ExtraInfoProcessor(ORSGraphHopper graphHopper, RoutingRequest req) throws _roadAccessRestrictionsInfo = new RouteExtraInfo("roadaccessrestrictions", _extRoadAccessRestrictions); _roadAccessRestrictionsBuilder = new SimpleRouteExtraInfoBuilder(_roadAccessRestrictionsInfo); } - + boolean yes = true; + if (yes) { + _extCountryTraversalInfo = GraphStorageUtils.getGraphExtension(graphHopper.getGraphHopperStorage(), BordersGraphStorage.class); + if(_extCountryTraversalInfo == null) + throw new Exception("BordersGraphStorage is not found"); + _countryTraversalInfo = new RouteExtraInfo("countryinfo", _extCountryTraversalInfo); + _countryTraversalBuilder = new SimpleRouteExtraInfoBuilder(_countryTraversalInfo); + } buffer = new byte[4]; } @@ -276,13 +290,40 @@ public List getExtras() extras.add(_osmIdInfo); if (_roadAccessRestrictionsInfo != null) extras.add(_roadAccessRestrictionsInfo); + if (_countryTraversalInfo != null) + extras.add(_countryTraversalInfo); return extras; } @Override public void processEdge(EdgeIteratorState edge, boolean isLastEdge, PointList geom) { double dist = edge.getDistance(); + short country1; + short country2; + + // TODO Add extra info for crossed countries + if (_extCountryTraversalInfo != null){ + country1 = _extCountryTraversalInfo.getEdgeValue(EdgeIteratorStateHelper.getOriginalEdge(edge), BordersGraphStorage.Property.COUNTRY1); + country2 = _extCountryTraversalInfo.getEdgeValue(EdgeIteratorStateHelper.getOriginalEdge(edge), BordersGraphStorage.Property.COUNTRY2); + if (country1 != 0) + LOGGER.info("country1: " + country1); + else + LOGGER.info(""); + if (country2 != 0) + LOGGER.info("country2: " + country2); + else + LOGGER.info(""); + if (_countryTraversalBuilder != null && country2 == 0) { + _countryTraversalBuilder.addSegment(country1, country1, geom, dist, isLastEdge && _lastSegment); + } + if (_countryTraversalBuilder != null && country2 != 0) { + int integer = Integer.parseInt(country1 + String.valueOf(0) + country2); + _countryTraversalBuilder.addSegment(integer, integer, geom, dist, isLastEdge && _lastSegment); + + } + + } if (_extWaySurface != null && _wayTypeInfo != null || _surfaceInfo != null) { WaySurfaceDescription wsd = _extWaySurface.getEdgeValue(EdgeIteratorStateHelper.getOriginalEdge(edge), buffer); diff --git a/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/edgefilters/AvoidBordersEdgeFilterTest.java b/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/edgefilters/AvoidBordersEdgeFilterTest.java index 72bea5e588..37b6ea61a4 100644 --- a/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/edgefilters/AvoidBordersEdgeFilterTest.java +++ b/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/edgefilters/AvoidBordersEdgeFilterTest.java @@ -45,9 +45,9 @@ public AvoidBordersEdgeFilterTest() { // (edgeId, borderType, startCountry, endCountry) - _graphStorage.setEdgeValue(1, BordersGraphStorage.CONTROLLED_BORDER, (short)1, (short)2); - _graphStorage.setEdgeValue(2, BordersGraphStorage.OPEN_BORDER, (short)3, (short)4); - _graphStorage.setEdgeValue(3, BordersGraphStorage.NO_BORDER, (short)5, (short)5); + _graphStorage.setEdgeValue(1, BordersGraphStorage.CONTROLLED_BORDER, (short)1, (short)2, (short) 0 , (short) 0); + _graphStorage.setEdgeValue(2, BordersGraphStorage.OPEN_BORDER, (short)3, (short)4, (short) 0 , (short) 0); + _graphStorage.setEdgeValue(3, BordersGraphStorage.NO_BORDER, (short)5, (short)5, (short) 0 , (short) 0); _searchParams = new RouteSearchParameters(); diff --git a/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/storages/BordersGraphStorageTest.java b/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/storages/BordersGraphStorageTest.java index e3cd79b7d1..6554144204 100644 --- a/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/storages/BordersGraphStorageTest.java +++ b/openrouteservice/src/test/java/heigit/ors/routing/graphhopper/extensions/storages/BordersGraphStorageTest.java @@ -29,10 +29,12 @@ public BordersGraphStorageTest() { @Test public void TestItemCreation() { - _storage.setEdgeValue(1, (short)1, (short)2, (short)3); + _storage.setEdgeValue(1, (short)1, (short)2, (short)3, (short) 4 , (short) 5); assertEquals(_storage.getEdgeValue(1, BordersGraphStorage.Property.TYPE), 1); assertEquals(_storage.getEdgeValue(1, BordersGraphStorage.Property.START), 2); assertEquals(_storage.getEdgeValue(1, BordersGraphStorage.Property.END), 3); + assertEquals(_storage.getEdgeValue(1, BordersGraphStorage.Property.END), 4); + assertEquals(_storage.getEdgeValue(1, BordersGraphStorage.Property.END), 5); } } diff --git a/openrouteservice/src/test/java/heigit/ors/routing/pathprocessors/BordersExtractorTest.java b/openrouteservice/src/test/java/heigit/ors/routing/pathprocessors/BordersExtractorTest.java index 947337c7c6..ed3ff66166 100644 --- a/openrouteservice/src/test/java/heigit/ors/routing/pathprocessors/BordersExtractorTest.java +++ b/openrouteservice/src/test/java/heigit/ors/routing/pathprocessors/BordersExtractorTest.java @@ -38,9 +38,9 @@ public BordersExtractorTest() { // (edgeId, borderType, startCountry, endCountry) - _graphstorage.setEdgeValue(1, BordersGraphStorage.CONTROLLED_BORDER, (short)1, (short)2); - _graphstorage.setEdgeValue(2, BordersGraphStorage.OPEN_BORDER, (short)3, (short)4); - _graphstorage.setEdgeValue(3, BordersGraphStorage.NO_BORDER, (short)5, (short)5); + _graphstorage.setEdgeValue(1, BordersGraphStorage.CONTROLLED_BORDER, (short)1, (short)2, (short) 0 , (short) 0); + _graphstorage.setEdgeValue(2, BordersGraphStorage.OPEN_BORDER, (short)3, (short)4, (short) 0 , (short) 0); + _graphstorage.setEdgeValue(3, BordersGraphStorage.NO_BORDER, (short)5, (short)5, (short) 0 , (short) 0); } private VirtualEdgeIteratorState generateEdge(int id) {