利用surfer提供的Automation技术和delphi编程语言的OLE自动化方法实现气象要素的等值线绘图功能,充分发挥surfer的网格化能力和绘图功能,数据处理简单、高效。
关键词:delphi;surfer;等值线绘图
Delphi是Borland公司的编程工具,凭借其开发数据库和网络应用程序的优势,成为较流行的开发工具,特别适合于基层气象台站气象业务系统的开发。surfer是Olden软件公司在windows环境下开发的地理数据绘图软件,具有强大的绘图和计算分析能力,从7.0开始增加Application技术,支持其它编程语言的二次开发。本文使用delphi7和surfer8。
1 surfer对象介绍
Surfer提供了完整OEL Automation功能供外部应用程序调用,常用Surfer对象有:Application,BaseMap,ContourMap,Documents,Grid,Levels,MapFrame,Overlays,PlotDocument,Selection,Shape等。其中Application对象代表Surfer应用程序实例,是其他Surfer对象的根。Shape是绘图元素对象的基类对象,Surfer中绘图元素很多,如坐标轴、等值线、底图、文本等。在程序中可以通过给对象的属性赋值改变对象的状态,实现Surfer绘图的程序化、自动化。surfer的主要对象层次关系如图1[1]。
图1 surfer主要对象层次关系图
2 实现等值线绘图功能
2.1 气象要素数据格式
气象要素数据的格式一般为文本格式,它包含的数据项有资料点的位置坐标、要素值。具体的数据格式如下:
I1 x1 y1 h1 z1
I2 x2 y2 h2 z2
…………………
In xn yn hn zn
五列数据分别是区站号、经度、纬度、海拔高度和要素值。
2.2 建立delphi与surfer服务器的通讯
为了实现surfer的嵌入,首先要引用surfer的Application对象。在delphi中可通过两种方式引用surfer的Application对象,一是导入surfer类型库,通过Import Typ Library 命令导入“surfer8 Typ Library”,安装后在控件面板上出现Application(Surfer_TLB)控件。二是在程序中用CreateoleObject()创建。通过Application根对象,下面各层对象便可逐一引用,实现客户程序对surfer主程序的控制。
2.3离散数据的空间内插
等值线图需要网格数据生成,必须先对离散数据进行空间内插。Surfer Automation提供了格网内插函数GridData,能将txt、dat、Excel等格式的原始数据文件转换为surfer格网文件(grd)。GridData函数包含57项参数,其中最重要的一项就是内插方式(Algorithm参数),在这项参数中提供了反距离加权插值法、克里格插值法、自然邻点插值法等12种方法,用户可根据需要设定。克里格(Kriging)插值法与经典插值算法相比,具有算法灵活、可获得估计方差等优点,在气象分析、环境监测等领域广泛应用。
2.4 等值线绘制
绘制等值线,surfer提供了Contourmap对象供用户开发使用。首先使用Shapes对象的AddContourMap函数,由格网数据直接生成等值线图,然后通过Contourmap对象的属性控制显示内容。比如,ShowColorScale属性控制颜色图例是否显示,smoothcontours属性控制等值线平滑,FillContours属性决定等值线填充。
Contourmap对象下面还有个Level子对象,它能对等值线进行间距、颜色、线型、注记等方面的设置。Level对象的AutoGenerate函数很重要,它有三个参数,分别为起始值、终止值和等值线间距,通过设置这些参数,用户可以轻松得到格网数据所对应的各式等值线。
2.5 添加背景底图
我们需要把本地的地图放在等值线下面作为参考,在surfer中的格式是*.bln、*.gsb、*.jpg等多种形式,比较常用的是*.bln,包含点、线、面信息的ASCII码文件。其数据格式是:
length,flag
x1,y1
x2,y2
...
xn,yn
length,flag
x1,y1
x2,y2
...
xn,yn
Bln为多段文件,每段一个实体(点、线、面)。每段文件由A,B两列数据组成,首行为标志行,length是背景底图曲线中点的个数,flag取0或1。Bln文件同时用作Blank作图(清除指定区域的等值线),当flag为1时,表示多边形内部的区域被空白,flag为0时,表示多边形外部的区域被空白。由第2行开始依次为各顶点的X,Y坐标。当x1=xn,y1=yn时,为封闭多边形。
Bln文件可以在其它地理信息软件中导出并按surfer的格式修改[2]。本文使用的Bln文件便是利用mapinfo从1:250000的地理数据中提取的行政区划线,导出MIF文件后修改得到。ArcView中的shp文件surfer可以直接使用。
surfer提供了BaseMap对象供用户使用,使用Shapes对象的AddbaseMap函数,由底图数据添加底图。
2.6 添加站点标注
有时候我们需要在图中加入测站的坐标,并用圆点、五星等符号将其标出,可用surfer的postMap对象(粘贴图),用Shapes的AddpostMap函数将测站信息数据生成postMap,粘贴图数据文件是含有测站经纬度坐标和台站信息的ASCII码文件后缀名为txt或dat,格式如下:
I1 x1 y1 h1 label1
I2 x1 y1 h2 label2
.................
In xn yn hn labeln
In是区站号,hn是海拔高度,xn,yn是坐标,labeln为标注内容(台站名称)。
2.7 等值线的裁剪
由离散的气象要素数据文件生成网格文件时,Surfer将根据原始X,Y的取值范围和所选用的数学模型,自动生成一个矩形网格。但在实际工作中,我们不需要边界以外的等值线。surfer提供了Blank功能,可以用边界bln文件将网格数据中边界以外的数据去掉。
用这种方法效果并不好,如果网格达不到一定的密度,生成的图形边界部分锯齿严重。本文采用底图覆盖的方式,用颜色填充的办法隐藏掉边界以外的等值线。具体方法是在其它地理信息软件中制作一张“圈饼”图,即中部镂空,镂空部分恰好是边界以内的区域,按2.5中的格式修改成bln文件添加底图。
2.8 图形合并
最后需要将各图层合并,配准坐标。使用Selection[PlotDocumentobject]对象的OverlayMaps方法。
3、实例
从气象要素数据出发,直接生成气象要素等值线,绘制过程在surfer后台程序中进行,结果显示在业务程序中。效果见图2。
图2 实例效果图
主要代码:
surfer_out(inDataFile:string;nlvls:integer);
//inDataFile数据文件
//nlvls:等值线条数
var
BaseMap,SeventhContour,Levels,surferapp,Plot,Shapes,MapFrame,ImageMap,ColorMap,contourMap,postSTATIONSMap,postvalueMap:Variant;
Bjfile,Gridfile,savefile,Basefile,postSTATIONSfile:string;
path:string;
Interval:Double;
cMin,cMax:Single;
begin
path:=ExtractFilePath(Application.ExeName)+'data/';
Bjfile:=path+'bj.shp';
Gridfile:=path+'data.grd';
Basefile:=path+'xj.bln';
savefile:=path+'outimage.bmp';
postSTATIONSfile:=path+'qxs.dat';
SurferApp:=CreateoleObject('Surfer.Application');//创建Surfe应用程序[3] [4]
Plot:=SurferApp.Documents.Add(1);//创建Plot文档对象
Shapes:=Plot.Shapes;//获取Plot文档对象的绘图元素对象集合
SurferApp.GridData(DataFile:=inDataFile,Algorithm:=2,DupMethod:=2,ShowReport:=False,OutGrid:=Gridfile,xmin:=103.604,xMax:=105.360,yMin:=27.838,yMax:=29.275,xcol:=2,ycol:=3,zcol:=5);//用克里格算法对原始数据进行网格化;
MapFrame:=Shapes.AddContourMap(Gridfile);//建立等值线对象
ContourMap:=MapFrame.Overlays.Item(1);//设置当前等值线对象
Contourmap.FillContours:=true;//允许等值线填充
Contourmap.smoothcontours:=4;//平滑等值线
Contourmap.ShowColorScale:=true;//显示图例
Levels:=Contourmap.Levels;//取得等值线等级
cMin:=Levels.Item(Index:=1).Value ;
cMax:=Levels.Item(Index:=Levels.Count).Value ;
Interval:=(cMax-cMin)/nlvls;
Levels.AutoGenerate(MinLevel:=cMin,MaxLevel:=cMax,Interval:=Interval);
MapFrame:=Shapes.AddBaseMap(ImportFileName:=Basefile);//建立行政区域底图对象
MapFrame:=Shapes.AddBaseMap(ImportFileName:=Bjfile);//建立镂空边界底图
BaseMap:=MapFrame.Overlays.Item(1);//设置当前底图对象
BaseMap.Fill.Pattern:='ForwardSlash';//填充方式
BaseMap.Fill.ForeColor:=rgb(255,255,255);//填充白色
MapFrame:=Shapes.AddpostMap(DataFileName:=postSTATIONSfile,xcol:=2,ycol:=3,labcol:=5);//建立站点信息粘贴图
MapFrame:=Shapes.AddpostMap(DataFileName:=inDataFile,xcol:=2,ycol:=3,labcol:=5);//建立站点数据粘贴图对象
Shapes.SelectAll;//选中所有
Plot.selection.overlaymaps;//合并图形
Plot.export(filename:=savefile);//输出图形
SurferApp.Documents.closeall;//关闭所有文档窗口
SurferApp.quit;//退出
end;
设置等值线区域填充颜色部分略,核心代码:Levels.Item(Index:=i).Fill.ForeColor:=rgb(r,g,b)。
4、结论
由于等值线的算法复杂,在气象业务系统中开发自己的等值线绘图程序比较困难,需耗费大量的时间和精力。surfer提供了强大的数值计算和绘图功能,结合delphi在数据库操作上的能力,可以快速地开发出气象要素等值线绘图程序,与气象资料数据库系统很好结合,轻松实现气象业务系统的等值线显示。