示例#1
0
        private void buttonAddMarker_Click(object sender, RoutedEventArgs e)
        {
            AXWaypoint waypoint = null;

            if (listBoxMarkers.SelectedItem != null)
            {
                waypoint = (AXWaypoint)listBoxMarkers.SelectedItem;
            }
            else if (TrackPointer != null)
            {
                waypoint = new AXWaypoint("00", TrackPointer);
            }
            else
            {
                return;
            }

            var dlg = new InputWindow(s => AXWaypoint.Parse(s) != null)
            {
                Title = "Enter marker",
                Text  = waypoint.ToString(AXPointInfo.Name | AXPointInfo.Date | AXPointInfo.Time | AXPointInfo.Coords | AXPointInfo.Altitude)
            };

            dlg.ShowDialog();
            if (dlg.Response == System.Windows.Forms.DialogResult.OK)
            {
                Report.AddMarker(AXWaypoint.Parse(dlg.Text));
                Engine.Display();
            }
        }
示例#2
0
        public override void Reset()
        {
            base.Reset();

            if (!isStatic)
            {
                Point = null;
                Notes.Clear();
            }
        }
示例#3
0
        public bool RemoveMarker(AXWaypoint marker)
        {
            var ok = Markers.Remove(marker);

            if (ok)
            {
                Notes.Add(string.Format("Marker {0} removed by {1}", marker, Debriefer));
                IsDirty = true;
            }
            return(ok);
        }
示例#4
0
        public static PdfWaypoint ToPdfWaypoint(this GeoWaypoint gwp, string datumName, string utmZone, AltitudeUnits units)
        {
            var utmCoords = gwp.Coordinates.ToUtm(Datum.GetInstance(datumName), utmZone);
            var altitude = utmCoords.Altitude;
            var wp = new AXWaypoint(gwp.Name, gwp.Time, utmCoords.Easting, utmCoords.Northing, altitude);

            return new PdfWaypoint()
            {
                Name = wp.Name,
                CompetitionCoords = wp.ToString(AXPointInfo.CompetitionCoords8).Replace("/", " / "),
                Altitude = wp.ToString(units == AltitudeUnits.Meters ? AXPointInfo.AltitudeInMeters : AXPointInfo.AltitudeInFeet)
            };
        }
示例#5
0
        private AXWaypoint TryResolveGoalDeclaration(GoalDeclaration goal, bool useDeclaredAltitude)
        {
            AXWaypoint tmpPoint = null;

            if (goal.Type == GoalDeclaration.DeclarationType.GoalName)
            {
                try
                {
                    tmpPoint = ((ScriptingPoint)Engine.Heap[goal.Name]).Point;
                }
                catch { }
            }
            else // competition coordinates
            {
                tmpPoint = Engine.Settings.ResolveDeclaredGoal(goal);
            }

            if (tmpPoint == null)
            {
                throw new InvalidOperationException("could not resolve goal declaration");
            }

            var altitude = 0.0;

            if (useDeclaredAltitude && !double.IsNaN(goal.Altitude))
            {
                altitude = goal.Altitude;
                AddNote(string.Format("using pilot declared altitude: {0}m", altitude));
            }
            else if (!double.IsNaN(defaultAltitude))
            {
                altitude = defaultAltitude;
                AddNote(string.Format("using default altitude: {0}m", altitude));
            }
            else
            {
                altitude = QueryEarthtoolsElevation(tmpPoint);
                AddNote(string.Format("using web service ground elevation: {0}m", altitude));
            }

            return(new AXWaypoint(string.Format("D{0:00}", goal.Number), goal.Time, tmpPoint.Easting, tmpPoint.Northing, altitude));
        }
示例#6
0
 public void AddMarker(AXWaypoint marker)
 {
     InsertIntoCollection(Markers, marker);
     Notes.Add(string.Format("New marker {0} added by {1}", marker, Debriefer));
     IsDirty = true;
 }
