// TEXT WKT like syntax
        //
        // Text("String to Display", sizeInDegrees, lat lng alt, rotation tilt bank)
        private void ParseTextString(string parens, string mods, Color lineColor, Color polyColor, double alt, Dates date)
        {
            if (!parens.StartsWith("(") && parens.EndsWith(")"))
            {
                return;
            }
            try
            {
                parens = parens.Substring(1, parens.Length - 2);

                var parts = UiTools.SplitString(parens, ',');

                if (textBatch == null)
                {
                    textBatch = new Text3dBatch();
                }

                var text = parts[0];
                double rawSize = float.Parse(parts[1].Trim());
                var textSize = (float)(.00012f * rawSize);

                // Test to compare angle vs est angle.
                //double textAngle = 2 * Math.Tan(((rawSize/180)*Math.PI) /2);

                var lla = parts[2].Trim().Split(new[] { ' ' });

                var lat = double.Parse(lla[1]);
                var lng = double.Parse(lla[0]);
                if (astronomical && bufferIsFlat)
                {
                    lng -= 180;
                }
                var altitude = alt == 0 ? 1 : alt;

                if (lla.Length > 2)
                {
                    altitude = 1 + double.Parse(lla[2]) / (astronomical ? 1 : meanRadius);
                }

                if (alt == 0 && astronomical && !bufferIsFlat)
                {
                    altitude = 1000 * UiTools.AuPerLightYear;

                    textSize = (float)(textSize * altitude);

                }

                if (alt == 0 && astronomical && !bufferIsFlat)
                {
                    altitude = 1000 * UiTools.AuPerLightYear;

                    textSize = (float)(textSize * altitude);

                }
                var location = Coordinates.GeoTo3dDouble(lat, lng, altitude);
                var up = Coordinates.GeoTo3dDouble(lat + 90, lng, 1);

                double rotation = 0;
                double tilt = 0;
                double bank = 0;

                if (parts.Length > 3)
                {
                    var rtb = parts[3].Trim().Split(new[] { ' ' });
                    rotation = double.Parse(rtb[0]);
                    if (rtb.Length > 1)
                    {
                        tilt = double.Parse(rtb[1]);
                    }

                    if (rtb.Length > 2)
                    {
                        bank = double.Parse(rtb[2]);
                    }
                }

                var text3d = new Text3d(location, up, text, astronomical ? 1 : -1, textSize);
                text3d.Color = polyColor;
                text3d.Rotation = rotation;
                text3d.Tilt = tilt;
                text3d.Bank = bank;
                textBatch.Add(text3d);
            }
            catch
            {
            }
        }
        private void ParseLineString(string parens, string mods, Color lineColor, double alt, bool single, Dates date)
        {
            if (!parens.StartsWith("(") && parens.EndsWith(")"))
            {
                return;
            }
            if (!single)
            {
                // string the top level of parens
                parens = parens.Substring(1, parens.Length - 2);
            }
            var shapes = UiTools.SplitString(parens, ',');
            foreach (var shape in shapes)
            {
                var lineList = new KmlLineList();
                lineList.Astronomical = astronomical;
                lineList.MeanRadius = meanRadius;

                lineList.ParseWkt(shape, mods, alt, date);

                AddPolygon(!bufferIsFlat && astronomical, lineList, 1, Color.White, lineColor, false, false, date);
            }
        }
        private void ParsePolygon(string parens, string mods, Color lineColor, Color polyColor, double alt, Dates date)
        {
            if (!parens.StartsWith("(") && parens.EndsWith(")"))
            {
                return;
            }
            // string the top level of parens
            parens = parens.Substring(1, parens.Length - 2);

            var shapes = UiTools.SplitString(parens, ',');
            foreach (var shape in shapes)
            {
                var lineList = new KmlLineList();
                lineList.Astronomical = astronomical;
                lineList.MeanRadius = meanRadius;
                lineList.ParseWkt(shape, mods, alt, date);
                if (alt == 0)
                {
                    AddPolygonFlat(false, lineList, 1, polyColor, lineColor, true, true, date);
                }
                else
                {
                    AddPolygon(false, lineList, 1, polyColor, lineColor, true, true, date);
                }
            }
        }
        private void AddPolygonFlat(bool sky, KmlLineList geo, float lineWidth, Color polyColor, Color lineColor, bool extrude, bool fill, Dates date)
        {
            //todo can we save this work for later?
            var vertexList = new List<Vector3d>();

            for (var i = 0; i < (geo.PointList.Count); i++)
            {
                vertexList.Add(Coordinates.GeoTo3dDouble(geo.PointList[i].Lat, geo.PointList[i].Lng, 1 + (geo.PointList[i].Alt / meanRadius)));
            }

            for (var i = 0; i < (geo.PointList.Count - 1); i++)
            {
                if (sky)
                {
                    lineList2d.AddLine
                        (Coordinates.RADecTo3d(-(180.0 - geo.PointList[i].Lng) / 15, geo.PointList[i].Lat, 1), Coordinates.RADecTo3d(-(180.0 - geo.PointList[i + 1].Lng) / 15, geo.PointList[i + 1].Lat, 1), lineColor, date);
                }
                else
                {
                    if (lineWidth > 0)
                    {
                        lineList2d.AddLine(vertexList[i], vertexList[i + 1], lineColor, date);
                    }
                }
            }
            if (fill)
            {
                var indexes = Glu.TesselateSimplePoly(vertexList);

                for (var i = 0; i < indexes.Count; i += 3)
                {
                    triangleList2d.AddTriangle(vertexList[indexes[i]], vertexList[indexes[i + 1]], vertexList[indexes[i + 2]], polyColor, date, 2);
                }
            }
        }
        private void ParseGeometry(string gs, Color lineColor, Color polyColor, double alt, Dates date)
        {
            gs = gs.Trim();

            var index = gs.IndexOf('(');

            if (index < 0)
            {
                return;
            }

            if (!gs.EndsWith(")"))
            {
                return;
            }
            var commandPart = gs.Substring(0, index ).Trim();

            var parens = gs.Substring(index);

            var parts = commandPart.Split(new[] { ' ' });

            string command = null;
            string mods = null;
            if (parts.Length > 0)
            {
                foreach (var item in parts)
                {
                    if (string.IsNullOrEmpty(command))
                    {
                        command = item;
                    }
                    else if (string.IsNullOrEmpty(mods))
                    {
                        mods = item;
                    }
                }
            }

            switch (command.ToLower())
            {
                case "multipolygon":
                case "polygon":
                    {
                        ParsePolygon(parens, mods, lineColor, polyColor, alt, date);

                    }
                    break;
                case "multilinestring":
                    {
                        ParseLineString(parens, mods, lineColor, alt, false, date);
                    }
                    break;
                case "linestring":
                    {
                        ParseLineString(parens, mods, lineColor, alt, true, date);
                    }
                    break;
                case "geometrycollection":
                    {
                         parens = parens.Substring(1, parens.Length - 2);
                         var shapes = UiTools.SplitString(parens, ',');
                         foreach (var shape in shapes)
                         {
                             ParseGeometry(shape, lineColor, polyColor, alt, date);
                         }
                    }
                    break;
                case "text":
                    {
                        ParseTextString(parens, mods, lineColor, polyColor, alt, date);
                    }
                    break;
                default:
                    break;
            }
        }
        protected void MakeBarChart(string[] row, double lat, double lng, double scale, double factor, Color color, bool selected, Dates date)
        {
            if (barChartBitmask == 0)
            {
                return;
            }

            var center = Coordinates.GeoTo3dDouble(lat, lng, 1);
            var up = Coordinates.GeoTo3dDouble(lat + 90, lng, 1);
            var right = Vector3d.Cross(center, up);
            var upleft = Vector3d.Subtract(up, right);
            upleft.Normalize();
            upleft.Multiply(.0005);

            var upright = Vector3d.Add(up, right);
            upright.Normalize();
            upright.Multiply(.0005);

            var base1 = Vector3d.Add(center, upright);
            var base2 = Vector3d.Add(center, upleft);
            var base3 = Vector3d.Subtract(center, upleft);
            var base4 = Vector3d.Subtract(center, upright);

            double currentBase = 1;

            var colorIndex = 0;

            var targetList = triangleList2d;

            for (var col = 0; col < Header.Length; col++)
            {
                if (((int)Math.Pow(2, col) & barChartBitmask) > 0)
                {

                    double alt = 0;
                    if (!double.TryParse(row[col], out alt))
                    {
                        alt = 0;
                    }
                    alt = factor * alt;

                    var alt2 = 1 + (factor * (alt + currentBase) / meanRadius);

                    var top1 = base1;
                    var top2 = base2;
                    var top3 = base3;
                    var top4 = base4;
                    top1.Normalize();
                    top2.Normalize();
                    top3.Normalize();
                    top4.Normalize();

                    top1.Multiply(alt2);
                    top2.Multiply(alt2);
                    top3.Multiply(alt2);
                    top4.Multiply(alt2);

                    var currentColor = (colorIndex == 0) ? Color.FromArgb(192, color) : Color.FromArgb(128, Color.Yellow);
                    targetList.AddQuad(top1, top2, top3, top4, currentColor, date);
                    // this.triangleList.AddQuad(top

                    targetList.AddQuad(top2, top1, base2, base1, currentColor, date);
                    targetList.AddQuad(top4, top2, base4, base2, currentColor, date);
                    targetList.AddQuad(top1, top3, base1, base3, currentColor, date);
                    targetList.AddQuad(top3, top4, base3, base4, currentColor, date);

                    base1 = top1;
                    base2 = top2;
                    base3 = top3;
                    base4 = top4;
                    colorIndex++;
                    currentBase += alt;
                }
            }
        }
        private void AddPolygon(bool sky, KmlLineList geo, float lineWidth, Color polyColor, Color lineColor, bool extrude, bool fill, Dates date)
        {
            //todo can we save this work for later?
            var vertexList = new List<Vector3d>();
            var vertexListGround = new List<Vector3d>();

            //todo list
            // We need to Wrap Around for complete polygone
            // we aldo need to do intereor
            //todo space? using RA/DEC
            for (var i = 0; i < (geo.PointList.Count); i++)
            {
                vertexList.Add(Coordinates.GeoTo3dDouble(geo.PointList[i].Lat, geo.PointList[i].Lng, 1 + (geo.PointList[i].Alt / meanRadius)));
                vertexListGround.Add(Coordinates.GeoTo3dDouble(geo.PointList[i].Lat, geo.PointList[i].Lng, 1));
            }

            for (var i = 0; i < (geo.PointList.Count - 1); i++)
            {
                if (sky)
                {
                    lineList2d.AddLine
                        (Coordinates.RADecTo3d(-(180.0 - geo.PointList[i].Lng) / 15 , geo.PointList[i].Lat,1), Coordinates.RADecTo3d(-(180.0 - geo.PointList[i + 1].Lng) / 15 , geo.PointList[i + 1].Lat,1), lineColor, date);
                }
                else
                {
                    if (extrude)
                    {

                        triangleList.AddQuad(vertexList[i], vertexList[i + 1], vertexListGround[i], vertexListGround[i + 1], polyColor, date);

                    }
                    if (lineWidth > 0)
                    {
                        if (extrude)
                        {
                            lineList.AddLine(vertexList[i], vertexList[i + 1], lineColor, date);
                        }
                        else
                        {
                            lineList2d.AddLine(vertexList[i], vertexList[i + 1], lineColor, date);
                        }
                        if (extrude)
                        {
                            lineList.AddLine(vertexListGround[i], vertexListGround[i + 1], lineColor, date);
                            lineList.AddLine(vertexList[i], vertexListGround[i], lineColor, date);
                            lineList.AddLine(vertexList[i + 1], vertexListGround[i + 1], lineColor, date);
                        }
                    }
                }
            }
            if (fill)
            {
                var indexes = Glu.TesselateSimplePolyB(vertexList);

                for (var i = 0; i < indexes.Count; i += 3)
                {
                    triangleList.AddTriangle(vertexList[indexes[i]], vertexList[indexes[i + 1]], vertexList[indexes[i + 2]], polyColor, date);
                }
            }
        }
 public void AddTriangle(Vector3d v1, Vector3d v2, Vector3d v3, Color color, Dates date)
 {
     trianglePoints.Add(v1.Vector311);
     trianglePoints.Add(v2.Vector311);
     trianglePoints.Add(v3.Vector311);
     triangleColors.Add(color);
     triangleDates.Add(date);
     EmptyTriangleBuffer();
 }
        public void AddTriangle(Vector3d v1, Vector3d v2, Vector3d v3, Color color, Dates date, int subdivisions)
        {
            subdivisions--;

            if (subdivisions < 0)
            {
                AddTriangle(v1, v2, v3, color, date);
            }
            else
            {
                Vector3d v12;
                Vector3d v23;
                Vector3d v31;

                v12 = Vector3d.MidPointByLength(v1, v2);
                v23 = Vector3d.MidPointByLength(v2, v3);
                v31 = Vector3d.MidPointByLength(v3, v1);

                // Add 1st
                AddTriangle(v1, v12, v31, color, date, subdivisions);
                // Add 2nd
                AddTriangle(v12, v23, v31, color, date, subdivisions);
                // Add 3rd
                AddTriangle(v12, v2, v23, color, date, subdivisions);
                // Add 4th
                AddTriangle(v23, v3, v31, color, date, subdivisions);

            }
        }
 public void AddQuad(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Color color, Dates date)
 {
     trianglePoints.Add(v1);
     trianglePoints.Add(v3);
     trianglePoints.Add(v2);
     trianglePoints.Add(v2);
     trianglePoints.Add(v3);
     trianglePoints.Add(v4);
     triangleColors.Add(color);
     triangleDates.Add(date);
     triangleColors.Add(color);
     triangleDates.Add(date);
     EmptyTriangleBuffer();
 }
 public void AddLine(Vector3d v1, Vector3d v2, Color color, Dates date)
 {
     linePoints.Add(v1);
     linePoints.Add(v2);
     lineColors.Add(color);
     lineDates.Add(date);
     EmptyLineBuffer();
 }
 public void ParseWkt(string geoText, string option, double alt, Dates date)
 {
     string[] parts = geoText.Split(new char[] { '(', ',', ')' });
     foreach (string part in parts)
     {
         string[] coordinates = part.Trim().Split(new char[] { ' ' });
         if (coordinates.Length > 1)
         {
             KmlCoordinate pnt = new KmlCoordinate();
             pnt.Lng = double.Parse(coordinates[0]);
             if (Astronomical)
             {
                 pnt.Lng -= 180;
             }
             pnt.Lat = double.Parse(coordinates[1]);
             if (coordinates.Length > 2 && alt == 0)
             {
                 pnt.Alt = double.Parse(coordinates[2]);
             }
             else
             {
                 pnt.Alt = alt;
             }
             pnt.Date = date;
             PointList.Add(pnt);
         }
     }
 }
 public void AddQuad(Vector3d v1, Vector3d v2, Vector3d v3, Vector3d v4, Color color, Dates date)
 {
     trianglePoints.Add(v1.Vector311);
     trianglePoints.Add(v3.Vector311);
     trianglePoints.Add(v2.Vector311);
     trianglePoints.Add(v2.Vector311);
     trianglePoints.Add(v3.Vector311);
     trianglePoints.Add(v4.Vector311);
     triangleColors.Add(color);
     triangleDates.Add(date);
     triangleColors.Add(color);
     triangleDates.Add(date);
     EmptyTriangleBuffer();
 }
 public void AddQuad(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Color color, Dates date)
 {
     trianglePoints.Add(v1);
     trianglePoints.Add(v3);
     trianglePoints.Add(v2);
     trianglePoints.Add(v2);
     trianglePoints.Add(v3);
     trianglePoints.Add(v4);
     triangleColors.Add(color);
     triangleDates.Add(date);
     triangleColors.Add(color);
     triangleDates.Add(date);
     EmptyTriangleBuffer();
 }