Example #1
0
        private void FindExits()
        {
            ExitGroups.Clear();
            TaxiNode groupStartNode = null;

            // First, group all nodes
            foreach (TaxiNode node in RunwayNodes)
            {
                foreach (TaxiEdge edge in node.IncomingEdges)
                {
                    if (edge.IsRunway)
                    {
                        continue;
                    }

                    if (edge.ReverseEdge == null)
                    {
                        continue;
                    }

                    TaxiEdge actualEdge = edge.ReverseEdge;
                    double   exitAngle  = VortexMath.TurnAngle(actualEdge.Bearing, Bearing);

                    if (Math.Abs(exitAngle) > VortexMath.Deg135Rad)
                    {
                        continue;
                    }

                    if (groupStartNode == null)
                    {
                        groupStartNode = node;
                        ExitGroups.Add(node, new List <ExitPoint>());
                    }

                    double landingLengthUsed = VortexMath.DistanceKM(DisplacedNode, node);  // 'distance used' actually

                    if (VortexMath.DistanceKM(groupStartNode, node) < 0.200)
                    {
                        ExitGroups[groupStartNode].Add(new ExitPoint()
                        {
                            OffRunwayNode = actualEdge.EndNode, OnRunwayNode = node, LandingLengthUsed = landingLengthUsed, TurnAngle = exitAngle
                        });
                    }
                    else
                    {
                        // add to new group
                        groupStartNode = node;
                        ExitGroups.Add(node, new List <ExitPoint>());
                        ExitGroups[groupStartNode].Add(new ExitPoint()
                        {
                            OffRunwayNode = actualEdge.EndNode, OnRunwayNode = node, LandingLengthUsed = landingLengthUsed, TurnAngle = exitAngle
                        });
                    }
                }
            }

            if (ExitGroups.Count == 0)
            {
                return; // todo: add warning
            }
            // Then pick groups based upon distance
            List <ExitPoint> minimumExit = null;
            List <ExitPoint> mediumExit  = null;
            List <ExitPoint> longExit    = null;
            List <ExitPoint> maxExit     = null;

            foreach (KeyValuePair <TaxiNode, List <ExitPoint> > exitGroup in ExitGroups.OrderBy(eg => eg.Value.First().LandingLengthUsed))
            {
                if (minimumExit == null || minimumExit.First().LandingLengthUsed < VortexMath.Feet4000Km)
                {
                    minimumExit = exitGroup.Value;
                }
                else if (mediumExit == null || mediumExit.First().LandingLengthUsed < VortexMath.Feet5000Km)
                {
                    mediumExit = exitGroup.Value;
                }
                else if (longExit == null || longExit.First().LandingLengthUsed < VortexMath.Feet6500Km)
                {
                    longExit = exitGroup.Value;
                }
                else
                {
                    maxExit = exitGroup.Value;
                }
            }

            ExitGroups.Clear();
            if (minimumExit != null)
            {
                ExitGroups.Add(minimumExit.First().OnRunwayNode, minimumExit);
            }
            if (mediumExit != null)
            {
                ExitGroups.Add(mediumExit.First().OnRunwayNode, mediumExit);
            }
            if (longExit != null)
            {
                ExitGroups.Add(longExit.First().OnRunwayNode, longExit);
            }
            if (maxExit != null)
            {
                ExitGroups.Add(maxExit.First().OnRunwayNode, maxExit);
            }

            foreach (var result in ExitGroups)
            {
                Logger.Log($"{Designator} Group: {result.Key.Id}");

                ExitPoint right = result.Value.Where(ep => ep.TurnAngle > 0).OrderBy(ep => ep.TurnAngle).FirstOrDefault();
                ExitPoint left  = result.Value.Where(ep => ep.TurnAngle < 0).OrderByDescending(ep => ep.TurnAngle).FirstOrDefault();
                ExitGroups[result.Key].Clear();

                if (right != null)
                {
                    Logger.Log($" Right Exit: {right.OnRunwayNode.Id}->{right.OffRunwayNode.Id} {right.TurnAngle * VortexMath.Rad2Deg:0.0} {right.LandingLengthUsed * VortexMath.KmToFoot:0}ft");
                    ExitGroups[result.Key].Add(right);
                }

                if (left != null)
                {
                    Logger.Log($" Left  Exit: {left.OnRunwayNode.Id}->{left.OffRunwayNode.Id} {left.TurnAngle * VortexMath.Rad2Deg:0.0} {left.LandingLengthUsed * VortexMath.KmToFoot:0}ft");
                    ExitGroups[result.Key].Add(left);
                }
            }
        }
Example #2
0
        public int FindInboundRoutes(bool normalOutput, ProgressBar progress)
        {
            string outputPath = normalOutput ? Path.Combine(Settings.WorldTrafficGroundRoutes, "Arrival") : Settings.ArrivalFolderKML;

            outputPath = Path.Combine(outputPath, ICAO);
            Settings.DeleteDirectoryContents(outputPath);

            int count = 0;

            progress.Minimum = 0;
            progress.Maximum = _parkings.Count * (int)XPlaneAircraftCategory.Max;
            progress.Value   = 0;

            foreach (Parking parking in _parkings)
            {
                InboundResults ir = new InboundResults(_edges, parking);

                progress.Value += (XPlaneAircraftCategory.Max - (parking.MaxSize + 1));

                for (XPlaneAircraftCategory size = parking.MaxSize; size >= XPlaneAircraftCategory.A; size--)
                {
                    // Nearest node should become 'closest to computed pushback point'
                    FindShortestPaths(_taxiNodes, parking.NearestNode, size);

                    // Pick the runway exit points for the selected size
                    foreach (Runway r in _runways)
                    {
                        foreach (KeyValuePair <TaxiNode, List <ExitPoint> > exit in r.ExitGroups)
                        {
                            double    bestDistance  = double.MaxValue;
                            double    bestTurnAngle = double.MaxValue;
                            ExitPoint bestExit      = null;

                            foreach (ExitPoint ep in exit.Value)
                            {
                                if (ep.OffRunwayNode.NextNodeToTarget != ep.OnRunwayNode)
                                {
                                    if ((ep.OffRunwayNode.DistanceToTarget < bestDistance / 1.2) || (bestTurnAngle - Math.Abs(ep.TurnAngle) > VortexMath.Deg020Rad) ||
                                        (ep.OffRunwayNode.DistanceToTarget < bestDistance && Math.Abs(ep.TurnAngle) < bestTurnAngle))
                                    {
                                        bestExit      = ep;
                                        bestDistance  = ep.OffRunwayNode.DistanceToTarget;
                                        bestTurnAngle = Math.Abs(ep.TurnAngle);
                                    }
                                }
                            }

                            if (bestExit != null)
                            {
                                ir.AddResult(size, bestExit.OnRunwayNode, bestExit.OffRunwayNode, r, bestExit.LandingLengthUsed);
                            }
                        }
                    }
                    progress.Value++;
                    progress.Update();
                }

                count += ir.WriteRoutes(outputPath, !normalOutput);
            }

            progress.Maximum++; progress.Value++; progress.Maximum--; progress.Value = progress.Maximum; // Work around for a side effect caused by windows animating the progress bar
            progress.Update();
            return(count);
        }