/// <summary> /// Produce an output that records ways that got kept. /// </summary> public void OutputGraph(Graph <Node> graph, DirectedEdgeMetadata <Node, Way> wayMap, string filename) { var fullPath = Path.Combine(_outputLocation, filename); var converter = new GeoJsonConverter(); var ways = new Dictionary <Way, int>(); foreach (var neighbor1 in graph.Neighbors) { foreach (var neighbor2 in neighbor1.Value.Where(x => x.PrimaryCopy)) { var way = wayMap[neighbor1.Key, neighbor2.Vertex]; if (ways.ContainsKey(way)) { ways[way]++; } else { ways.Add(way, 1); } } } var polygonOut = converter.Convert(ways.Keys); var serialized = JsonConvert.SerializeObject(polygonOut); File.WriteAllLines(fullPath, new[] { serialized }); }
/// <summary> /// Produce an output that records ways that got kept. /// </summary> public void OutputGraph(LinkedList <WeightedAdjacencyNode <Node> > route, DirectedEdgeMetadata <Node, Way> wayMap, string filename) { var fullPath = Path.Combine(_outputLocation, filename); var converter = new GeoJsonConverter(); // var prevIt = route.First; // for (var it = prevIt.Next; it != null;) // { // if (prevIt.Value.Vertex != it.Value.Vertex) // { // if (wayMap.ContainsKey(prevIt.Value.Vertex, it.Value.Vertex)) // { // var way = wayMap[prevIt.Value.Vertex, it.Value.Vertex]; // Console.WriteLine(way.Tags["name"]); // } // else // { // Console.WriteLine("Missing"); // } // } // // it = it.Next; // } var polygonOut = converter.Convert(route.Select(x => x.Vertex)); var serialized = JsonConvert.SerializeObject(polygonOut); File.WriteAllLines(fullPath, new[] { serialized }); }
private void AddWay(Graph <Node> graph, Way way, bool mustHit, DirectedEdgeMetadata <Node, Way> originalEdgeWays) { var nodes = way.Nodes; var totalDistance = 0.0; for (var i = 0; i < nodes.Count() - 1; i++) { totalDistance += SimpleDistance.Compute(nodes[i], nodes[i + 1]); } var id1 = nodes.First(); var id2 = nodes.Last(); var weight = _graphCoster.Cost(way, totalDistance); if (graph.AddEdge(id1, id2, totalDistance, weight, mustHit)) { originalEdgeWays.Add(id1, id2, way); } if (mustHit) { graph.MustHitVertices.Add(id1); graph.MustHitVertices.Add(id2); } }
public FindRoutesGeneral(Geometry geometry) { var localGeometry = new OnlyTraversable().Transform(geometry); var newWays = new SplitBisectedWays().Transform(geometry.Ways); var gb = new GraphBuilder(new NoopGraphFilter(), new ReasonablyEnjoyableRunningCost()); _graph = gb.BuildGraph(newWays.ToArray(), out var originalEdgeWays); _originalEdgeWays = originalEdgeWays; }
private static List <Way> CreateExtraEdges(IEnumerable <Way> ways) { // identify nodes that will enter the graph var nodes = new HashSet <Node>(); var finalWays = new List <Way>(); var edgeTracker = new DirectedEdgeMetadata <Node, bool>(Node.NodeComparer); // todo it would be good to get rid of this thing. foreach (var way in ways) { var start = way.Nodes.First(); var end = way.Nodes.Last(); if (start == end) { // this is a loop! nodes.Add(start); if (way.Nodes.Count < 2) { throw new InvalidOperationException($"Way {way.Id} has too few nodes"); } var copyNode = way.Nodes[1]; var newNode = new Node(copyNode.Id + "_copy_0", copyNode.Latitude, copyNode.Longitude); var newWay1 = new Way(way.Id + "_gb_short", new[] { start, newNode }, new Dictionary <string, string>(way.Tags)); var newWay2 = new Way(way.Id + "_gb_short", way.Nodes.Skip(1).ToArray(), new Dictionary <string, string>(way.Tags)); var newWay3 = new Way(way.Id + "_gb_fake", new[] { copyNode, newNode }, new Dictionary <string, string>(way.Tags)); finalWays.Add(newWay1); finalWays.Add(newWay2); finalWays.Add(newWay3); nodes.Add(newNode); nodes.Add(copyNode); edgeTracker.Add(newWay1.Nodes.First(), newWay1.Nodes.Last(), true); edgeTracker.Add(newWay2.Nodes.First(), newWay2.Nodes.Last(), true); edgeTracker.Add(newWay3.Nodes.First(), newWay3.Nodes.Last(), true); } else if (edgeTracker.ContainsKey(start, end)) { // two ways exist between the same two points. For instance, two 1-way lanes. // we want to ignore these for now. We could eventually either say "run both!" or // take the shorter one? // NOTE! this does drop a few sidewalks and could drop trails (none in Cougar when I checked) // so maybe consider something smarter for paths/sidewalks and keep the exclusion only for roads. //Console.WriteLine($"Graphbuilder is ignoring way {way.Id}"); } else { finalWays.Add(way); nodes.Add(start); nodes.Add(end); edgeTracker.Add(start, end, true); } } return(finalWays); }
public Graph <Node> BuildGraph(Way[] ways, out DirectedEdgeMetadata <Node, Way> originalEdgeWays) { originalEdgeWays = new DirectedEdgeMetadata <Node, Way>(Node.NodeComparer); var finalWays = CreateExtraEdges(ways); var nodes = new HashSet <Node>(finalWays.SelectMany(x => x.Nodes)); var g = new Graph <Node>(nodes, Node.NodeComparer); foreach (var way in finalWays) { AddWay(g, way, way.MustHit(), originalEdgeWays); } var reducedGraph = _filter.Filter(g); return(reducedGraph); }