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构造函数分析 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 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,
,
                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,
,
, -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,
,
                    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,
,
, -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,
,
        //从文件系统里加载影像图片
                    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,
,
, -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();
        }


原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)。

定时器处理代码 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/--> 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代码 


Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->        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();
            }
        }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值