예제 #1
0
 private void TryCreateDefaultArgs(IRasterDataProvider srcRaster, NOAA_PrjSettings prjSettings, ref ISpatialReference dstSpatialRef)
 {
     if (dstSpatialRef == null)
     {
         dstSpatialRef = _srcSpatialRef;
     }
     if (string.IsNullOrWhiteSpace(prjSettings.OutFormat))
     {
         prjSettings.OutFormat = "LDF";
     }
     if (prjSettings.OutResolutionX == 0 || prjSettings.OutResolutionY == 0)
     {
         if (dstSpatialRef.ProjectionCoordSystem == null)
         {
             prjSettings.OutResolutionX = 0.01F;
             prjSettings.OutResolutionY = 0.01F;
         }
         else
         {
             prjSettings.OutResolutionX = 1000F;
             prjSettings.OutResolutionY = 1000F;
         }
     }
     if (prjSettings.OutBandNos == null || prjSettings.OutBandNos.Length == 0)
     {
         prjSettings.OutBandNos = new int[] { 1, 2, 3, 4, 5 };
     }
 }
예제 #2
0
        //453
        private string PrjNOAA_1BD_L1(IRasterDataProvider fileName, ISpatialReference projRef)
        {
            IRasterDataProvider srcRaster = fileName;

            try
            {
                IFileProjector   projTor    = FileProjector.GetFileProjectByName("NOAA_1BD");
                NOAA_PrjSettings prjSetting = new NOAA_PrjSettings();
                prjSetting.OutPathAndFileName = GetOutPutFile(fileName.fileName, projRef);
                prjSetting.OutBandNos         = new int[] { 3, 4, 5 };
                ISpatialReference dstSpatialRef = projRef;
                projTor.Project(srcRaster, prjSetting, dstSpatialRef, _progress);
                return(prjSetting.OutPathAndFileName);
            }
            finally
            {
            }
        }
예제 #3
0
        private void Project(IRasterDataProvider srcRaster, NOAA_PrjSettings prjSettings, ISpatialReference dstSpatialRef, Action <int, string> progressCallback)
        {
            PrjEnvelope envelops = prjSettings.OutEnvelope;

            if (envelops.IntersectsWith(_maxPrjEnvelope))
            {
                switch (prjSettings.OutFormat)
                {
                case "LDF":
                    ProjectToLDF(srcRaster, prjSettings, dstSpatialRef, progressCallback);
                    break;

                case "MEMORY":
                default:
                    throw new NotSupportedException(string.Format("暂不支持的输出格式", prjSettings.OutFormat));
                }
            }
            else
            {
                throw new Exception("数据不在目标区间内");
            }
        }
