摘要:本文介绍了城市测量地块面积计算公式及测量坐标系到计算机屏幕坐标系转换的数学基础,然后详述了VB.NET编写面积打印程序的思路、处理方法及程序中需要考虑的细节问题,并给出了实现部分功能的程序代码。
关键词:VB.NET编程城市地块面积程序设计
1、引言
在城市测量工作中,地块面积测量是比较常见的测绘工作,面积测量成果一般要附有坐标表、略图、面积数值、标题、说明、责任栏、相邻界址点边长等信息。如果仅编写单个地块的面积打印程序,这是比较容易实现的。但是,在实际工作中,一方面,一个总地块往往包含有多个分类小块,面积测量成果需要反映各类地块的信息;另一方面,也需要考虑面积成果的紧凑性,比如有时在页面上打印一块面积信息,效果可能比较好,有时在页面上打印多块面积信息,看起来比较紧凑,而且比较节约纸张。如果综合考虑各种因素,编写一个面积打印效果较好的程序,还是不容易的。
2、坐标法面积计算公式
设ABC……N为任意多边形,其顶点的坐标分别为(,),(,),……,(,)。
从图中可以看出,该任意多边形的面积P为:
由此可得下式:
式中,n为多边形顶点的个数,,。
3、测量坐标系到计算机屏幕坐标系的换算
如图3-1和图3-2所示,对实地点P,测量坐标系转换到计算机屏幕坐标系中的坐标计算公式如下:
其中,为点P在测量坐标系中的坐标,为要显示区域的最小坐标(左下角),为最大测量坐标(右上角)。为点P在计算机屏幕显示区的屏幕坐标,为屏幕显示区的最小坐标(左上角),为屏幕显示区最大坐标(右下角),Sx,Sy为测量坐标到屏幕坐标换算的比例系数,计算公式如下:
为了使得在计算机屏幕上显示的图形不至变形,从测量坐标到屏幕坐标换算的比例系数Sxy,在X方向和Y方向应采用相同的比例系数,即Sxy=Min(Sx,Sy)。
4、VB.NET打印机制
VB.NET打印时,要调用PrintDocument对象的Print方法,这个方法不生成任何打印输出,但会发出PrintPage事件,PrintPage事件传递e变元,提供当前Printer对象的Graphics属性以及其他成员,我们就在PrintPage事件处理器中编写打印输出代码。如果需要打印其他页面,则要在退出事件处理器之前将e.HasMorePages属性设置为True,这就反复激发PrintPage事件,直到打印完全部页面。所有页面打印完成后,将e.HasMorePages属性设置为False,不再触发PrintPage事件,打印过程流程如下:
5、面积打印程序流程图
我们用VB.NET设计面积打印程序时,就是利用VB.NET的打印机制,通过计算信息,在程序运行中控制e.HasMorePages属性,不断激发PrintPage事件,在当前页面上打印信息。流程图如下:
6、程序设计中需要考虑的细节
6.1作者设计的面积程序打印效果图
6.2面积数据文件格式
假如面积数据文件中采用如下坐标格式:
……
1, 界址点名,X,Y
2, 界址点名,X,Y
……
在描述某块面积信息时,这种坐标格式很适用,例如A块面积由1,2,3,4,5,6连续序号界址点对应的面积,我们在描述其面积打印信息时,可写成…1-6…。
6.3坐标表页数的确定
设一行打印两个坐标,页数用Page表示,页面可打印区的高度为PrintHeight、可打印的行数为PageRow、行间距为a、坐标文字高度XYHeight、坐标总数为XY.Count,则
PageRow=Int(PrintHeight/(XYHeight+a))
Page=XY.Count/(2*PageRow)
IfPage>Int(Page)Then
XYPage=Int(Page)+1
Else
XYPage=Int(Page)
EndIf
6.4面积略图绘制
DimSx,Sy,SkAsDouble
Sx=(MaxXs-MinXs)/(MaxYg-MinYg)
Sy=(MaxYs-MinYs)/(MaxXg-MinXg)
Sk=Math.Min(Sx,Sy)
IfSy>SxThen
MaxYs=MinYs+Sk*(MaxXg-MinXg)
EndIf
DimPlotAsNewSystem.Drawing.Drawing2D.GraphicsPath
DimOldX,OldY,NewX,NewYAsDouble
OldX=MinXs+Sk*(AreaY(0)-MinYg)
OldY=MaxYs-Sk*(AreaX(0)-MinXg)
IfPrintDmName(0)="-2"Then
e.Graphics.DrawString(AreaDm(0),Dhfont,Brushes.Black,OldX,OldY)
EndIf
NewX=MinXs+(AreaY(AreaY.Count-1)-MinYg)*Sk
NewY=MaxYs-Sk*(AreaX(AreaX.Count-1)-MinXg)
IfPrintDmName(AreaX.Count-1)="-2"Then
e.Graphics.DrawString(AreaDm(AreaX.Count-1),Dhfont,Brushes.Black,NewX,NewY)
EndIf
Plot.AddLine(CSng(OldX),CSng(OldY),CSng(NewX),CSng(NewY))
ForI=1ToAreaX.Count-1
NewX=MinXs+(AreaY(I)-MinYg)*Sk
NewY=MaxYs-Sk*(AreaX(I)-MinXg)
IfPrintDmName(I)="-2"Then
e.Graphics.DrawString(AreaDm(I),Dhfont,Brushes.Black,NewX,NewY)
EndIf
Plot.AddLine(CSng(OldX),CSng(OldY),CSng(NewX),CSng(NewY))
OldX=NewX
OldY=NewY
Next
DimPlotpenAsPen=NewPen(Color.Black,0)
e.Graphics.DrawPath(Plotpen,Plot)
Sk为比例缩放系数,为了在绘图区全部画出图形,Sk选取Sx和Sy比例系数最小值,我们用e.Graphics.DrawString方法可以绘制点名,Plot为绘图轨迹,当我们用Plot.AddLine方法创建完线段后,可以直接用e.Graphics.DrawPath方法绘出。
6.5程序中控制页面生成
一方面,当前页面可打印空间已经用完,或者剩下空间不能很好存放后面的信息,则要考虑生成新页;另一方面,如果打印完一页坐标表后,当剩下空间较小,而要在页面上绘制比较大的地块,点号也较多,这样的略图看起来效果很不得体,这种情况也要考虑换页。为了在程序中控制合理页面的生成,我们可以使用一个可打印区比PK(即剩下空间高度除以可打印范围高度)变量,通过判断PK值,来确定是否要把当前信息打印在当前的页面上。
6.6页面上绘制文本
标题、工程号、界址点号、坐标、单位名称、说明、责任栏、日期等这些都是文本,绘制时都采用e.Graphics.DrawString和e.Graphics.MeasureString方法,其中e.Graphics.MeasureString方法可以测量文本的高度和宽度,而e.Graphics.DrawString可以在一个指定的矩形范围内绘制文本,这两个方法结合起来使用。比如在绘制说明时,事先用e.Graphics.MeasureString方法测量说明字体的高度和宽度,确定一个矩形范围对象,然后用e.Graphics.DrawString方法在这个矩形范围内绘制文本。
7、结束语
在编写面积打印程序时,中间还有许多小细节:①如有时想输出部分相邻点的边长信息;有时相邻点间距很小,为了不影响面积略图效果,只绘制出部分点号;这就需要有控制任意面积点号输出的功能。②如果为了使说明位置适当,这需要有能够任意移动说明位置功能。③有时想横向输出成果、标题、工程号、界址点号、坐标、单位名称、说明、责任栏、日期字体及大小设置等。总之,在程序设计时必须考虑许多细节问题。但只要撑握VB.NET的打印机制和一些基本方法,加上面积计算和坐标变换等数学知识,编写出适合本单位使用的地块面积打印的程序是可行的。本文是作者编写面积打印的实践经验和处理方法,仅供读者参考。
参考资料
[1]丘仲潘等译.VisualBasic.NET从入门到精通.电子工业出版社,北京
[2]潘正风罗年学.大例尺测图自动化.原武汉测绘科技大学.1995.12