public WayPoint(WayPoint p)
     : base(p)
 {
     _op = TwoTrails.Engine.OpType.WayPoint;
 }
        public bool ImportTt(List<string> polys, bool useNmea)
        {
            if (!_MetaOpen)
                return false;

            _Points = new List<TtPoint>();
            _Polygons = new Dictionary<string, TtPolygon>();
            _IdToCN = new Dictionary<string, string>();
            pidToCN = new Dictionary<int, string>();
            _PolyIndexes = new Dictionary<string, int>();

            Dictionary<string, TtMetaData> metaData = new Dictionary<string, TtMetaData>();
            Dictionary<string, string> metaLinkToId = new Dictionary<string, string>();
            Dictionary<string, int> qndLinks = new Dictionary<string, int>();
            List<int> pointWNMEA = new List<int>();

            Dictionary<int, List<TwoTrails.GpsAccess.NmeaBurst>> nmeas = new Dictionary<int, List<TwoTrails.GpsAccess.NmeaBurst>>();

            int viewId = metaKitViews[polydata];
            int rowCount;
            int polyCount = (int)dal.GetPolyCount();
            polyCount++;

            string tmpStr, tmpStr2;
            int tmpInt;
            double tmpDouble;

            try
            {
                #region Polygons
                rowCount = metaKit.GetRowCount(viewId);
                for (int i = 0; i < rowCount; i++)
                {
                    _Poly = new TtPolygon();

                    tmpStr = metaKit.GetString(viewId, i, 0);

                    if (!tmpStr.IsEmpty())
                    {
                        tmpStr2 = null;
                        _Poly.Name = tmpStr;
                    }
                    else
                    {
                        tmpStr2 = tmpStr;
                        _Poly.Name = String.Format("Poly {0}", polyCount);
                    }

                    _Poly.PointStartIndex = 1000 * polyCount + 10;

                    if (!polys.Contains(tmpStr))
                        continue;
                    polyCount++;

                    tmpStr = metaKit.GetString(viewId, i, 1);
                    if (!tmpStr.IsEmpty())
                        _Poly.Description = tmpStr;

                    tmpStr = metaKit.GetString(viewId, i, 10);
                    if (!tmpStr.IsEmpty())
                    {
                        if(_Poly.Description.IsEmpty())
                            _Poly.Description = tmpStr;
                        else
                            String.Format("{0}, Comment: {1}", _Poly.Description, tmpStr);
                    }

                    tmpDouble = metaKit.GetDouble(viewId, i, 11);
                    if(tmpDouble > 0)
                        _Poly.PolyAccu = tmpDouble;

                    _Polygons.Add(_Poly.CN, _Poly);
                    _IdToCN.Add(_Poly.Name, _Poly.CN);
                    _PolyIndexes.Add(_Poly.CN, 0);

                    if (tmpStr2 != null)
                    {
                        _IdToCN.Add(tmpStr2, _Poly.CN);
                    }
                }
                #endregion

                #region Metadata
                viewId = metaKitViews[metadata];

                TtMetaData newMeta;

                for (int i = 0; i < metaKit.GetRowCount(viewId); i++)
                {
                    newMeta = new TtMetaData();
                    newMeta.CN = Guid.NewGuid().ToString();

                    tmpInt = metaKit.GetInt(viewId, i, 2);
                    if (tmpInt > -1)
                        newMeta.Zone = tmpInt;

                    newMeta.Receiver = metaKit.GetString(viewId, i, 3);
                    newMeta.Laser = metaKit.GetString(viewId, i, 4);
                    newMeta.Compass = metaKit.GetString(viewId, i, 5);
                    newMeta.Crew = metaKit.GetString(viewId, i, 9);
                    newMeta.Comment = metaKit.GetString(viewId, i, 17);

                    tmpStr = metaKit.GetString(viewId, i, 10);
                    if(tmpStr.IsEmpty())
                    {
                        newMeta.Name = String.Format("Metadata {0}", metaData.Count + 1);
                        metaLinkToId.Add(newMeta.Name, newMeta.CN);
                        if (!metaLinkToId.ContainsKey(tmpStr))
                            metaLinkToId.Add(tmpStr, newMeta.CN);
                    }
                    else
                    {
                        newMeta.Name = tmpStr;
                        metaLinkToId.Add(tmpStr, newMeta.CN);
                    }

                    tmpStr = metaKit.GetString(viewId, i, 11);
                    tmpStr = tmpStr.ToLower();
                    if (tmpStr.Contains("meter"))
                        newMeta.uomDistance = UomDistance.Meters;
                    else if (tmpStr.Contains("chain"))
                        newMeta.uomDistance = UomDistance.Chains;
                    else if (tmpStr.Contains("tenth"))
                        newMeta.uomDistance = UomDistance.FeetTenths;
                    else if (tmpStr.Contains("inch"))
                        newMeta.uomDistance = UomDistance.FeetInches;
                    else if (tmpStr.Contains("yard"))
                        newMeta.uomDistance = UomDistance.Yards;

                    tmpStr = metaKit.GetString(viewId, i, 15);
                    tmpStr = tmpStr.ToLower();
                    if (tmpStr.Contains("feet"))
                        newMeta.uomElevation = UomElevation.Feet;
                    else if (tmpStr.Contains("meter"))
                        newMeta.uomElevation = UomElevation.Meters;

                    tmpStr = metaKit.GetString(viewId, i, 16);
                    tmpStr = tmpStr.ToLower();
                    if (tmpStr.Contains("deg"))
                        newMeta.uomSlope = UomSlope.Degrees;
                    else if (tmpStr.Contains("per"))
                        newMeta.uomSlope = UomSlope.Percent;

                    metaData.Add(newMeta.CN, newMeta);
                }
                #endregion

                #region Points
                TtPoint point;

                GpsPoint gps;
                SideShotPoint ssp;

                viewId = metaKitViews[ptdata];
                rowCount = metaKit.GetRowCount(viewId);
                for (int i = 0; i < rowCount; i++)
                {
                    tmpStr = metaKit.GetString(viewId, i, 0);

                    if (tmpStr.IsEmpty() || !polys.Contains(tmpStr))
                        continue;

                    point = new TtPoint();

                    _Poly = _Polygons[_IdToCN[tmpStr]];
                    point.PolyCN = _Poly.CN;
                    point.PolyName = _Poly.Name;

                    point.GroupCN = Values.MainGroup.CN;
                    point.GroupName = Values.MainGroup.Name;

                    tmpInt = metaKit.GetInt(viewId, i, 1);
                    if (tmpInt > 0)
                        point.PID = tmpInt;
                    else
                    {
                        if (_Points.Count > 1)
                            PointNaming.NamePoint(_Points[_Points.Count - 1], _Poly);
                        else
                            PointNaming.NameFirstPoint(_Poly);
                    }

                    pidToCN.Add(point.PID, point.CN);

                    tmpStr = metaKit.GetString(viewId, i, 2);
                    if (tmpStr.IsEmpty() || !tmpStr.IsBool())
                        point.OnBnd = false;
                    else
                        point.OnBnd = tmpStr.ToBool();

                    OpType op;

                    tmpStr = metaKit.GetString(viewId, i, 3);
                    if (tmpStr.IsEmpty())
                        continue;
                    else
                    {
                        try
                        {
                            op = (OpType)Enum.Parse(typeof(OpType), tmpStr, true);
                        }
                        catch
                        {
                            continue;
                        }
                    }

                    switch (op)
                    {
                        case OpType.GPS:
                        case OpType.Walk:
                        case OpType.WayPoint:
                            {
                                gps = new GpsPoint(point);

                                gps.UnAdjX = metaKit.GetDouble(viewId, i, 4);
                                gps.UnAdjY = metaKit.GetDouble(viewId, i, 5);
                                gps.UnAdjZ = metaKit.GetDouble(viewId, i, 6);
                                //gps.UnAdjX = gps.X;
                                //gps.UnAdjY = gps.Y;
                                //gps.UnAdjZ = gps.Z;

                                tmpDouble = metaKit.GetDouble(viewId, i, 32);
                                if (tmpDouble != 0)
                                    gps.ManualAccuracy = tmpDouble;

                                tmpDouble = metaKit.GetDouble(viewId, i, 33);
                                if (tmpDouble != 0)
                                    gps.RMSEr = tmpDouble;

                                if(metaKit.GetInt(viewId, i, 55) > 0)
                                    pointWNMEA.Add(point.PID);

                                if (op == OpType.Walk)
                                    point = new WalkPoint(gps);
                                else if (op == OpType.WayPoint)
                                    point = new WayPoint(gps);
                                else
                                    point = gps;
                            }
                            break;
                        case OpType.SideShot:
                        case OpType.Traverse:
                            {
                                ssp = new SideShotPoint(point);

                                tmpDouble = metaKit.GetDouble(viewId, i, 22);
                                if (tmpDouble != -1)
                                    ssp.ForwardAz = tmpDouble;

                                tmpDouble = metaKit.GetDouble(viewId, i, 23);
                                if (tmpDouble != -1)
                                    ssp.BackwardAz = tmpDouble;

                                ssp.SlopeDistance = metaKit.GetDouble(viewId, i, 24);
                                ssp.SlopeAngle = metaKit.GetDouble(viewId, i, 25);

                                if (op == OpType.Traverse)
                                    point = new TravPoint(ssp);
                                else
                                    point = ssp;
                            }
                            break;
                        case OpType.Quondam:
                            {
                                point = new QuondamPoint(point);

                                tmpStr = metaKit.GetString(viewId, i, 29);
                                try
                                {
                                    if (!tmpStr.IsEmpty())
                                    {
                                        tmpStr2 = tmpStr.Split(',')[1].Trim();
                                        qndLinks.Add(point.CN, tmpStr2.ToInteger());
                                    }
                                }
                                catch
                                {
                                    //bad quondam
                                }
                            }
                            break;
                        default:
                            continue;
                    }

                    tmpStr = metaKit.GetString(viewId, i, 56);
                    if (tmpStr.IsEmpty() || !metadata.Contains(tmpStr))
                        point.MetaDefCN = _Meta.CN;
                    else
                    {
                        point.MetaDefCN = metaData[tmpStr].CN;
                    }

                    tmpStr = metaKit.GetString(viewId, i, 38);
                    if (!tmpStr.IsEmpty())
                        point.Comment = tmpStr;

                    point.Index = _PolyIndexes[point.PolyCN];
                    _PolyIndexes[point.PolyCN]++;

                    point.Time = DateTime.Now;

                    _Points.Add(point);
                }

                for (int i = 0; i < _Points.Count; i++)
                {
                    if (_Points[i].op == OpType.Quondam)
                    {
                        if(qndLinks.ContainsKey(_Points[i].CN))
                        {
                            QuondamPoint qp = ((QuondamPoint)_Points[i]);
                            qp.ParentPoint = _Points.Where(p => p.PID == qndLinks[qp.CN]).First();
                            _Points[i] = qp;
                        }
                    }
                }

                #endregion

                #region NMEA
                if (useNmea)
                {
                    TwoTrails.GpsAccess.NmeaBurst burst;

                    viewId = metaKitViews[nmeadata];
                    tmpInt = metaKit.GetRowCount(viewId);
                    for (int i = 0; i < tmpInt; i++)
                    {
                        tmpStr = metaKit.GetString(viewId, i, 1);
                        if (tmpStr.IsInteger())
                        {
                            int pid = tmpStr.ToInteger();
                            if (pointWNMEA.Contains(pid))
                            {
                                if (!nmeas.ContainsKey(pid))
                                    nmeas.Add(pid, new List<TwoTrails.GpsAccess.NmeaBurst>());

                                burst = new TwoTrails.GpsAccess.NmeaBurst();
                                burst._CN = Guid.NewGuid().ToString();

                                burst._Used = metaKit.GetInt(viewId, i, 2) > 0;

                                tmpStr = metaKit.GetString(viewId, i, 3);
                                if (!tmpStr.IsEmpty())
                                    burst._date = DateTime.ParseExact(tmpStr, "MMddyy", null);

                                tmpStr2 = metaKit.GetString(viewId, i, 4);
                                if (!tmpStr2.IsEmpty())
                                    burst._date = DateTime.ParseExact(tmpStr + tmpStr2, "MMddyyHHmmss", null);

                                burst._GGA_longitude = metaKit.GetDouble(viewId, i, 5);
                                burst._RMC_longitude = burst._GGA_longitude;

                                burst._GGA_latitude = metaKit.GetDouble(viewId, i, 6);
                                burst._RMC_latitude = burst._GGA_latitude;

                                burst._alt_unit = Unit.METERS;
                                burst._altitude = metaKit.GetFloat(viewId, i, 11);

                                burst._horiz_dilution_position = metaKit.GetDouble(viewId, i, 12);
                                burst._fix_quality = metaKit.GetInt(viewId, i, 13);

                                burst._fix = metaKit.GetInt(viewId, i, 15);

                                burst._PDOP = metaKit.GetFloat(viewId, i, 16);
                                burst._HDOP = metaKit.GetFloat(viewId, i, 17);
                                burst._VDOP = metaKit.GetFloat(viewId, i, 18);

                                burst._magVar = metaKit.GetFloat(viewId, i, 19);
                                burst._num_of_sat = metaKit.GetInt(viewId, i, 20);
                                burst._fixed_PRNs = metaKit.GetString(viewId, i, 21);

                                burst._GGA_latDir = TwoTrails.GpsAccess.NorthSouth.North;
                                burst._GGA_longDir = TwoTrails.GpsAccess.EastWest.West;
                                burst._magVarDir = TwoTrails.GpsAccess.EastWest.East;
                                burst._RMC_latDir = TwoTrails.GpsAccess.NorthSouth.North;
                                burst._RMC_longDir = TwoTrails.GpsAccess.EastWest.West;

                                for (int j = 22; j < 70; j += 4)
                                {
                                    GpsAccess.Satellite s = new TwoTrails.GpsAccess.Satellite();

                                    s.ID = metaKit.GetString(viewId, i, j);
                                    s.Elevation = metaKit.GetInt(viewId, i, j + 1);
                                    s.Azimuth = metaKit.GetInt(viewId, i, j + 2);
                                    s.SNR = metaKit.GetInt(viewId, i, j + 3);

                                    burst.AddSatalite(s);
                                }

                                burst.Complete();

                                nmeas[pid].Add(burst);
                            }
                        }
                    }
                }

                #endregion

                dal.InsertPoints(_Points);

                foreach (TtMetaData m in metaData.Values)
                    dal.InsertMetaData(m);
                foreach (TtPolygon poly in _Polygons.Values)
                    dal.InsertPolygon(poly);

                foreach (KeyValuePair<int, List<GpsAccess.NmeaBurst>> bl in nmeas)
                    dal.SaveNmeaBursts(bl.Value, pidToCN[bl.Key]);
            }
            catch (Exception ex)
            {
                TtUtils.WriteError(ex.Message, "DataImport:ImportTt", ex.StackTrace);
                return false;
            }

            return true;
        }
        private void Generate()
        {
            ThreadRunning = true;

            if (Points.Count > 2)
            {
                TtMetaData meta = DAL.GetMetaDataByCN(Points.First().Value.MetaDefCN);
                if (meta == null)
                {
                    throw new Exception("No Meta Data");
                }

                TtPolygon newPoly = new TtPolygon();
                newPoly.Name = polyName;
                newPoly.Description = "Plot Grid";
                newPoly.PointStartIndex = ((int)DAL.GetPolyCount() + 1) * 1000 + 10;
                newPoly.IncrementBy = 1;

                DAL.InsertPolygon(newPoly);

                Random rand = new Random();

                double gridX = ix, gridY = iy, angle;

                TtUtils.ShowWaitCursor();

                try
                {
                    //convert to meters if not meters
                    if (dist != Unit.METERS)
                    {
                        gridX = TtUtils.ConvertToMeters(gridX, dist);
                        gridY = TtUtils.ConvertToMeters(gridY, dist);
                    }

                    //get rotation
                    if (tilt == null)
                        angle = rand.Next(-45, 45);
                    else
                        angle = (double)tilt * -1;

                    newPoly.Description = String.Format("Angle: {0}, GridX(Mt): {1}, GridY(Mt): {2}",
                        angle, gridX, gridY);

                    //add list of DoublePoints from TtPoints (using DoublePoints is Faster in the calculations)
                    List<DoublePoint> _Points = new List<DoublePoint>();

                    //return if canceled
                    if (_killThread)
                    {
                        ThreadRunning = false;
                        return;
                    }

                    foreach (TtPoint p in Points.Values.Where( pt => pt.OnBnd))
                    {
                        _Points.Add(new DoublePoint(p.AdjX, p.AdjY));
                    }

                    double startX, startY;
                    double top, bottom, left, right;
                    top = bottom = left = right = 0;

                    if (!TtUtils.GetFarthestPoints(_Points, out top, out bottom, out left, out right))
                    {
                        //if CurrPoint is null get random start point, else use selected StartPoint
                        if (CurrPoint == null)
                        {
                            startY = rand.NextDouble() * (top - bottom) + bottom;
                            startX = rand.NextDouble() * (right - left) + left;
                        }
                        else
                        {
                            startX = CurrPoint.AdjX;
                            startY = CurrPoint.AdjY;
                        }

                        //push boundaries of the polygon box by 10 meters (for Extents)
                        top += 10;
                        bottom -= 10;
                        left -= 10;
                        right += 10;

                        double farX = startX, farY = startY;
                        TtUtils.GetFarthestCorner(startX, startY, top, bottom, left, right, out farX, out farY);

                        double dist2 = TtUtils.Distance(startX, startY, farX, farY);

                        int ptAmtY = (int)(Math.Floor(dist2 / gridY) + 1);
                        int ptAmtX = (int)(Math.Floor(dist2 / gridX) + 1);

                        double farLeft, farRight, farTop, farBottom;

                        farLeft = startX - (ptAmtX * gridX);
                        farRight = startX + (ptAmtX * gridX);
                        farTop = startY + (ptAmtY * gridY);
                        farBottom = startY - (ptAmtY * gridY);

                        double i = farLeft;
                        double j = farTop;

                        List<DoublePoint> dblPts = new List<DoublePoint>();

                        DoublePoint _point;

                        List<DoublePoint> rec = new List<DoublePoint>();
                        rec.Add(new DoublePoint(left, top));
                        rec.Add(new DoublePoint(right, top));
                        rec.Add(new DoublePoint(right, bottom));
                        rec.Add(new DoublePoint(left, bottom));

                        while (i <= farRight)
                        {
                            while (j >= farBottom)
                            {
                                //return if canceled
                                if (_killThread)
                                {
                                    ThreadRunning = false;
                                    return;
                                }

                                //add the rotated point

                                _point = TtUtils.RotatePoint(i, j, angle, startX, startY);

                                if (loc == PointLocation.Inside)
                                {
                                    //add if point inside the polygon

                                    if (TtUtils.PointInPoly(_point, ref _Points))
                                        dblPts.Add(_point);
                                }
                                else
                                {
                                    //add if point inside the polygon box

                                    if (TtUtils.PointInPoly(_point, ref rec))
                                        dblPts.Add(_point);
                                }

                                j -= gridY;

                            }
                            i += gridX;
                            j = farTop;
                        }

                        List<TtPoint> _NewPoints = new List<TtPoint>();
                        WayPoint way;
                        WayPoint lastWay = null;

                        //add points to polygon
                        for (int a = 0; a < dblPts.Count; a++)
                        {
                            //return if canceled
                            if (_killThread)
                            {
                                ThreadRunning = false;
                                return;
                            }

                            way = new WayPoint();

                            DoublePoint dp = dblPts[a];
                            //way.X = dp.X;
                            way.UnAdjX = dp.X;
                            //way.Y = dp.Y;
                            way.UnAdjY = dp.Y;
                            way.UnAdjZ = 0;
                            way.PolyCN = newPoly.CN;
                            way.PolyName = newPoly.Name;
                            way.OnBnd = false;
                            way.ManualAccuracy = null;
                            way.Index = a;
                            way.Comment = "Generated Point";
                            way.GroupCN = Values.MainGroup.CN;
                            way.GroupName = Values.MainGroup.Name;

                            if (lastWay == null)
                                way.PID = PointNaming.NameFirstPoint(newPoly);
                            else
                                way.PID = PointNaming.NamePoint(lastWay, newPoly);

                            way.Time = DateTime.Now;
                            way.MetaDefCN = meta.CN;

                            _NewPoints.Add(way);

                            lastWay = way;
                        }

                        DAL.SavePoints(null, _NewPoints, ref _killThread);

                        //return if canceled
                        if (_killThread)
                        {
                            ThreadRunning = false;
                            return;
                        }

                        DAL.SavePolygon(newPoly, newPoly);
                        TtUtils.HideWaitCursor();

                        lstPoly.Add(polyName);
                        _Polys.Add(newPoly);

                        AutoClosingMessageBox.Show(String.Format("{0} Points Generated.", dblPts.Count),
                            "Points Generated", 1000);
                        _generated = true;
                    }
                    else
                    {
                        //polygon has less than 3 sides
                        MessageBox.Show("No Points Generated.");

                        DAL.DeletePolygon(newPoly.CN);
                    }

                }
                catch (Exception ex)
                {
                    if (!_killThread)
                    {
                        TtUtils.WriteError(ex.Message, "PlotGirdFormLogic:Generate", ex.StackTrace);
                        MessageBox.Show("Plot Generate Error.");
                    }
                }

                TtUtils.HideWaitCursor();
            }
            else
            {
                MessageBox.Show("Polygon must have minimum of 3 points.");
            }

            ThreadRunning = false;
            btnPlot.GuiInvoke(() =>
                {
                    btnPlot.Enabled = true;
                });
        }