Exemplo n.º 1
0
        public void TestSerialize()
        {
            const string Expected =
                "<kml xmlns:atom=\"http://www.w3.org/2005/Atom\" xmlns=\"http://www.opengis.net/kml/2.2\">" +
                "<Document>" +
                "<atom:author>" +
                "<atom:name>Name</atom:name>" +
                "</atom:author>" +
                "<atom:link href=\"http://www.example.com/\" />" +
                "</Document>" +
                "</kml>";

            Document document = new Document();

            document.AtomAuthor = new Author {
                Name = "Name"
            };
            document.AtomLink = new SharpKml.Dom.Atom.Link {
                Href = new Uri("http://www.example.com")
            };

            Kml root = new Kml();

            root.AddNamespacePrefix(KmlNamespaces.AtomPrefix, KmlNamespaces.AtomNamespace);
            root.Feature = document;

            Serializer serializer = new Serializer();

            serializer.SerializeRaw(root);

            Assert.That(serializer.Xml, Is.EqualTo(Expected));
        }
Exemplo n.º 2
0
        private static Kml NewGxKml()
        {
            Kml kml = new Kml();

            kml.AddNamespacePrefix(KmlNamespaces.GX22Prefix, KmlNamespaces.GX22Namespace);
            return(kml);
        }
        private Document StartDocument(out Kml rootElement)
        {
            var kml = new Kml();

            kml.AddNamespacePrefix(KmlNamespaces.GX22Prefix, KmlNamespaces.GX22Namespace);
            kml.AddNamespacePrefix(KmlNamespaces.AtomPrefix, KmlNamespaces.AtomNamespace);
            kml.AddNamespacePrefix(KmlNamespaces.Kml22Prefix, KmlNamespaces.Kml22Namespace);

            var document = new Document
            {
                Open = true,
                Name = $"Link between {this.From.Callsign?.ToUpperInvariant()} and {this.To.Callsign?.ToUpperInvariant()}"
            };

            kml.Feature = document;
            rootElement = kml;

            return(document);
        }
Exemplo n.º 4
0
        public override void saveKmlDocument(Document kmlDoc)
        {
            // This allows us to save and Element easily.
            var kml = new Kml();

            kml.AddNamespacePrefix(KmlNamespaces.GX22Prefix, KmlNamespaces.GX22Namespace);
            kml.Feature = kmlDoc;


            KmlFile kmlF = KmlFile.Create(kml, false);

            kmlF.Save(@"mykmlFile.kml");
        }
