WorldWind学习系列九:Blue Marble插件学习

it2024-10-31  7

  有两三天没更新博客了,感觉自己又偷懒啦!周五其实主要还是看了研究WorldWind中的Virtual Earth插件功能,我以后准备开发的跟VirtualEarth很类似的,一定得把它攻下。当时Virtual Earth学习没太有大的进展,遇到的难题是:1.图片如何叠加到球体上?(包括投影变换、定位、缩放等)2.Direct 3D开发 。因为Virtual Earth是在Blue Marble插件的基础上开发,所以周六我主要是看了Direct X的基础知识和研究Blue Marble。现在与大家一起分析一下BlueMarble。

  Blue Marble插件实现主要是BMNG.cs文件,里面包括两个类BMNG类和BmngLoader类。

  BMNG复杂实现BlueMarble功能的控制窗体,BMNG的意思是Blue Marble Next Generation。

  

      BmngLoader类继承自Plugin类,是负责实现插件功能的。它重载了Plugin.cs的Load()和Unload()方法,实现了菜单项点击处理功能menuItemClicked()。这跟一般的实现插件功能的流程是一样的。

   

  下面分别看一下,关键代码的实现。

  BMNG类:主要是BMNG构造函数里的处理,这是实现图片叠加到球体上处理的关键,也是分析学习的重点。

 

