ConfigurationLoader主要负责WW中各个图层的加载。
首先看看安装目录Config文件夹下Earth.xml文件
View Code
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 }