Exemplo n.º 5
0
        /// <summary>
        /// converte la feature class in kml. Se non sono presenti le coordinate il dato non viene inserito
        /// </summary>
        /// <param name="sourceWorkspace">workspace con la feature class</param>
        /// <param name="outputName">nome della feature class e del csv di output</param>
        /// <param name="targetPath">percorso dove salvare il file di output</param>
        /// <param name="delimitator">delimitatore utilizzato nel csv</param>
        private void ConvertFeatureClassPointToKml(IWorkspace sourceWorkspace, string outputName, string targetPath)
        {
            IFeatureCursor featureCursor = null;

            try
            {
                IFeatureWorkspace featureWorkspace = sourceWorkspace as IFeatureWorkspace;
                IFeatureClass     featureClass     = featureWorkspace.OpenFeatureClass(outputName);
                if (featureClass.ShapeType != esriGeometryType.esriGeometryPoint)
                {
                    throw new Exception($"Per esportare in {Enum.GetName(typeof(FileExtension), FileExtension.kmz)} occorre una feature class di tipo {Enum.GetName(typeof(esriGeometryType), esriGeometryType.esriGeometryPoint)}!");
                }

                featureCursor = featureClass.Search(null, true);

                var folder = new Folder();
                folder.Id   = outputName;
                folder.Name = outputName;

                Dictionary <int, string> fields = new Dictionary <int, string>();
                IField field = null;
                for (int i = 0; i < featureCursor.Fields.FieldCount; i++)
                {
                    field = featureCursor.Fields.Field[i];
                    if ((field.Type == esriFieldType.esriFieldTypeBlob) || (field.Type == esriFieldType.esriFieldTypeGeometry) ||
                        (field.Type == esriFieldType.esriFieldTypeGlobalID) || (field.Type == esriFieldType.esriFieldTypeGUID) ||
                        (field.Type == esriFieldType.esriFieldTypeRaster) || (field.Type == esriFieldType.esriFieldTypeXML))
                    {
                        continue;
                    }

                    fields.Add(i, field.Name);
                }

                IFeature     feature      = null;
                Placemark    placemark    = null;
                Vector       vector       = null;
                ExtendedData extendedData = null;
                while ((feature = featureCursor.NextFeature()) != null)
                {
                    if ((feature.ShapeCopy == null) || (feature.ShapeCopy.IsEmpty))
                    {
                        continue;
                    }

                    IPoint p = feature.ShapeCopy as IPoint;
                    if (p.SpatialReference.FactoryCode != Helper.SpatialReferenceWGS84.FactoryCode)
                    {
                        p.Project(Helper.SpatialReferenceWGS84);
                    }

                    vector = new Vector(p.Y, p.X);


                    placemark      = new Placemark();
                    placemark.Id   = feature.OID.ToString();
                    placemark.Name = feature.OID.ToString();

                    extendedData = new ExtendedData();
                    foreach (int i in fields.Keys)
                    {
                        Data data = new Data();
                        data.DisplayName = fields[i];
                        data.Name        = fields[i];
                        data.Value       = feature.get_Value(i).ToString();
                        extendedData.AddData(data);
                    }

                    placemark.ExtendedData = extendedData;
                    placemark.Geometry     = new SharpKml.Dom.Point {
                        Coordinate = vector
                    };

                    folder.AddFeature(placemark);
                }

                Kml kml = new Kml();
                kml.AddNamespacePrefix(KmlNamespaces.GX22Prefix, KmlNamespaces.GX22Namespace);
                kml.Feature = folder;
                KmlFile kmlfile = KmlFile.Create(kml, false);
                using (var stream = File.OpenWrite(System.IO.Path.Combine(targetPath, System.IO.Path.ChangeExtension(outputName, Enum.GetName(typeof(FileExtension), FileExtension.kmz)))))
                {
                    kmlfile.Save(stream);
                }
            }
            catch
            {
                throw;
            }
            finally
            {
                if (featureCursor != null)
                {
                    Marshal.FinalReleaseComObject(featureCursor);
                }
            }
        }
