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 8, 2019
1 parent 8f967aa commit 203db89
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 55 deletions.
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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,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 = 6; // byte location of the first country id
private final int EF_COUNTRY_2 = 8; // byte location of the second country id

// border types
public static final short NO_BORDER = 0;
Expand All @@ -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
Expand All @@ -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);

Expand All @@ -68,6 +74,8 @@ 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); }
Expand All @@ -83,20 +91,33 @@ public void setEdgeValue(int edgeId, short borderType, short start, short end) {
* @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 = 0, start = 0, end = 0, country1 = 0, country2 = 0;
border = orsEdges.getShort(edgePointer + EF_BORDER);
start = orsEdges.getShort(edgePointer + EF_START);
end = orsEdges.getShort(edgePointer + EF_END);
try {
country1 = orsEdges.getShort(edgePointer + EF_COUNTRY_1);
country2 = orsEdges.getShort(edgePointer + EF_COUNTRY_2);
} catch (ArrayIndexOutOfBoundsException e) {
LOGGER.error("Countries Exception: %s%n", e);
LOGGER.info(String.format("EdgeID: %d", edgeId));
LOGGER.info(String.format("country1: %s", country1));
LOGGER.info(String.format("country2: %s", country2));
}

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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 @@ -126,6 +125,10 @@ public void processWay(ReaderWay way, Coordinate[] coords, HashMap<Integer, Hash
if (countries.length > 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]);
}
}
}
Expand All @@ -139,35 +142,46 @@ 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 either of these is empty, then there is no crossing
short country1 = 0;
short country2 = 0;
if (way.hasTag("country1") && way.hasTag("country2")) {
String startVal = way.getTag("country1");
String endVal = way.getTag("country2");
// Lookup values
short start = 0;
short end = 0;
try {
start = Short.parseShort(cbReader.getId(startVal));
end = Short.parseShort(cbReader.getId(endVal));
country1 = Short.parseShort(cbReader.getId(startVal));
country2 = Short.parseShort(cbReader.getId(endVal));
} catch (NumberFormatException nfe) {
LOGGER.error("Error in lookup for ids " + startVal + " and " + endVal);
}
// Todo add add three extra bits to the edge value relating the country
short type = (cbReader.isOpen(cbReader.getEngName(startVal), cbReader.getEngName(endVal))) ? (short) 2 : (short) 1;

_storage.setEdgeValue(edge.getEdge(), type, start, end, country1, country2);
} else if (way.hasTag("country1")) {
String startVal = way.getTag("country1");
try {
country1 = Short.parseShort(cbReader.getId(startVal));
} catch (NumberFormatException nfe) {
LOGGER.error("Error in lookup for ids " + startVal);
}
_storage.setEdgeValue(edge.getEdge(), (short) 0, (short) 0, (short) 0, country1, country2);
} else {
_storage.setEdgeValue(edge.getEdge(), (short) 0, (short) 0, (short) 0, country1, country2);
}
}
}

/**
* Method identifying the name of the extension which is used in various building processes
Expand Down Expand Up @@ -257,6 +271,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
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,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 +81,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 +208,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 +287,22 @@ 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();
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 (_extWaySurface != null && _wayTypeInfo != null || _surfaceInfo != null)
{
WaySurfaceDescription wsd = _extWaySurface.getEdgeValue(EdgeIteratorStateHelper.getOriginalEdge(edge), buffer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit 203db89

Please sign in to comment.