예제 #4
0
 public override void Project(IRasterDataProvider srcRaster, FilePrjSettings prjSettings, ISpatialReference dstSpatialRef, Action <int, string> progressCallback)
 {
     if (srcRaster == null)
     {
         throw new ArgumentNullException("srcRaster");
     }
     if (prjSettings == null)
     {
         throw new ArgumentNullException("prjSettings");
     }
     if (progressCallback != null)
     {
         progressCallback(0, "准备相关参数");
     }
     _dstSpatialRef = dstSpatialRef;
     if (prjSettings.OutEnvelope == null || prjSettings.OutEnvelope == PrjEnvelope.Empty)
     {
         MemoryHelper.MemoryNeed(800, 1280);
     }
     else
     {
         MemoryHelper.MemoryNeed(600, 1280);     //剩余900MB,已使用1.2GB
     }
     try
     {
         NOAA_PrjSettings noaaPrjSettings = prjSettings as NOAA_PrjSettings;
         TryCreateDefaultArgs(srcRaster, noaaPrjSettings, ref dstSpatialRef);
         _isSensorZenith = noaaPrjSettings.IsSensorZenith;
         DoSession(srcRaster, dstSpatialRef, noaaPrjSettings, progressCallback);
         if (prjSettings.OutEnvelope == null || prjSettings.OutEnvelope == PrjEnvelope.Empty)
         {
             prjSettings.OutEnvelope = _maxPrjEnvelope;
             _orbitBlock             = new Block {
                 xOffset = 0, yBegin = 0, xEnd = srcRaster.Width - 1, yEnd = srcRaster.Height - 1
             };
         }
         else
         {
             GetEnvelope(_xs, _ys, srcRaster.Width, srcRaster.Height, prjSettings.OutEnvelope, out _orbitBlock);
             if (_orbitBlock == null || _orbitBlock.Width <= 0 || _orbitBlock.Height <= 0)
             {
                 throw new Exception("数据不在目标区间内");
             }
             float invalidPresent = (_orbitBlock.Width * _orbitBlock.Height * 1.0F) / (srcRaster.Width * srcRaster.Height);
             if (invalidPresent < 0.001)
             {
                 throw new Exception("数据不在目标区间内,有效率" + invalidPresent + "。");
             }
             if (invalidPresent > 0.60)
             {
                 _orbitBlock = new Block {
                     xOffset = 0, yBegin = 0, xEnd = srcRaster.Width - 1, yEnd = srcRaster.Height - 1
                 }
             }
             ;
         }
         if (dstSpatialRef.ProjectionCoordSystem == null && _maxPrjEnvelope.MaxX > 180 && _maxPrjEnvelope.MinX < -180 && _maxPrjEnvelope.MaxY > 90 && _maxPrjEnvelope.MinY < -90)
         {
             throw new Exception("读取NOAA 1a5经纬度不在合理范围内[" + _maxPrjEnvelope.ToString() + "]");
         }
         if (dstSpatialRef.ProjectionCoordSystem == null && (prjSettings.OutEnvelope.MaxY > 80 || prjSettings.OutEnvelope.MaxY < -80))
         {
             throw new Exception(string.Format("高纬度数据[>80],不适合投影为等经纬度数据[{0}]", _maxPrjEnvelope));
         }
         Project(srcRaster, noaaPrjSettings, dstSpatialRef, progressCallback);
     }
     catch
     {
         EndSession();
         TryDeleteCurCatch();
         throw;
     }
     finally
     {
         if (_curSession == null)
         {
             EndSession();
             if (prjSettings.IsClearPrjCache)
             {
                 TryDeleteCurCatch();
             }
         }
     }
 }
