itinero / routing

The routing core of itinero.
Apache License 2.0
221 stars 69 forks source link

Resolve point at custom routerdb #223

Open Sonnenspeer opened 6 years ago

Sonnenspeer commented 6 years ago

//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?

xivk commented 6 years ago

Sorry I don't have time to review this in much detail. You basically need to add:

This line is not correct:

routerDb.Network.Sort();

This should be:

routerDb.Sort();