Exemplo n.º 6
0
        // function that writes out KML file based on the flight chosen by the user
        private void CreateKMLButton_Click(object sender, EventArgs e)
        {
            int    nCount;
            int    nFlightID;
            string sfilename;
            long   lprevTimestamp;

            bLoggingEnabled = false;

            if (FlightPickerLV.SelectedItems.Count < 1)
            {
                MessageBox.Show("Please choose a flight before exporting.", "Export KML File");
                return;
            }

            if (KMLFilePathTBRO.Text.Length == 0)
            {
                MessageBox.Show("Please choose a folder location before exporting.", "Export KML File");
                return;
            }

            nFlightID = (int)FlightPickerLV.SelectedItems[0].Tag;

            // This is the root element of the file
            var    kml        = new Kml();
            Folder mainFolder = new Folder();

            mainFolder.Name        = String.Format("{0} {1}", FlightPickerLV.SelectedItems[0].SubItems[1].Text, FlightPickerLV.SelectedItems[0].SubItems[0].Text);
            mainFolder.Description = new Description
            {
                Text = "Overall Data for the flight"
            };

            kml.Feature = mainFolder;

            // start of Flight Path Line
            var placemarkLine = new Placemark();

            mainFolder.AddFeature(placemarkLine);
            placemarkLine.Name        = "Flight Path Line";
            placemarkLine.Description = new Description
            {
                Text = "Line of the flight"
            };
            var linestring           = new LineString();
            var coordinatecollection = new CoordinateCollection();

            linestring.Coordinates  = coordinatecollection;
            linestring.AltitudeMode = AltitudeMode.Absolute;

            SharpKml.Dom.LineStyle lineStyle = new SharpKml.Dom.LineStyle();
            lineStyle.Color = Color32.Parse("ff0000ff");
            lineStyle.Width = 5;
            Style flightStyle = new Style();

            flightStyle.Id     = "FlightStyle";
            flightStyle.Line   = lineStyle;
            linestring.Extrude = false;
            mainFolder.AddStyle(flightStyle);

            SharpKml.Dom.Style waypointStyle = new SharpKml.Dom.Style();
            waypointStyle.Id        = "WaypointStyle";
            waypointStyle.Icon      = new SharpKml.Dom.IconStyle();
            waypointStyle.Icon.Icon = new SharpKml.Dom.IconStyle.IconLink(new System.Uri("https://maps.google.com/mapfiles/kml/paddle/grn-square.png"));
            mainFolder.AddStyle(waypointStyle);

            SharpKml.Dom.Style pushpinblueStyle = new SharpKml.Dom.Style();
            pushpinblueStyle.Id        = "PushPinBlueStyle";
            pushpinblueStyle.Icon      = new SharpKml.Dom.IconStyle();
            pushpinblueStyle.Icon.Icon = new SharpKml.Dom.IconStyle.IconLink(new System.Uri("https://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png"));
            mainFolder.AddStyle(pushpinblueStyle);

            SharpKml.Dom.Style pushpingreenStyle = new SharpKml.Dom.Style();
            pushpingreenStyle.Id        = "PushPinGreenStyle";
            pushpingreenStyle.Icon      = new SharpKml.Dom.IconStyle();
            pushpingreenStyle.Icon.Icon = new SharpKml.Dom.IconStyle.IconLink(new System.Uri("https://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png"));
            mainFolder.AddStyle(pushpingreenStyle);

            placemarkLine.StyleUrl = new Uri("#FlightStyle", UriKind.Relative);

            List <FlightPathData> FlightPath = new List <FlightPathData>();

            FlightPath = FlightPathDB.GetFlightPathData(nFlightID);
            foreach (FlightPathData fpd in FlightPath)
            {
                coordinatecollection.Add(new Vector(fpd.latitude, fpd.longitude, fpd.altitude * 0.3048));
            }
            placemarkLine.Geometry = linestring;

            // start of Flight Plan Waypoints
            List <FlightWaypointData> FlightWaypoints = new List <FlightWaypointData>();

            FlightWaypoints = FlightPathDB.GetFlightWaypoints(nFlightID);
            if (FlightWaypoints.Count > 0)
            {
                Folder FlightPlanFolder = new Folder();

                FlightPlanFolder.Name        = "Flight Plan";
                FlightPlanFolder.Description = new Description
                {
                    Text = "Waypoints along the flight plan"
                };
                mainFolder.AddFeature(FlightPlanFolder);
                foreach (FlightWaypointData waypointData in FlightWaypoints)
                {
                    var placemarkPoint = new Placemark();

                    placemarkPoint.Name     = waypointData.gps_wp_name;
                    placemarkPoint.StyleUrl = new System.Uri("#WaypointStyle", UriKind.Relative);
                    placemarkPoint.Geometry = new SharpKml.Dom.Point
                    {
                        Coordinate   = new Vector(waypointData.gps_wp_latitude, waypointData.gps_wp_longitude, (double)waypointData.gps_wp_altitude * 0.3048),
                        AltitudeMode = AltitudeMode.Absolute
                    };
                    placemarkPoint.Description = new Description
                    {
                        Text = String.Concat(String.Format("Coordinates ({0:0.0000}, {1:0.0000}, {2} feet)", waypointData.gps_wp_longitude, waypointData.gps_wp_latitude, waypointData.gps_wp_altitude))
                    };
                    FlightPlanFolder.AddFeature(placemarkPoint);
                }
            }

            // start of Flight Data Points
            Folder DataPointsfolder = new Folder();

            DataPointsfolder.Name        = "Flight Path Data Points";
            DataPointsfolder.Visibility  = false;
            DataPointsfolder.Description = new Description
            {
                Text = "Data Points along the flight path"
            };
            mainFolder.AddFeature(DataPointsfolder);

            nCount = 0;
            foreach (FlightPathData fpd in FlightPath)
            {
                var    placemarkPoint = new Placemark();
                string descriptioncard;
                bool   bAnyLightsOn = false;

                nCount++;
                // if Google Earth App then you need to turn off visibility on each data point also
                if (GoogleEarthAppRB.Checked == true)
                {
                    placemarkPoint.Visibility = false;
                }
                placemarkPoint.Name = String.Concat("Flight Data Point ", nCount.ToString());
                placemarkPoint.Id   = nCount.ToString();
                descriptioncard     = String.Concat("<br>Timestamp = ", new DateTime(fpd.timestamp).ToString());

                descriptioncard += String.Concat(String.Format("<br><br>Coordinates ({0:0.0000}, {1:0.0000}, {2} feet)", fpd.latitude, fpd.longitude, fpd.altitude));
                descriptioncard += String.Format("<br>Temperature: {0:0.00}C / {1:0.00}F", fpd.ambient_temperature, fpd.ambient_temperature * 9 / 5 + 32);
                descriptioncard += String.Format("<br>Wind: {0:0.00} knts from {1:0.00} degrees", fpd.ambient_wind_velocity, fpd.ambient_wind_direction);
                descriptioncard += String.Format("<br>Altitude Above Ground: {0} feet", fpd.altitudeaboveground);
                if (fpd.sim_on_ground == 1)
                {
                    descriptioncard += String.Format("<br>Plane Is On The Ground");
                }

                descriptioncard += String.Format("<br><br>Heading Indicator: {0:0.00} degrees", fpd.heading_indicator);
                descriptioncard += String.Format("<br>True Heading: {0:0.00} degrees", fpd.plane_heading_true);
                descriptioncard += String.Format("<br>Magnetic Heading {0:0.00} degrees", fpd.plane_heading_magnetic);

                descriptioncard += string.Format("<br><br>Airspeed Indicated: {0:0.00 knts}", fpd.plane_airspeed_indicated);
                descriptioncard += string.Format("<br>Airspeed True: {0:0.00} knts", fpd.airspeed_true);
                descriptioncard += string.Format("<br>Ground Velocity: {0:0.00} knts", fpd.ground_velocity);
                descriptioncard += string.Format("<br>Engine 1: {0} RPM", fpd.Eng1Rpm);
                if (fpd.Eng2Rpm > 0)
                {
                    descriptioncard += string.Format("<br>Engine 2: {0} RPM", fpd.Eng2Rpm);
                }
                if (fpd.Eng3Rpm > 0)
                {
                    descriptioncard += string.Format("<br>Engine 3: {0} RPM", fpd.Eng3Rpm);
                }
                if (fpd.Eng4Rpm > 0)
                {
                    descriptioncard += string.Format("<br>Engine 4: {0} RPM", fpd.Eng4Rpm);
                }

                descriptioncard += string.Format("<br><br>Pitch: {0:0.00} degrees {1}", Math.Abs(fpd.plane_pitch), fpd.plane_pitch < 0 ? "Up" : "Down");
                descriptioncard += string.Format("<br>Bank: {0:0.00} degrees {1}", Math.Abs(fpd.plane_bank), fpd.plane_bank < 0 ? "Right" : "Left");
                descriptioncard += string.Format("<br>Vertical Speed: {0:0} feet per minute", fpd.vertical_speed);
                descriptioncard += string.Concat("<br>Flaps Position: ", fpd.flaps_handle_position);

                descriptioncard += string.Concat("<br><br>Lights On: ");

                // go thru mask and set lights that are on
                if ((fpd.LightsMask & (int)FlightPathData.LightStates.Nav) == (int)FlightPathData.LightStates.Nav)
                {
                    descriptioncard += string.Concat("Nav, ");
                    bAnyLightsOn     = true;
                }
                if ((fpd.LightsMask & (int)FlightPathData.LightStates.Beacon) == (int)FlightPathData.LightStates.Beacon)
                {
                    descriptioncard += string.Concat("Beacon, ");
                    bAnyLightsOn     = true;
                }
                if ((fpd.LightsMask & (int)FlightPathData.LightStates.Landing) == (int)FlightPathData.LightStates.Landing)
                {
                    descriptioncard += string.Concat("Landing, ");
                    bAnyLightsOn     = true;
                }
                if ((fpd.LightsMask & (int)FlightPathData.LightStates.Taxi) == (int)FlightPathData.LightStates.Taxi)
                {
                    descriptioncard += string.Concat("Taxi, ");
                    bAnyLightsOn     = true;
                }
                if ((fpd.LightsMask & (int)FlightPathData.LightStates.Strobe) == (int)FlightPathData.LightStates.Strobe)
                {
                    descriptioncard += string.Concat("Strobe, ");
                    bAnyLightsOn     = true;
                }
                if ((fpd.LightsMask & (int)FlightPathData.LightStates.Panel) == (int)FlightPathData.LightStates.Panel)
                {
                    descriptioncard += string.Concat("Panel, ");
                    bAnyLightsOn     = true;
                }
                // commented out the following lights because most planes don't use them and it messes up the GA aircraft

                /*                if ((fpd.LightsMask & (int)FlightPathData.LightStates.Recognition) == (int)FlightPathData.LightStates.Recognition)
                 *              {
                 *                  descriptioncard += string.Concat("Recognition, ");
                 *                  bAnyLightsOn = true;
                 *              }
                 *              if ((fpd.LightsMask & (int)FlightPathData.LightStates.Wing) == (int)FlightPathData.LightStates.Wing)
                 *              {
                 *                  descriptioncard += string.Concat("Wing, ");
                 *                  bAnyLightsOn = true;
                 *              }
                 *              if ((fpd.LightsMask & (int)FlightPathData.LightStates.Logo) == (int)FlightPathData.LightStates.Logo)
                 *              {
                 *                  descriptioncard += string.Concat("Logo, ");
                 *                  bAnyLightsOn = true;
                 *              }*/
                if ((fpd.LightsMask & (int)FlightPathData.LightStates.Cabin) == (int)FlightPathData.LightStates.Cabin)
                {
                    descriptioncard += string.Concat("Cabin, ");
                    bAnyLightsOn     = true;
                }

                // if there are no masks then put none else remove last two characters which are the comma and the space from above
                if (bAnyLightsOn == false)
                {
                    descriptioncard += string.Concat("None");
                }
                else
                {
                    descriptioncard = descriptioncard.Remove(descriptioncard.Length - 2, 2);
                }

                if (fpd.is_gear_retractable == 1)
                {
                    descriptioncard += String.Concat("<br>Gear Position: ", fpd.gear_handle_position == 1 ? "Down" : "Up");
                }
                if (fpd.spoiler_available == 1)
                {
                    descriptioncard += String.Concat("<br>Spoiler Position: ", fpd.spoilers_handle_position == 1 ? "On" : "Off");
                }
                if (fpd.stall_warning == 1)
                {
                    descriptioncard += "<br>Stall Warning";
                }
                if (fpd.overspeed_warning == 1)
                {
                    descriptioncard += "<br>Overspeed Warning";
                }

                placemarkPoint.Description = new Description
                {
                    Text = descriptioncard
                };

                // turned off showing time with data points as it caused issues of not showing in Google Earth
                // if user turned them off and then back on

                /*                placemarkPoint.Time = new SharpKml.Dom.Timestamp
                 *              {
                 *                  When = new DateTime(fpd.timestamp)
                 *              };*/
                if (fpd.sim_on_ground == 1)
                {
                    placemarkPoint.StyleUrl = new System.Uri("#PushPinGreenStyle", UriKind.Relative);
                }
                else
                {
                    placemarkPoint.StyleUrl = new System.Uri("#PushPinBlueStyle", UriKind.Relative);
                }

                placemarkPoint.Geometry = new SharpKml.Dom.Point
                {
                    Coordinate   = new Vector(fpd.latitude, fpd.longitude, (double)fpd.altitude * 0.3048),
                    AltitudeMode = AltitudeMode.Absolute
                };
                DataPointsfolder.AddFeature(placemarkPoint);
            }

            // add 1st person feature
            SharpKml.Dom.GX.Tour tour = new SharpKml.Dom.GX.Tour();
            tour.Name = "First Person View of Flight";
            kml.AddNamespacePrefix("gx", "http://www.google.com/kml/ext/2.2");
            SharpKml.Dom.GX.Playlist playlist = new SharpKml.Dom.GX.Playlist();
            tour.Playlist = playlist;
            mainFolder.AddFeature(tour);
            lprevTimestamp = 0;
            nCount         = 0;
            foreach (FlightPathData fpd in FlightPath)
            {
                nCount++;
                SharpKml.Dom.GX.FlyTo flyto = new SharpKml.Dom.GX.FlyTo();

                // assume duration will be based on difference between timestamps
                // if first time thru loop and don't have old time or user wants to speed up video playback above threshold
                // then set duration to 1 if it is greater than 1 else leave as-is
                flyto.Duration = (new DateTime(fpd.timestamp) - new DateTime(lprevTimestamp)).TotalMilliseconds / 1000;
                if ((lprevTimestamp == 0) ||
                    (SpeedUpVideoPlaybackCB.Checked == true))
                {
                    if (flyto.Duration > 1)
                    {
                        flyto.Duration = 1;
                    }
                }

                lprevTimestamp = fpd.timestamp;
                flyto.Mode     = SharpKml.Dom.GX.FlyToMode.Smooth;
                SharpKml.Dom.Camera cam = new SharpKml.Dom.Camera();
                cam.AltitudeMode = SharpKml.Dom.AltitudeMode.Absolute;
                cam.Latitude     = fpd.latitude;
                cam.Longitude    = fpd.longitude;
                cam.Altitude     = fpd.altitude * 0.3048;
                cam.Heading      = fpd.plane_heading_true;
                if (GoogleEarthAppRB.Checked == true)
                {
                    cam.Roll = fpd.plane_bank;
                }
                else
                {
                    cam.Roll = fpd.plane_bank * -1;
                }
                cam.Tilt = (90 - fpd.plane_pitch);

                SharpKml.Dom.Timestamp tstamp = new SharpKml.Dom.Timestamp();
                tstamp.When = new DateTime(fpd.timestamp);

                cam.GXTimePrimitive = tstamp;

                flyto.View = cam;
                playlist.AddTourPrimitive(flyto);

                // change it so balloons show during first person view (for potential future use)

                /*
                 * var placemarkPoint = new Placemark();
                 * placemarkPoint.TargetId = nCount.ToString();
                 * placemarkPoint.GXBalloonVisibility = true;
                 * SharpKml.Dom.Update update = new SharpKml.Dom.Update();
                 * update.AddUpdate(new ChangeCollection() { placemarkPoint });
                 * SharpKml.Dom.GX.AnimatedUpdate animatedUpdate = new SharpKml.Dom.GX.AnimatedUpdate();
                 * animatedUpdate.Update = update;
                 * playlist.AddTourPrimitive(animatedUpdate);*/
            }

            // write out KML file
            char[] invalidFileNameChars = Path.GetInvalidFileNameChars();
            sfilename = String.Format("{0}_{1}.kml", FlightPickerLV.SelectedItems[0].SubItems[1].Text, FlightPickerLV.SelectedItems[0].SubItems[0].Text);
            var validfilename = new string(sfilename.Select(ch => invalidFileNameChars.Contains(ch) ? '_' : ch).ToArray());

            sfilename  = string.Concat(KMLFilePathTBRO.Text, "\\");
            sfilename += validfilename;

            System.IO.File.Delete(sfilename);
            KmlFile kmlfile = KmlFile.Create(kml, true);

            using (var stream = System.IO.File.OpenWrite(sfilename))
            {
                kmlfile.Save(stream);
            }
            MessageBox.Show(String.Format("Flight successfully exported to {0}", sfilename), "Export KML File");
        }
