public Checkpoint(string name, double coordinateX, double coordinateY, Cell c, List <Checkpoint> allCheckpoints, Airstrip strip, List <Checkpoint> exitCheckpoints) { this.Name = name; this.CoordinateX = coordinateX; this.CoordinateY = coordinateY; ShortestPath = new LinkedList <AbstractCheckpoint>(); DistanceFromSource = Int32.MaxValue; ReachableNodes = new Dictionary <AbstractCheckpoint, double>(); ParentCellType = c.Type; switch (c.Type) { case CellType.BORDER: MinSpeed = 500; MaxSpeed = 800; MaxAltitude = 7500; MinAltitude = 6500; break; case CellType.UNASSIGNED: MinSpeed = 330; MaxSpeed = Int32.MaxValue; MaxAltitude = 8000; MinAltitude = 6100; break; case CellType.UPPER: MinSpeed = 310; MaxSpeed = 330; MinAltitude = 5800; MaxAltitude = 6100; break; case CellType.MIDDLE: MinSpeed = 170; MaxSpeed = 190; MinAltitude = 2800; MaxAltitude = 3100; break; case CellType.LOWER: MinSpeed = 150; MaxSpeed = 170; MinAltitude = 1200; MaxAltitude = 1500; break; case CellType.FINAL: MinSpeed = 120; MaxSpeed = 150; MinAltitude = 500; MaxAltitude = 300; break; default: break; } AddReachables(allCheckpoints, strip, exitCheckpoints); }
/// <summary> /// Calculates the shortest path between the airplane and its final destination - the airstrip. /// </summary> /// <param name="points">All the checkpoints in the airspace. No airstrips, no airplanes.</param> /// <param name="landingStrip">The landing strip the airplane is going for.</param> public void CalculateShortestPathToAirstrip(List <Checkpoint> points, Airstrip landingStrip) { this.ReachableNodes.Clear(); this.ShortestPath.Clear(); foreach (Checkpoint point in points) { if (target == null && (point.ParentCellType == CellType.UPPER || point.ParentCellType == CellType.UNASSIGNED)) { this.AddSingleDestination(point, CalculateTimeBetweenPoints(point)); } else if (target != null && target.Value.GetType() == typeof(Airstrip)) { ShortestPath.Clear(); ShortestPath.AddFirst(target); return; } else if (target != null && point.ParentCellType == ((Checkpoint)target.Value).ParentCellType) { this.AddSingleDestination(point, CalculateTimeBetweenPoints(point)); } point.ShortestPath.Clear(); point.DistanceFromSource = int.MaxValue; } landingStrip.DistanceFromSource = int.MaxValue; landingStrip.ShortestPath.Clear(); HashSet <AbstractCheckpoint> settledCheckpoints = new HashSet <AbstractCheckpoint>(); HashSet <AbstractCheckpoint> unsettledCheckpoints = new HashSet <AbstractCheckpoint> { this }; while (unsettledCheckpoints.Count != 0) { AbstractCheckpoint currentCheckpnt = this.GetLowestDistanceNode(unsettledCheckpoints); unsettledCheckpoints.Remove(currentCheckpnt); foreach (var pair in currentCheckpnt.ReachableNodes) { AbstractCheckpoint reachableCheckpoint = pair.Key; double edgeWeight = pair.Value; if (!settledCheckpoints.Contains(reachableCheckpoint)) { var shortestPath = CalculateMinDistance(reachableCheckpoint, edgeWeight, currentCheckpnt); if (shortestPath != null && reachableCheckpoint.GetType() == typeof(Airstrip)) { shortestPath.AddLast(reachableCheckpoint); this.ShortestPath = new LinkedList <AbstractCheckpoint>(); var pathNode = shortestPath.First; while (pathNode != null) { this.ShortestPath.AddLast(pathNode.Value); pathNode = pathNode.Next; } } unsettledCheckpoints.Add(reachableCheckpoint); } } settledCheckpoints.Add(currentCheckpnt); } if (this.ShortestPath.Count != 0) { movingDirectionHasChanged = true; target = ShortestPath.First; target = target.Next; } }
/// <summary> /// Adds all the checkpoints existing in the <see cref="Grid"/> to the current checkpoint's reachables. /// Also adds the current checkpoint to those others' reachables. The addition goes through only if their /// <see cref="ParentCellType"/>s allow it. Does the same with the landing strip. /// </summary> /// <param name="allCheckpoints">The list of all other checkpoints already on the <see cref="Grid"/>.</param> /// <param name="strip">The <see cref="Airstrip"/> on which the <see cref="Airplane"/> will be landing.</param> /// <param name="exitCheckpoints">The list of checkpoints, for which an <see cref="Airplane"/> can be aiming in order /// to exit the airspace.</param> public void AddReachables(List <Checkpoint> allCheckpoints, Airstrip strip, List <Checkpoint> exitCheckpoints) { switch (ParentCellType) { case CellType.BORDER: case CellType.UNASSIGNED: foreach (Checkpoint point in allCheckpoints) { if (point.ParentCellType == CellType.BORDER || point.ParentCellType == CellType.UNASSIGNED || point.ParentCellType == CellType.UPPER) { this.AddSingleDestination(point, CalculateDistanceBetweenPoints(point)); point.AddSingleDestination(this, CalculateDistanceBetweenPoints(this)); } } break; case CellType.UPPER: foreach (Checkpoint point in allCheckpoints.Concat(exitCheckpoints)) { if (point.ParentCellType == CellType.BORDER || point.ParentCellType == CellType.UNASSIGNED || point.ParentCellType == CellType.UPPER || point.ParentCellType == CellType.MIDDLE) { this.AddSingleDestination(point, CalculateDistanceBetweenPoints(point)); point.AddSingleDestination(this, CalculateDistanceBetweenPoints(this)); } } break; case CellType.MIDDLE: foreach (Checkpoint point in allCheckpoints) { if (point.ParentCellType == CellType.UPPER || point.ParentCellType == CellType.MIDDLE || point.ParentCellType == CellType.LOWER) { this.AddSingleDestination(point, CalculateDistanceBetweenPoints(point)); point.AddSingleDestination(this, CalculateDistanceBetweenPoints(this)); } } break; case CellType.LOWER: foreach (Checkpoint point in allCheckpoints) { if (point.ParentCellType == CellType.MIDDLE || point.ParentCellType == CellType.LOWER || point.ParentCellType == CellType.FINAL) { this.AddSingleDestination(point, CalculateDistanceBetweenPoints(point)); point.AddSingleDestination(this, CalculateDistanceBetweenPoints(this)); } } break; case CellType.FINAL: foreach (Checkpoint point in allCheckpoints) { if (point.ParentCellType == CellType.LOWER || point.ParentCellType == CellType.FINAL) { this.AddSingleDestination(point, CalculateDistanceBetweenPoints(point)); point.AddSingleDestination(this, CalculateDistanceBetweenPoints(this)); } } try { this.AddSingleDestination(strip, CalculateDistanceBetweenPoints(strip)); strip.AddSingleDestination(this, CalculateDistanceBetweenPoints(this)); } catch (System.NullReferenceException e) { MessageBox.Show( $"A strip needs to be added before{Environment.NewLine}adding a checkpoint in the final zone.", "No strip found.", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); } break; default: break; } }