1. 程式人生 > >PIE SDK開啟靜止衛星資料

PIE SDK開啟靜止衛星資料

 

1. 功能簡介

靜止衛星是位於地球赤道上空約3.58萬km處,與地面始終保持相對靜止的衛星,靜止衛星的特點是覆蓋區域廣,具有很強的機動靈活性,能夠對特定區域進行分鐘級高重複觀測,可快速監測災害目標的動態變化。目前風雲2系列、風雲4系列、葵花(Himawari)系列、高分4衛星均為靜止衛星。

 

[靜止衛星位置示意圖]

 

[衛星執行軌跡圖]

        

[FY2G資料成像圖]                                               [GF4

資料成像圖]

PIE支援靜止衛星資料的顯示和瀏覽,同時提供了針對常用靜止衛星資料顯示的優化方案,下面以FY4A資料為例來進行介紹。

2. 功能實現說明

2.1   FY4A資料介紹

 

[FY4A資料成像圖]

FY4A衛星是氣象衛星,其資料採用HDF方式儲存,包括4000、2000、1000、500四種解析度的資料,不同解析度資料包括不同的通道。其各通道均為預設標稱投影的全圓盤的資料,其星下點和衛星姿態等資訊均儲存中HDF的對應資料集下。

 

[FY4A資料檔案截圖]

 

[HDF Explorer檢視FY4A4000解析度資料]

HDF資料是採用了高效率壓縮的資料,實現了高效的儲存、分發。但卻造成了資料的顯示瀏覽緩慢(每次資料瀏覽,都需要從壓縮檔案中解壓出原始資料,再獲取到要顯示瀏覽的資料),並且整個過程會佔用大量的記憶體資源,為了保證資料的高效瀏覽效率,我們建議將HDF中的各通道資料生成一份支援快速瀏覽檢視的tiff本地快取資料,以滿足瀏覽檢視的需求。

下面我們以FY4A 4000m資料的NOMChannel13通道為例,來演示如何完成對FY4A資料的快速讀取、瀏覽。

2.2  實現思路及原理說明

讀取靜止衛星的資料的思路為把靜止衛星資料中的對應通道(NOMChannel13)儲存為一份本地的柵格資料,再通過對柵格資料的瀏覽,完成對靜止衛星資料的瀏覽。

第一步

開啟靜止衛星資料為多資料集

第二步

獲取指定通道的柵格資料集

第三步

讀取第二步中的資料集的資料至記憶體中

第四步

建立與靜止衛星同資料型別、同寬高、同波段數的目標柵格檔案

第五步

將資料寫入目標柵格資料檔案

第六步

對目標柵格資料賦值空間參考和六引數

2.3  核心介面與方法

介面/類

方法

說明

DataSource.DatasetFactory

OpenDataset

開啟資料集

DataSource.DatasetFactory

CreateRasterDataset

建立柵格資料集

DataSource.IRasterDataset

Read

將柵格資料讀取至記憶體中

DataSource.IRasterDataset

Write

將記憶體資料寫入至柵格資料中

2.4  示例程式碼

專案路徑

百度雲盤地址下/PIE示例程式/05.開啟靜止衛星資料

資料路徑

百度雲盤地址下/PIE示例資料/科學資料集\HDF資料夾下資料

視訊路徑

百度雲盤地址下/PIE視訊教程/05.開啟靜止衛星資料.avi

示例程式碼

OpenFileDialog openFile = new OpenFileDialog();

    openFile.Filter = "HDF資料|*.hdf";

    if (openFile.ShowDialog() != DialogResult.OK)

        return;

    string channelName = "NOMChannel13";//波段名稱

    string tempTif = System.IO.Path.GetDirectoryName(openFile.FileName) + "\\NOMChannel13.tiff";//輸出tiff路徑

    ISpatialReference spatialReference = new ProjectedCoordinateSystem();//目標空間參考

    spatialReference.ImportFromUserInput("+proj=geos +h=35785863 +a=6378137.0 +b=6356752.3 +lon_0=104.7 +no_defs");

    IRasterLayer rasterLayer = OpenStaticData(openFile.FileName, channelName, tempTif, spatialReference);// OpenStaticData方法的定義在下面

    if (rasterLayer == null)

        return;

    //新增至地圖並重新整理檢視

    mapControlMain.FocusMap.AddLayer(rasterLayer as ILayer);

