In order to identify the street name(s) for a map matched track/segment I would need the reference to the OSM resource. Is this information available in the match result?
If yes, how can this information been accessed?
Many thanks in advance!
In order to identify the street name(s) for a map matched track/segment I would need the reference to the OSM resource. Is this information available in the match result?
If yes, how can this information been accessed?
Many thanks in advance!
Street names are the only properties which should be already available via edgeIteratorState.getName
Other properties you would need a ID mapping, see this example on how to do this
Thanks for the hint, I have tried to implement the mapping as in the referenced example but in the version map-matching 0.5.
The problem is OSMWayId is always 0.
I assume the reason is that method storeOsmWayID is private in version 0.5 and protected in version 0.6, right?
Do I need to change to newest version in order to implement the OSM id mapping?
Many thanks!
Werner
For 0.5 it is not possible due to this private method, yes.
And 0.6 is subject to change and not released yet (therefor the SNAPSHOT in the version), but you’d need that.
Thanks for the fast reply!
Is there a chance to get the protected method storeOsmWayID() backported to version 0.5?
I think this would be highly benefitial for the stable version!
Thanks
Werner
There are no plans to backport features yet, only if there are critical or security bugs.
Hi karussell,
I tried your graphhopper-osm-id-mapping
example and id works as expected.
But I can’t get it to work with mappping of internal node ids to osm node ids.
I’m getting some osm node with match.getEdgeState().getBaseNode()
but they are not even near the osm way with match.getEdgeState().getEdge()
Could you pleaes have a look?
public class OSMReaderOSM extends OSMReader {
public OSMReaderOSM( GraphHopperStorage ghStorage )
{
super( ghStorage );
}
@Override
boolean addNode( OSMNode node )
{
boolean result = super.addNode( node );
if( result )
{
int internalNodeId = this.getNodeMap().get( node.getId() );
if( internalNodeId >= 0 )
{
storeOsmNodeID( internalNodeId, node.getId() );
}
}
return result;
}
protected void storeOsmNodeID( int nodeId, long osmNodeId )
{
}
}
public class MyGraphHopper extends GraphHopper {
// mapping of internal edge ID to OSM way ID
private DataAccess edgeMapping;
private DataAccess nodeMapping;
private BitUtil bitUtil;
@Override
public boolean load( String graphHopperFolder )
{
boolean loaded = super.load( graphHopperFolder );
Directory dir = getGraphHopperStorage().getDirectory();
bitUtil = BitUtil.get( dir.getByteOrder() );
edgeMapping = dir.find( "edge_mapping" );
nodeMapping = dir.find( "node_mapping" );
if( loaded )
{
edgeMapping.loadExisting();
nodeMapping.loadExisting();
}
return loaded;
}
@Override
protected DataReader createReader( GraphHopperStorage ghStorage )
{
OSMReader reader = new OSMReaderOSM( ghStorage )
{
{
edgeMapping.create( 1000 );
nodeMapping.create( 1000 );
}
@Override
protected void storeOsmWayID( int internalEdgeId, long osmWayId )
{
super.storeOsmWayID( internalEdgeId, osmWayId );
long pointer = 8L * internalEdgeId;
edgeMapping.ensureCapacity( pointer + 8L );
edgeMapping.setInt( pointer + 0, bitUtil.getIntLow( osmWayId ) );
edgeMapping.setInt( pointer + 4, bitUtil.getIntHigh( osmWayId ) );
}
@Override
protected void storeOsmNodeID( int internalNodeId, long osmNodeId )
{
long pointer = 8L * internalNodeId;
nodeMapping.ensureCapacity( pointer + 8L );
nodeMapping.setInt( pointer + 0, bitUtil.getIntLow( osmNodeId ) );
nodeMapping.setInt( pointer + 4, bitUtil.getIntHigh( osmNodeId ) );
//System.out.println( internalNodeId + " -> " + osmNodeId );
}
@Override
protected void finishedReading()
{
super.finishedReading();
edgeMapping.flush();
nodeMapping.flush();
}
};
return initOSMReader( reader );
}
public long getOSMWay( int internalEdgeId )
{
long pointer = 8L * internalEdgeId;
return bitUtil.combineIntsToLong( edgeMapping.getInt( pointer ), edgeMapping.getInt( pointer + 4L ) );
}
public long getOsmNode( int internalNodeId )
{
long pointer = 8L * internalNodeId;
return bitUtil.combineIntsToLong( nodeMapping.getInt( pointer ), nodeMapping.getInt( pointer + 4L ) );
}
}
This could be virtual nodes too and you’ll need to use the queryGraph or fetch the underlying edge. See discussion: How to expand a matched trip along the graph or Retrieve closest Tower Node id of a given virtual node id or What are virtual edges and how are they used in the current Map Matching implementation?
Hi karussel,
even with
EdgeExplorer ee = graph.createEdgeExplorer();
// ...
EdgeIterator iter = ee.setBaseNode( match.getEdgeState().getBaseNode() );
while( iter.next() ) {
osmNodeId = hopper.getOsmNode( iter.getAdjNode() );
// draw
}
I’m getting not the expected result, instead valid osm node ids are returned but they are not even near the matched way.
Maybe the mapping LongIntMap osmNodeIdToInternalNodeMap;
in OSMReader
is not the real mapping for the imported data?
Make sure the node IDs are not virtual i.e. lower than graph.getNodes
Even the neighboring nodes can be virtual if e.g. two query points are on the same edge.
It seems I’m not getting virtual nodes. Take a look at this data
graph.getNodes() = 60351
match.getEdgeState().getBaseNode() = 680
By using the mapping
long osmNodeId = hopper.getOsmNode( match.getEdgeState().getBaseNode() );
long osmWayId = hopper.getOSMWay( match.getEdgeState().getEdge() );
I’m getting the desired osm way id but not the osm node id
osmNodeId = 21521975
osmWayId = 38623452
Thanks for your input so far
Ah, okay. Please try with disabling subnetwork removal and see if it works:
prepare.min_network_size=0
prepare.min_one_way_network_size=0
I.e. the internal node change directly after the import (inPlaceNodeRemove) and you would need to change the mapping too: https://github.com/graphhopper/graphhopper/blob/master/core/src/main/java/com/graphhopper/storage/BaseGraph.java#L626
Unfortunately it does not work with the new parameters.
I tried the following:
properties
filehopper.setMinNetworkSize( 0, 0 );
hopper.importOrLoad();
BaseGraph#inPlaceNodeRemove
seems to be the problem, but following the changes to the ids looks like a lot of work for which I don’t have time right now unfortunatley.
It’s a pity that graphhopper(-map-matching) does not support this use-case natively.
I will have to use the workaround by querying the osm node id with osm way id and gpx pair.
Remove the full folder and re-import again. IF you use the config (hopper.init(cmdLineArgs)) you do not need to set this in the Java API.
Yes, we plan to do so but as you mention: this is all work
Yep, I already removed the full folder (that was what I meant with “removed graphhopper data”),
I tried all options (using the init, editing the config and setting with java-api) while always removing the full folder.
Strange, as you can see here we do not call ghStorage.optimize();
if both properties are 0 or negative.
Can you confirm inPlaceNodeRemove is not called afterwards? If yes, then there is something else wrong.
Yep, I already removed the full folder (that was what I meant with “removed graphhopper data”),
I was a bit irritated as you said you edited the properties file in the graphhopper folder
It was my first attempt to just edit the property file. Then I removed the full folder and tried an re-import with your suggested settings (by init
or setMinNetworkSize
)
Anyway you are right, inPlaceNodeRemove
does not get called. Do you have a suggestion where I should look next?
I think the problem is your setOSMId hook. If the ID is a pillar node it should not be used. See here about tower vs. pillar nodes.
Let me think more about this and how to make it easy and working
Hi karussell, any news on some working storeOsmNodeID
hook?
No, too many things on the table.