How to checking if edge is in table of coordinates during graph generation

Please pardon my terminology - I’m fairly new to Graphhopper.

Background
I’m generating a new graphhopper map/nodes/edges from an OSM file using GraphHopperOSM. I’m using a custom encoder that adds a new parameter to each edge. Let’s call this new parameter the “danger” value. I have a separate table that maps various coordinates (longitude and latitude) to integer danger values. When generating the graph edge, (i think in the applyWayTags method) I want to be able to check if each edge I’m given matches any of the coordinates in my table, and, if so, assign it the danger value in my table. Otherwise, just assign a default.

My Issue
I’m not sure how to do this. My original idea was to turn my table of coordinates-danger, into a table of edges-danger. I would then be able to easily check if each edge passed into my applyWayTags method was in my table of edges-danger. I could do this by turning each coordinate into a GeoPoint. I could then turn each GeoPoint into its closest edge by creating a LocationIndex instance from hopper.getLocationIndex, and using the LoactionIndex.findClosest function. However, I can’t do this until the edges of my “hopper” have been generated, by which point all the danger values should have been assigned because the OSM file will have already been translated into the nodes and edges used by graphhopper. It’s a bit of a Catch 22.

Question
How can I solve this problem? Is there another way for me to easily to see if an edge exists within a table of coordinates?

Thank you very much.

However, I can’t do this until the edges of my “hopper” have been generated

This should be already done in applyWayTags, e.g. in Bike2WeightFlagEncoder we use the edge properties to determine the speed from elevation values.

You’ll need a spatial index (or if not too many just loop through your danger areas or danger points) so that you can lookup the edge coordinates in your table like

value = yourIndexOrDataBaseFunction(edge.fetchWayGeometry)
edge.setFlags(encoder.setDanger(value))

Another possibility if you want to use graphhopper its ability to traverse the graph and then there is no need for a spatial index, you can apply the values after the graph was created like in GraphHopper.postProcessing: loop over your points or areas and then use BreadthFirstSearch to efficiently traverse the graph.

I don’t follow. What is a spatial index?

My Understanding of Solution #1
The line:
value = yourIndexOrDataBaseFunction(edge.fetchWayGeometry)

Implies that I get a PointList associated with the edge passed to applyWayTags. This point list contains many coordinates. I then loop through the coordinates to see if any of them are contained in my table of coordinate-danger pairings.

The Problem that Remains
What if the coordinates in my table don’t perfectly match the coordinates in the PointList. Don’t I need to instead use LocationIndex.findClosest to see if the edge I am looking at is the closest match for any of the coordinates in my coordinate-danger table?

Solution #2
I don’t understand this. After the graph has been created, how can I modify the flags of specific edges? Ideally, I would like to iterate over all of the edges in the graph, and modify the “danger” flags of the edges that i find in my edge-danger table.

Thank you - this is very helpfull

Normally this magic is more efficiently done from the spatial index or data base, but yes.

What if the coordinates in my table don’t perfectly match the coordinates in the PointList

Therefor you have a good spatial index. Hhave a look into postgresql, elasticsearch etc or even just one in-memory from geotools or our LocationIndexTree.

Solution #2 I don’t understand this.

you get the graph, call graph.getAllEdges and then you can call edge.setFlag again

Great, I will look into postgresql, elasticsearch etc.

For solution 2, after I have called edge.setFlag again to update the flag, how do I then write the updated edge back into the graph? Does my question make sense?

The setFlags method already writes the state into the graph (so every query should already consider this value). If you use the in_memory setting and you want that the change will be on disc too, you have to call the rather expensive graph.flush.

The important part is that you call this post processing step before any preparation for CH or LM is done. Ie you do

postProcessing() {
 myWork();
 super.postProcesing();
}

and not

postProcessing() {
 super.postProcesing();
 myWork();
}