/// <summary> /// Calculates the shortest path between the airplane and the point through which it has to leave the airspace. /// </summary> /// <param name="points">All the checkpoints in the airspace. No airstrips, no airplanes.</param> /// <param name="exitCheckpoint">The checkpoint through which the plane has to leave the airspace.</param> public void CalculateShortestPathLeavingAirspace(List <Checkpoint> points) { this.ReachableNodes.Clear(); this.ShortestPath.Clear(); foreach (Checkpoint point in points) { if (target == null && point.ParentCellType == CellType.FINAL) { this.AddSingleDestination(point, CalculateTimeBetweenPoints(point)); } else if (target != null && target.Equals(ShortestPath.Last) ) //if this doesn't work: ((Checkpoint)target.Value).ParentCellType == Cell.BORDER { 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; } exitDestination.DistanceFromSource = int.MaxValue; exitDestination.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(Checkpoint) && ((Checkpoint)reachableCheckpoint).ParentCellType == CellType.BORDER) { 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> /// Uses Pythagoras' theorem to calculate the distance between two checkpoints. /// </summary> /// <param name="a">The checkpoint we are looking for the distance from.</param> /// <returns>The distance between the two checkpoints given as arguments.</returns> public virtual double CalculateDistanceBetweenPoints(AbstractCheckpoint a) { return(Math.Sqrt(Math.Pow(Math.Abs(this.CoordinateX - a.CoordinateX), 2) + Math.Pow(Math.Abs(this.CoordinateY - a.CoordinateY), 2))); }
/// <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> /// Using just the distance as a factor for the shortest distance calculation seems silly. /// This is why this method calculates the time it will take an <see cref="Airplane"/> /// to get from the current point to a. /// </summary> /// <param name="a">The point, to which the time needed to get to it needs to be calculated. </param> /// <returns></returns> public virtual double CalculateTimeBetweenPoints(AbstractCheckpoint a) { return(CalculateDistanceBetweenPoints(a) / this.MaxSpeed); }