zoukankan      html  css  js  c++  java
  • WorldWind学习系列九:Blue Marble插件学习

      有两三天没更新博客了,感觉自己又偷懒啦!周五其实主要还是看了研究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,
                    
    -9090-1801801.0fnull);
                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-180180,
                    
    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,
                        
    -9090-1801801.0fnull);
    //从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-180180,
                        
    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),
                        
    -9090-1801801.0fnull);

                    
    //    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-180180true, 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学习系列一:顺利起航篇

      

  • 相关阅读:
    Programming Style
    一则SQL问题
    C# WINFORM中读取config文件
    《Windows Communication Foundation之旅》系列之四 (转)
    [译]ASP.Net 2.0: Export GridView to Excel (转) 如果GridView中有其它控件,比如Checkboxes,Dropdownlists,我们需要将它转换为其相关的值,以下递归就用于导出Excel前的准备工作,将各类控件转换为其相关值.
    Windows Communication Foundation入门(Part One) (转)
    DOM方法和属性 使用范例
    一套.net面试题~ 没有正确答案~ 大家做做看
    一则 Oracle 和 SqlServer 语法区别 (原创)
    最基本的Socket编程 C#版 [转]
  • 原文地址:https://www.cnblogs.com/wuhenke/p/1628081.html
Copyright © 2011-2022 走看看