Resolve point at custom routerdb
//edit: Answering my own question: Adding
profile.AddOrReplace("highway", "pedestrian");
fixed it. Is this the correct way? What about an edge that is possible for all profiles? Is it then "residential" instead of "pedestrian"?
Hi.
Refering to https://github.com/itinero/routing/issues/222 I've implemented my own custom routerdb with custom nodes and edges. So far it seems to work.
But trying to resolve a point that is clearly in the network still fails. I wanted to create a database for a pedestrian route. So far I have not assigned anywhere that this is limited to pedestrian but I got no limitations at all (as far as I understand). Using only a blank profile (might this be the problem?)
Error (Coordinates replaced by placeholder):
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Itinero.Exceptions.ResolveFailedException: Could not resolve point at [XX.XXXXX, YY.YYYYY]. Probably too far from closest road or outside of the loaded network.
My code so far (shorted)
RouterDb routerDb = new RouterDb();
routerDb.AddSupportedVehicle(Vehicle.Pedestrian);
var nodeIds = routerDb.VertexData.AddInt64("node_id");
var edgeIds = routerDb.EdgeData.AddInt64("edge_id");
uint counter = 0;
// Mapper for nodes (id is not incremental) to map node ids from 0 to X
Dictionary<int, uint> nodeToVertexMapping = new Dictionary<int, uint>();
// Add nodes
foreach (Node node in nodes)
{
uint id = (uint)node.Id;
// Ignore nodes without gps data
if(node.Lat == 0 || node.Lon == 0)
{
continue;
}
routerDb.Network.AddVertex(counter, (float)node.Lat, (float)node.Lon);
nodeIds[counter] = counter;
nodeToVertexMapping[node.Id] = counter;
counter++;
}
List<Edge> edges = GetAllEdges();
// Add edges
foreach (Edge edge in edges)
{
uint sourceVertexId;
uint targetVertexId;
bool sourceNodeFound = nodeToVertexMapping.TryGetValue(edge.SourceNodeID, out sourceVertexId);
bool targetNodeFound = nodeToVertexMapping.TryGetValue(edge.SinkNodeID, out targetVertexId);
// Ignore broken edges (source or sink not found)
if(!sourceNodeFound || !targetNodeFound)
{
continue;
}
var profile = new Itinero.Attributes.AttributeCollection();
// empty profile
var profileId = routerDb.EdgeProfiles.Add(profile);
var vertexSource = routerDb.Network.GetVertex(sourceVertexId); // sourceNodeId
var vertexTarget = routerDb.Network.GetVertex(targetVertexId); // targetNodeId
var distance = Coordinate.DistanceEstimateInMeter(vertexSource.Latitude, vertexSource.Longitude, vertexTarget.Latitude, vertexTarget.Longitude);
List<Coordinate> shape = new List<Coordinate>
{
vertexSource,
vertexTarget
};
var edgeId = routerDb.Network.AddEdge(sourceVertexId, targetVertexId, new Itinero.Data.Network.Edges.EdgeData()
{
Distance = distance,
Profile = (ushort)profileId
}, new ShapeEnumerable(shape));
edgeIds[edgeId] = vertexSource.GetHashCode() ^ vertexTarget.GetHashCode();
}
routerDb.Network.Sort();
Router router = new Router(routerDb);
var routingProfile = Vehicle.Pedestrian.Fastest();
//var start = router.Resolve(routingProfile, routerDb.Network.GetVertex(0).Latitude, routerDb.Network.GetVertex(0).Longitude);
//var end = router.Resolve(routingProfile, routerDb.Network.GetVertex(1).Latitude, routerDb.Network.GetVertex(1).Longitude);
var start = routerDb.Network.GetVertex(0);
var end = routerDb.Network.GetVertex(1);
// calculate a route.
var calculatedRoute = router.Calculate(routingProfile, start, end);
Could it be that the given profile is not suitable? Does it need specific characteristics?
Sorry I don't have time to review this in much detail. You basically need to add:
- Vertices and their locations.
- Edges between the vertices with a profileId
- A routing profile that uses the profile id.
This line is not correct:
routerDb.Network.Sort();
This should be:
routerDb.Sort();