예제 #5
0
        /// <summary>
        /// 0、先生成目标文件,以防止目标空间不足。
        /// 1、计算查找表
        /// 2、读取通道数据
        /// 3、计算通道数据亮温
        /// 4、投影通道。
        /// </summary>
        private void ProjectToLDF(IRasterDataProvider srcRaster, NOAA_PrjSettings prjSettings, ISpatialReference dstSpatialRef, Action <int, string> progressCallback)
        {
            string outFormat   = prjSettings.OutFormat;
            string outfilename = prjSettings.OutPathAndFileName;
            string dstProj4    = dstSpatialRef.ToProj4String();

            int[] outBandNos   = prjSettings.OutBandNos;
            int   dstBandCount = outBandNos.Length;
            Size  srcSize      = new Size(srcRaster.Width, srcRaster.Height);
            Size  dstSize      = prjSettings.OutSize;
            Size  srcJdSize    = srcSize;

            using (IRasterDataDriver drv = GeoDataDriver.GetDriverByName("LDF") as IRasterDataDriver)
            {
                PrjEnvelope dstEnvelope = prjSettings.OutEnvelope;
                string[]    options     = new string[] {
                    "INTERLEAVE=BSQ",
                    "VERSION=LDF",
                    "WITHHDR=TRUE",
                    "SPATIALREF=" + dstSpatialRef.ToProj4String(),
                    "MAPINFO={" + 1 + "," + 1 + "}:{" + dstEnvelope.MinX + "," + dstEnvelope.MaxY + "}:{" + prjSettings.OutResolutionX + "," + prjSettings.OutResolutionY + "}"
                    , "BANDNAMES=" + BandNameString(prjSettings.OutBandNos)
                };
                if (progressCallback != null)
                {
                    progressCallback(6, "生成输出文件");
                }
                using (IRasterDataProvider prdWriter = drv.Create(outfilename, dstSize.Width, dstSize.Height, dstBandCount, enumDataType.UInt16, options) as IRasterDataProvider)
                {
                    float outResolutionX = prjSettings.OutResolutionX;
                    float outResolutionY = prjSettings.OutResolutionY;
                    Size  outSize        = dstEnvelope.GetSize(outResolutionX, outResolutionY);
                    int   blockXNum      = 0;
                    int   blockYNum      = 0;
                    int   blockWidth     = 0;
                    int   blockHeight    = 0;
                    GetBlockNumber(outSize, out blockXNum, out blockYNum, out blockWidth, out blockHeight);
                    Size     dstBlockSize   = new Size(blockWidth, blockHeight);
                    UInt16[] dstRowBlockLUT = new UInt16[blockWidth * blockHeight];
                    UInt16[] dstColBlockLUT = new UInt16[blockWidth * blockHeight];
                    int      blockCount     = blockYNum * blockXNum;
                    int      progress       = 0;
                    int      percent        = 0;
                    int      progressCount  = blockCount * dstBandCount;
                    for (int blockYIndex = 0; blockYIndex < blockYNum; blockYIndex++)
                    {
                        for (int blockXIndex = 0; blockXIndex < blockXNum; blockXIndex++)
                        {
                            PrjEnvelope blockEnvelope = null;
                            Block       orbitBlock    = null; //经纬度数据集,计算轨道数据范围偏移
                            double[]    blockOrbitXs  = null;
                            double[]    blockOrbitYs  = null;
                            if (blockCount == 1)            //没分块的情况
                            {
                                orbitBlock = _orbitBlock;
                                if (_orbitBlock.Width == srcJdSize.Width && _orbitBlock.Height == srcJdSize.Height)
                                {
                                    blockOrbitXs = _xs;
                                    blockOrbitYs = _ys;
                                }
                                else                        //源
                                {
                                    GetBlockDatas(_xs, _ys, srcJdSize.Width, srcJdSize.Height, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height, out blockOrbitXs, out blockOrbitYs);
                                }
                                blockEnvelope = dstEnvelope;
                            }
                            else
                            {
                                //当前块的四角范围
                                double blockMinX = dstEnvelope.MinX + blockWidth * outResolutionX * blockXIndex;
                                double blockMaxX = blockMinX + blockWidth * outResolutionX;
                                double blockMaxY = dstEnvelope.MaxY - blockHeight * outResolutionY * blockYIndex;
                                double blockMinY = blockMaxY - blockHeight * outResolutionY;
                                blockEnvelope = new PrjEnvelope(blockMinX, blockMaxX, blockMinY, blockMaxY);
                                //根据当前输出块,反推出对应的源数据块起始行列
                                GetEnvelope(_xs, _ys, srcJdSize.Width, srcJdSize.Height, blockEnvelope, out orbitBlock);
                                if (orbitBlock.Width <= 0 || orbitBlock.Height <= 0) //当前分块不在图像内部
                                {
                                    progress += dstBandCount;
                                    continue;
                                }
                                GetBlockDatas(_xs, _ys, srcJdSize.Width, srcJdSize.Height, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height, out blockOrbitXs, out blockOrbitYs);
                            }
                            float[] solarZenithData = null;
                            if (prjSettings.IsRadiation && prjSettings.IsSolarZenith)
                            {
                                if (File.Exists(_szDataFilename))
                                {
                                    ReadBandData(out solarZenithData, _solarZenithCacheRaster, 1, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height);
                                }
                                TryReadZenithData(orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height);
                            }
                            Size orbitBlockSize = new Size(orbitBlock.Width, orbitBlock.Height);
                            _rasterProjector.ComputeIndexMapTable(blockOrbitXs, blockOrbitYs, orbitBlockSize, dstBlockSize, blockEnvelope, _maxPrjEnvelope, out dstRowBlockLUT, out dstColBlockLUT, null);
                            //执行投影
                            UInt16[] srcBandData = new UInt16[orbitBlock.Width * orbitBlock.Height];
                            UInt16[] dstBandData = new UInt16[blockWidth * blockHeight];
                            for (int i = 0; i < dstBandCount; i++)      //读取原始通道值,投影到目标区域
                            {
                                if (progressCallback != null)
                                {
                                    progress++;
                                    percent = progress * 100 / progressCount;
                                    progressCallback(percent, string.Format("投影第{0}/{1}块,第{2}/{3}通道", blockXIndex + blockYIndex, blockCount, i + 1, dstBandCount));
                                }
                                int bandNo = outBandNos[i];
                                ReadBandData(srcBandData, srcRaster, bandNo, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height);
                                if (prjSettings.IsRadiation)
                                {
                                    DoRadiation(srcBandData, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Size, bandNo, prjSettings.IsRadiation, prjSettings.IsSolarZenith, solarZenithData);
                                }
                                _rasterProjector.Project <UInt16>(srcBandData, orbitBlock.Size, dstRowBlockLUT, dstColBlockLUT, dstBlockSize, dstBandData, 0, null);
                                IRasterBand band = prdWriter.GetRasterBand(i + 1);
                                {
                                    unsafe
                                    {
                                        fixed(UInt16 *ptr = dstBandData)
                                        {
                                            IntPtr bufferPtr    = new IntPtr(ptr);
                                            int    blockOffsetY = blockYIndex * dstBlockSize.Height;
                                            int    blockOffsetX = blockXIndex * dstBlockSize.Width;

                                            band.Write(blockOffsetX, blockOffsetY, blockWidth, blockHeight, bufferPtr, enumDataType.UInt16, blockWidth, blockHeight);
                                        }
                                    }
                                }
                            }
                            ReleaseZenithData();
                            srcBandData  = null;
                            dstBandData  = null;
                            blockOrbitXs = null;
                            blockOrbitYs = null;
                        }
                    }
                    dstRowBlockLUT = null;
                    dstColBlockLUT = null;
                }
            }
        }
