得到某点的缓冲区并画圆


我们在做GIS空间分析的时候常常需要计算某个点的缓冲区,这时需要以这个点为中心,画一个圆。怎么来实现呢?

  缓冲区的做法在arcims里有相应的API,但是我们现在的做法是抛开IMS的API,只在前台画圆。这里利用了VML来画圆。

  用VML技术来画圆还是比较简单的,这里较困难的是需要解决每像素代表实地多少距离的问题,知道了这个值就可以利用需要画的缓冲区的半径得到到底用VML要画多少像素。

  概念中我们最重要的是要弄清楚“像素”的含义。我们常常大概明白它的意思,但是想想:为什么我们写程序时都是用像素呢?而不用米之类的长度单位,而如果分辨率不同的话,像素值是不变的,对结果会产生什么影响?等等。还有,我们说的“每像素代表实地多少距离”并不是我们在学地图学里说的“比例尺”。比例尺是实地距离除以图上距离(1厘米),而对电子地图来说,比例尺没什么意义,因为在电子地图里, “每像素代表实地多少距离”的分母是像素值,并不是长度值。我们在IMS返回的是MBR的四个值XMin,YMin,XMax,YMax和Width,Height,其中width和height是像素值,这点需要明确。

  我们建立一个Map对象,用于存放IMS里返回的地图状态:MBR的四个值XMin,YMin,XMax,YMax和地图的长度width(像素值)和高度height(像素值)。通过它们就可以得到一些我们很常用且重要的函数:屏幕坐标与地理坐标的相互转化函数,输入屏幕坐标得到距离函数(测距时用),判断输入的经纬度点是否在地图范围内(如果不在的话就不加载进来)函数。如下:

  Js代码   

function Map() 
{ 
 this.XMin = 0; 
 this.YMin = 0; 
 this.XMax = 0; 
 this.YMax = 0; 
 this.Width = 0; 
 this.Height = 0; 
 this.ImageURL = ''; 
 this.getXDistance = function(){ 
 return this.XMax - this.XMin; 
 } 
 this.getYDistance = function(){ 
 return this.YMax - this.YMin; 
 } 
 
 
 this.getPixelX = function(){ 
 return this.getXDistance()/this.Width; 
 } 
 this.getPixelY = function(){ 
 return this.getYDistance()/this.Height; 
 } 
 
 this.toScreenX = function(x){ 
 return (x-this.XMin)/this.getPixelX(); 
 } 
 this.toScreenY = function(y){ 
 return (this.YMax-y)/this.getPixelY(); 
 } 
 
 this.toGeoX = function(x){ 
 return this.XMin + x*this.getPixelX(); 
 } 
 this.toGeoY = function(y){ 
 return this.YMax - y*this.getPixelY(); 
 } 
 
 this.distance = function(x1, y1, x2, y2){ 
 var num1 = Math.PI/180; 
 var num2 = 1 / num1; 
 x1 = this.toGeoX(x1) * num1; 
 y1 = this.toGeoY(y1) * num1; 
 x2 = this.toGeoX(x2) * num1; 
 y2 = this.toGeoY(y2) * num1; 
 return ((111120 * num2) * Math.acos((Math.sin(y1) * Math.sin(y2)) + ((Math.cos(y1) * Math.cos(y2)) * Math.cos(x2 - x1)))); 
 } 
 
 this.include = function(x, y){ 
 return (x>this.XMin && x<this.XMax && y>this.YMin && y<this.YMax); 
 } 
}

然后我们得到像素与实地距离比,如下:    

  Js代码  

 //像素与实地距离比 
 getScale: function(){ 
 var map = webmap.getMap(); 
 var x1 = map.toScreenX(map.XMin); 
 var x2 = map.toScreenX(map.XMax); 
 var y1 = map.toScreenY(map.YMin); 
 var y2 = map.toScreenY(map.YMax); 
 geoDis = map.distance(x1, y1, x2, y1); 
 scepx = map.Width; 
 return parseFloat(scepx)/(parseFloat(geoDis)*100); 
 }

  接着我们写出画圆接口,调用这个接口就可以把一个圆对象放到webmap的全局数组displayed_circle里,如下:

  Js代码

 //画圆接口(缓冲区时用) 
 setDisplayCircle: function(args){ 
  function setcircle(left,top,width,height,showColor,showTitle,clickFun,circleProp){ 
  var o = new Object(); 
  o.left = left; 
  o.top = top; 
  o.width = width; 
  o.height = height; 
  o.showColor = showColor; 
  if(showTitle) 
  o.showTitle = function(){Tip(showTitle)}; 
  if(clickFun) 
  o.clickFun = clickFun; 
  if(circleProp) 
  o.circleProp = circleProp; 
  webmap.displayed_circle[webmap.displayed_circle.length] = o; 
  } 
  setcircle(args.left,args.top,args.width,args.height,args.showColor||'red',args.showTitle,args.clickFun,args.circleProp); 
 }

以上代码需要明确以下方面:

  1.setcircle函数传入的参数是一个对象。为什么要传入对象而不直接传入字符串参数呢?因为传入对象可以允许调用这个方法的人只写要传入的参数即可,不需要每个参数都传。

  2.传入的对象参数里的属性又包含一个对象。args.circleProp就是一个对象,它主要是传入一些将要画的圆的一些额外的属性,如你可以传入它的KEY,这样如果你画了若干个圆,就可以根据这个值来得到它更详尽的属性了。 3.displayed_circle是webmap的全局数组,用于保存每个圆对象。画线接口完成后,就可以在地图刷新完返回地图的状态后调用如下函数来画线,用到了VML技术, 如下:

  Js代码  

 //地图刷新完画圆(缓冲区时用) 
 _RefreshCircle: function(){ 
 document.getElementById('frontMap').innerHTML = ''; 
 for(var i=0;i<this.displayed_circle.length;i++){ 
  var o = this.displayed_circle[i]; 
  var objCircle = document.createElement("v:oval"); 
  var scale = this.getScale(); 
  objCircle.style.width = o.width*100000*scale; 
  objCircle.style.height = o.height*100000*scale; 
  objCircle.style.left = (webmap.getMap().toScreenX(o.left)-o.width*100000*scale/2)+'px';//定位以左上角来定 
  objCircle.style.top = (webmap.getMap().toScreenY(o.top)-o.height*100000*scale/2)+'px'; 
  objCircle.style.opacity = 0.8; 
  objCircle.style.filter = 'alpha(opacity=80)'; 
  objCircle.style.fillcolor = '#99cccc'; 
  objCircle.id = "objCircle"; 
  objCircle.strokecolor = o.showColor; 
  if(o.showTitle) 
  objCircle.onmouseover = o.showTitle; 
  if(o.clickFun) 
  objCircle.onmousedown = o.clickFun; 
  if(o.circleProp) { 
  for(var key in o.circleProp){ 
   circleProp[key] = o.circleProp[key]; 
  } 
  } 
  document.getElementById("frontMap").appendChild(objCircle); 
 } 
 },


  以上代码需要明确以下方面:

  1.frontMap是地图div上的内的一个div,首先先把它清空,用innerHMTL=''来实现。

  2.然后循环遍历displayed_circle数组,得到每一个圆对象的属性,放到VML建立好的圆元素里。

  3.最后通过appendChild()把每个圆元素加到DIV进来。

  4.这里要注意的是:objCircle.style.width,objCircle.style.height,objCircle.style.left,objCircle.style.top这四个值需要做相应地转化。

  5.用如下方法把圆的属性增加进来:    for(var key in o.circleProp){     circleProp[key] = o.circleProp[key];    }   

  注:这里不能用circleProp.key


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3