using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using GMap.NET; using AStar; namespace ArdupilotMega.Utilities { class PathFind { public static List FindPath(PointLatLng start, List list) { Graph graph = new Graph(); Node home = new Node("Home", null, start.Lat, start.Lng); Node destination = new Node("End", null, start.Lat, start.Lng); graph.AddNode(home); graph.AddNode(destination); int a = 0; foreach (GCSViews.FlightPlanner.linelatlng line in list) { Node n1 = new Node(a.ToString(), null, line.p1.Lat, line.p1.Lng); a++; Node n2 = new Node(a.ToString(), null, line.p2.Lat, line.p2.Lng); a++; graph.AddNode(n1); graph.AddNode(n2); // add the home to point initial refrence - 1 way graph.AddDirectedEdge(home, n1, (int)GetDistance(start,line.p1)); graph.AddDirectedEdge(home, n2, (int)GetDistance(start, line.p2)); // add points to destination graph.AddDirectedEdge(n1, destination, (int)GetDistance(start, line.p1)); graph.AddDirectedEdge(n2, destination, (int)GetDistance(start, line.p2)); // 0 cost as it is a line graph.AddUndirectedEdge(n1, n2, 0); foreach (GCSViews.FlightPlanner.linelatlng line2 in list) { Node n11 = new Node(a.ToString(), null, line2.p1.Lat, line2.p1.Lng); a++; Node n21 = new Node(a.ToString(), null, line2.p2.Lat, line2.p2.Lng); a++; if (line.p1 == line2.p1 && line.p2 == line2.p2) continue; graph.AddNode(n11); graph.AddNode(n21); graph.AddUndirectedEdge(n1, n11, GetDistance(line.p1, line2.p1)); graph.AddUndirectedEdge(n2, n11, GetDistance(line.p2, line2.p1)); graph.AddUndirectedEdge(n1, n21, GetDistance(line.p1, line2.p2)); graph.AddUndirectedEdge(n2, n21, GetDistance(line.p2, line2.p2)); // 0 cost graph.AddUndirectedEdge(n11, n21, 0); } } // Function which tells us the exact distance between two neighbours. Func distance = new Func(PathFind.distance); // Estimation/Heuristic function (Haversine distance) // It tells us the estimated distance between the last node on a proposed path and the destination node. Func haversineEstimation = n => Haversine.Distance(n, destination, DistanceType.km); // foreach (GCSViews.FlightPlanner.linelatlng line in list) // { Path shortestPath = AStar.AStar.FindPath(home, destination, distance, haversineEstimation); // } List shortest = new List(); foreach (Path path in shortestPath) { if (path.PreviousSteps != null) { shortest.Add(new PointLatLng(path.PreviousSteps.LastStep.Latitude, path.PreviousSteps.LastStep.Longitude)); } } return shortest; } public static double distance(Node node1, Node node2) { return node1.Neighbors.Cast().Single( etn => etn.Neighbor.Key == node2.Key).Cost; } static PointLatLng findClosestPoint(PointLatLng start, GCSViews.FlightPlanner.linelatlng line) { List list = new List(); list.Add(line.p1); list.Add(line.p2); PointLatLng closest = findClosestPoint(start, list); return closest; } static PointLatLng findClosestPoint(PointLatLng start, List list) { PointLatLng answer = PointLatLng.Zero; double currentbest = double.MaxValue; foreach (PointLatLng pnt in list) { double dist1 = GetDistance(start, pnt); if (dist1 < currentbest) { answer = pnt; currentbest = dist1; } } return answer; } static GCSViews.FlightPlanner.linelatlng findClosestLine(PointLatLng start, List list) { GCSViews.FlightPlanner.linelatlng answer = list[0]; double shortest = double.MaxValue; foreach (GCSViews.FlightPlanner.linelatlng line in list) { double ans1 = GetDistance(start, line.p1); double ans2 = GetDistance(start, line.p2); PointLatLng shorterpnt = ans1 < ans2 ? line.p1 : line.p2; if (shortest > GetDistance(start, shorterpnt)) { answer = line; shortest = GetDistance(start, shorterpnt); } } return answer; } /// /// Calc Distance in M /// /// /// Distance in M public static double GetDistance(PointLatLng p1, PointLatLng p2) { double d = p1.Lat * 0.017453292519943295; double num2 = p1.Lng * 0.017453292519943295; double num3 = p2.Lat * 0.017453292519943295; double num4 = p2.Lng * 0.017453292519943295; double num5 = num4 - num2; double num6 = num3 - d; double num7 = Math.Pow(Math.Sin(num6 / 2.0), 2.0) + ((Math.Cos(d) * Math.Cos(num3)) * Math.Pow(Math.Sin(num5 / 2.0), 2.0)); double num8 = 2.0 * Math.Atan2(Math.Sqrt(num7), Math.Sqrt(1.0 - num7)); return (6371 * num8); // M } } }