/// <summary> /// Parses Multi Polygons /// </summary> /// <param name="inNode">The node containing Polygons</param> /// <param name="layer">The layer to add the resulting Polygons to</param> private void ParseMultiGeometry(XmlNode inNode, RIcons layer) { // Parse all Placemarks that have a name and Polygon XmlNodeList placemarkNodes = inNode.SelectNodes("Placemark[name and MultiGeometry]"); Random rand = new Random((int)DateTime.Now.Ticks); foreach(XmlNode placemarkNode in placemarkNodes) { XmlNode nameNode = placemarkNode.SelectSingleNode("name"); string name = nameNode.InnerText; // change this to something that unifies the geometry into a single object instead of a user-accessible list RIcons multiGeometryList = new RIcons(name); Style style = null; // get StyleUrl XmlNode styleUrlNode = placemarkNode.SelectSingleNode("styleUrl"); if(styleUrlNode != null) { string styleUrlKey = styleUrlNode.InnerText.Trim(); if(styleUrlKey.StartsWith("#")) styleUrlKey = styleUrlKey.Substring(1, styleUrlKey.Length - 1); style = (Style)iconStyles[styleUrlKey]; } else { XmlNode styleNode = placemarkNode.SelectSingleNode("Style"); if(styleNode != null) style = GetStyle( styleNode, new Style(), ""); } if(style == null) style = new Style(); if(style.LineStyle == null) style.LineStyle = new LineStyle(); if(style.PolyStyle == null) style.PolyStyle = new PolyStyle(); XmlNodeList lineStringNodes = placemarkNode.SelectNodes("MultiGeometry/LineString"); foreach(XmlNode lineStringNode in lineStringNodes) { bool extrude = false; XmlNode extrudeNode = lineStringNode.SelectSingleNode("extrude"); if (extrudeNode != null) extrude = Convert.ToBoolean(Convert.ToInt16(extrudeNode.InnerText)); XmlNode coordinateNode = lineStringNode.SelectSingleNode("coordinates"); Point3d[] points = ParseCoordinates(coordinateNode); XmlNode altitudeModeNode = lineStringNode.SelectSingleNode("altitudeMode"); AltitudeMode altitudeMode = GetAltitudeMode(altitudeModeNode); if(points != null && points.Length > 0) { LineFeature line = new LineFeature( name, m_world, points, System.Drawing.Color.FromArgb(style.LineStyle.Color.Color) ); line.AltitudeMode = altitudeMode; if(style.PolyStyle.Color != null) line.PolygonColor = System.Drawing.Color.FromArgb(style.PolyStyle.Color.Color); line.LineWidth = (float)style.LineStyle.Width.Value; line.Extrude = extrude; multiGeometryList.Add(line); } } XmlNodeList polygonNodes = placemarkNode.SelectNodes("MultiGeometry/Polygon"); foreach(XmlNode polygonNode in polygonNodes) { bool extrude = false; XmlNode extrudeNode = polygonNode.SelectSingleNode("extrude"); if (extrudeNode != null) extrude = Convert.ToBoolean(Convert.ToInt16(extrudeNode.InnerText)); XmlNode altitudeModeNode = polygonNode.SelectSingleNode("altitudeMode"); AltitudeMode altitudeMode = GetAltitudeMode(altitudeModeNode); LinearRing outerRing = null; LinearRing[] innerRings = null; // Parse Outer Ring XmlNode outerRingNode = polygonNode.SelectSingleNode("outerBoundaryIs/LinearRing/coordinates"); if (outerRingNode != null) { Point3d[] points = ParseCoordinates(outerRingNode); outerRing = new LinearRing(); outerRing.Points = points; } // Parse Inner Ring XmlNodeList innerRingNodes = polygonNode.SelectNodes("innerBoundaryIs"); if (innerRingNodes != null) { innerRings = new LinearRing[innerRingNodes.Count]; for(int i = 0; i < innerRingNodes.Count; i++) { Point3d[] points = ParseCoordinates(innerRingNodes[i]); innerRings[i] = new LinearRing(); innerRings[i].Points = points; } } if(outerRing != null) { PolygonFeature polygonFeature = new PolygonFeature( name, m_world, outerRing, innerRings, (style.PolyStyle.Color != null ? System.Drawing.Color.FromArgb(style.PolyStyle.Color.Color) : System.Drawing.Color.Yellow) ); polygonFeature.Extrude = extrude; polygonFeature.AltitudeMode = altitudeMode; polygonFeature.Outline = style.PolyStyle.Outline; if(style.LineStyle.Color != null) polygonFeature.OutlineColor = System.Drawing.Color.FromArgb(style.LineStyle.Color.Color); multiGeometryList.Add(polygonFeature); } } XmlNode visibilityNode = placemarkNode.SelectSingleNode("visibility"); if(visibilityNode != null) multiGeometryList.IsOn = (visibilityNode.InnerText == "1" ? true : false); layer.Add(multiGeometryList); } }
/// <summary> /// This Method parses screen overlays and adds to renderables /// using ScreenOverlay Object /// </summary> /// <param name="inNode">The node containing the Screen Overlay</param> /// <param name="layer">The layer to add the resulting Screen Overlay to</param> private void ParseScreenOverlays(XmlNode inNode, RIcons layer) { XmlNodeList screenOverlays = inNode.SelectNodes("ScreenOverlay"); if(screenOverlays!=null) { foreach(XmlNode screenOverlayNode in screenOverlays) { XmlNode nameNode = screenOverlayNode.SelectSingleNode("name"); String name = ""; if(nameNode != null) name = nameNode.InnerText; XmlNode uriNode = screenOverlayNode.SelectSingleNode("Icon/href"); String uri = "http://www.apogee.com.au/logo_topleft.gif"; if (uriNode != null) { uri = uriNode.InnerText; } float posX = 0; float posY = 0; ScreenUnits posXUnits = ScreenUnits.Pixels; ScreenUnits posYUnits = ScreenUnits.Pixels; XmlNode positionNode = screenOverlayNode.SelectSingleNode("screenXY"); if (positionNode != null) { if (positionNode.Attributes["x"] != null) { posX = float.Parse(positionNode.Attributes["x"].InnerText, CultureInfo.InvariantCulture); if (positionNode.Attributes["xunits"].InnerText.ToLower() == "fraction") { posXUnits = ScreenUnits.Fraction; } } if (positionNode.Attributes["y"] != null) { posY = float.Parse(positionNode.Attributes["y"].InnerText, CultureInfo.InvariantCulture); if (positionNode.Attributes["yunits"].InnerText.ToLower() == "fraction") { posYUnits = ScreenUnits.Fraction; } } } ScreenOverlay scoverlay = new ScreenOverlay(name, posX, posY, uri); scoverlay.PositionXUnits = posXUnits; scoverlay.PositionYUnits = posYUnits; scoverlay.ShowHeader = false; XmlNode sizeNode = screenOverlayNode.SelectSingleNode("size"); if (sizeNode != null) { if (sizeNode.Attributes["x"] != null) { scoverlay.Width = float.Parse(sizeNode.Attributes["x"].InnerText, CultureInfo.InvariantCulture); if(sizeNode.Attributes["xunits"].InnerText.ToLower() == "fraction") { scoverlay.SizeXUnits = ScreenUnits.Fraction; } } if (sizeNode.Attributes["y"] != null) { scoverlay.Height = float.Parse(sizeNode.Attributes["y"].InnerText, CultureInfo.InvariantCulture); if (sizeNode.Attributes["yunits"].InnerText.ToLower() == "fraction") { scoverlay.SizeYUnits = ScreenUnits.Fraction; } } } layer.Add(scoverlay); } } }
/// <summary> /// Parses LineStrings /// </summary> /// <param name="inNode">The node containing LineStrings</param> /// <param name="layer">The layer to add the resulting lines to</param> /// <param name="KmlPath">The path to the KML file that is being loaded</param> private void ParseLineStrings(XmlNode inNode, RIcons layer) { // Parse all Placemarks that have a name and LineString XmlNodeList lineStrings = inNode.SelectNodes("Placemark[name and LineString]"); foreach (XmlNode node in lineStrings) { // Extract the name from this node XmlNode nameNode = node.SelectSingleNode("name"); string name = nameNode.InnerText; Style style = null; // get StyleUrl XmlNode styleUrlNode = node.SelectSingleNode("styleUrl"); if(styleUrlNode != null) { string styleUrlKey = styleUrlNode.InnerText.Trim(); if(styleUrlKey.StartsWith("#")) styleUrlKey = styleUrlKey.Substring(1, styleUrlKey.Length - 1); style = (Style)iconStyles[styleUrlKey]; } else { XmlNode styleNode = node.SelectSingleNode("Style"); if(styleNode != null) style = GetStyle( styleNode, new Style(), ""); } if(style == null) style = new Style(); if(style.LineStyle == null) style.LineStyle = new LineStyle(); if(style.PolyStyle == null) style.PolyStyle = new PolyStyle(); // See if this LineString has to be extruded to the ground bool extrude = false; XmlNode extrudeNode = node.SelectSingleNode("LineString/extrude"); if (extrudeNode != null) extrude = Convert.ToBoolean(Convert.ToInt16(extrudeNode.InnerText)); //Parse Coordinates XmlNode outerRingNode = node.SelectSingleNode("LineString/coordinates"); if(outerRingNode != null) { // Parse the list of line coordinates Point3d[] points = ParseCoordinates(outerRingNode); LineFeature line = new LineFeature(name, m_world, points, System.Drawing.Color.FromArgb(style.LineStyle.Color.Color)); XmlNode altitudeModeNode = node.SelectSingleNode("LineString/altitudeMode"); line.AltitudeMode = GetAltitudeMode(altitudeModeNode); line.LineWidth = (float)style.LineStyle.Width.Value; if (extrude) { line.Extrude = true; if(style.PolyStyle.Color != null) { line.PolygonColor = System.Drawing.Color.FromArgb(style.PolyStyle.Color.Color); } } XmlNode visibilityNode = node.SelectSingleNode("visibility"); if(visibilityNode != null) line.IsOn = (visibilityNode.InnerText == "1" ? true : false); layer.Add(line); } } }
/// <summary> /// Loads this plugin. Initializes variables and adds layers and menu items /// </summary> public override void Load() { // Load settings Settings.LoadSettings(Path.Combine(KmlDirectory, "KMLImporter.xml")); // Initialize the main Icons layer KMLIcons = new RIcons("KML Icons"); KMLIcons.IsOn = false; // Setup Drag&Drop functionality m_Application.WorldWindow.DragEnter += new DragEventHandler(WorldWindow_DragEnter); m_Application.WorldWindow.DragDrop += new DragEventHandler(WorldWindow_DragDrop); // Add a menu item to the File menu and the Help menu MenuItem loadMenuItem = new MenuItem(); loadMenuItem.Text = "Import KML/KMZ file..."; loadMenuItem.Click += new EventHandler(loadMenu_Click); aboutMenuItem.Text = "About KMLImporter"; aboutMenuItem.Click += new EventHandler(aboutMenu_Click); int mergeOrder = 0; foreach (MenuItem menuItem in m_Application.MainMenu.MenuItems) { if (menuItem.Text.Replace("&", "") == "File") { foreach (MenuItem subMenuItem in menuItem.MenuItems) { subMenuItem.MergeOrder = mergeOrder; if (subMenuItem.Text == "-") mergeOrder = 2; // Everything after this should come after our new items } tempMenu.Text = menuItem.Text; tempMenu.MergeOrder = 1; // MergeOrder 1 will have 0 before it and 2 after it tempMenu.MenuItems.Add(loadMenuItem); tempMenu.MenuItems.Add(new MenuItem("-")); menuItem.MergeMenu(tempMenu); } if (menuItem.Text.Replace("&", "") == "Help") menuItem.MenuItems.Add(aboutMenuItem); } // Napalm enable/disable menu item bool bEnabled = Napalm.NapalmIsEnabled(KmlDirectory); if (bEnabled) napalmMenuItem.Text = "Disable KMLImporter autoupdate"; else napalmMenuItem.Text = "Enable KMLImporter autoupdate"; napalmMenuItem.Click += new EventHandler(napalmMenu_Click); pluginMenuItem.MenuItems.Add(napalmMenuItem); // Allways show labels enable/disable menu item labelMenuItem.Text = "Show all labels"; labelMenuItem.Checked = Settings.ShowAllLabels; labelMenuItem.Click += new EventHandler(labelMenuItem_Click); pluginMenuItem.MenuItems.Add(labelMenuItem); // Add a menu item to the Plugins menu pluginMenuItem.Text = "KMLImporter"; m_Application.PluginsMenu.MenuItems.Add(pluginMenuItem); // Some magic to provide backward compability Type typecontroller = typeof(MainApplication); System.Reflection.PropertyInfo finfo = typecontroller.GetProperty("CmdArgs", BindingFlags.Static|BindingFlags.Public|BindingFlags.GetProperty); string[] temp = null; if(finfo != null) { temp = (string[])finfo.GetValue(null, null); // If command line arguments are available, try to find one pointing to a kml/kmz file if (temp != null) { foreach (string arg in temp) { if (!File.Exists(arg)) continue; string fExt = Path.GetExtension(arg); if (fExt != ".kml" && fExt != ".kmz") continue; LoadDiskKM(arg); break; } } } // Add the main Icons layer to the globe m_Application.WorldWindow.CurrentWorld.RenderableObjects.Add(KMLIcons); //Set the currentworld m_world = m_Application.WorldWindow.CurrentWorld; base.Load(); }
/// <summary> /// Parse Ground Overlays /// </summary> /// <param name="inNode">The node containing Ground Overlays</param> /// <param name="layer">The layer to add the resulting Ground Overlays to</param> private void ParseGroundOverlays(XmlNode inNode, RIcons layer) { // Parse all Placemarks that have a name and LineString XmlNodeList groundOverlays = inNode.SelectNodes("GroundOverlay[name and LatLonBox]"); foreach (XmlNode node in groundOverlays) { // Extract the name from this node XmlNode nameNode = node.SelectSingleNode("name"); string name = nameNode.InnerText; XmlNode latLonBoxNode = node.SelectSingleNode("LatLonBox"); //Parse Coordinates if(latLonBoxNode != null) { XmlNode northNode = latLonBoxNode.SelectSingleNode("north"); XmlNode southNode = latLonBoxNode.SelectSingleNode("south"); XmlNode westNode = latLonBoxNode.SelectSingleNode("west"); XmlNode eastNode = latLonBoxNode.SelectSingleNode("east"); double north = ConfigurationLoader.ParseDouble(northNode.InnerText); double south = ConfigurationLoader.ParseDouble(southNode.InnerText); double west = ConfigurationLoader.ParseDouble(westNode.InnerText); double east = ConfigurationLoader.ParseDouble(eastNode.InnerText); // Create GroundOverlay WorldWind.Renderable.ImageLayer imageLayer = new ImageLayer( name, ParentApplication.WorldWindow.CurrentWorld, 0, null, south, north, west, east, 1.0, ParentApplication.WorldWindow.CurrentWorld.TerrainAccessor ); imageLayer.DisableZBuffer = true; imageLayer.ImageUrl = node.SelectSingleNode("Icon/href").InnerText; XmlNode visibilityNode = node.SelectSingleNode("visibility"); if(visibilityNode != null) imageLayer.IsOn = (visibilityNode.InnerText == "1" ? true : false); layer.Add(imageLayer); } } }
/// <summary> /// Parse NetworkLinks /// </summary> /// <param name="inNode">The XmlNode to load NetworkLinks from</param> /// <param name="layer">The layer to add NetworkLinks to</param> private void ParseNetworkLinks(XmlNode inNode, RIcons layer) { // Find NetworkLinks, initialize them and download them for the first time XmlNodeList networklinks = inNode.SelectNodes("NetworkLink"); foreach (XmlNode node in networklinks) { try { // Find out the name for this NetworkLink string nlName = "NetworkLink"; XmlNode nameNode = node.SelectSingleNode("name"); if (nameNode != null) nlName = nameNode.InnerText; // See if a folder for this NetworkLink already exists RIcons folder = null; foreach (RenderableObject ro in layer.ChildObjects) { RIcons ricons = ro as RIcons; if ((ricons != null) && (ro.Name == nlName)) { folder = ricons; } } // Create a new folder if none is available if (folder == null) { folder = new RIcons(nlName); layer.Add(folder); } XmlNode visibilityNode = node.SelectSingleNode("visibility"); if(visibilityNode != null) folder.IsOn = (visibilityNode.InnerText == "1" ? true : false); // Find the URL to download the file from string loadFile = null; XmlNode hrefNode = node.SelectSingleNode("Url/href"); if ((hrefNode != null) && (hrefNode.InnerText.Length > 0)) loadFile = hrefNode.InnerText; // Give up if no URL can be found if (loadFile == null) continue; int tickSeconds = -1; int viewSeconds = -1; bool fired = false; if (node.SelectSingleNode("Url/refreshMode") != null) { if (node.SelectSingleNode("Url/refreshMode").InnerText == "onInterval") { string refreshText = node.SelectSingleNode("Url/refreshInterval").InnerText; tickSeconds = Convert.ToInt32(refreshText, CultureInfo.InvariantCulture); } if (node.SelectSingleNode("Url/refreshMode").InnerText == "once") { NetworkLink netLink = new NetworkLink(this, folder, loadFile, -1, -1); netLink.Fire(); netLink.Dispose(); fired = true; } } if ((node.SelectSingleNode("Url/viewRefreshMode") != null) && (node.SelectSingleNode("Url/viewRefreshMode").InnerText == "onStop")) { string refreshText = node.SelectSingleNode("Url/viewRefreshTime").InnerText; viewSeconds = Convert.ToInt32(refreshText, CultureInfo.InvariantCulture); } // Initialize the actual NetworkLink object to handle updates for us if (tickSeconds != -1 || viewSeconds != -1) { NetworkLink netLink = new NetworkLink(this, folder, loadFile, tickSeconds*1000, viewSeconds*1000); netLink.Fire(); networkLinks.Add(netLink); } else if(!fired) { NetworkLink netLink = new NetworkLink(this, folder, loadFile, -1, -1); netLink.Fire(); netLink.Dispose(); } } catch (Exception ex) { Log.Write(Log.Levels.Error, "KMLImporter: " + ex.ToString()); } } }
/// <summary> /// Parses Placemarks /// </summary> /// <param name="inNode">The node containing Placemarks</param> /// <param name="layer">The layer to add the resulting icons or folders to</param> /// <param name="KmlPath">The path to the KML file that is being loaded</param> private void ParsePlacemarks(XmlNode inNode, RIcons layer, string KmlPath) { foreach (WorldWind.Renderable.RenderableObject ro in layer.ChildObjects) { RIcon ricon = ro as RIcon; if (ricon != null) ricon.HasBeenUpdated = false; } // Parse all Placemarks that have a name and location XmlNodeList placemarks = inNode.SelectNodes("Placemark[name and Point]"); foreach (XmlNode node in placemarks) { try { string name = node.SelectSingleNode("name").InnerText; RIcon update = null; // Extract the location string for this Placemark node and split it up string loc = node.SelectSingleNode("Point/coordinates").InnerText.Trim(); LLA lla = ParseCoordinate(loc); string desc = null; string uri = null; // Extract a description and make sure it's not too long XmlNode xnode = node.SelectSingleNode("description"); if (xnode != null) { string descRaw = xnode.InnerText; uri = SearchUri(descRaw); // Ashish Datta - commented so that the HTML stays in the description property. desc = descRaw; if (desc.Length > 505) desc = desc.Substring(0, 500) + "..."; } float rotation = 0; bool bRotated = false; string rotRaw = null; // Locate a node containing rotation XmlNode rotNode1 = node.SelectSingleNode("Point/rotation"); if (rotNode1 != null) rotRaw = rotNode1.InnerText; else { XmlNode rotNode2 = node.SelectSingleNode("IconStyle/heading"); if (rotNode2 != null) rotRaw = rotNode2.InnerText; else { XmlNode rotNode3 = node.SelectSingleNode("Style/IconStyle/heading"); if (rotNode3 != null) rotRaw = rotNode3.InnerText; } } // If rotation was found parse it if (rotRaw != null) { rotation = Convert.ToSingle(rotRaw, CultureInfo.InvariantCulture); bRotated = true; } // Find a style for this icon Style style = LocateStyle(node, KmlPath); // Check if this icon has to be extruded bool bExtrude = false; XmlNode extrudeNode = node.SelectSingleNode("Point/extrude"); if (extrudeNode != null) { if (extrudeNode.InnerText == "1") bExtrude = true; } // See if this icon already exists, and store it if it does foreach (WorldWind.Renderable.RenderableObject ro in layer.ChildObjects) { RIcon ricon = ro as RIcon; if (ricon != null) { if ((ro.Name == name) && ((style == null) || ((ricon.NormalIcon == style.NormalIcon) && (!ricon.HasBeenUpdated)))) { update = ricon; update.HasBeenUpdated = true; break; } } } // If a previous icons has been found update it's location if (update != null) { update.IsRotated = bRotated; if (bRotated) { update.Rotation = Angle.FromDegrees(rotation); } if (style != null) { update.Height = Double.IsNaN(style.NormalScale) ? IconSizeConstant : (int)(style.NormalScale * Math.Min(((Bitmap)bitmapCache[style.NormalIcon]).Height, IconSizeConstant)); update.Width = Double.IsNaN(style.NormalScale) ? IconSizeConstant : (int)(style.NormalScale * Math.Min(((Bitmap)bitmapCache[style.NormalIcon]).Width, IconSizeConstant)); update.Description = desc; update.SetPosition(lla.lat, lla.lon, lla.alt); } } else { // Create the icon with either the generated bitmap or the default dot if (style != null) { CreateIcon(layer, name, desc, uri, lla.lat, lla.lon, lla.alt, style, bRotated, rotation, bExtrude); } else { // Use the default 'tack' icon if no style was found string pal3Path = Path.Combine(KmlDirectory, "icons/palette-3.png"); if (File.Exists(pal3Path)) { if (!bitmapCache.Contains(pal3Path)) bitmapCache.Add(pal3Path, (Bitmap)Bitmap.FromFile(pal3Path)); Style pinStyle = new Style(GetSubImage(new Style(pal3Path), 448, 64, 64, 64)); CreateIcon(layer, name, desc, uri, lla.lat, lla.lon, lla.alt, pinStyle, bRotated, rotation, bExtrude); } } } } catch (Exception ex) { Log.Write(Log.Levels.Error, "KMLImporter: " + ex.ToString()); } } // Cleanup icons that have not been updated RemoveUnusedIcons(layer); }
/// <summary> /// Parses everything that is not a style /// </summary> /// <param name="inNode">The node containing renderables</param> /// <param name="layer">The layer to add the resulting renderables to</param> /// <param name="KmlPath">The path to the KML file that is being loaded</param> private void ParseRenderables(XmlNode inNode, RIcons layer, string KmlPath) { // Extract and set layer visibility for the current layer XmlNode visible = inNode.SelectSingleNode("visibility"); if (visible != null) { if (visible.InnerText == "0") layer.IsOn = false; } // Parse all Folders ParseFolders(inNode, layer, KmlPath); // Parse NetworkLinks ParseNetworkLinks(inNode, layer); // Parse GroundOverlays ParseGroundOverlays(inNode, layer); //Parse ScreenOverlays ParseScreenOverlays(inNode, layer); // Parse Placemarks ParsePlacemarks(inNode, layer, KmlPath); // Parse LineStrings ParseLineStrings(inNode, layer); // Parse Polygons ParsePolygons(inNode, layer); // Parse MultiGeometry ParseMultiGeometry(inNode, layer); // Update metadata for this layer layer.MetaData["Child count"] = layer.ChildObjects.Count; }
/// <summary> /// Locates Folders and parses them recursively /// </summary> /// <param name="inNode">The XmlNode to extract the Folders from</param> /// <param name="layer">The layer to add the folders to</param> /// <param name="KmlPath">The path to the KML file that is being loaded</param> private void ParseFolders(XmlNode inNode, RIcons layer, string KmlPath) { // Find Folders and initialize them recursively XmlNodeList folders = inNode.SelectNodes("Folder"); foreach (XmlNode node in folders) { try { // Find the name of the folder string foldername = "Folder"; XmlNode nameNode = node.SelectSingleNode("name"); if (nameNode != null) foldername = nameNode.InnerText; // See if the folder already exists RIcons folder = null; foreach (RenderableObject ro in layer.ChildObjects) { RIcons ricons = ro as RIcons; if ((ricons != null) && (ro.Name == foldername)) { folder = ricons; } } // Create a new folder if it doesn't exist yet if (folder == null) { folder = new RIcons(foldername); layer.Add(folder); } XmlNode visibilityNode = node.SelectSingleNode("visibility"); if(visibilityNode != null) layer.IsOn = (visibilityNode.InnerText == "1" ? true : false); // Parse placemarks into the folder ParseRenderables(node, folder, KmlPath); } catch (Exception ex) { Log.Write(Log.Levels.Error, "KMLImporter: " + ex.ToString()); } } }
/// <summary> /// Load given KML data /// </summary> /// <param name="kml">The KML data to load</param> internal void LoadKML(string kml, RIcons layer) { kml = kml.Replace("xmlns=\"http://earth.google.com/kml/2.0\"", ""); // HACK kml = kml.Replace("xmlns='http://earth.google.com/kml/2.0'", ""); // DOUBLE HACK kml = kml.Replace("xmlns=\"http://earth.google.com/kml/2.1\"", ""); // MULTI HACK! kml = kml.Replace("xmlns='http://earth.google.com/kml/2.1'", ""); // M-M-M-M-M-M-M-MONSTER HACK!!!! // Open the downloaded xml in an XmlDocument to allow for XPath searching XmlDocument doc = new XmlDocument(); doc.LoadXml(kml); // Try to find some sort of name for this kml from various places XmlNode node = doc.SelectSingleNode("//Document[name]/name"); if(layer.Name == null || layer.Name.Length == 0 || layer.Name.Equals("KML Icons")) { if (node != null) layer.Name = node.InnerText; } // Parse Style and StyleMap nodes and store them ParseStyles(doc, KMLPath); // Load Placemarks recursively and put them in folders XmlNode inNode = doc.SelectSingleNode("/kml/Document"); if (inNode == null) inNode = doc.SelectSingleNode("/kml"); /// if(inNode == null) // inNode = doc.SelectSingleNode("/Document"); if(inNode != null) ParseRenderables(inNode, layer, KMLPath); }
/// <summary> /// Creates and initializes a new NetworkLink /// </summary> /// <param name="owner">The owner of this NetworkLink</param> /// <param name="layer">The layer to update the NetworkLink to</param> /// <param name="url">The URL to update the NetworkLink from</param> /// <param name="tickTime">The interval, in milliseconds, at which the NetworkLink should update</param> /// <param name="viewTime">The time, in milliseconds, after the view stops moving which the NetworkLink should update</param> internal NetworkLink(KMLImporter owner, RIcons layer, string url, int tickTime, int viewTime) { this.owner = owner; this.url = url; this.layer = layer; if (tickTime > 0) { tickTimer.Interval = (double)tickTime; tickTimer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); tickTimer.Start(); } if (viewTime > 0) { viewTimer.Interval = (double)viewTime; viewTimer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); viewTimer.Start(); } }
/// <summary> /// Removes unused icons from a given layer /// </summary> /// <param name="layer">The layer to remove icons from</param> private static void RemoveUnusedIcons(RIcons layer) { // Stores removed icons ArrayList VFD = new ArrayList(); // Search for removed icons foreach (WorldWind.Renderable.RenderableObject ro in layer.ChildObjects) { RIcon ricon = ro as RIcon; if ((ricon != null) && (!ricon.HasBeenUpdated)) { VFD.Add(ro); } } // Remove all icons that were found to be removed foreach (WorldWind.Renderable.RenderableObject ro in VFD) { layer.Remove(ro); ro.Dispose(); } }
/// <summary> /// Creates a scaled icon on the globe /// </summary> /// <param name="Name">The name of the item</param> /// <param name="Desc">The description</param> /// <param name="Lat">The latitude for the icon</param> /// <param name="Lon">The longitude for the icon</param> /// <param name="Alt">The altitude to draw the icon at</param> /// <param name="bitmapPath">The path to the bitmap to show</param> private void CreateIcon(RIcons layer, string Name, string Desc, string Uri, float Lat, float Lon, float Alt, Style style, bool bRotated, float rotation, bool bExtrude) { // Create the icon and set initial settings RIcon ic = new RIcon( Name, // name Lat, // latitude Lon, // longitude style.NormalIcon, // helper Alt); // altitude // Set optional icon settings if (Desc != null) ic.Description = Desc; if (Uri != null) ic.ClickableActionURL = Uri; if (bRotated) { ic.Rotation = Angle.FromDegrees(rotation); ic.IsRotated = true; } ic.m_drawGroundStick = bExtrude; if (style.NormalIcon != null && bitmapCache.Contains(style.NormalIcon)) { ic.Image = (Bitmap)bitmapCache[style.NormalIcon]; ic.Height = Double.IsNaN(style.NormalScale) ? IconSizeConstant : (int)(style.NormalScale * Math.Min(((Bitmap)bitmapCache[style.NormalIcon]).Height, IconSizeConstant)); ic.Width = Double.IsNaN(style.NormalScale) ? IconSizeConstant : (int)(style.NormalScale * Math.Min(((Bitmap)bitmapCache[style.NormalIcon]).Width, IconSizeConstant)); } // Add the icon to the layer layer.Add(ic); }
/// <summary> /// Parses Polygons /// </summary> /// <param name="inNode">The node containing Polygons</param> /// <param name="layer">The layer to add the resulting Polygons to</param> private void ParsePolygons(XmlNode inNode, RIcons layer) { // Parse all Placemarks that have a name and Polygon XmlNodeList polygons = inNode.SelectNodes("Placemark[name and Polygon]"); Random rand = new Random((int)DateTime.Now.Ticks); foreach (XmlNode node in polygons) { // Extract the name from this node XmlNode nameNode = node.SelectSingleNode("name"); string name = nameNode.InnerText; Style style = null; // get StyleUrl XmlNode styleUrlNode = node.SelectSingleNode("styleUrl"); if(styleUrlNode != null) { string styleUrlKey = styleUrlNode.InnerText.Trim(); if(styleUrlKey.StartsWith("#")) styleUrlKey = styleUrlKey.Substring(1, styleUrlKey.Length - 1); style = (Style)iconStyles[styleUrlKey]; } else { XmlNode styleNode = node.SelectSingleNode("Style"); if(styleNode != null) style = GetStyle( styleNode, new Style(), ""); } if(style == null) style = new Style(); if(style.LineStyle == null) style.LineStyle = new LineStyle(); if(style.PolyStyle == null) style.PolyStyle = new PolyStyle(); // See if this LineString has to be extruded to the ground bool extrude = false; XmlNode extrudeNode = node.SelectSingleNode("Polygon/extrude"); if (extrudeNode != null) extrude = Convert.ToBoolean(Convert.ToInt16(extrudeNode.InnerText)); XmlNode altitudeModeNode = node.SelectSingleNode("Polygon/altitudeMode"); AltitudeMode altitudeMode = GetAltitudeMode(altitudeModeNode); LinearRing outerRing = null; LinearRing[] innerRings = null; // Parse Outer Ring XmlNode outerRingNode = node.SelectSingleNode("Polygon/outerBoundaryIs/LinearRing/coordinates"); if (outerRingNode != null) { Point3d[] points = ParseCoordinates(outerRingNode); Console.WriteLine(points.Length); outerRing = new LinearRing(); outerRing.Points = points; } // Parse Inner Ring XmlNodeList innerRingNodes = node.SelectNodes("Polygon/innerBoundaryIs"); if (innerRingNodes != null) { innerRings = new LinearRing[innerRingNodes.Count]; for(int i = 0; i < innerRingNodes.Count; i++) { Point3d[] points = ParseCoordinates(innerRingNodes[i]); innerRings[i] = new LinearRing(); innerRings[i].Points = points; } } if(outerRing != null) { PolygonFeature polygonFeature = new PolygonFeature( name, m_world, outerRing, innerRings, System.Drawing.Color.FromArgb(style.PolyStyle.Color.Color)); polygonFeature.Extrude = extrude; polygonFeature.AltitudeMode = altitudeMode; polygonFeature.Outline = style.PolyStyle.Outline; if(style.LineStyle.Color != null) polygonFeature.OutlineColor = System.Drawing.Color.FromArgb(style.LineStyle.Color.Color); XmlNode visibilityNode = node.SelectSingleNode("visibility"); if(visibilityNode != null) polygonFeature.IsOn = (visibilityNode.InnerText == "1" ? true : false); layer.Add(polygonFeature); } } }