BMNG构造函数分析   public  BMNG(WorldWind.WorldWindow worldWindow, MenuItem menuItem)        {             //              //  Required for Windows Form Designer support             //             InitializeComponent();             this .m_MenuItem  =  menuItem;  //  Plugin menu item ref              int  lastSelectedDatasetIndex  =   1 ;             try             {         //从"Plugins\BlueMarble\settings.txt"读取配置:上次启动时,加载的Blue Marble类型                 using  (StreamReader reader  =   new  StreamReader(Path.GetDirectoryName(Application.ExecutablePath)  +   " \\Plugins\\BlueMarble\\settings.txt " ))                {                    lastSelectedDatasetIndex  =   int .Parse(reader.ReadLine().Trim());                }            }             catch             {            }       //设置Blue Marble类型            comboBoxBmngVersion.SelectedIndex  =  lastSelectedDatasetIndex;            m_WorldWindow  =  worldWindow;       //设置同时显示的层数            m_RenderableList.ShowOnlyOneLayer  =   true ;             bool  foundImagesObject  =   false ;             lock  (m_WorldWindow.CurrentWorld.RenderableObjects.ChildObjects.SyncRoot)            {                 foreach  (WorldWind.Renderable.RenderableObject ro  in  m_WorldWindow.CurrentWorld.RenderableObjects.ChildObjects)                { //从所有的RenderableObjects数组里,查找是否已经存在名为“Images”的RenderableObjectList对象, //这里把所有的影像的RenderableObject图层,放在该层下面管理(参见下面图片3)                      if  (ro  is  WorldWind.Renderable.RenderableObjectList  &&  (ro.Name  ==   " Images " ))     //  SF FIX: don't add to layers called 'xxxx images'!                     {                         WorldWind.Renderable.RenderableObjectList imagesList  =  ro  as  WorldWind.Renderable.RenderableObjectList;                         imagesList.ChildObjects.Insert( 0 , m_RenderableList);                         foundImagesObject  =   true ;                         break ;                      }                 }            }        //如果没找到,直接在顶层添加图层列表m_RenderableList              if  ( ! foundImagesObject)            {                m_WorldWindow.CurrentWorld.RenderableObjects.ChildObjects.Add(m_RenderableList);            }      //新建图层ImageLayer            m_BlueMarbleBase  =   new  WorldWind.Renderable.ImageLayer(                 " Blue Marble Base Image " ,                m_WorldWindow.CurrentWorld,                 0 ,                 null ,                 - 90 90 - 180 180 1.0f null );            m_BlueMarbleBase.ImageUrl  =   " http://worldwind.arc.nasa.gov/downloads/land_shallow_topo_2048.dds " ;      //新建NltImageStore对象,主要是辅助实现QuadTileSet(瓦片式图层)            WorldWind.NltImageStore ia  =   new  WorldWind.NltImageStore( " 106 " " http://nww.terraserver-usa.com/nwwtile.ashx " );            ia.DataDirectory  =   null ;            ia.LevelZeroTileSizeDegrees  =   36.0 ;            ia.LevelCount  =   4 ;            ia.ImageExtension  =   " jpg " ;            ia.CacheDirectory  =  String.Format( " {0}\\Blue Marble " , m_WorldWindow.Cache.CacheDirectory);            WorldWind.ImageStore[] ias  =   new  WorldWind.ImageStore[ 1 ];            ias[ 0 =  ia;       //新建名为"Blue Marble Tiled"的QuadTileSet(瓦片式图层),这是重点            m_BlueMarbleTiled  =   new  WorldWind.Renderable.QuadTileSet(                 " Blue Marble Tiled " ,                m_WorldWindow.CurrentWorld,                 0 ,                 90 - 90 - 180 180 ,                 true ,                ias);             m_BlueMarbleTiled.ServerLogoFilePath  =  Path.GetDirectoryName(Application.ExecutablePath)  +   " \\Data\\Icons\\Interface\\meatball.png " ;       //BlueMarble图层集合               m_BlueMarbleList  =   new  WorldWind.Renderable.RenderableObjectList( " Blue Marble " );             m_BlueMarbleList.IsOn  =   false ;             m_BlueMarbleList.Add(m_BlueMarbleBase);             m_BlueMarbleList.Add(m_BlueMarbleTiled );         //BMNG图层集合             m_ShadedList  =   new  WorldWind.Renderable.RenderableObjectList( " BMNG " );             m_ShadedList.ShowOnlyOneLayer  =   true ;             m_ShadedList.IsOn  =   false ;       //12个月的影像图层             for  ( int  i  =   0 ; i  <   12 ; i ++ )             {                 m_ImageLayers[ 0 , i]  =   new  WorldWind.Renderable.ImageLayer(                     String.Format( " Base Image - {0}.2004 " , i  +   1 ),                     m_WorldWindow.CurrentWorld,                     0 ,                     null ,                     - 90 ,  90 ,  - 180 ,  180 ,  1.0f ,  null ); //从http://worldwind28.arc.nasa.gov/public/上加载图片,构建ImageLayer图层                 m_ImageLayers[ 0 , i].ImageUrl  =  String.Format( " {0}world.topo.2004{1:D2}.jpg " , m_BmngBaseImageUrl, i  +   1 );                 WorldWind.NltImageStore imageStore  =   new  WorldWind.NltImageStore(String.Format( " bmng.topo.2004{0:D2} " , i  +   1 ),  " http://worldwind25.arc.nasa.gov/tile/tile.aspx " );                 imageStore.DataDirectory  =   null ;                 imageStore.LevelZeroTileSizeDegrees  =   36.0 ;                 imageStore.LevelCount  =   5 ;                 imageStore.ImageExtension  =   " jpg " ;                 imageStore.CacheDirectory  =  String.Format( " {0}\\BMNG\\{1} " , m_WorldWindow.Cache.CacheDirectory, String.Format( " BMNG (Shaded) Tiled - {0}.2004 " , i  +   1 ));                 ias  =   new  WorldWind.ImageStore[ 1 ];                 ias[ 0 ]  =  imageStore;      //构建QuadTileSet瓦片图层                 m_QuadTileLayers[ 0 , i]  =   new  WorldWind.Renderable.QuadTileSet(                     String.Format( " Tiled - {0}.2004 " , i  +   1 ),                     m_WorldWindow.CurrentWorld,                     0 ,                     90 ,  - 90 ,  - 180 ,  180 ,                     true ,                     ias);                 m_QuadTileLayers[ 0 , i].ServerLogoFilePath  =  Path.GetDirectoryName(Application.ExecutablePath)  +   " \\Data\\Icons\\Interface\\meatball.png " ;                 m_RenderableLayers[ 0 , i]  =   new  WorldWind.Renderable.RenderableObjectList(String.Format( " {0}.2004 " , i  +   1 ));                 m_RenderableLayers[ 0 , i].IsOn  =   false ;                 m_RenderableLayers[ 0 , i].Add(m_ImageLayers[ 0 , i]);                 m_RenderableLayers[ 0 , i].Add(m_QuadTileLayers[ 0 , i]);                 m_ShadedList.Add(m_RenderableLayers[ 0 , i]);             }             m_ShadedBathyList  =   new  WorldWind.Renderable.RenderableObjectList( " BMNG (Bathymetry) " );             m_ShadedBathyList.ShowOnlyOneLayer  =   true ;             m_ShadedBathyList.IsOn  =   false ;             for  ( int  i  =   0 ; i  <   12 ; i ++ )             {                 m_ImageLayers[ 1 , i]  =   new  WorldWind.Renderable.ImageLayer(                     String.Format( " Base Image - {0}.2004 " , i  +   1 ),                     m_WorldWindow.CurrentWorld,                     0 ,         //从文件系统里加载影像图片                      String.Format( " {0}\\Data\\Earth\\BmngBathy\\world.topo.bathy.2004{1:D2}.jpg " , Path.GetDirectoryName(Application.ExecutablePath), i  +   1 ),                     - 90 ,  90 ,  - 180 ,  180 ,  1.0f ,  null );                 //     m_ImageLayers[1, i].ImageUrl = String.Format("{0}world.topo.bathy.2004{1:D2}.jpg", m_BmngBaseImageUrl, i+1);                 //根据http://worldwind25.arc.nasa.gov/tile/tile.aspx构建瓦片式影像的URI地址                 WorldWind.NltImageStore imageStore  =   new  WorldWind.NltImageStore(String.Format( " bmng.topo.bathy.2004{0:D2} " , i  +   1 ),  " http://worldwind25.arc.nasa.gov/tile/tile.aspx " );                 imageStore.DataDirectory  =   null ;                 imageStore.LevelZeroTileSizeDegrees  =   36.0 ;                 imageStore.LevelCount  =   5 ;                 imageStore.ImageExtension  =   " jpg " ;                 imageStore.CacheDirectory  =  String.Format( " {0}\\BMNG\\{1} " , m_WorldWindow.Cache.CacheDirectory, String.Format( " BMNG (Shaded + Bathymetry) Tiled - {0}.2004 " , i  +   1 ));                 ias  =   new  WorldWind.ImageStore[ 1 ];                 ias[ 0 ]  =  imageStore;         //构建瓦片式影像                 m_QuadTileLayers[ 1 , i]  =   new  WorldWind.Renderable.QuadTileSet(                         String.Format( " Tiled - {0}.2004 " , i  +   1 ),                         m_WorldWindow.CurrentWorld,                         0 ,                         90 ,  - 90 ,  - 180 ,  180 ,  true , ias);                 m_QuadTileLayers[ 0 , i].ServerLogoFilePath  =  Path.GetDirectoryName(Application.ExecutablePath)  +   " \\Data\\Icons\\Interface\\meatball.png " ;                 m_RenderableLayers[ 1 , i]  =   new  WorldWind.Renderable.RenderableObjectList(String.Format( " {0}.2004 " , i  +   1 ));                 m_RenderableLayers[ 1 , i].IsOn  =   false ;                 m_RenderableLayers[ 1 , i].Add(m_ImageLayers[ 1 , i]);                 m_RenderableLayers[ 1 , i].Add(m_QuadTileLayers[ 1 , i]);                 m_ShadedBathyList.Add(m_RenderableLayers[ 1 , i]);             }                        m_RenderableList.Add(m_BlueMarbleList);             m_RenderableList.Add(m_ShadedList);             m_RenderableList.Add(m_ShadedBathyList);             //     m_RenderableList.Add(m_UnShadedList);              this .trackBarMonth.Value  =  System.DateTime.Now.Month  -   1 ;             timer  =   new  Timer();             timer.Interval  =   1000 ;             timer.Tick  +=   new  EventHandler(timer_Tick);             timer.Start();         }

 

 

   图3: 

原143行   m_ImageLayers[0, i].ImageUrl = String.Format("{0}world.topo.2004{1:D2}.jpg", m_BmngBaseImageUrl, i + 1);从http://worldwind28.arc.nasa.gov/public/上加载图片,构建ImageLayer图层

 原183行  String.Format("{0}\\Data\\Earth\\BmngBathy\\world.topo.bathy.2004{1:D2}.jpg", Path.GetDirectoryName(Application.ExecutablePath), i + 1),从文件系统中获取影像图片,构建ImageLayer图层。

另外,构造函数中有个定时器timer,实现每1秒,执行一次timer_Tick(object sender, EventArgs e)。

定时器处理代码   private   void  timer_Tick( object  sender, EventArgs e)        {             try             {                 // Added TimeKeeper based Modis Month                 // if (WorldWind.TimeKeeper.CurrentTimeUtc.Month != trackBarMonth.Value)                 //     trackBarMonth.Value = WorldWind.TimeKeeper.CurrentTimeUtc.Month-1;                  if  (m_CurrentMonth  !=  trackBarMonth.Value)                {                    TurnOffLayers();                     for  ( int  i  =   0 ; i  <   2 ; i ++ )                    {                        m_RenderableLayers[i, trackBarMonth.Value].IsOn  =   true ;                    }                    m_CurrentMonth  =  trackBarMonth.Value;                     this .statusBarMonth.Text  =  GetMonth(trackBarMonth.Value  +   1 +   "  - 2004 " ;                }                 if  (m_CurrentVersion  !=  comboBoxBmngVersion.SelectedIndex)                {                    m_CurrentVersion  =  comboBoxBmngVersion.SelectedIndex;                     if  (m_BlueMarbleList.IsOn)                        m_BlueMarbleList.IsOn  =   false ;                     if  (m_ShadedList.IsOn)                        m_ShadedList.IsOn  =   false ;                     if  (m_ShadedBathyList.IsOn)                        m_ShadedBathyList.IsOn  =   false ;                     if  (comboBoxBmngVersion.SelectedIndex  ==   2 ) // 3)                     {                         //  show blue marble (original)                         m_BlueMarbleList.IsOn  =   true ;                         this .statusBarMonth.Text  =   "" ;                        setMonthLabelsAndSlider( false );                    }                     else                     {                        setMonthLabelsAndSlider( true );                         switch  (comboBoxBmngVersion.SelectedIndex)                        {                             case   0 :                                m_ShadedList.IsOn  =   true ;                                 break ;                             case   1 :                                m_ShadedBathyList.IsOn  =   true ;                                 break ;                             //         case 2:                             //             m_UnShadedList.IsOn = true;                             //             break;                              default :                                 break ;                        }                    }                }            }             catch             { }        }    }

 

我个人认为,使用定时器处理,是有些浪费效率,但是主要是为了LayerManager管理里关闭/打开某个图层处理的。如果仅仅为了Blue Marble类型改变球体的底图,完全可以使用Combox的处理事件,就没必要用定时器处理。

 

BMNGLoader类,按一般插件重载实现Plugin.cs的Load() 、Unload()方法即可。这也是一般套路,无需多说。

BmngLoader代码          public   override   void  Load()        {             if  (ParentApplication.WorldWindow.CurrentWorld.Name.IndexOf( " Earth " >=   0 )            {                m_MenuItem  =   new  MenuItem( " Blue Marble " );                m_MenuItem.Click  +=   new  EventHandler(menuItemClicked);          //加到PluginsMenu菜单下                ParentApplication.PluginsMenu.MenuItems.Add(m_MenuItem);                m_BmngForm  =   new  BMNG(ParentApplication.WorldWindow, m_MenuItem);                m_BmngForm.Owner  =  ParentApplication;                m_ToolbarItem  =   new  WorldWind.WindowsControlMenuButton(                     " NASA Blue Marble " ,                    Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath)  +   " \\Data\\Icons\\Interface\\bmng.png " ,                    m_BmngForm);         //加载到WorldWindow.MenuBar菜单里                ParentApplication.WorldWindow.MenuBar.AddToolsMenuButton(m_ToolbarItem);                 base .Load();            }        }

 

 

 本系列其他部分:

WorldWind学习系列八:Load/Unload Plugins——直捣黄龙篇

WorldWind学习系列七:Load/Unload Plugins——投石问路篇

 

WorldWind学习系列六:渲染过程解析篇

WorldWind学习系列五:插件加载过程全解析

WorldWind学习系列四:功能分析——Show Planet Axis、Show Position 、Show Cross Hairs功能

WorldWind学习系列三:简单功能分析——主窗体的键盘监听处理及拷贝和粘贴位置坐标功能

WorldWind学习系列三:功能分析——截屏功能和“关于”窗体分析

WorldWind学习系列二:擒贼先擒王篇2

WorldWind学习系列二:擒贼先擒王篇1

WorldWind学习系列一:顺利起航篇

 

 

 

 

 

  

转载于:https://www.cnblogs.com/wuhenke/archive/2009/12/20/1628081.html

相关资源:数据结构—成绩单生成器
最新回复(0)