Building routes ..., people regularly use it, especially for car routes, in navigators.
There are also a lot of solutions for building a route, including GraphHopper , which knows how to build routes for cars, and for pedestrians, and even for hiking, which is probably suitable in 99% of cases.
Next, we will talk about what to do in other situations, more precisely about my experience of using GraphHopper when the existing solution did not fit. It was necessary to take into account additional restrictions: to build walking routes for people with disabilities. There will be no significant features of the implementation of this particular task. Generalized.
It will describe how to create a web service based on the GraphHopper library, which, based on the coordinates of the start and end of the path, will return an array of route coordinates.
A sample application, with all the stubs you need to run, can be found in my repository on GitHub .
GraphHopper is a routing engine written in Java. Released under the Apache license, and can be embedded in closed source products.
Articles of this kind on Habré are found, for example, Walking around the city wisely , but it does not provide implementation details, unfortunately, and ... well, that's all.
Also in the publication News from the world of OpenStreetMap No. 512 (05/05/2020 - 05/11/2020) , there was news of the following content:
The GraphHopper developers are waiting for our comments, as they introduced a new feature that allows even people without programming or Java knowledge to change the route building model.
Probably, this new function will cover another 0.99% of possible situations, it will probably be suitable for your task as well, knowledge of Java is not required, and in general there will be no problems. I will tell you about my experience in creating rules for building routes, when this function was not there, and 2 years were left before its creation.
Knowledge of Java is required.
, , :
GraphHopper OSM, , OSM. , , OSM. . , .
GraphHopper 0.10.0, .
.
Maven:
<dependency>
<groupId>com.graphhopper</groupId>
<artifactId>graphhopper-reader-osm</artifactId>
<version>0.10.0</version>
</dependency>
GraphHopper, , github. , How to create new routing profile aka a new FlagEncoder? , , FlagEncoder
. FlagEncoder
, com.graphhopper.routing.util
, FootFlagEncoder
, .. , AbstractFlagEncoder
, .
GraphHopper ( ) GraphHopper Documentation RoutingExample.java.
FlagEncoder
, FlagEncoder
AbstractFlagEncoder
, FootFlagEncoder
, FootFlagEncoder
, . AbstractFlagEncoder
FootFlagEncoder
, , FootFlagEncoder
.
acceptWay
, - ReaderWay
/ . FlagEncoder
. FlagEncoder
, . acceptWay
, – 0.
restricted
, id
way
OSM.
public class MyFlagEncoder {
…
private List<Long> restricted;
@Override
public long acceptWay(ReaderWay way) {
if (restricted.contains(way.getId()))
return 0;
…
}
…
}
, , , 0.
FlagEncoder
, , .
GraphHopper closableInstance = new GraphHopperOSM().setOSMFile(osmFilePath).forServer();
closableInstance.setStoreOnFlush(true);
closableInstance.setGraphHopperLocation(graphFolder);
closableInstance.setEncodingManager(new EncodingManager(encoder));
closableInstance.setCHEnabled(false);
GraphHopper hopper = closableInstance.importOrLoad();
osmFilePath - pbf- , pbf geofabrik, , OSM;
encoder –
FlagEncoder
, , ;
graphFolder – .
importOrLoad
, FlagEncoder
, .
GraphHopper: Low level API.
importOrLoad
.
GraphHopper closableInstance = new GraphHopperOSM().
setOSMFile(pbfFile).
forServer().
setStoreOnFlush(true).
setGraphHopperLocation(graphFolder).
setEncodingManager(new EncodingManager(encoder)).
setCHEnabled(false);
GraphHopper hopper = closableInstance.importOrLoad();
LocationIndex
:
GraphHopperStorage graph = hopper.getGraphHopperStorage();
LocationIndex index = new LocationIndexTree(graph, new RAMDirectory());
index.prepareIndex();
: GraphHopperStorage
, FlagEncoder
, LocationIndex
.
, List<Double[]>
:
QueryResult fromQR = index.findClosest(fromLon, fromLat, EdgeFilter.ALL_EDGES);
QueryResult toQR = index.findClosest(toLon, toLat, EdgeFilter.ALL_EDGES);
QueryGraph queryGraph = new QueryGraph(graph);
//
queryGraph.lookup(fromQR, toQR);
Dijkstra dij = new Dijkstra(queryGraph, new FastestWeighting(encoder), TraversalMode.NODE_BASED);
Path path = dij.calcPath(fromQR.getClosestNode(), toQR.getClosestNode());
PointList pl = path.calcPoints();
return pl.toGeoJson();
.. ( acceptWay
) ( ) :
if (restricted.contains(way.getId()))
return 0;
- , OSM, :
if (way.hasTag("foot", intendedValues)) {
return acceptBit;
}
If you have the opportunity, for your task, use the second option, based on checking tags - it is better to prefer it. This does not hurt to mix in additional logic that does not fit into this approach.
Good luck!