【资料名称】:mapinfo中绘制基站扇形的算法讨论和工具共享(原创)
【资料作者】:YZL
【资料日期】:2009.01
【资料语言】:中文
【资料格式】:其它
【资料目录和简介】:
mapinfo中绘制基站扇形的算法讨论和工具共享. 讨论5种算法并将我以前弄的一个工具贡献给大家试试
----------------------讨论和说明-----------------------------
很多同仁在论坛中谈论也自己编程做了一些基站扇区(扇形、直线)图形绘制工具,包括很多规划软件都有一个问题
就是生成的扇形图形在mapinfo等gis系统中有一定失真。当然由网友说这点失真可能不算啥了,如果是这样你就不必看下面的方法了。
下面以MAGPINFO为例来说明,MAPINFO采用的WGS-84椭球体坐标系,而我们日常一般习惯于在笛卡尔坐标系中处理,这也是处理容易失真原因
我总结了一下,很多人在编制mapinfo下生成扇形图形的时候有如下做法:
方法1:(极端做法):直接将直角坐标用于计算,如:x=r*cos(theta) ,y=r*sin(theta)这种做法完全将一个地球球体表面当成平面来处理,这种做法失真最大(当然如果地表面积足够小的时候误差也不是很明显)。这种做法论坛里很多excel2ge/excel2mapinfo都是这种方法。我个人认为此方法不可取。
方法2:采用直角坐标到经纬度的近似转换关系计算,这种算法采用经纬度和直角坐标之间 的简单关系【/ (69.093 * 1609) 】。如网上的“[vb+Mapx]实现扇区三叶草图形" ,大家可以搜索学习一下。这种算法个人感觉也不够精确。
方法3:采用大地主题解算算法来实现。这种算法需要很多专业知识背景(我就是猛学了一段时间的测量专业的教材才理解的)。大地主题解算有很多算法,我采用了白赛尔算法实现,具体算法我已经放到了上帝之眼上,大家有兴趣可以自行看看:
http://bbs.godeyes.cn/showtopic-248479.aspx。其实我的"googleearth基站扇区绘制工具(YZL)"就是按照这个算法弄的。
方法4:(mapinfo中,我采用mapbasic编程),将经纬度转换成直角坐标系,然后再在直接坐标系下(SETE COORDSYS nonearth语句)画线和画圆弧,然后再切换到经纬度坐标系下。这个方案比较简单,但是从earth坐标系到nonearth坐标系的转化,暂时没有找到好的方法,而且误差也很大。我认为不可取)
方法5:(mapinfo中,我采用mapbasic编程),想了另外一种方法:充分利用MAPINFO自身功能,完全抛开直角坐标到经纬度的转换,实现起来很方便而且效果很好。
下面简单介绍一下方法5:
主要思路:采用类似于我们高中几何中常用到的辅助线的方法,直接再经纬度坐标系下处理。
mapinfo下绘制圆弧采用的命令是Create Arc。但mapinfo中Create Arc语句没有基于两个端点和圆心来绘制的方式。而是采用了四个点的坐标方式(这又涉及到了坐标转换的问题了)。庆幸的是我们可以通过采用辅助圆的方式取得需要绘制圆弧的四个点的坐标:
1、使用CREATECIRCLE语句创建圆,然后再用ObjectGeography求出圆的外接矩形的左下角和右上角的坐标(左下角(minx miny) 右上角(maxx maxy)。
2、根据这两个点(minx miny) (maxx maxy) 和中心点以及起始角和终止角来绘制弧形。
3、将弧形转换成pline取出弧形的两个端点。
4、将两个端点和中心相连
5、图元合并就可以得出扇形
这种做法缺点也有:由于mapinfo的处理精度问题,所以半径小于10m或者 大于500km均还是有一定误差,但是这已经不影响使用了。
主要算法如下:
'主要问题是mapinfo中Create Arc语句没有基于两个端点和圆心来绘制的方式。而是采用了四个点的坐标方式。
'采用辅助圆的方式取得需要绘制圆弧的四个点的坐标
'通过这四个点绘制弧形,然后取得该弧形的两个端点坐标
'通过端点坐标和圆心绘制直线
'最后合并直线和圆弧就得到了标准的扇形,效果不错
function mycreateregion(经度,纬度,方向角,半功率角,半径 as float) as object
dim x,y,r,x1,y1,x2,y2,start_angle,end_angle as float
dim arc_obj,line1_obj ,line2_obj,obj1,obj2,circle_objas object
dim endpointstring,endxstring,endystring as string
dim minx,miny,maxx,maxy as float'''''''园的左下角和右上角坐标
X=经度
Y=纬度
r=半径
start_angle=方向角-半功率角/2
end_angle=半功率角/2+方向角
circle_obj=CreateCircle(x,y,r)''这里绘制辅助圆,
minx=ObjectGeography(circle_obj,obj_geo_minx)
miny=ObjectGeography(circle_obj,obj_geo_miny)
maxx=ObjectGeography(circle_obj,obj_geo_maxx)
maxy=ObjectGeography(circle_obj,obj_geo_maxy) '''这四行取得绘制圆弧的关键点坐标,
if (方向角<>-270) and (半功率角<>360)then' 此处的方向角是经过处理后的方向角
Create Arc into Variable arc_obj
(minx,miny) (maxx,maxy)
start_angleend_angle
dim xx1,yy1,xx2,yy2 as float
xx1=getArcBEGX(arc_obj)
yy1=getArcBEGY(arc_obj)
xx2= getArcENDX(arc_obj)
yy2= getArcENDY(arc_obj)'这里是取得圆弧的端点坐标
Create Line into Variable line1_obj
(x,y) (xx1,yy1)
Create Line into Variable line2_obj
(x,y) (xx2,yy2)'这里是绘制两条直线
obj1 = ConvertToRegion(Combine(arc_obj,Combine(line1_obj,line2_obj))) '合并
else
obj1=circle_obj''''''''''''''''''''''全向站的处理,直接画圆
end if
mycreateregion=obj1 '返回扇形。
end function
''''求圆弧端点的程序''''''''''''''''''
function getArcBEGX(byval obj as object) as float
ifobjectinfo(obj,OBJ_INFO_TYPE )=1 then
dim d as object
d=ConvertToPline( obj )
getArcBEGX =ObjectNodeX( d ,1 ,1)
else
getArcBEGX=0
end if
end function
function getArcBEGY(byval obj as object) as float
ifobjectinfo(obj,OBJ_INFO_TYPE )=1 then
dim d as object
d=ConvertToPline( obj )
getArcBEGY =ObjectNodeY( d ,1 ,1)
else
getArcBEGY=0
end if
end function
function getArcENDX(byval obj as object) as float
ifobjectinfo(obj,OBJ_INFO_TYPE )=1 then
dim d as object
d=ConvertToPline( obj )
getArcENDX =ObjectNodeX( d ,1 , objectinfo(d,OBJ_INFO_NPNTS))
else
getArcENDX=0
end if
end function
function getArcENDY(byval obj as object) as float
ifobjectinfo(obj,OBJ_INFO_TYPE )=1 then
dim d as object
d=ConvertToPline( obj )
getArcENDY =ObjectNodeY( d ,1 ,objectinfo(d,OBJ_INFO_NPNTS))
else
getArcENDY=0
end if
end function
我基于方法5做了一个简单的mapinfo基站扇区图形生成工具,大家试试看。大家使用超级用户密码登录就可以了,密码为:leizi_y。这个工具实现了点、线、面图形的自定义等等功能,但没有做excel/TXT导入mapinfo这样基本的功能(我认为这个mapinfo自身已经能够足够处理了)。
欢迎大家讨论
leizi_y@126.com,qq:31933208
[
本帖最后由 leizi_y 于 2009-5-6 19:37 编辑 ]