/// <summary> /// AStar Constructor. /// </summary> /// <param name="G">The graph on which AStar will perform the search.</param> public AStar(Graph G) { _Graph = G; _Open = new SortableList(); _Closed = new SortableList(); ChoosenHeuristic = EuclidianHeuristic; DijkstraHeuristicBalance = 0.5; }
private static string ListNodesAndArcs(Graph GraphToDescribe) { StringBuilder SB = new StringBuilder("Description of the Graph:\n\tNodes> "); foreach (Node N in GraphToDescribe.Nodes) SB.Append( N.ToString()+"; " ); SB.Append("\n\tArcs> "); foreach (Arc A in GraphToDescribe.Arcs) SB.Append( A.ToString()+"; " ); return SB.ToString(); }
// 0 1 2 3 4 // 0 __ __ __ N6 __ // 1 N3 __ N5 __ __ // 2 __ N2 __ N4 __ // 3 __ __ N1 __ __ // 4 __ __ __ __ __ // // Begin:N1 // Goal:N6 // Links of Nodes: N3<-N2<-N1->N4->N5->N6 // Result way:N1->N4->N5->N6 public static void Main() { try { var G = new Graph(); Node N1 = G.AddNode(2,3,0); Node N2 = G.AddNode(1,2,0); Node N3 = G.AddNode(0,1,0); Node N4 = G.AddNode(3,2,0); Node N5 = G.AddNode(2, 1, 0); Node N6 = G.AddNode(3, 0, 0); G.AddArc(N1,N2,1); G.AddArc(N2,N3,1); G.AddArc(N1,N4,1); G.AddArc(N4,N5,1); G.AddArc(N5, N6, 1); Console.WriteLine( ListNodesAndArcs(G) ); Console.WriteLine("Start:"+N1.ToString()); Console.WriteLine("Goal:" + N6.ToString()); AStar AS = new AStar(G); if (AS.SearchPath(N1, N6)) { foreach (Arc A in AS.PathByArcs) Console.WriteLine(A.ToString()); } else { Console.WriteLine("No result !"); } } catch(Exception e) { Console.Write( "Error :\n\n"+e.ToString() ); } Console.ReadLine(); }
private void Route(string s1, string s2, float maxrange, int mode) { Stopwatch sw = new Stopwatch(); if (lastJumprange != maxrange) { G = new Graph(); PrepareNodes(G, out nodes, maxrange, mode); //Console.WriteLine("Prepare nodes time: {0}", sw.Elapsed); lastJumprange = maxrange; } AStar AS = new AStar(G); Node start, stop; start = nodes.FirstOrDefault(x => x.System.SearchName == s1.ToLower()); stop = nodes.FirstOrDefault(x => x.System.SearchName == s2.ToLower()); bool res; if (start == null) { AppendText("Start system: " + s1 + " unknown"); return; } if (stop == null) { AppendText("Destination system: " + s2 + " unknown"); return; } sw = new Stopwatch(); sw.Start(); res = AS.SearchPath(start, stop); sw.Stop(); AppendText("Searching route from " + s1 + " to " + s2 + Environment.NewLine); AppendText("Find route Time: " + sw.Elapsed.TotalSeconds.ToString("0.000s") + Environment.NewLine); AppendText("Total distance: " + SystemData.Distance(s1, s2).ToString("0.00") + Environment.NewLine); AppendText("Max jumprange:" + maxrange + Environment.NewLine); double totdist = 0; int jumps = 0; if (res) { foreach (Arc A in AS.PathByArcs) { double dist = SystemData.Distance(A.StartNode.System.name, A.EndNode.System.name); AppendText(A.EndNode.System.name + " \tDist: " + dist.ToString("0.00") + " ly" + Environment.NewLine); totdist += dist; jumps++; Console.WriteLine(A.ToString()); } // JArray ja = Path2JSON(AS); } else Console.WriteLine("No result !"); AppendText("Total distance: " + totdist.ToString("0.00") + Environment.NewLine); AppendText("Jumps: " + jumps + Environment.NewLine); }
private void PrepareNodes(Graph G, out List<Node> nodes, float maxrange, int mode) { List<SystemClass> systems = SystemData.SystemList; nodes = new List<Node>(); SystemClass arcsystem; float distance, maxrangex2 = maxrange * maxrange; Node N2; float weight = 1; float dx, dy, dz; Stopwatch sw = new Stopwatch(); sw.Start(); SystemClass system; Node N1; for (int ii = 0; ii < systems.Count; ii++) { system = systems[ii]; N1 = new Node(system.x, system.y, system.z, system); G.AddNodeWithNoChk(N1); nodes.Add(N1); } sw.Stop(); AppendText("Add stars: " + sw.Elapsed.TotalSeconds.ToString("0.000s") + Environment.NewLine); sw.Restart(); for (int ii = 0; ii < systems.Count; ii++) { system = systems[ii]; N1 = nodes[ii]; for (int jj = ii; jj < systems.Count; jj++) { arcsystem = systems[jj]; dx = (float)(system.x - arcsystem.x); dy = (float)(system.y - arcsystem.y); dz = (float)(system.z - arcsystem.z); distance = dx * dx + dy * dy + dz * dz; //distance = (float)((system.x - arcsystem.x) * (system.x - arcsystem.x) + (system.y - arcsystem.y) * (system.y - arcsystem.y) + (system.z - arcsystem.z) * (system.z - arcsystem.z)); if (distance > 0 && distance <= maxrangex2) { N2 = nodes[jj]; if (mode == 1) weight = (float)(1 / distance); G.AddArcWithNoChk(N1, N2, weight); G.AddArcWithNoChk(N2, N1, weight); } } } sw.Stop(); //Console.WriteLine("Create arcs: {0}", sw.Elapsed); AppendText("Create arcs: " + sw.Elapsed.TotalSeconds.ToString("0.000s") + Environment.NewLine); }
private static void ParseDataIntoGraph() { g = new Graph(); // LOAD NODES for (int y = 0; y <= squareSize_1; y++) { for (int x = 0; x <= squareSize_1; x++) { g.AddNode(nodes[x, y]); } } // LOAD ARCS for (int y = 0; y <= squareSize_1; y++) { for (int x = 0; x <= squareSize_1; x++) { // check up if (y > 0) { g.AddArc(nodes[x, y], nodes[x, y - 1], fileNodes[x, y - 1]); } // check down if (y < squareSize_1) { g.AddArc(nodes[x, y], nodes[x, y + 1], fileNodes[x, y + 1]); } // check left if (x >0) { g.AddArc(nodes[x, y], nodes[x - 1, y], fileNodes[x - 1, y]); } // check right if (x < squareSize_1) { g.AddArc(nodes[x, y], nodes[x + 1, y], fileNodes[x + 1, y]); } } } }
/// <summary> /// Build level graph /// </summary> /// <param name="l"></param> public void LoadData(LevelMapData l) { level = l; //make graph based on map try { MapGraph = new Graph(); MapNodes = new Node[level.Height * level.Width]; // put nodes in graph and array for (int i = 0; i < level.Height * level.Width; i++) { if (level.GetSquareAt(i % level.Width, i / level.Width).type == MapSquareType.Open) { MapNodes[i] = MapGraph.AddNode((i % level.Width) * 16 -8, (i / level.Width) * 16 -8, 0); } } for (int i = 0; i < level.Height * level.Width; i++) { //updown if (i / level.Width > 0) { if (MapNodes[i - level.Width] != null && MapNodes[i] != null) MapGraph.Add2Arcs(MapNodes[i], MapNodes[i - level.Width], 1); } //leftright if (i % level.Width > 0) { if (MapNodes[i - 1] != null && MapNodes[i] != null) MapGraph.Add2Arcs(MapNodes[i], MapNodes[i - 1], 1); } //top left diag if (i % level.Width > 0 && i / level.Width > 0) { if (MapNodes[i - level.Width - 1] != null && MapNodes[i] != null && MapNodes[i - level.Width] != null && MapNodes[i - 1] != null) MapGraph.Add2Arcs(MapNodes[i], MapNodes[i - level.Width - 1], 1); } //top right diag if (i % level.Width < level.Width - 1 && i / level.Width > 0) { if (MapNodes[i - level.Width + 1] != null && MapNodes[i] != null && MapNodes[i + 1] != null && MapNodes[i - level.Width] != null) MapGraph.Add2Arcs(MapNodes[i], MapNodes[i - level.Width + 1], 1); } } } catch (Exception e) { throw e; } }
private void Route(string s1, string s2, float maxrange, int mode) { EDDiscovery2.DB.ISystem ds1 = SystemData.GetSystem(s1); EDDiscovery2.DB.ISystem ds2 = SystemData.GetSystem(s2); if (ds1 == null) // warn here, quicker to complain than waiting for nodes to populate. { AppendText("Start system: " + s1 + " unknown"); return; } if (ds2 == null) { AppendText("Destination system: " + s2 + " unknown"); return; } double earea = 10.0; // add a little to the box for first/end points allowing out of box systems Point3D minpos = new EMK.LightGeometry.Point3D( Math.Min(ds1.x, ds2.x) - earea, Math.Min(ds1.y, ds2.y) - earea, Math.Min(ds1.z, ds2.z) - earea ); Point3D maxpos = new EMK.LightGeometry.Point3D( Math.Max(ds1.x, ds2.x) + earea, Math.Max(ds1.y, ds2.y)+ earea, Math.Max(ds1.z, ds2.z) + earea ); AppendText("Bounding Box " + minpos.X + "," + minpos.Y + "," + minpos.Z + " to " + maxpos.X + "," + maxpos.Y + "," + maxpos.Z + Environment.NewLine); Stopwatch sw = new Stopwatch(); G = new Graph(); // need to compute each time as systems in range changes each time PrepareNodes(G, maxrange, mode,minpos,maxpos); AStar AS = new AStar(G); Node start, stop; start = G.GetNodes.FirstOrDefault(x => x.System.SearchName == s1.ToLower()); stop = G.GetNodes.FirstOrDefault(x => x.System.SearchName == s2.ToLower()); bool res; sw = new Stopwatch(); sw.Start(); res = AS.SearchPath(start, stop); sw.Stop(); AppendText("Searching route from " + ds1.name + " to " + ds2.name + Environment.NewLine); AppendText("Find route Time: " + sw.Elapsed.TotalSeconds.ToString("0.000s") + Environment.NewLine); AppendText("Total distance: " + SystemData.Distance(s1, s2).ToString("0.00") + Environment.NewLine); AppendText("Max jumprange:" + maxrange + Environment.NewLine); if (res) { AppendText(Environment.NewLine + "Depart " + ds1.name + Environment.NewLine); double totdist = 0; int jumps = 0; foreach (Arc A in AS.PathByArcs) { double dist = SystemData.Distance(A.StartNode.System.name, A.EndNode.System.name); AppendText(string.Format("{0,-30}Dist: {1:0.00} ly" + Environment.NewLine, A.EndNode.System.name, dist)); totdist += dist; jumps++; Console.WriteLine(A.ToString()); } AppendText(Environment.NewLine + "Total distance: " + totdist.ToString("0.00") + Environment.NewLine); AppendText("Jumps: " + jumps + Environment.NewLine); // JArray ja = Path2JSON(AS); } else AppendText(Environment.NewLine + "NO Solution found - jump distance is too small or not enough star data between systems" + Environment.NewLine); }
private void PrepareNodes(Graph G, float maxrange, int mode, Point3D minpos , Point3D maxpos) { List<SystemClass> systems = SystemData.SystemList; float distance, maxrangex2 = maxrange * maxrange; Node N1,N2; float weight = 1; float dx, dy, dz; Stopwatch sw = new Stopwatch(); sw.Start(); SystemClass system; for (int ii = 0; ii < systems.Count; ii++) { system = systems[ii]; // screening out stars reduces number and makes the arc calculator much quicker. if (system.x >= minpos.X && system.x <= maxpos.X && system.y >= minpos.Y && system.y <= maxpos.Y && system.z >= minpos.Z && system.z <= maxpos.Z ) { N1 = new Node(system.x, system.y, system.z, system); G.AddNodeWithNoChk(N1); } } sw.Stop(); AppendText("Add stars: " + sw.Elapsed.TotalSeconds.ToString("0.000s") + Environment.NewLine); AppendText("No stars within bounds " + G.Count + Environment.NewLine); sw.Restart(); for (int ii = 0; ii < G.Count; ii++) { N1 = G.GetN(ii); for (int jj = ii; jj < G.Count; jj++) { N2 = G.GetN(jj); dx = (float)(N1.X - N2.X); dy = (float)(N1.Y - N2.Y); dz = (float)(N1.Z - N2.Z); distance = dx * dx + dy * dy + dz * dz; if (distance > 0 && distance <= maxrangex2) { if (mode == 1) weight = (float)(1 / distance); G.AddArcWithNoChk(N1, N2, weight); G.AddArcWithNoChk(N2, N1, weight); } } } sw.Stop(); //Console.WriteLine("Create arcs: {0}", sw.Elapsed); AppendText("Create arcs: " + sw.Elapsed.TotalSeconds.ToString("0.000s") + Environment.NewLine); }