用VTK绘制DEM之一

DEM的显示是GIS的基本功能,利用GDAL和VTK强大的功能可以很容易做到这一点,而Python则使实现更为简单。

关于GDAL可以参考lilin的学习笔记http://wiki.woodpecker.org.cn/moin/lilin/gdal-index,VTK可以参考我博客里的其他文章。

先看看我的效果图,目前只显示地形,没有根据高程设置颜色,也没有叠加遥感影像。高程数据采用的是SRTM3,可以去http://www2.jpl.nasa.gov/srtm/cbanddataproducts.html下载。

用VTK绘制DEM之一_第1张图片

先看代码再解释几个关键函数。

# !C:/Python24/python.exe
#
coding=utf-8

# app.py
#
author:liujunzhi
#
date:20071210

import  vtk
from  vtk.wx.wxVTKRenderWindow  import  wxVTKRenderWindow

import  sys, time
from  gdal  import  gdal
from  wxPython.wx  import   *

VTK_POLYGON 
=   7

def  display_dem(renWin, demName):
    
# open dem file with gdal
    dataset  =  gdal.Open(demName)
    
    
if  dataset  is  None:
        
print   ' open DEM file failed! '
        sys.exit(0)
    
    geoTrans 
=  dataset.GetGeoTransform()
    
    band 
=  dataset.GetRasterBand( 1 )
    
# ReadAsArray(self, xoff=0, yoff=0, win_xsize=None, win_ysize=None, buf_xsize=None, buf_ysize=None, buf_obj=None)
    array  =  band.ReadAsArray(0, 0,  500 500 )
    
    width 
=  len(array[0])
    height 
=  len(array)
    
    polyData 
=  vtk.vtkPolyData()
    polyData.SetLines(vtk.vtkCellArray())
    polyData.SetPolys(vtk.vtkCellArray())
    
    points 
=  vtk.vtkPoints()
    
for  yPixel  in  range(height):
        
for  xPixel  in  range(width):
            xGeo 
=  geoTrans[0]  +  xPixel * geoTrans[ 1 +  yPixel * geoTrans[ 2 ]
            yGeo 
=  geoTrans[ 3 +  xPixel * geoTrans[ 4 +  yPixel * geoTrans[ 5 ]
            
# print "X:%f   Y:%f  Z:%f" % (xGeo, yGeo, array[yPixel][xPixel])
            points.InsertNextPoint(xGeo, yGeo, array[yPixel][xPixel] / 10000 )
    
    
# set points
    polyData.SetPoints(points)
    
    
# set polygon info
    ids  =  vtk.vtkIdList()
    
for  yPixel  in  range(height - 1 ):
        
for  xPixel  in  range(width - 1 ):
            indexTL 
=  yPixel * width  +  xPixel
            indexTR 
=  yPixel * width  +  xPixel  +   1
            indexBL 
=  indexTL  +  width
            indexBR 
=  indexTR  +  width
            ids.Reset()
            ids.InsertNextId(indexTL)
            ids.InsertNextId(indexBL)
            ids.InsertNextId(indexBR)
            cell 
=  polyData.InsertNextCell(VTK_POLYGON, ids)
            ids.Reset()
            ids.InsertNextId(indexTL)
            ids.InsertNextId(indexTR)
            ids.InsertNextId(indexBR)
            cell 
=  polyData.InsertNextCell(VTK_POLYGON, ids)        
   
# end vtkPolyData 
    
    polyDataMapper 
=  vtk.vtkPolyDataMapper()
    polyDataMapper.SetInput(polyData)
    
    actor 
=  vtk.vtkActor()
    actor.SetMapper(polyDataMapper)
    actor.GetProperty().SetColor(
1 1 , 0)
    
    ren 
=  vtk.vtkRenderer()
    ren.AddActor(actor)
    
    renWin.AddRenderer(ren)


# ----------------------------------------------------------------------------  
def  main():
    
#  every wx app needs an app
    app  =  wxPySimpleApp()

    
#  create the widget
    frame  =  wxFrame(None,  - 1 " 3d Demo " , size = wxSize( 400 , 400 ))
    widget 
=  wxVTKRenderWindow(frame,  - 1 )
    renWin 
=  widget.GetRenderWindow()

    demname 
=   ' data/36074346 '
    display_dem(renWin, demname)

    frame.Show(
1 )
    app.MainLoop()

if   __name__   ==   " __main__ " :
    main()

 解释几个关键的函数:

1.GDAL中的ReadAsArray

ReadAsArray(self, xoff=0, yoff=0, win_xsize=None, win_ysize=None, buf_xsize=None , buf_ysize=None, buf_obj=None) 

 这里引用lilin的解释:

>>> band
.ReadAsArray(100,100,10,10)

头两个100是取值窗口的左上角在实际数据中所处象元的xy位置。后两个是取值窗口覆盖的区域大小,再后面是取值窗口取出数组进行缩放后数组的大小。这里需要注意的是这里的buffer大小是根据参数自动分配的,可以不指定,如果不指定,则和第3,4个参数一致。经过5,6两个参数的设置,可以进行缩放。比如真的取值窗口大小可以是20*20,而取出后数组就可以人工设置大小。让他称为10*10的数组,或者是40*40的数组。如果设置20*40则取出的数组对于真实图像来说有了变形。

2.VTK的vtkPolyData

这个类是用来组织数据的,分两部分:

1.vtkPoints

用来存放数据集中的点数据,可通过SetPoints函数指定

如:polyData.SetPoints(points)

2.vtkCellArray

用来指定这些点数据是怎么组成线、多边形的

比如points中有5个点,我指定前三个点组成一个三角形,后两个点组成一条线,代码如下:

import  vtk

VTK_LINE 
=   3
VTK_POLYGON 
=   7

#  initialize polydata object
polydata  =  vtk.vtkPolyData()
polydata.SetLines(vtk.vtkCellArray())
polydata.SetPolys(vtk.vtkCellArray())

points 
=  vtk.vtkPoints()
#  points for poly 1 (triangle)
points.InsertNextPoint( 0.2 0.3 , 0)
points.InsertNextPoint(
0.4 0.55 , 0)
points.InsertNextPoint(
0.2 0.8 , 0)
#  points for line 1 (line)
points.InsertNextPoint( 0.5 0.3 , 0)
points.InsertNextPoint(
0.5 0.8 , 0)

#  create poly 1
ids  =  vtk.vtkIdList()
ids.InsertNextId(0)
ids.InsertNextId(
1 )
ids.InsertNextId(
2 )
cell 
=  polydata.InsertNextCell(VTK_POLYGON, ids)

#  create line 1
ids.Reset()
ids.InsertNextId(
3 )
ids.InsertNextId(
4 )
cell 
=  polydata.InsertNextCell(VTK_LINE, ids)

你可能感兴趣的:(用VTK绘制DEM之一)