예제 #6
0
 private void DoSession(IRasterDataProvider srcRaster, ISpatialReference dstSpatialRef, NOAA_PrjSettings prjSettings, Action <int, string> progressCallback)
 {
     if (_curSession == null || _curSession != srcRaster || _isBeginSession)
     {
         Size srcSize = new Size(srcRaster.Width, srcRaster.Height);
         ReadyLocations(srcRaster, dstSpatialRef, srcSize, out _xs, out _ys, out _maxPrjEnvelope, progressCallback);
         if (progressCallback != null)
         {
             progressCallback(4, "准备亮温计算参数");
         }
         if (prjSettings.IsRadiation)
         {
             ReadyRadiationArgs(srcRaster);
         }
         if (progressCallback != null)
         {
             progressCallback(5, "准备亮温计算参数");
         }
         if (prjSettings.IsSolarZenith && prjSettings.IsRadiation)
         {
             _szDataFilename = GetSolarZenithCacheFilename(srcRaster.fileName);
             if (!File.Exists(_szDataFilename))
             {
                 ReadySolarZenithArgsToFile(srcRaster);
             }
             else
             {
                 _solarZenithCacheRaster = GeoDataDriver.Open(_szDataFilename) as IRasterDataProvider;
             }
             if (prjSettings.IsSensorZenith)
             {
                 ReadySensorZenith(srcRaster);
             }
         }
         _isBeginSession = false;
     }
 }