Exemplo n.º 7
0
        public static string getKMLstring(Color lapColor,
                                          List <double> latitudes,
                                          List <double> longitudes,
                                          List <double> altitudes = null)
        {
            // make sure the parameters are of the same length
            if (((altitudes != null) && !(latitudes.Count == longitudes.Count && altitudes.Count == longitudes.Count)) ||
                !(latitudes.Count == longitudes.Count))
            {
                throw new Exception("The length of the parameters must match");
            }

            // Create the KML stuff
            Kml kml = new Kml();

            kml.AddNamespacePrefix("gx", "http://www.google.com/kml/ext/2.2");
            Document   doc   = new Document();
            Style      style = new Style();
            Placemark  pMark = new Placemark();
            LineString ls    = new LineString();

            ls.Coordinates = new CoordinateCollection();

            // Define the style
            style.Line       = new LineStyle();
            style.Id         = "redline";
            style.Line.Color = new Color32(lapColor.A, lapColor.B, lapColor.G, lapColor.R);
            //style.Line.ColorMode = ColorMode.Normal;
            style.Line.Width = 2;

            // Define a new style
            Style style2 = new Style();

            style2.Line       = new LineStyle();
            style2.Id         = "blueline";
            style2.Line.Color = new Color32(Colors.LightBlue.A, Colors.LightBlue.B, Colors.LightBlue.G, Colors.LightBlue.R);
            //style2.Line.ColorMode = ColorMode.Normal;
            style2.Line.Width = 2;

            // add style to placemark
            pMark.StyleUrl = new Uri("#redline", UriKind.Relative);

            // loop through the lines in the file
            if (altitudes != null)
            {
                ls.AltitudeMode = AltitudeMode.Absolute;
                for (int i = 0; i < latitudes.Count; i++)
                {
                    ls.Coordinates.Add(new Vector(latitudes[i], longitudes[i], altitudes[i]));
                }
            }
            else // no altitude provided
            {
                for (int i = 0; i < latitudes.Count; i++)
                {
                    ls.Coordinates.Add(new Vector(latitudes[i], longitudes[i]));
                }
            }

            // Set properties on the line string
            ls.Extrude    = false;
            ls.Tessellate = true;

            // Add the line string to the placemark
            pMark.Geometry = ls;

            // Generate a LookAt object to center the view on the placemark
            doc.Viewpoint = pMark.CalculateLookAt();

            // Add the placemark and style to the document
            doc.AddFeature(pMark);
            doc.AddStyle(style);
            doc.AddStyle(style2);

            // Add the document to the kml object
            kml.Feature = doc;

            // Create the KML file
            KmlFile kmlFile = KmlFile.Create(kml, false);

            //TODO for debugging purposes, save the kml file to test folder.
            kmlFile.Save("test.kml");

            // Return the KML file as a string
            return(kmlFile.SaveString());
        }