阅读:2790回复:5
AE开发TinToRaster的问题
<DIV >在帮助系统里面有这样一段vb谢的代码,据说在vb环境下运行的结果是perfect但是我把它改成.net平台下用c@写就没有结果显示,在toc控件中显示value的值巨大,应该是double float的范围值,不知道有没有人做过类似的东东,何故没有结果显示呢<BR>example中的示例代码(VB)<BR>' Supported pixel types limited to float and long because output currently limited to native ESRI Grid<BR>' This routine handles cancel tracking so passed TIN should not have its CancelTracker set.<BR>Public Function TinToRaster(pTin As ITinAdvanced, eRastConvType As esriRasterizationType, _<BR> sDir As String, sName As String, ePixelType As rstPixelType, cellsize As Double, pExtent As IEnvelope, _<BR> bPerm As Boolean) As IRasterDataset<BR><BR> ' The origin used by CreateRasterDataset is the lower left cell corner.<BR> ' The extent passed is that of the TIN's.<BR> ' Define the raster origin and number of rows and columns so that the raster<BR> ' is of sufficient extent to capture area defined by passed envelope. The cell<BR> ' center is located at the origin.<BR> Dim pOrigin As IPoint<BR> Set pOrigin = pExtent.LowerLeft<BR> pOrigin.x = pOrigin.x - (cellsize * 0.5)<BR> pOrigin.y = pOrigin.y - (cellsize * 0.5)<BR><BR> Dim nCol As Long, nRow As Long<BR> nCol = Round(pExtent.Width / cellsize) + 1<BR> nRow = Round(pExtent.Height / cellsize) + 1<BR><BR> Dim pGDS As IGeoDataset<BR> Set pGDS = pTin<BR> Dim pSR As ISpatialReference2<BR> Set pSR = pGDS.SpatialReference<BR><BR> Dim pRDS As IRasterDataset<BR> Set pRDS = dbUtil.CreateRasterSurf(sDir, sName, "GRID", pOrigin, nCol, nRow, cellsize, cellsize, ePixelType, pSR, bPerm)<BR><BR> DoEvents<BR><BR> Dim pRawPixels As IRawPixels<BR> Set pRawPixels = dbUtil.GetRawPixels(pRDS, 0)<BR><BR> Dim pCache As stdole.IUnknown<BR> Set pCache = pRawPixels.AcquireCache<BR><BR> Dim pTinSurf As ITinSurface<BR> Set pTinSurf = pTin<BR><BR> Dim pRasterProps As IRasterProps<BR> Set pRasterProps = pRawPixels<BR><BR> Dim nodataFloat As Single<BR> Dim nodataInt As Long<BR><BR> Dim dZMin As Double<BR> dZMin = pTin.Extent.zmin<BR><BR> Dim vNoData As Variant<BR> If (ePixelType = PT_FLOAT) Then<BR> vNoData = CSng(dZMin - 1)<BR> Else<BR> vNoData = CLng(dZMin - 1)<BR> End If<BR><BR> pRasterProps.NoDataValue = vNoData<BR><BR> Dim pOffset As IPnt<BR> Set pOffset = New DblPnt<BR><BR> ' Set blocksize. Restrict how large it is as not to consume too much memory for<BR> ' big output datasets.<BR> Dim lMaxBlockX As Long<BR> lMaxBlockX = 2048<BR> If (nCol < lMaxBlockX) Then<BR> lMaxBlockX = nCol<BR> End If<BR><BR> Dim lMaxBlockY As Long<BR> lMaxBlockY = 2048<BR> If (nRow < lMaxBlockY) Then<BR> lMaxBlockY = nRow<BR> End If<BR><BR> Dim pBlockSize As IPnt<BR> Set pBlockSize = New DblPnt<BR> pBlockSize.x = lMaxBlockX<BR> pBlockSize.y = lMaxBlockY<BR><BR> Dim pPixelBlock As IPixelBlock3<BR> Set pPixelBlock = pRawPixels.CreatePixelBlock(pBlockSize)<BR><BR> Dim blockArray As Variant<BR> blockArray = pPixelBlock.PixelDataByRef(0)<BR><BR> ' Set up cancel tracking and progress bar<BR> Dim pCancel As ITrackCancel<BR> Set pCancel = New CancelTracker<BR> pCancel.CancelOnClick = False<BR> pCancel.CancelOnKeyPress = True<BR> Dim pApp As IApplication<BR> Set pApp = New AppRef<BR> Dim pProg As IStepProgressor<BR> Set pProg = pApp.StatusBar.ProgressBar<BR> pCancel.Progressor = pProg<BR> Dim lBlockCount As Long<BR> lBlockCount = Round((nCol / lMaxBlockX) + 0.49) * Round((nRow / lMaxBlockY) + 0.49)<BR> pProg.Message = "Rasterizing. Press ESC to cancel..."<BR> pProg.Position = 0<BR> If (lBlockCount = 1) Then ' tin querypixelblock can do the tracking/progressing with 1 block<BR> pProg.Show<BR> Set pTin.TrackCancel = pCancel<BR> Else ' more than 1 block requires this routine, rather than tin function, to track/progress<BR> pProg.MinRange = 0<BR> pProg.MaxRange = lBlockCount<BR> pProg.StepValue = 1<BR> pProg.Show<BR> End If<BR> DoEvents ' make sure the bar and the text get updated on screen<BR><BR> Dim pBlockOrigin As IPoint<BR> Set pBlockOrigin = New Point<BR><BR> Dim lColOffset As Long<BR> Dim lRowOffset As Long<BR><BR> ' Left to right, top to bottom, iteration of pixel blocks.<BR> For lRowOffset = 0 To (nRow - 1) Step lMaxBlockY<BR><BR> For lColOffset = 0 To (nCol - 1) Step lMaxBlockX<BR><BR> ' See if pixelblock needs to be resized in X for last column chunk.<BR> ' RawPixel.Write will clip the pixelblock if it's too big, so the resize<BR> ' isn't absolutely necessary, but resizing will eliminate unecessary<BR> ' effort for TIN's QueryPixelBlock.<BR> If ((nCol - lColOffset) < lMaxBlockX) Then<BR> pBlockSize.x = (nCol - lColOffset)<BR> Set pPixelBlock = pRawPixels.CreatePixelBlock(pBlockSize)<BR> blockArray = pPixelBlock.PixelDataByRef(0)<BR> End If<BR><BR> ' QueryPixelBlock takes an origin representing the upper left cell center.<BR> ' Calculate that cell center's position here. Calculate it based on the<BR> ' raster's origin (lower left) and current row/col offset.<BR> pBlockOrigin.x = pOrigin.x + (lColOffset * cellsize) + (cellsize * 0.5)<BR> pBlockOrigin.y = pOrigin.y + ((nRow - lRowOffset) * cellsize) - (cellsize * 0.5)<BR><BR> pTinSurf.QueryPixelBlock pBlockOrigin.x, pBlockOrigin.y, cellsize, cellsize, eRastConvType, vNoData, blockArray<BR><BR> pOffset.x = lColOffset<BR> pOffset.y = lRowOffset<BR><BR> ' The offset for 'write' is the upper left of the pixel block by col/row number.<BR> ' Base is 0.<BR> pRawPixels.Write pOffset, pPixelBlock<BR><BR> If (lBlockCount > 1) Then<BR> If (Not pCancel.Continue) Then GoTo Cancel<BR> Else<BR> If (pTin.ProcessCancelled) Then GoTo Cancel<BR> End If<BR><BR> Next lColOffset<BR><BR> ' See if pixelblock size needs to be reset for columns<BR> Dim bReset As Boolean<BR> bReset = False<BR> If (pBlockSize.x <> lMaxBlockX) Then<BR> pBlockSize.x = lMaxBlockX<BR> bReset = True<BR> End If<BR><BR> ' See if pixelblock size needs to be reset for rows<BR> If ((nRow - lRowOffset) < lMaxBlockY) Then<BR> pBlockSize.y = (nRow - lRowOffset)<BR> bReset = True<BR> End If<BR><BR> If (bReset) Then<BR> Set pPixelBlock = pRawPixels.CreatePixelBlock(pBlockSize)<BR> blockArray = pPixelBlock.PixelDataByRef(0)<BR> End If<BR><BR> Next lRowOffset<BR><BR> 'pProg.Message = "Returning cache..."<BR> pRawPixels.ReturnCache pCache<BR> Set pCache = Nothing<BR><BR> ' need this for some reason with temporary integer grids<BR> 'If (Not bPerm) And (ePixelType = PT_LONG) Then<BR>' pProg.Message = "Stats..."<BR>' Dim pBand As iRasterBand<BR>' Set pBand = pRawPixels<BR>' Dim pStats As IRasterStatistics<BR>' Set pStats = pBand.Statistics<BR>' pStats.Recalculate<BR> 'End If<BR><BR> 'If (bPerm) Then<BR> ' flush edits to disk by freeing all pointers<BR> 'pProg.Message = "Freeing and opening..."<BR> Set pRDS = Nothing<BR> Set pRawPixels = Nothing<BR> Set pPixelBlock = Nothing<BR> Set pRasterProps = Nothing<BR> blockArray = 0<BR> Set pRDS = dbUtil.OpenRasterDataset(sDir, sName)<BR> 'End If<BR><BR> pApp.StatusBar.HideProgressBar<BR><BR> If (lBlockCount = 1) Then<BR> Set pTin.TrackCancel = Nothing<BR> End If<BR><BR> Set TinToRaster = pRDS<BR> Exit Function<BR><BR>Cancel:<BR> pApp.StatusBar.HideProgressBar<BR> Set TinToRaster = Nothing<BR>End Function<BR><BR>Public Function CreateRasterSurf(sDir As String, sName As String, sFormat As String, _<BR> pOrigin As IPoint, nCol As Long, nRow As Long, cellsizeX As Double, cellsizeY As Double, _<BR> ePixelType As rstPixelType, pSR As ISpatialReference2, bPerm As Boolean) As IRasterDataset<BR><BR> Dim rWksFac As IWorkspaceFactory<BR> Set rWksFac = New RasterWorkspaceFactory<BR><BR> Dim wks As IWorkspace<BR> Set wks = rWksFac.OpenFromFile(sDir, 0)<BR><BR> Dim rWks As IRasterWorkspace2<BR> Set rWks = wks<BR><BR> Dim numbands As Long<BR> numbands = 1<BR><BR> Dim pRDS As IRasterDataset<BR> Set pRDS = rWks.CreateRasterDataset(sName, sFormat, pOrigin, nCol, nRow, cellsizeX, cellsizeY, numbands, ePixelType, pSR, bPerm)<BR><BR> Set CreateRasterSurf = pRDS<BR>End Function<BR><BR><BR><BR>Public Function GetRawPixels(pRDS As IRasterDataset, band As Long) As IRawPixels<BR> Dim pBandCollection As IRasterBandCollection<BR> Set pBandCollection = pRDS<BR><BR> Dim pRasterBand As iRasterBand<BR> Set pRasterBand = pBandCollection.Item(band)<BR><BR> Set GetRawPixels = pRasterBand<BR>End Function<BR><BR>我改写的C# 的代码<BR><BR><BR>有没有大哥知道究竟错在哪里,<BR>我看esri online 的discussion上似乎这个QueryPixelBlock用在.net上有问题<BR>而在vb里面似乎可以正常运行出结果</DIV>
|
|
|
1楼#
发布于:2007-03-26 20:28
<DIV 12px">我写的C#的代码<BR>public IRasterDataset TinToRaster(ITinAdvanced pTin,esriRasterizationType eRastConvType,string sDir,string sName,rstPixelType ePixelType,double cellsize, IEnvelope pExtent,bool bPerm)<BR> {<BR> <BR> try<BR> {<BR><BR> IPoint pOrigin;<BR> pOrigin = pExtent.LowerLeft;<BR> pOrigin.X = pOrigin.X - (cellsize * 0.5);<BR> pOrigin.Y = pOrigin.Y - (cellsize * 0.5);<BR><BR> int nCol;<BR> int nRow;<BR> nCol = (int)Math.Round(pExtent.Width/cellsize) + 1;<BR> nRow = (int)Math.Round(pExtent.Height/cellsize) + 1;<BR><BR> IGeoDataset pGDS;<BR> pGDS = pTin as IGeoDataset;<BR> ISpatialReference2 pSR;<BR> pSR = pGDS.SpatialReference as ISpatialReference2;<BR><BR> IRasterDataset pRDS;<BR> pRDS = CreateRasterSurf(sDir, sName, "GRID", pOrigin, nCol, nRow, cellsize,cellsize, ePixelType, pSR, bPerm);<BR><BR> IRawPixels pRawPixels;<BR> pRawPixels = GetRawPixels(pRDS, 0);<BR><BR> IRasterProps pRasterProps;<BR> pRasterProps = pRawPixels as IRasterProps;<BR><BR> stdole.IUnknown pCache;<BR> pCache = pRawPixels.AcquireCache() as stdole.IUnknown;<BR><BR> ITinSurface pTinSurf;<BR> pTinSurf = pTin as ITinSurface;<BR><BR> float nodataFloat;<BR> long nodataInt;<BR><BR> double dZMin;<BR> dZMin = pTin.Extent.ZMin;<BR><BR> object vNoData;<BR> if(ePixelType == rstPixelType.PT_FLOAT) <BR> {<BR> vNoData = Convert.ToSingle(dZMin - 1);<BR> }<BR> else<BR> {<BR> vNoData = Convert.ToInt64(dZMin - 1);<BR> }<BR> pRasterProps.NoDataValue = vNoData;<BR><BR> IPnt pOffset=null;<BR> pOffset = new DblPnt();<BR><BR> long lMaxBlockX;<BR> lMaxBlockX = 2048;<BR> if (nCol < lMaxBlockX) <BR> {<BR> lMaxBlockX = nCol;<BR> }<BR> long lMaxBlockY;<BR> lMaxBlockY = 2048;<BR> if (nRow < lMaxBlockY)<BR> {<BR> lMaxBlockY = nRow;<BR> }<BR><BR> IPnt pBlockSize=null;<BR> pBlockSize = new DblPnt();<BR><BR><BR> pBlockSize.X = lMaxBlockX;<BR> pBlockSize.Y = lMaxBlockY;<BR><BR><BR> IPixelBlock3 pPixelBlock3;<BR> pPixelBlock3 = pRawPixels.CreatePixelBlock(pBlockSize) as IPixelBlock3;<BR> <BR><BR> // Get pixeldata array<BR> System.Array blockArray;<BR> blockArray=(System.Array)pPixelBlock3.get_PixelDataByRef(0);<BR>/ <BR> <BR> // Create pixelblock<BR> IPnt pBlockOrigin;<BR> pBlockOrigin = new DblPntClass();<BR><BR><BR> //定义栅格化时高程的内插方法--自然邻居内插方法<BR> pTinSurf.RasterInterpolationMethod=esriSurfaceInterpolationType.esriNaturalNeighborInterpolation;<BR> <BR> // Write the pixeldata back<BR> System.Object cachePointer;<BR><BR> cachePointer = pRawPixels.AcquireCache();<BR><BR> long lColOffset;<BR> long lRowOffset;<BR> <BR> // See if pixelblock needs to be resized in X for last column chunk.<BR> //RawPixel.Write will clip the pixelblock if it's too big, so the resize<BR> //isn't absolutely necessary, but resizing will eliminate unecessary<BR> //effort for TIN's QueryPixelBlock.<BR> for(lRowOffset = 0; lRowOffset<=(nRow - 1); lRowOffset=lRowOffset+lMaxBlockY)<BR> {<BR> for(lColOffset = 0; lColOffset<=(nCol - 1); lColOffset=lColOffset+lMaxBlockX)<BR> {<BR> <BR> if ((nCol - lColOffset) < lMaxBlockX) <BR> {<BR> pBlockSize.X = (nCol - lColOffset);<BR><BR> //See if pixelblock size needs to be reset for columns<BR> bool bReset;<BR> bReset = false;<BR> if (pBlockSize.X != lMaxBlockX) <BR> {<BR> pBlockSize.X = lMaxBlockX;<BR> bReset = true;<BR> }<BR> //See if pixelblock size needs to be reset for rows<BR> if ((nRow - lRowOffset) < lMaxBlockY) <BR> {<BR> pBlockSize.Y = (nRow - lRowOffset);<BR> bReset = true;<BR> }<BR> if (bReset) <BR> {<BR> pPixelBlock3 = pRawPixels.CreatePixelBlock(pBlockSize) as IPixelBlock3;<BR> blockArray = (System.Array)pPixelBlock3.get_PixelDataByRef(0);<BR> <BR> }<BR><BR> }<BR><BR> pPixelBlock3 = pRawPixels.CreatePixelBlock(pBlockSize) as IPixelBlock3;<BR> blockArray = (System.Array)pPixelBlock3.get_PixelDataByRef(0);<BR> //QueryPixelBlock takes an origin representing the upper left cell center.<BR> //Calculate that cell center's position here. Calculate it based on the<BR> //raster's origin (lower left) and current row/col offset.<BR> pBlockOrigin.X = pOrigin.X + (lColOffset * cellsize) + (cellsize * 0.5);<BR> pBlockOrigin.Y = pOrigin.Y + ((nRow - lRowOffset) * cellsize) - (cellsize * 0.5);<BR> <BR> pTinSurf.QueryPixelBlock(pBlockOrigin.X, pBlockOrigin.Y, cellsize, cellsize, eRastConvType, vNoData, blockArray);<BR> }<BR> <BR> <BR> <BR> pOffset.X = lColOffset;<BR> pOffset.Y = lRowOffset;<BR> pRawPixels.Write(pOffset, (IPixelBlock)pPixelBlock3);<BR> }<BR><BR><BR><BR><BR> pRawPixels.ReturnCache(cachePointer);<BR> <BR> return pRDS;<BR><BR> }<BR><BR> catch(Exception ex)<BR> {<BR> System.Diagnostics.Debug.WriteLine(ex.Message);<BR> return null;<BR> }<BR><BR><BR><BR>}<BR><BR>//***************************************<BR> //*目的:返回IRawPixels<BR> //*输入:Raster数据集<BR> //***************************************<BR> public IRawPixels GetRawPixels(IRasterDataset pRDS, int band) <BR> {<BR> IRawPixels pRP;<BR> IRasterBandCollection pBandCollection;<BR> pBandCollection = pRDS as IRasterBandCollection;<BR><BR> IRasterBand pRasterBand;<BR> pRasterBand = pBandCollection.Item(band);<BR><BR> pRP = pRasterBand as IRawPixels;<BR> return pRP;<BR> <BR> }<BR> //***************************************<BR> //*目的:创建Raster数据集<BR> //*输入:Raster数据<BR> //***************************************<BR> public IRasterDataset CreateRasterSurf(string sDir, string sName, string sFormat, IPoint pOrigin,int nCol, int nRow, double cellsizeX,double cellsizeY, rstPixelType ePixelType, ISpatialReference2 pSR, bool bPerm)<BR> {<BR> <BR> IWorkspaceFactory rWksFac;<BR> rWksFac = new RasterWorkspaceFactory();<BR><BR> IWorkspace wks;<BR> wks = rWksFac.OpenFromFile(sDir, 0);<BR><BR> IRasterWorkspace2 rWks;<BR> rWks = wks as IRasterWorkspace2;<BR><BR> int numbands;<BR> numbands = 1;<BR><BR> IRasterDataset pRDS;<BR> pRDS = rWks.CreateRasterDataset(sName, sFormat, pOrigin, nCol, nRow, cellsizeX, cellsizeY, numbands, ePixelType, pSR, bPerm);<BR><BR> return pRDS;<BR> <BR> }<BR><BR>有没有大哥知道究竟错在哪里, 急啊<BR>我看esri online 的discussion上似乎这个QueryPixelBlock用在.net上有问题<BR>而在vb里面似乎可以正常运行出结果</DIV>
|
|
|
2楼#
发布于:2007-03-26 21:47
<P><STRONG>我看esri online 的discussion上似乎这个QueryPixelBlock用在.net上有问题</STRONG><BR></P>
<P>是有这样的问题,不知道你是不是使用的9.2版本?</P> |
|
|
3楼#
发布于:2007-03-27 08:17
<P>我用的是AE9.1 SP3 </P>
<P>不知道有没有解决的办法啊</P> |
|
|
4楼#
发布于:2007-03-27 09:02
<P>vb可以自己转换数值的精度</P>
<P>c#就不回自己转换,要在你转换的数值前加上Convert.ToDouble辅助转换</P> |
|
|
5楼#
发布于:2007-03-27 09:59
<P>谢谢阿</P>
<P>但是我在 if(ePixelType == rstPixelType.PT_FLOAT) <BR> {<BR> vNoData = Convert.ToSingle(dZMin - 1);<BR> }</P> <P>已经把它转成了单精度浮点型阿,并且rstPixelType.PT_FLOAT就是Pixel values are single precision floating point.应该不需要转成Convert.ToDouble双精度吧,我刚才试了Convert.ToDouble,运行会报错.</P> |
|
|