예제 #7
0
 public override void Project(IRasterDataProvider srcRaster, FilePrjSettings prjSettings, ISpatialReference dstSpatialRef, Action <int, string> progressCallback)
 {
     if (srcRaster == null)
     {
         throw new ArgumentNullException("srcRaster");
     }
     if (prjSettings == null)
     {
         throw new ArgumentNullException("prjSettings");
     }
     if (progressCallback != null)
     {
         progressCallback(0, "准备相关参数");
     }
     _dstSpatialRef = dstSpatialRef;
     if (prjSettings.OutEnvelope == null || prjSettings.OutEnvelope == PrjEnvelope.Empty)
     {
         MemoryHelper.MemoryNeed(200, 1536);
     }
     else
     {
         MemoryHelper.MemoryNeed(200, 1536);     //剩余900MB,已使用1.2GB
     }
     try
     {
         NOAA_PrjSettings noaaPrjSettings = prjSettings as NOAA_PrjSettings;
         TryCreateDefaultArgs(srcRaster, noaaPrjSettings, ref dstSpatialRef);
         _isSensorZenith = noaaPrjSettings.IsSensorZenith;
         DoSession(srcRaster, dstSpatialRef, noaaPrjSettings, progressCallback);
         if (prjSettings.OutEnvelope == null || prjSettings.OutEnvelope == PrjEnvelope.Empty)
         {
             prjSettings.OutEnvelope = _maxPrjEnvelope;
             _orbitBlock             = new Block {
                 xOffset = 0, yBegin = 0, xEnd = srcRaster.Width - 1, yEnd = srcRaster.Height - 1
             };
         }
         else
         {
             GetEnvelope(_xs, _ys, srcRaster.Width, srcRaster.Height, prjSettings.OutEnvelope, out _orbitBlock);
             if (_orbitBlock == null || _orbitBlock.Width <= 0 || _orbitBlock.Height <= 0)
             {
                 throw new Exception("数据不在目标区间内");
             }
             float invalidPresent = (_orbitBlock.Width * _orbitBlock.Height * 1.0F) / (srcRaster.Width * srcRaster.Height);
             if (invalidPresent < 0.0001f)
             {
                 throw new Exception("数据占轨道数据比例太小,有效率" + invalidPresent * 100 + "%");
             }
             if (invalidPresent > 0.60)
             {
                 _orbitBlock = new Block {
                     xOffset = 0, yBegin = 0, xEnd = srcRaster.Width - 1, yEnd = srcRaster.Height - 1
                 }
             }
             ;
         }
         if (dstSpatialRef.ProjectionCoordSystem == null && _maxPrjEnvelope.MaxX > 180 && _maxPrjEnvelope.MinX < -180 && _maxPrjEnvelope.MaxY > 90 && _maxPrjEnvelope.MinY < -90)
         {
             throw new Exception("读取FY1X 1a5经纬度不在合理范围内[" + _maxPrjEnvelope.ToString() + "]");
         }
         //if (dstSpatialRef.ProjectionCoordSystem == null && (prjSettings.OutEnvelope.MaxY > 80 || prjSettings.OutEnvelope.MaxY < -80))
         //    throw new Exception(string.Format("高纬度数据[>80],不适合投影为等经纬度数据[{0}]", _maxPrjEnvelope));
         PrjEnvelope envelops = prjSettings.OutEnvelope;
         if (!envelops.IntersectsWith(_maxPrjEnvelope))
         {
             throw new Exception("数据不在目标区间内");
         }
         float    outResolutionX = prjSettings.OutResolutionX;
         float    outResolutionY = prjSettings.OutResolutionY;
         int      dstBandCount   = prjSettings.OutBandNos.Length;
         Size     outSize        = prjSettings.OutSize;
         string[] angleOptions   = new string[] {
             "INTERLEAVE=BSQ",
             "VERSION=LDF",
             "WITHHDR=TRUE",
             "SPATIALREF=" + dstSpatialRef.ToProj4String(),
             "MAPINFO={" + 1 + "," + 1 + "}:{" + prjSettings.OutEnvelope.MinX + "," + prjSettings.OutEnvelope.MaxY + "}:{" + outResolutionX + "," + outResolutionY + "}"
         };
         string outfilename = prjSettings.OutPathAndFileName;
         ReadyAngleFiles(srcRaster, outfilename, prjSettings, outSize, angleOptions);
         Project(srcRaster, noaaPrjSettings, dstSpatialRef, progressCallback);
     }
     catch
     {
         EndSession();
         TryDeleteCurCatch();
         throw;
     }
     finally
     {
         if (_curSession == null)
         {
             EndSession();
             if (prjSettings.IsClearPrjCache)
             {
                 TryDeleteCurCatch();
             }
         }
     }
 }