示例#7
0
        public override void CheckConstructorSyntax()
        {
            base.CheckConstructorSyntax();

            //check syntax and resolve static values (well defined at constructor time, not pilot dependent)
            switch (Definition.ObjectType)
            {
            default:
                throw new ArgumentException("Unknown point type '" + Definition.ObjectType + "'");

            case "SLL":     //WGS84 lat/lon
                //SLL(<lat>, <long>, <alt>)
            {
                isStatic = true;

                AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length == 3);
                var lat = ParseOrDie <double>(0, Parsers.ParseDouble);
                var lng = ParseOrDie <double>(1, Parsers.ParseDouble);
                var alt = ParseOrDie <double>(2, Parsers.ParseLength);
                Point = new AXWaypoint(Definition.ObjectName, Engine.Settings.FromLatLonToAXPoint(lat, lng, alt));
            }
            break;

            case "SUTM":     //UTM
                //SUTM(<easting>, <northing>, <alt>). The datum and zone are defined in settings
            {
                isStatic = true;

                AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length == 3);
                var easting  = ParseOrDie <double>(0, Parsers.ParseDouble);
                var northing = ParseOrDie <double>(1, Parsers.ParseDouble);
                var alt      = ParseOrDie <double>(2, Parsers.ParseLength);
                Point = new AXWaypoint(Definition.ObjectName, Engine.Settings.Date.Date, easting, northing, alt);
            }
            break;

            case "LNP":     //nearest to point from list
                //LNP(<desiredPoint>, <listPoint1>, <listPoint2>, ..., <altitudeThreshold>)
                AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length >= 3);
                ResolveNOrDie <ScriptingPoint>(0, Definition.ObjectParameters.Length - 1);
                altitudeThreshold = ParseOrDie <double>(Definition.ObjectParameters.Length - 1, Parsers.ParseLength);
                break;

            case "LFT":     //first in time from list
            case "LLT":     //last in time from list
            case "LFNN":    //LFNN: first not null from list
            case "LLNN":    //last not null
                //XXXX(<listPoint1>, <listPoint2>, …)
                AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length >= 1);
                ResolveNOrDie <ScriptingPoint>(0, Definition.ObjectParameters.Length);
                break;

            case "MVMD":
                //MVMD: virtual marker drop
                //MVMD(<number>)
                AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length == 1);
                number = ParseOrDie <int>(0, int.Parse);
                break;

            case "MPDGD":
            case "MPDGF":
                //MPDGD: pilot declared goal with default altitude
                //MPDGF: pilot declared goal with forced altitude
                //XXXX(<number>[, <defaultAltitude>])
                AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length == 1 || Definition.ObjectParameters.Length == 2);
                number = ParseOrDie <int>(0, int.Parse);
                if (Definition.ObjectParameters.Length == 2)
                {
                    defaultAltitude = ParseOrDie <double>(1, Parsers.ParseLength);
                }
                break;

            case "TLCH":     //TLCH: take off
            case "TLND":     //TLND: landing
                //XXXX()
                //TODO: check if they are really needed or should be automatic
                AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length == 1 && Definition.ObjectParameters[0] == "");
                break;

            case "TNL":     //nearest to point list
                //LNP(<listPoint1>, <listPoint2>, ..., <altitudeThreshold>)
                AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length >= 2);
                ResolveNOrDie <ScriptingPoint>(0, Definition.ObjectParameters.Length - 1);
                altitudeThreshold = ParseOrDie <double>(Definition.ObjectParameters.Length - 1, Parsers.ParseLength);
                break;

            case "TPT":     //TPT at point time
                //TPT(<pointName>)
                AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length == 1);
                ResolveOrDie <ScriptingPoint>(0);
                break;

            case "TNP":     //nearest to point
            case "TFP":     //farthest from point
                //XXX(<pointName>, <altitudeThreshold>)
                AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length == 2);
                ResolveOrDie <ScriptingPoint>(0);
                altitudeThreshold = ParseOrDie <double>(1, Parsers.ParseLength);
                break;

            case "TDT":     //delayed in time
                //TDT(<pointName>, <timeDelay>[, <maxTime>])
                AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length == 2 || Definition.ObjectParameters.Length == 3);
                ResolveOrDie <ScriptingPoint>(0);
                timeDelay = ParseOrDie <TimeSpan>(1, Parsers.ParseTimeSpan);
                if (Definition.ObjectParameters.Length == 3)
                {
                    maxTime = Engine.Settings.Date.Date + ParseOrDie <TimeSpan>(2, Parsers.ParseTimeSpan);
                }
                break;

            case "TDD":      //delayed in distance
                //TDD(<pointName>, <distanceDelay>[, <maxTime>])
                AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length == 2 || Definition.ObjectParameters.Length == 3);
                ResolveOrDie <ScriptingPoint>(0);
                distanceDelay = ParseOrDie <double>(1, Parsers.ParseLength);
                if (Definition.ObjectParameters.Length == 3)
                {
                    maxTime = Engine.Settings.Date.Date + ParseOrDie <TimeSpan>(2, Parsers.ParseTimeSpan);
                }
                break;

            case "TAFI":     //area first in
            case "TAFO":     //area first out
            case "TALI":     //area last in
            case "TALO":     //area last out
                //XXXX(<areaName>)
                AssertNumberOfParametersOrDie(Definition.ObjectParameters.Length == 1);
                ResolveOrDie <ScriptingArea>(0);
                break;
            }
        }
