关于利用矩形,圆和多边形选择动态GraphicLayer上的Graphic的研究(学习笔记)
2012-06-26 14:02
621 查看
根据数据来源生成对应的Layer,发布在服务器上,作为一个不可见的层,根据你的Geometry对那个不可见的图层使用QueryTask,展现依然在GraphicLayer上进行展示,一种貌似在对GraphicLayer进行的选择。
但是如果我们想要的是动态的GraphicLayer,可以动态地在图层上添加和删除Graphic,这种服务的方式显然不能满足我们的要求,但我们可以通过GraphicLayer上的Graphic和选择范围进行关系判断,进行关系判断有两种方式:
方式一:把GraphicLayer上要查询的那些Geometry组成一个Array,再将你要用来选择的图形来构成一个Array,利用服务器上的GeometryService进行Relation操作,返回在范围内的Graphic,但是这种方法返回的Graphic是新的Graphic,其中原有Graphic的attribute属性将会被设置为null,而且并未脱离服务器运行,下面是示例代码:
方法二:通过GIS原理中的基本判定方法进行判定,这也许比较麻烦,但是能够最少利用服务器的资源,下面我们单独实现各种选择方式:
1)矩形选择
矩形比较简单,基本思路就是遍历GraphicLayer中的每个Graphic,将每个Graphic与用来选择的矩形进行关系判断,如果Graphic的x,y小于矩形的Extent的xmin,ymin,大于Extent的xmax,ymax,则判断在矩形内部,示例代码如下:
圆选择也很简单,基本思路就是获得用于选择的圆的中心点和半径,然后遍历GraphicLayer中的每个Graphic,计算每个Graphic与中心点的距离,如果距离小于半径则在圆内,反之在圆外,示例代码如下:
多边形选择是比较复杂的,判断方式也很多,比如射线判别法、角度和判别法、面积和判别法和点线判别法,我只尝试了射线判别和角度和判别,个人觉得射线判别更加准确,基本思路为:
如果一个点在多边形内部,任意角度做射线肯定会与多边形要么有一个交点,要么有与多边形边界线重叠。
如果一个点在多边形外部,任意角度做射线要么与多边形有一个交点,要么有两个交点,要么没有交点,要么有与多边形边界线重叠。
利用上面的结论,我们只要判断这个点与多边形的交点个数,就可以判断出点与多边形的位置关系了。
相关判别法链接:摘自http://www.cnblogs.com/hhyypp/archive/2011/12/05/2276984.html
转换为Flex的示例代码如下:
方法三:经过优化,发现了一种更为简单的判别点在多边形内部的方法,利用Polygon的Polygon.contains(point:MapPoint):Boolean
对于圆形,多边形是可以直接转为Polygon使用的,但是Extent有所不同,需要将Extent.toPolygon(),才能使用,基本思路与上面方法类似,遍历每个Graphic并判断是否在Polygon内部即可。
但是如果我们想要的是动态的GraphicLayer,可以动态地在图层上添加和删除Graphic,这种服务的方式显然不能满足我们的要求,但我们可以通过GraphicLayer上的Graphic和选择范围进行关系判断,进行关系判断有两种方式:
方式一:把GraphicLayer上要查询的那些Geometry组成一个Array,再将你要用来选择的图形来构成一个Array,利用服务器上的GeometryService进行Relation操作,返回在范围内的Graphic,但是这种方法返回的Graphic是新的Graphic,其中原有Graphic的attribute属性将会被设置为null,而且并未脱离服务器运行,下面是示例代码:
//利用GeometryService查询 private function QueryGeometry(gra:Graphic):void { var geometryService:GeometryService=new GeometryService(); geometryService.url="http://172.39.8.215/ArcGIS/rest/services/Geometry/GeometryServer"; geometryService.addEventListener(GeometryServiceEvent.RELATION_COMPLETE,relationComplete); var graphics1:Array=new Array; var graphics2:Array=new Array; graphics2.push(gra.geometry); if(SelectType=="MonitorStation") { geoArrayCol=MonitorStationLayer.graphicProvider as ArrayCollection; } else if(SelectType=="MonitorCar") { geoArrayCol=MonitorCarLayer.graphicProvider as ArrayCollection; } else if(SelectType=="Station") { geoArrayCol=StationLayer.graphicProvider as ArrayCollection; } if(geoArrayCol==null) return; var count:Number=geoArrayCol.length; for(var i:Number=0;i<count;i++) { var g:Graphic = geoArrayCol[i] as Graphic; graphics1.push(g.geometry); } var parm:RelationParameters=new RelationParameters(); parm.geometries1=graphics1; parm.geometries2=graphics2; parm.comparisonString="SPATIAL_REL_RELATION"; parm.spatialRelationship="esriGeometryRelationIn"; geometryService.relation(parm); } private function relationComplete(event:GeometryServiceEvent):void { var relations:Array = event.result as Array; clearAllSelect(); for (var i:int=0; i<relations.length; i++) { var g:Graphic = new Graphic(relations[i].geometry1); for(var j:Number=0;j<geoArrayCol.length;j++) { var geo:Graphic= geoArrayCol[j] as Graphic; if((geo.geometry as MapPoint).x==relations[i].geometry1.x&&(geo.geometry as MapPoint).y==relations[i].geometry1.y) { g.attributes=geo.attributes; } } findLayer.add(g); } }
方法二:通过GIS原理中的基本判定方法进行判定,这也许比较麻烦,但是能够最少利用服务器的资源,下面我们单独实现各种选择方式:
1)矩形选择
矩形比较简单,基本思路就是遍历GraphicLayer中的每个Graphic,将每个Graphic与用来选择的矩形进行关系判断,如果Graphic的x,y小于矩形的Extent的xmin,ymin,大于Extent的xmax,ymax,则判断在矩形内部,示例代码如下:
//利用矩形选择,polygon为用于选择的多边形,gArrayCollection 为所查图层的graphic集合 public static function PointSelectByExtent(polygon:Graphic,gArrayCol:ArrayCollection): Array { var extent:Extent = polygon.geometry.extent; var res: Array= new Array (); for each (var grap:Graphic in gArrayCol) { var mp:MapPoint = grap.geometry as MapPoint; if(extent.xmin<=mp.x &&extent.ymin <= mp.y && mp.x <=extent.xmax && mp.y <= extent.ymax) { res.push(grap); } } return res; }2)圆选择
圆选择也很简单,基本思路就是获得用于选择的圆的中心点和半径,然后遍历GraphicLayer中的每个Graphic,计算每个Graphic与中心点的距离,如果距离小于半径则在圆内,反之在圆外,示例代码如下:
//利用圆形选择 public static function PointSelectByCircle(polygon:Graphic,gArrayCol:ArrayCollection):Array { var extent:Extent = polygon.geometry.extent; var ceterPt:MapPoint=extent.center; var radius:Number=extent.width/2; var res: Array= new Array (); for each (var grap:Graphic in gArrayCol) { var mp:MapPoint = grap.geometry as MapPoint; var dis:Number=Math.sqrt(Math.pow((mp.x-ceterPt.x),2)+Math.pow((mp.y-ceterPt.y),2)); if(dis<=radius) { res.push(grap); } } return res; }3)多边形选择
多边形选择是比较复杂的,判断方式也很多,比如射线判别法、角度和判别法、面积和判别法和点线判别法,我只尝试了射线判别和角度和判别,个人觉得射线判别更加准确,基本思路为:
如果一个点在多边形内部,任意角度做射线肯定会与多边形要么有一个交点,要么有与多边形边界线重叠。
如果一个点在多边形外部,任意角度做射线要么与多边形有一个交点,要么有两个交点,要么没有交点,要么有与多边形边界线重叠。
利用上面的结论,我们只要判断这个点与多边形的交点个数,就可以判断出点与多边形的位置关系了。
相关判别法链接:摘自http://www.cnblogs.com/hhyypp/archive/2011/12/05/2276984.html
转换为Flex的示例代码如下:
//利用多边形选择 public static function PointSelectByPolygon(polygon:Graphic,gArrayCol:ArrayCollection):Array { var pg:Polygon=polygon.geometry as Polygon; var polygonArr:Array=pg.rings[0]; var res: Array= new Array (); for each (var grap:Graphic in gArrayCol) { if(InsidePolygon(polygonArr,polygonArr.length,grap.geometry as MapPoint)) { res.push(grap); } } return res; } //判断是否在多边形内部 private static function InsidePolygon(polygon:Array, N:uint,pt:MapPoint ):Boolean { var i:uint; var j:uint; var inside:Boolean; var redo:Boolean; redo = true; for (i = 0;i < N;++i) { if (polygon[i].x == pt.x && // 是否在顶点上 polygon[i].y == pt.y ) { redo = false; inside = true; break; } } while (redo) { redo = false; inside = false; for (i = 0,j = N - 1;i < N;j = i++) { if ( (polygon[i].y < pt.y && pt.y < polygon[j].y) || (polygon[j].y < pt.y && pt.y < polygon[i].y) ) { if (pt.x <= polygon[i].x || pt.x <= polygon[j].x) { var _x:Number= (pt.y-polygon[i].y)*(polygon[j].x-polygon[i].x)/(polygon[j].y-polygon[i].y)+polygon[i].x; if (pt.x < _x) // 在线的左侧 inside = !inside; else if (pt.x == _x) // 在线上 { inside = true; break; } } } else if ( pt.y == polygon[i].y) { if (pt.x < polygon[i].x) // 交点在顶点上 { polygon[i].y > polygon[j].y ? --pt.y : ++pt.y; redo = true; break; } } else if ( polygon[i].y == polygon[j].y && // 在水平的边界线上 pt.y == polygon[i].y && ( (polygon[i].x < pt.x && pt.x < polygon[j].x) || (polygon[j].x < pt.x && pt.x < polygon[i].x) ) ) { inside = true; break; } } } return inside; }
方法三:经过优化,发现了一种更为简单的判别点在多边形内部的方法,利用Polygon的Polygon.contains(point:MapPoint):Boolean
对于圆形,多边形是可以直接转为Polygon使用的,但是Extent有所不同,需要将Extent.toPolygon(),才能使用,基本思路与上面方法类似,遍历每个Graphic并判断是否在Polygon内部即可。
相关文章推荐
- 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)
- 关于Struts2 namespace 的学习笔记(DMI动态方法调用)
- Python学习笔记(二)关于Python的IDE选择
- Plug-in(1) 动态加载机制研究学习笔记
- 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)
- 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)
- [关于OPC的研究1]c# opc client源码调试和学习笔记
- 【小白笔记】PHP学习之路 (29) --图像处理、绘制像素、矩形、多边形
- javascript学习笔记—简单的动态选择收件人/联系人
- 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)
- openGL学习笔记四 : 关于颜色, 大小, 虚线, 多边形反转, 镂空, 使用位图
- 利用Mono.Cecil动态修改程序集来破解商业组件(仅用于研究学习)
- opencv学习笔记(十)画直线、矩形、圆形、椭圆以及多边形程序
- OpenCV学习笔记(18):在OpenCV中利用鼠标绘制矩形和截取图像的矩形区域
- OpenCv学习笔记(六):使用opencv画线、矩形、椭圆、多边形线、多边形体等
- [关于OPC的研究1]c# opc client源码调试和学习笔记
- OpenCv学习笔记(七)---OpenCv中的基本绘图函数,圆,椭圆,线段,矩形,多边形的绘制(1)
- 关于Fragment的学习笔记1——利用布局文件创建固定Fragment
- jquery插件开发学习笔记(五)——动态选择触发器
- Effective C# 学习笔记(四十一)使利用DynamicObject或IDynamicMetaObjectProvider接口实现数据驱动的动态类型