예제 #8
0
        /// <summary>
        /// 0、先生成目标文件,以防止目标空间不足。
        /// 1、计算查找表
        /// 2、读取通道数据
        /// 3、计算通道数据亮温
        /// 4、投影通道。
        /// </summary>
        private void ProjectToLDF(IRasterDataProvider srcRaster, NOAA_PrjSettings prjSettings, ISpatialReference dstSpatialRef, Action <int, string> progressCallback)
        {
            string outFormat   = prjSettings.OutFormat;
            string outfilename = prjSettings.OutPathAndFileName;
            string dstProj4    = dstSpatialRef.ToProj4String();

            int[] outBandNos   = prjSettings.OutBandNos;
            int   dstBandCount = outBandNos.Length;
            Size  srcSize      = new Size(srcRaster.Width, srcRaster.Height);
            Size  dstSize      = prjSettings.OutSize;
            Size  srcJdSize    = srcSize;

            using (IRasterDataDriver drv = GeoDataDriver.GetDriverByName("LDF") as IRasterDataDriver)
            {
                PrjEnvelope dstEnvelope = prjSettings.OutEnvelope;

                List <string> opts = new List <string>();
                opts.AddRange(new string[] {
                    "INTERLEAVE=BSQ",
                    "VERSION=LDF",
                    "WITHHDR=TRUE",
                    "SPATIALREF=" + dstSpatialRef.ToProj4String(),
                    "MAPINFO={" + 1 + "," + 1 + "}:{" + dstEnvelope.MinX + "," + dstEnvelope.MaxY + "}:{" + prjSettings.OutResolutionX + "," + prjSettings.OutResolutionY + "}",
                    "BANDNAMES=" + BandNameString(prjSettings.OutBandNos),
                    "SENSOR=AVHRR"
                });
                if (srcRaster.DataIdentify != null)
                {
                    string   satellite = srcRaster.DataIdentify.Satellite;
                    DateTime dt        = srcRaster.DataIdentify.OrbitDateTime;
                    bool     asc       = srcRaster.DataIdentify.IsAscOrbitDirection;
                    if (!string.IsNullOrWhiteSpace(satellite))
                    {
                        opts.Add("SATELLITE=" + satellite);
                    }
                    if (dt != DateTime.MinValue && dt != DateTime.MaxValue)
                    {
                        opts.Add("DATETIME=" + dt.ToString("yyyy/MM/dd HH:mm"));
                    }
                    opts.Add("ORBITDIRECTION=" + (asc ? "ASC" : "DESC"));
                }
                if (progressCallback != null)
                {
                    progressCallback(6, "生成输出文件");
                }
                using (IRasterDataProvider prdWriter = drv.Create(outfilename, dstSize.Width, dstSize.Height, dstBandCount, enumDataType.UInt16, opts.ToArray()) as IRasterDataProvider)
                {
                    float outResolutionX = prjSettings.OutResolutionX;
                    float outResolutionY = prjSettings.OutResolutionY;
                    Size  outSize        = dstEnvelope.GetSize(outResolutionX, outResolutionY);
                    int   blockXNum      = 0;
                    int   blockYNum      = 0;
                    int   blockWidth     = 0;
                    int   blockHeight    = 0;
                    GetBlockNumber(outSize, out blockXNum, out blockYNum, out blockWidth, out blockHeight);
                    Size     dstBlockSize   = new Size(blockWidth, blockHeight);
                    UInt16[] dstRowBlockLUT = new UInt16[blockWidth * blockHeight];
                    UInt16[] dstColBlockLUT = new UInt16[blockWidth * blockHeight];
                    int      blockCount     = blockYNum * blockXNum;
                    progress      = 0;
                    progressCount = blockCount * (dstBandCount + (_angleBands == null ? 0 : _angleBands.Length));
                    percent       = 0;
                    for (int blockYIndex = 0; blockYIndex < blockYNum; blockYIndex++)
                    {
                        for (int blockXIndex = 0; blockXIndex < blockXNum; blockXIndex++)
                        {
                            PrjEnvelope blockEnvelope = null;
                            Block       orbitBlock    = null; //经纬度数据集,计算轨道数据范围偏移
                            double[]    blockOrbitXs  = null;
                            double[]    blockOrbitYs  = null;
                            if (blockCount == 1)            //没分块的情况
                            {
                                orbitBlock = _orbitBlock;
                                if (_orbitBlock.Width == srcJdSize.Width && _orbitBlock.Height == srcJdSize.Height)
                                {
                                    blockOrbitXs = _xs;
                                    blockOrbitYs = _ys;
                                }
                                else                        //源
                                {
                                    GetBlockDatas(_xs, _ys, srcJdSize.Width, srcJdSize.Height, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height, out blockOrbitXs, out blockOrbitYs);
                                }
                                blockEnvelope = dstEnvelope;
                            }
                            else
                            {
                                //当前块的四角范围
                                double blockMinX = dstEnvelope.MinX + blockWidth * outResolutionX * blockXIndex;
                                double blockMaxX = blockMinX + blockWidth * outResolutionX;
                                double blockMaxY = dstEnvelope.MaxY - blockHeight * outResolutionY * blockYIndex;
                                double blockMinY = blockMaxY - blockHeight * outResolutionY;
                                blockEnvelope = new PrjEnvelope(blockMinX, blockMaxX, blockMinY, blockMaxY);
                                //根据当前输出块,反推出对应的源数据块起始行列
                                GetEnvelope(_xs, _ys, srcJdSize.Width, srcJdSize.Height, blockEnvelope, out orbitBlock);
                                if (orbitBlock.Width <= 0 || orbitBlock.Height <= 0) //当前分块不在图像内部
                                {
                                    progress += dstBandCount;
                                    continue;
                                }
                                GetBlockDatas(_xs, _ys, srcJdSize.Width, srcJdSize.Height, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height, out blockOrbitXs, out blockOrbitYs);
                            }
                            float[] solarZenithData = null;
                            if (prjSettings.IsRadiation && prjSettings.IsSolarZenith)
                            {
                                if (File.Exists(_szDataFilename))
                                {
                                    ReadBandData(out solarZenithData, _solarZenithCacheRaster, 1, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height);
                                }
                                TryReadZenithData(orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height);
                            }
                            Size orbitBlockSize = new Size(orbitBlock.Width, orbitBlock.Height);
                            _rasterProjector.ComputeIndexMapTable(blockOrbitXs, blockOrbitYs, orbitBlockSize, dstBlockSize, blockEnvelope, _maxPrjEnvelope, out dstRowBlockLUT, out dstColBlockLUT, null);
                            //执行投影
                            UInt16[] srcBandData = new UInt16[orbitBlock.Width * orbitBlock.Height];
                            UInt16[] dstBandData = new UInt16[blockWidth * blockHeight];
                            for (int i = 0; i < dstBandCount; i++)      //读取原始通道值,投影到目标区域
                            {
                                if (progressCallback != null)
                                {
                                    progress++;
                                    percent = progress * 100 / progressCount;
                                    progressCallback(percent, string.Format("投影完成{0}%", percent));
                                }
                                int bandNo = outBandNos[i];
                                ReadBandData(srcBandData, srcRaster, bandNo, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Width, orbitBlock.Height);
                                if (prjSettings.IsRadiation)
                                {
                                    DoRadiation(srcBandData, orbitBlock.xOffset, orbitBlock.yBegin, orbitBlock.Size, bandNo, prjSettings.IsRadiation, prjSettings.IsSolarZenith, solarZenithData);
                                }
                                _rasterProjector.Project <UInt16>(srcBandData, orbitBlock.Size, dstRowBlockLUT, dstColBlockLUT, dstBlockSize, dstBandData, 0, null);
                                IRasterBand band = prdWriter.GetRasterBand(i + 1);
                                {
                                    unsafe
                                    {
                                        fixed(UInt16 *ptr = dstBandData)
                                        {
                                            IntPtr bufferPtr    = new IntPtr(ptr);
                                            int    blockOffsetY = blockYIndex * dstBlockSize.Height;
                                            int    blockOffsetX = blockXIndex * dstBlockSize.Width;

                                            band.Write(blockOffsetX, blockOffsetY, blockWidth, blockHeight, bufferPtr, enumDataType.UInt16, blockWidth, blockHeight);
                                        }
                                    }
                                }
                            }
                            ReleaseZenithData();
                            srcBandData  = null;
                            dstBandData  = null;
                            blockOrbitXs = null;
                            blockOrbitYs = null;
                            Size srcBufferSize = new Size(orbitBlock.Width, orbitBlock.Height);
                            ProjectAngle(dstBlockSize, srcBufferSize, blockWidth, blockHeight, blockYIndex, blockXIndex, orbitBlock, dstRowBlockLUT, dstColBlockLUT, progressCallback);
                        }
                    }
                    dstRowBlockLUT = null;
                    dstColBlockLUT = null;
                }
            }
        }