示例#8
0
        public override void Process()
        {
            base.Process();

            // parse and resolve pilot dependent values
            // the static values are already defined
            // syntax is already checked
            switch (Definition.ObjectType)
            {
            case "LNP":
                //nearest to point from list
                //LNP(<desiredPoint>, <listPoint1>, <listPoint2>, ..., <altitudeThreshold>)
                //TODO: what kind of distance should be used? d2d, d3d or drad?
            {
                var list = ResolveN <ScriptingPoint>(0, Definition.ObjectParameters.Length - 1);

                var referencePoint = list[0].Point;
                if (referencePoint == null)
                {
                    Point = null;
                    AddNote(list[0].GetFirstNoteText(), true);         //inherit notes from ref point
                }
                else
                {
                    for (var i = 1; i < list.Length; i++)
                    {
                        var nextPoint = list[i].Point;
                        if (nextPoint == null)
                        {
                            continue;
                        }
                        else if (Point == null ||
                                 Physics.DistanceRad(referencePoint, nextPoint, altitudeThreshold) < Physics.DistanceRad(referencePoint, Point, altitudeThreshold))
                        {
                            Point = nextPoint;
                        }
                    }
                    if (Point == null)
                    {
                        //all points are null
                        AddNote(list[1].GetFirstNoteText(), true);         //inherit notes from first point
                    }
                }
            }
            break;

            case "LFT":
                //first in time from list
                //LFT(<listPoint1>, <listPoint2>, …)
            {
                var list = ResolveN <ScriptingPoint>(0, Definition.ObjectParameters.Length);

                foreach (var p in list)
                {
                    var nextPoint = p.Point;
                    if (nextPoint == null)
                    {
                        continue;
                    }
                    else if (Point == null ||
                             nextPoint.Time < Point.Time)
                    {
                        Point = nextPoint;
                    }
                }
                if (Point == null)
                {
                    //all points are null
                    AddNote(list[0].GetFirstNoteText(), true);         //inherit notes from first point
                }
            }
            break;

            case "LLT":
                //last in time from list
                //LLT(<listPoint1>, <listPoint2>)
            {
                var list = ResolveN <ScriptingPoint>(0, Definition.ObjectParameters.Length);

                foreach (var p in list)
                {
                    var nextPoint = p.Point;
                    if (nextPoint == null)
                    {
                        continue;
                    }
                    else if (Point == null ||
                             nextPoint.Time > Point.Time)
                    {
                        Point = nextPoint;
                    }
                }
                if (Point == null)
                {
                    //all points are null
                    AddNote(list[0].GetFirstNoteText(), true);;          //inherit notes from first point
                }
            }
            break;

            case "LFNN":
                //first not null from list
                //LFNN(<listPoint1>, <listPoint2>, …)
            {
                var list = ResolveN <ScriptingPoint>(0, Definition.ObjectParameters.Length);

                foreach (var p in list)
                {
                    var nextPoint = p.Point;
                    if (nextPoint != null)
                    {
                        Point = nextPoint;
                        break;
                    }
                }
                if (Point == null)
                {
                    //all points are null
                    AddNote(list[0].GetFirstNoteText(), true);         //inherit notes from first point
                }
            }
            break;

            case "LLNN":
                //last not null from list
                //LLNN(<listPoint1>, <listPoint2>, …)
            {
                var list = ResolveN <ScriptingPoint>(0, Definition.ObjectParameters.Length);

                foreach (var p in list.Reverse())
                {
                    var nextPoint = p.Point;
                    if (nextPoint != null)
                    {
                        Point = nextPoint;
                        break;
                    }
                }
                if (Point == null)
                {
                    //all points are null
                    AddNote(list[0].GetFirstNoteText(), true);         //inherit notes from first point
                }
            }
            break;

            case "MVMD":
                //MVMD: virtual marker drop
                //MVMD(<number>)

                /*
                 * algorithm:
                 * if exists marker with the same number
                 *      if the marker is valid
                 *          point = marker
                 *      else
                 *          point = null
                 * else
                 *      if the contest landing is valid
                 *          point = landing
                 *      else
                 *          point = null
                 */
            {
                var marks = from mark in Engine.Report.Markers
                            where int.Parse(mark.Name) == number
                            select "M" + mark.ToString(AXPointInfo.CustomReport);
                Task.LoggerMarks.AddRange(marks);

                var marker = Engine.Report.Markers.FirstOrDefault(m => int.Parse(m.Name) == number);

                if (marker != null)
                {
                    var nearestPoint = Engine.TaskValidTrack.Points.FirstOrDefault(p => Math.Abs((p.Time - marker.Time).TotalSeconds) == 0);
                    if (nearestPoint != null)
                    {
                        Point = new AXWaypoint("M" + marker.Name, marker);
                    }
                    else
                    {
                        AddNote(string.Format("R12.21.1: invalid marker drop #{0}", number), true);
                    }
                }
                else
                {
                    if (Engine.Settings.ContestLanding && Engine.Report.Markers.FirstOrDefault(m => int.Parse(m.Name) > number) != null)
                    {
                        var validLanding = Engine.TaskValidTrack.Points.FirstOrDefault(p => Math.Abs((p.Time - Engine.Report.LandingPoint.Time).TotalSeconds) == 0);
                        if (validLanding != null)
                        {
                            Point = new AXWaypoint("Landing", Engine.Report.LandingPoint);
                            AddNote(string.Format("no marker #{0}: assuming contest landing", number), true);
                        }
                    }
                    else
                    {
                        AddNote(string.Format("RII.17.d: no marker drop #{0}", number), true);
                    }
                }
            }
            break;

            case "MPDGD":
                //pilot declared goal with default altitude
                //MPDGD(<number>, <defaultAltitude>)
            {
                var marks = from mark in Engine.Report.DeclaredGoals
                            where mark.Number == number
                            select "D" + mark.ToString(AXPointInfo.CustomReport);
                Task.LoggerMarks.AddRange(marks);

                // look for declarations
                var goals = Engine.Report.DeclaredGoals.Where(g => g.Number == number);
                if (goals.Count() == 0)
                {
                    AddNote("no goal declaration #" + number.ToString(), true);
                }
                else
                {
                    //look for last declaration
                    var goal = goals.Last();
                    try
                    {
                        Point = TryResolveGoalDeclaration(goal, true);
                    }
                    catch (InvalidOperationException)
                    {
                        AddNote("R12.3: invalid goal declaration #" + number.ToString(), true);
                    }
                }
            }
            break;

            case "MPDGF":
                //pilot declared goal with forced altitude
                //MPDGF(<number>, <defaultAltitude>)
            {
                var marks = from mark in Engine.Report.DeclaredGoals
                            where mark.Number == number
                            select "D" + mark.ToString(AXPointInfo.CustomReport);
                Task.LoggerMarks.AddRange(marks);

                // look for declarations
                var goals = Engine.Report.DeclaredGoals.Where(g => g.Number == number);
                if (goals.Count() == 0)
                {
                    AddNote("no goal declaration #" + number.ToString(), true);
                }
                else
                {
                    //look for last declaration
                    var goal = goals.Last();
                    try
                    {
                        Point = TryResolveGoalDeclaration(goal, false);
                    }
                    catch (InvalidOperationException)
                    {
                        AddNote("R12.3: invalid goal declaration #" + number.ToString(), true);
                    }
                }
            }
            break;

            case "TLCH":
                //TLCH: take off
                //TLCH()
                if (Engine.Report != null)
                {
                    Point = new AXWaypoint(Definition.ObjectName, Engine.Report.TakeOffPoint);
                }
                break;

            case "TLND":
                //TLND: landing
                //TLND()
                if (Engine.Report != null)
                {
                    Point = new AXWaypoint(Definition.ObjectName, Engine.Report.LandingPoint);
                }
                break;

            case "TPT":
                //TPT at point time
                //TPT(<pointName>)
                try
                {
                    var referenceScriptingPoint = Resolve <ScriptingPoint>(0);
                    var referencePoint          = referenceScriptingPoint.Point;
                    if (referencePoint == null)
                    {
                        Point = null;
                        AddNote(referenceScriptingPoint.GetFirstNoteText(), true);     // inherit ref point notes
                    }
                    else
                    {
                        Point = new AXWaypoint(Definition.ObjectName, Engine.Report.CleanTrack.First(p => p.Time == referencePoint.Time));
                    }
                }
                catch (InvalidOperationException)
                {
                    AddNote("no valid track point at specified time", true);
                }     //none found
                break;

            case "TNP":
                //nearest to point
                //TNP(<pointName>, <altitudeThreshold>)
                //TODO: what kind of distance should be used? d2d, d3d or drad?
            {
                var referenceScriptingPoint = Resolve <ScriptingPoint>(0);
                var referencePoint          = referenceScriptingPoint.Point;
                if (referencePoint == null)
                {
                    Point = null;
                    AddNote(referenceScriptingPoint.GetFirstNoteText(), true);         // inherit ref point notes
                }
                else
                {
                    foreach (var nextTrackPoint in Engine.TaskValidTrack.Points)
                    {
                        if (Point == null ||
                            Physics.DistanceRad(referencePoint, nextTrackPoint, altitudeThreshold) < Physics.DistanceRad(referencePoint, Point, altitudeThreshold))
                        {
                            Point = new AXWaypoint(Definition.ObjectName, nextTrackPoint);
                        }
                    }
                    if (Point == null)
                    {
                        AddNote("no remaining valid track points", true);
                    }
                }
            }
            break;

            case "TFP":
                //farthest from point
                //TFP(<pointName>, <altitudeThreshold>)
            {
                var referenceScriptingPoint = Resolve <ScriptingPoint>(0);
                var referencePoint          = referenceScriptingPoint.Point;
                if (referencePoint == null)
                {
                    Point = null;
                    AddNote(referenceScriptingPoint.GetFirstNoteText(), true);         // inherit ref point notes
                }
                else
                {
                    foreach (var nextTrackPoint in Engine.TaskValidTrack.Points)
                    {
                        if (Point == null ||
                            Physics.DistanceRad(referencePoint, nextTrackPoint, altitudeThreshold) > Physics.DistanceRad(referencePoint, Point, altitudeThreshold))
                        {
                            Point = new AXWaypoint(Definition.ObjectName, nextTrackPoint);
                        }
                    }
                    if (Point == null)
                    {
                        AddNote("no remaining valid track points", true);
                    }
                }
            }
            break;

            case "TNL":
                //nearest to point list
                //TNL(<listPoint1>, <listPoint2>, ..., <altitudeThreshold>)
            {
                var list = ResolveN <ScriptingPoint>(0, Definition.ObjectParameters.Length - 1);

                var bestDistance = double.PositiveInfinity;
                var nnull        = 0;
                foreach (var p in list)
                {
                    var listPoint = p.Point;
                    if (listPoint == null)
                    {
                        nnull++;
                        continue;
                    }
                    foreach (var trackPoint in Engine.TaskValidTrack.Points)
                    {
                        var dist = Physics.DistanceRad(listPoint, trackPoint, altitudeThreshold);
                        if (Point == null || dist < bestDistance)
                        {
                            Point        = new AXWaypoint(Definition.ObjectName, trackPoint);
                            bestDistance = dist;
                        }
                    }
                }

                if (nnull == list.Length)
                {
                    //all points are null
                    AddNote(list[0].GetFirstNoteText(), true);         //inherit notes from first point
                }
                else if (Point == null)
                {
                    AddNote("no remaining valid track points", true);
                }
            }
            break;

            case "TDT":
                //delayed in time
                //TDT(<pointName>, <timeDelay>[, <maxTime>])
            {
                var referencePoint = Resolve <ScriptingPoint>(0).Point;
                if (referencePoint == null)
                {
                    AddNote("the reference point is null", true);
                }
                else
                {
                    AXPoint point_tmp;
                    if (maxTime.HasValue)
                    {
                        point_tmp = Engine.TaskValidTrack.Points.FirstOrDefault(p => p.Time >= referencePoint.Time + timeDelay && p.Time <= maxTime);
                    }
                    else
                    {
                        point_tmp = Engine.TaskValidTrack.Points.FirstOrDefault(p => p.Time >= referencePoint.Time + timeDelay);
                    }

                    if (point_tmp != null)
                    {
                        Point = new AXWaypoint(Definition.ObjectName, point_tmp);
                    }
                    else
                    {
                        AddNote("no valid track point within time limits", true);
                    }
                }
            }
            break;

            case "TDD":
                //delayed in distance
                //TDD(<pointName>, <distanceDelay>[, <maxTime>])
            {
                var referencePoint = Resolve <ScriptingPoint>(0).Point;
                if (referencePoint == null)
                {
                    AddNote("the reference point is null", true);
                }
                else
                {
                    AXPoint point_tmp;
                    if (maxTime.HasValue)
                    {
                        point_tmp = Engine.TaskValidTrack.Points.FirstOrDefault(p => Physics.Distance2D(p, referencePoint) >= distanceDelay && p.Time <= maxTime);
                    }
                    else
                    {
                        point_tmp = Engine.TaskValidTrack.Points.FirstOrDefault(p => Physics.Distance2D(p, referencePoint) >= distanceDelay);
                    }

                    if (point_tmp != null)
                    {
                        Point = new AXWaypoint(Definition.ObjectName, point_tmp);
                    }
                    else
                    {
                        AddNote("no valid track point within distance limits", true);
                    }
                }
            }
            break;

            case "TAFI":
                //area first in
                //TAFI(<areaName>)
            {
                var area = Resolve <ScriptingArea>(0);

                try
                {
                    var tafi = Engine.TaskValidTrack.Points.First(p => area.Contains(p));
                    Point = new AXWaypoint(Definition.ObjectName, tafi);
                }
                catch
                {
                    AddNote("no valid track point inside the area", true);
                }
            }
            break;

            case "TAFO":
                //area first out
                //TAFO(<areaName>)
            {
                var area = Resolve <ScriptingArea>(0);

                try
                {
                    var     tafi    = Engine.TaskValidTrack.Points.First(p => area.Contains(p));
                    var     tafi_no = Engine.TaskValidTrack.Points.FirstOrDefault(p => p.Time > tafi.Time && !area.Contains(p));     //next out
                    AXPoint tafo;
                    if (tafi_no != null)
                    {
                        tafo = Engine.TaskValidTrack.Points.Last(p => p.Time < tafi_no.Time && area.Contains(p));
                    }
                    else
                    {
                        //last valid track point is inside the area and no exits
                        tafo = Engine.TaskValidTrack.Points.Last(p => area.Contains(p));        // == TALO
                    }
                    Point = new AXWaypoint(Definition.ObjectName, tafo);
                }
                catch
                {
                    AddNote("no valid track point inside the area", true);
                }
            }
            break;

            case "TALI":
                //area last in
                //TALI(<areaName>)
            {
                var area = Resolve <ScriptingArea>(0);

                try
                {
                    var     talo    = Engine.TaskValidTrack.Points.Last(p => area.Contains(p));
                    var     talo_po = Engine.TaskValidTrack.Points.LastOrDefault(p => p.Time < talo.Time && !area.Contains(p));     //previous out
                    AXPoint tali;
                    if (talo_po != null)
                    {
                        tali = Engine.TaskValidTrack.Points.First(p => p.Time > talo_po.Time && area.Contains(p));
                    }
                    else
                    {
                        //first valid track point is inside the area and no exits
                        tali = Engine.TaskValidTrack.Points.First(p => area.Contains(p));        // == TAFI
                    }
                    Point = new AXWaypoint(Definition.ObjectName, tali);
                }
                catch
                {
                    AddNote("no valid track point inside the area", true);
                }
            }
            break;

            case "TALO":
                //area last out
                //TALO(<areaName>)
            {
                var area = Resolve <ScriptingArea>(0);
                try
                {
                    var talo = Engine.TaskValidTrack.Points.Last(p => area.Contains(p));
                    Point = new AXWaypoint(Definition.ObjectName, talo);
                }
                catch
                {
                    AddNote("no valid track point inside the area", true);
                }
            }
            break;
            }

            if (Point != null)
            {
                AddNote("resolved to " + Point.ToString());
            }
            else
            {
                AddNote("could not be resolved");
            }

            //if (!string.IsNullOrEmpty(Log))
            //    Notes = ObjectName + ":" + Notes;
        }