mapControlMain.ActiveView.PartialRefresh(ViewDrawPhaseType.ViewAll);

 

 

      /// <summary>

        /// 開啟風雲4A、風雲2G等靜止衛星資料,讀取指定波段資料為tiff

        /// </summary>

        /// <param name="filePath">hdf路徑</param>

        /// <param name="channelName">波段通道名稱</param>

        /// <param name="tiffPath">生成tiff路徑</param>

        /// <param name="spatialReference">空間參考</param>

        /// <returns></returns>

        private IRasterLayer OpenStaticData(string filePath, string channelName, string tiffPath, ISpatialReference spatialReference)

        {

        IRasterLayer rasteLayer = null;

        try

        {

            //開啟MultiDataset

            IMultiDataset hdfDataset = PIE.DataSource.DatasetFactory.OpenDataset(filePath, OpenMode.ReadOnly) as IMultiDataset;

            if (hdfDataset != null)

            {

                //遍歷,查詢指定通道的Dataset,進行資料格式轉換

                for (int i = 0; i < hdfDataset.GetDatasetCount(); i++)

                {

                    IDataset pTempDataset = hdfDataset.GetDataset(i);

                    if (pTempDataset.Name == channelName)

                    {

                        //將RasterDataset寫入指定tiff

                        IRasterDataset hdfRasterDatasetBand = pTempDataset as IRasterDataset;

 

                        int nWidth = hdfRasterDatasetBand.GetRasterXSize();

                        int nHeight = hdfRasterDatasetBand.GetRasterYSize();

 

                        PixelDataType eDateType = hdfRasterDatasetBand.GetRasterBand(0).GetRasterDataType();

                        int count = hdfRasterDatasetBand.GetBandCount();

 

                        int[] bandMap = new int[count];

                        for (int j = 0; j < count; j++)

                        {

                            bandMap[j] = j + 1;

                        }

                        string[] tempList = null;

                        IPixelBuffer pixBuffer = hdfRasterDatasetBand.Read(0, 0, nWidth, nHeight, nWidth, nHeight, bandMap);

                        //建立輸出柵格資料集

                        IRasterDataset tifRasterDataset = DatasetFactory.CreateRasterDataset(tiffPath, nWidth, nHeight, count, eDateType, "GTiff", tempList);

                        bool flag = tifRasterDataset.Write(0, 0, nWidth, nHeight, pixBuffer.GetData_Ref(), nWidth, nHeight, eDateType, count, bandMap);

                        tifRasterDataset.SpatialReference = spatialReference;

                        tifRasterDataset.GetRasterBand(0).SetNoDataValue(65535);

 

                        //六引數,根據輸入座標的不同需要進行動態設定,本示例程式碼以風雲4A-4000m的資料作為實驗資料。

                        int beginLineNum = 0;

                        int nReslution = 4000;

                        string beginlineNumStr = hdfDataset.GetMetadataItem("Begin_Line_Number", "");

                        if (string.IsNullOrEmpty(beginlineNumStr))

                        {

                            beginlineNumStr = hdfDataset.GetMetadataItem("geospatial_lat_lon_extent_begin_line_number", "");

                            if (string.IsNullOrEmpty(beginlineNumStr)) beginLineNum = 183;

                        }

 

                        if (!string.IsNullOrEmpty(beginlineNumStr))

                        {

                            StringBuilder sb = new StringBuilder();

                            foreach (char charStr in beginlineNumStr)

                            {

                                if ((charStr >= '0' && charStr <= '9') || charStr == ' ' || charStr == '-') sb.Append(charStr);

                            }

                            bool result = int.TryParse(sb.ToString(), out beginLineNum);

                        }

 

                        double[] geoTransform = new double[6];

                        geoTransform[0] = -5496000;

                        geoTransform[1] = nReslution;

                        geoTransform[2] = 0;

                        geoTransform[3] = 5496000 - beginLineNum * nReslution;

                        geoTransform[4] = 0;

                        geoTransform[5] = -nReslution;

                        tifRasterDataset.SetGeoTransform(geoTransform);

 

                        (tifRasterDataset as IDisposable).Dispose();

                        (hdfRasterDatasetBand as IDisposable).Dispose();

                        (pixBuffer as IDisposable).Dispose();

 

                        rasteLayer = PIE.Carto.LayerFactory.CreateDefaultLayer(tiffPath) as IRasterLayer;

                        break;

                    }

                }

            }

        }

        catch (Exception ex)

        {

            rasteLayer = null;

        }

        return rasteLayer;

        }

  

   mapControlMain.FocusMap.AddLayer(fLayer as ILayer);

   mapControlMain.ActiveView.PartialRefresh(PIE.Carto.ViewDrawPhaseType.ViewAll);

 

2.5  示例截圖