Skip to content

Commit

Permalink
feature-#349 list traversal countries
Browse files Browse the repository at this point in the history
  • Loading branch information
Julian Psotta committed May 10, 2019
1 parent 8f967aa commit 1ccec59
Show file tree
Hide file tree
Showing 8 changed files with 117 additions and 63 deletions.
Expand Up @@ -63,7 +63,8 @@ public enum ExtraInfo {
TOLLWAYS("tollways"),
TRAIL_DIFFICULTY("traildifficulty"),
OSM_ID("osmid"),
ROAD_ACCESS_RESTRICTIONS("roadaccessrestrictions");
ROAD_ACCESS_RESTRICTIONS("roadaccessrestrictions"),
COUNTRY_INFO("countryinfo");

private final String value;

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

public static boolean isSet(int extraInfo, int value) {
return (extraInfo & value) == value;
Expand Down Expand Up @@ -77,6 +78,8 @@ public static int getFromString(String value) {
break;
case "roadaccessrestrictions":
res |= RoadAccessRestrictions;
case "countryinfo":
res |= CountryInfo;
break;
}
}
Expand Down
Expand Up @@ -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;
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down
@@ -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 <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Lesser General Public License along with this library;
* if not, see <https://www.gnu.org/licenses/>.
*/
package heigit.ors.routing.graphhopper.extensions.storages;

Expand All @@ -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
Expand All @@ -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
Expand All @@ -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++;
Expand All @@ -74,24 +76,28 @@ 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<br/><br/>
*
* <p>
* 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 genuineCountry;
short edge = orsEdges.getShort(edgePointer);
border = orsEdges.getShort(edgePointer + EF_BORDER);
start = orsEdges.getShort(edgePointer + EF_START);
end = orsEdges.getShort(edgePointer + EF_END);

switch (prop) {
case TYPE:

return border;
case START:
return start;
Expand Down
@@ -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 <https://www.gnu.org/licenses/>.
* You should have received a copy of the GNU Lesser General Public License along with this library;
* if not, see <https://www.gnu.org/licenses/>.
*/
package heigit.ors.routing.graphhopper.extensions.storages.builders;

Expand All @@ -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;
Expand Down Expand Up @@ -119,13 +118,15 @@ public void processWay(ReaderWay way) {
public void processWay(ReaderWay way, Coordinate[] coords, HashMap<Integer, HashMap<String,String>> 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]);
}
}
}
Expand All @@ -139,35 +140,33 @@ public void processWay(ReaderWay way, Coordinate[] coords, HashMap<Integer, Hash
* @param way The OSM way obtained from the OSM reader. This way corresponds to the edge to be processed
* @param edge The graph edge to be process
*/
@Override
public void processEdge(ReaderWay way, EdgeIteratorState edge) {
// Make sure we actually have the storage initialised - if there were errors accessing the data then this could be the case
if(_storage != null) {
// If there is no border crossing then we set the edge value to be 0

// First get the start and end countries - if either of these is empty, then there is no crossing
if (way.hasTag("country1") && way.hasTag("country2")) {
String startVal = way.getTag("country1");
String endVal = way.getTag("country2");

// Lookup values
short start = 0, end = 0;

try {
start = Short.parseShort(cbReader.getId(startVal));
end = Short.parseShort(cbReader.getId(endVal));
} catch (NumberFormatException nfe) {
LOGGER.error("Error in lookup for ids " + startVal + " and " + endVal);
}

short type = (cbReader.isOpen(cbReader.getEngName(startVal), cbReader.getEngName(endVal))) ? (short) 2 : (short) 1;

_storage.setEdgeValue(edge.getEdge(), type, start, end);
} else {
_storage.setEdgeValue(edge.getEdge(), (short) 0, (short) 0, (short) 0);
}
}
}
@Override
public void processEdge(ReaderWay way, EdgeIteratorState edge) {
// Make sure we actually have the storage initialised - if there were errors accessing the data then this could be the case
if (_storage != null) {
// If there is no border crossing then we set the edge value to be 0

// First get the start and end countries - if they are equal, then there is no crossing
String startVal = way.getTag("country1");
String endVal = way.getTag("country2");
short type;
short start = 0;
short end = 0;
try {
start = Short.parseShort(cbReader.getId(startVal));
end = Short.parseShort(cbReader.getId(endVal));
} catch (Exception ex) {
LOGGER.info("Skipping country borders for edge: " + edge.getEdge());
} finally {
if (start != end) {
type = (cbReader.isOpen(cbReader.getEngName(startVal), cbReader.getEngName(endVal))) ? (short) 2 : (short) 1;
} else {
type = BordersGraphStorage.NO_BORDER;
}
}
_storage.setEdgeValue(edge.getEdge(), type, start, end);
}
}

/**
* Method identifying the name of the extension which is used in various building processes
Expand Down Expand Up @@ -257,6 +256,9 @@ public String[] findBorderCrossing(Coordinate[] coords) {
// Replace the arraylist
countries = temp;
}
// if (countries.size() > 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.
Expand Down
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -80,6 +84,9 @@ public class ExtraInfoProcessor extends PathProcessor {
private RouteExtraInfo _roadAccessRestrictionsInfo;
private RouteExtraInfoBuilder _roadAccessRestrictionsBuilder;

private RouteExtraInfo _countryTraversalInfo;
private RouteExtraInfoBuilder _countryTraversalBuilder;

private List<Integer> warningExtensions;

private int _profileType = RoutingProfileType.UNKNOWN;
Expand Down Expand Up @@ -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];
}

Expand Down Expand Up @@ -276,13 +290,24 @@ public List<RouteExtraInfo> 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();

// TODO Add extra info for crossed countries
if (_extCountryTraversalInfo != null){
short country = _extCountryTraversalInfo.getEdgeValue(EdgeIteratorStateHelper.getOriginalEdge(edge), BordersGraphStorage.Property.START);

if (_countryTraversalBuilder != null && country != 0) {
_countryTraversalBuilder.addSegment(country, country, geom, dist, isLastEdge && _lastSegment);

}
}
if (_extWaySurface != null && _wayTypeInfo != null || _surfaceInfo != null)
{
WaySurfaceDescription wsd = _extWaySurface.getEdgeValue(EdgeIteratorStateHelper.getOriginalEdge(edge), buffer);
Expand Down
Expand Up @@ -118,8 +118,10 @@ public void TestProcessWay() {

_builder.processWay(rw2, cs2, null);

Assert.assertFalse(rw2.hasTag("country1"));
Assert.assertFalse(rw2.hasTag("country2"));
// Assert.assertFalse(rw2.hasTag("country1"));
// Assert.assertFalse(rw2.hasTag("country2"));
Assert.assertEquals("c1", rw2.getTag("country1"));
Assert.assertEquals("c1", rw2.getTag("country2"));
}

/**
Expand Down

0 comments on commit 1ccec59

Please sign in to comment.