ConfigurationLoader主要负责WW中各个图层的加载。
首先看看安装目录Config文件夹下Earth.xml文件
1 <?xml version="1.0" encoding="UTF-8"?> 2 <World Name="Earth" EquatorialRadius="6378137.0" LayerDirectory="Earth" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="WorldXmlDescriptor.xsd"> 3 <TerrainAccessor Name="SRTM"> 4 <TerrainTileService> 5 <ServerUrl>http://worldwind25.arc.nasa.gov/wwelevation/wwelevation.aspx</ServerUrl> 6 <DataSetName>srtm30pluszip</DataSetName> 7 <LevelZeroTileSizeDegrees>20.0</LevelZeroTileSizeDegrees> 8 <NumberLevels>12</NumberLevels> 9 <SamplesPerTile>150</SamplesPerTile> 10 <DataFormat>Int16</DataFormat> 11 <FileExtension>bil</FileExtension> 12 <CompressonType>zip</CompressonType> 13 </TerrainTileService> 14 <LatLonBoundingBox> 15 <North> 16 <Value>90.0</Value> 17 </North> 18 <South> 19 <Value>-90.0</Value> 20 </South> 21 <West> 22 <Value>-180.0</Value> 23 </West> 24 <East> 25 <Value>180.0</Value> 26 </East> 27 </LatLonBoundingBox> 28 </TerrainAccessor> 29 </World>
MainApplication构造函数中截取了如下代码:
1 foreach (FileInfo worldXmlDescriptorFile in worldXmlDescriptorFiles) 2 { 3 try 4 { 5 Log.Write(Log.Levels.Debug+1, "CONF", "checking world " + worldXmlDescriptorFile.FullName + " ..."); 6 World w = WorldWind.ConfigurationLoader.Load(worldXmlDescriptorFile.FullName, worldWindow.Cache); 7 if(!availableWorldList.Contains(w.Name)) 8 this.availableWorldList.Add(w.Name, worldXmlDescriptorFile.FullName); 9 10 w.Dispose(); 11 System.Windows.Forms.MenuItem mi = new System.Windows.Forms.MenuItem(w.Name, new System.EventHandler(OnWorldChange)); 12 menuItemFile.MenuItems.Add(worldIndex, mi); 13 worldIndex++; 14 } 15 catch( Exception caught ) 16 { 17 splashScreen.SetError( worldXmlDescriptorFile + ": " + caught.Message ); 18 Log.Write(caught); 19 } 20 } 21 22 Log.Write(Log.Levels.Debug, "CONF", "loading startup world..."); 23 OpenStartupWorld();
首先验证世界是否存在列表中,接着就释放了w。
OpenStartupWorld()方法体最后调用了OpenWorld( curWorldFile );
1 /// <summary> 2 /// Loads a new planet 3 /// </summary> 4 private void OpenWorld(string worldXmlFile) 5 { 6 7 if(this.worldWindow.CurrentWorld != null) 8 { 9 try 10 { 11 this.worldWindow.ResetToolbar(); 12 } 13 catch 14 {} 15 16 try 17 { 18 foreach(PluginInfo p in this.compiler.Plugins) 19 { 20 try 21 { 22 if(p.Plugin.IsLoaded) 23 p.Plugin.Unload(); 24 } 25 catch 26 {} 27 } 28 } 29 catch 30 {} 31 32 try 33 { 34 this.worldWindow.CurrentWorld.Dispose(); 35 } 36 catch 37 {} 38 39 } 40 41 42 if(this.gotoDialog != null) 43 { 44 this.gotoDialog.Dispose(); 45 this.gotoDialog = null; 46 } 47 48 if(this.rapidFireModisManager != null) 49 { 50 this.rapidFireModisManager.Dispose(); 51 this.rapidFireModisManager = null; 52 } 53 54 if(this.animatedEarthMananger != null) 55 { 56 this.animatedEarthMananger.Dispose(); 57 this.animatedEarthMananger = null; 58 } 59 60 if(this.wmsBrowser != null) 61 { 62 this.wmsBrowser.Dispose(); 63 this.wmsBrowser = null; 64 } 65 66 //currentWorld = world; 67 68 // TerrainAccessor terrainAccessor = null; 69 // if(worldDescriptor.HasTerrainAccessor()) 70 // terrainAccessor = this.getTerrainAccessorFromXML(worldDescriptor.TerrainAccessor); 71 72 worldWindow.CurrentWorld = WorldWind.ConfigurationLoader.Load(worldXmlFile, worldWindow.Cache); 73 74 75 /* if(this.currentWorld.HasLayerDirectory()) 76 { 77 string dirPath = worldDescriptor.LayerDirectory.Value; 78 if(!Path.IsPathRooted(dirPath)) 79 if (worldDescriptor.LayerDirectory.Value.IndexOf("//") < 0) // ? 80 dirPath = Path.Combine( Settings.ConfigPath, dirPath ); 81 82 ArrayList nodes = new ArrayList(); 83 foreach (string layerSetFile in Directory.GetFiles( dirPath, "*.xml" )) 84 { 85 try 86 { 87 88 LayerSet.LayerSetDoc curLayerSetDoc = new LayerSet.LayerSetDoc(); 89 LayerSet.Type_LayerSet curLayerSet = new LayerSet.Type_LayerSet(curLayerSetDoc.Load(layerSetFile)); 90 91 RenderableObject wwroi = getRenderableObjectListFromLayerSet(this.worldWindow.CurrentWorld, curLayerSet, layerSetFile); 92 world.RenderableObjects.Add( wwroi ); 93 } 94 catch (Exception caught) 95 { 96 // Altova throws System.Exception 97 splashScreen.SetError( 98 String.Format(CultureInfo.CurrentCulture, "The file '{0}' is invalid: {1}", 99 Path.GetFileName(layerSetFile), caught.Message) ); 100 } 101 } 102 103 this.layerTreeNodes = (TreeNode[])nodes.ToArray(typeof(TreeNode)); 104 } 105 */ 106 107 this.splashScreen.SetText("Initializing menus..."); 108 109 InitializePluginCompiler(); 110 111 foreach(RenderableObject worldRootObject in this.worldWindow.CurrentWorld.RenderableObjects.ChildObjects) 112 { 113 this.AddLayerMenuButtons(this.worldWindow, worldRootObject); 114 } 115 116 this.AddInternalPluginMenuButtons(); 117 118 this.menuItemModisHotSpots.Enabled = worldWindow.CurrentWorld.IsEarth; 119 this.menuItemAnimatedEarth.Enabled = worldWindow.CurrentWorld.IsEarth; 120 121 122 }
worldWindow.CurrentWorld = WorldWind.ConfigurationLoader.Load(worldXmlFile, worldWindow.Cache);
真正加载世界。
ConfigurationLoader的改造和使用方法:
1 public static World Load(string filename, Cache cache) 2 { 3 Log.Write(Log.Levels.Debug, "CONF", "Loading " + filename); 4 5 // get the World Wind Settings through reflection to avoid changing the signature of Load(). 6 Assembly a = Assembly.GetEntryAssembly(); 7 Type appType = a.GetType("WorldWind.MainApplication"); 8 System.Reflection.FieldInfo finfo = appType.GetField("Settings", BindingFlags.Static | BindingFlags.Public | BindingFlags.GetField); 9 WorldWindSettings settings = finfo.GetValue(null) as WorldWindSettings; 10 11 XmlReaderSettings readerSettings = new XmlReaderSettings(); 12 13 if (settings.ValidateXML) 14 { 15 Log.Write(Log.Levels.Debug, "CONF", "validating " + filename + " against WorldXmlDescriptor.xsd and LayerSet.xsd"); 16 readerSettings.ValidationType = ValidationType.Schema; 17 /* load the schema to validate against instead of hoping for an inline schema reference */ 18 XmlSchemaSet schemas = new XmlSchemaSet(); 19 schemas.Add(null, settings.ConfigPath + "/WorldXmlDescriptor.xsd"); 20 schemas.Add(null, settings.ConfigPath + "/Earth/LayerSet.xsd"); 21 22 23 readerSettings.Schemas = schemas; 24 readerSettings.ValidationEventHandler += new ValidationEventHandler(XMLValidationCallback); 25 readerSettings.ValidationFlags |= System.Xml.Schema.XmlSchemaValidationFlags.ReportValidationWarnings; 26 } 27 else 28 { 29 Log.Write(Log.Levels.Debug, "CONF", "loading " + filename + " without validation"); 30 readerSettings.ValidationType = ValidationType.None; 31 } 32 33 try 34 { 35 XmlReader docReader = XmlReader.Create(filename, readerSettings); 36 XPathDocument docNav = new XPathDocument(docReader); 37 XPathNavigator nav = docNav.CreateNavigator(); 38 39 XPathNodeIterator worldIter = nav.Select("/World[@Name]"); 40 if (worldIter.Count > 0) 41 { 42 worldIter.MoveNext(); 43 string worldName = worldIter.Current.GetAttribute("Name", ""); 44 double equatorialRadius = ParseDouble(worldIter.Current.GetAttribute("EquatorialRadius", "")); 45 string layerDirectory = worldIter.Current.GetAttribute("LayerDirectory", ""); 46 47 if (layerDirectory.IndexOf(":") < 0) 48 { 49 layerDirectory = Path.Combine(Path.GetDirectoryName(filename), layerDirectory); 50 } 51 52 TerrainAccessor[] terrainAccessor = getTerrainAccessorsFromXPathNodeIterator(worldIter.Current.Select("TerrainAccessor"), 53 System.IO.Path.Combine(cache.CacheDirectory, worldName)); 54 55 World newWorld = new World( 56 worldName, 57 new Microsoft.DirectX.Vector3(0, 0, 0), 58 new Microsoft.DirectX.Quaternion(0, 0, 0, 0), 59 equatorialRadius, 60 cache.CacheDirectory, 61 (terrainAccessor != null ? terrainAccessor[0] : null)//TODO: Oops, World should be able to handle an array of terrainAccessors 62 ); 63 64 //调用getRenderablesFromLayerDirectory()方法. 65 newWorld.RenderableObjects = getRenderablesFromLayerDirectory(layerDirectory, newWorld, cache); 66 67 return newWorld; 68 } 69 } 70 catch (XmlSchemaException ex) 71 { 72 Log.Write(Log.Levels.Error, "CONF", "Exception caught during XML parsing: " + ex.Message); 73 Log.Write(Log.Levels.Error, "CONF", "File " + filename + " was not read successfully."); 74 // TODO: should pop up a message box or something. 75 return null; 76 } 77 78 return null; 79 }
getRenderablesFromLayerDirectory()方法:
1 private static RenderableObjectList getRenderablesFromLayerDirectory(string layerDirectory, World parentWorld, Cache cache) 2 { 3 RenderableObjectList renderableCollection = new RenderableObjectList(parentWorld.Name); 4 5 DirectoryInfo layerDir = new DirectoryInfo(layerDirectory); 6 if(!layerDir.Exists) 7 { 8 return renderableCollection; 9 } 10 //从layerDirectory文件夹中读取所有的xml文件,并从xml文件中读取图层信息 11 foreach(FileInfo layerFile in layerDir.GetFiles("*.xml")) 12 { 13 //调用getRenderableFromLayerFile()方法,从中读取RenderableObjectList 对象。 14 RenderableObjectList currentRenderable = getRenderableFromLayerFile(layerFile.FullName, parentWorld, cache); 15 if(currentRenderable != null) 16 { 17 renderableCollection.Add(currentRenderable); 18 } 19 } 20 //返回RenderableObjectList对象 21 return renderableCollection; 22 }