arcgis api for Flex画贝赛尔曲线

         最近在研究用arcgis api for Flex客户端动态画曲线的问题。虽然花了不少时间,最终等值线还是没有预期效果那样画在地图之上,但还是有不少收获。画等值线过程中,需要利用贝赛尔曲线函数来画平滑曲线。网上找了很多资料,都是在用flash环境中的curveTo()方法来画,但是好像这样画出来的曲线是不能在gis图层中显示的,即只能在flash.display.Graphics下的graphics才能使用这个方法,ags中的graphics是不是使用这个方法的。要么本人还没有找到转换方法,要么就根本不能用在gis图层。在网上找到了一篇关于在ags图层中画军标的文章,从这篇文件中得到启示。

先看效果 :




<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark" 
			   xmlns:mx="library://ns.adobe.com/flex/mx" 
			   minWidth="955" minHeight="600" creationComplete="init()" 
			   xmlns:esri="http://www.esri.com/2008/ags">
	<fx:Declarations>
		<!-- 将非可视元素(例如服务、值对象)放在此处 -->
	</fx:Declarations>
    <fx:Script>
		<![CDATA[
			import com.esri.ags.Graphic;
			import com.esri.ags.SpatialReference;
			import com.esri.ags.geometry.MapPoint;
			import com.esri.ags.geometry.Polyline;
			import com.esri.ags.layers.GraphicsLayer;
			
			
			private var m_firstpoints:Array;
			private var graphicsLayer:GraphicsLayer;
			private var full_polyline:Graphic;
			
			private function init():void{
				map.addEventListener(MouseEvent.CLICK,map_mouseClickHandler);
				map.addEventListener(MouseEvent.DOUBLE_CLICK,map_mouseDoubleClickHandler);
				
				graphicsLayer=new GraphicsLayer();
				map.addLayer(graphicsLayer);
			}
			
			public function map_mouseClickHandler(event:MouseEvent):void
			{
				map.mapNavigationEnabled=false;
				//确定点击的地图点的坐标,然后放到数组中
				var m_point:MapPoint=map.toMapFromStage(event.stageX,event.stageY);
				if (m_firstpoints == null)
				{
					m_firstpoints=new Array();
				}
				m_firstpoints.push(m_point);
			}
			public function map_mouseDoubleClickHandler(event:MouseEvent):void{
				var pg:Polyline=drawLine(m_firstpoints,100);
				full_polyline=new Graphic(pg);
				graphicsLayer.add(full_polyline);
			}
			private function drawLine(inputPoints:Array,mapWidth:Number):Polyline{
				
				var points:Array=new Array();
				for(var k:int=0;k<inputPoints.length;k++){
					points.push(inputPoints[k]);
					if(k>0&&k<inputPoints.length-2){
						var p:MapPoint=new MapPoint((inputPoints[k].x+inputPoints[k+1].x)/2,(inputPoints[k].y+inputPoints[k+1].y)/2,new SpatialReference(4326));
						points.push(p);
					}
				}
				
				var curvepoints:Array=getzz_geometry(points,20);
				
				var dgbj_geometry:Array=getdbx_geometry(curvepoints,mapWidth,20);
				var full_gbjpolyline:Polyline=new Polyline(dgbj_geometry);
				return full_gbjpolyline;
			}
			
			/* 求中轴线上所有的点 */
			private function getzz_geometry(inputPoints:Array,bzt:Number):Array
			{
				//首先定义中轴曲线的点坐标
				var curvepoints:Array=new Array();
				var i:int;
				var j:Number;
				var pos_x:Number;
				var pos_y:Number;
				var m_point:MapPoint;
				for ( i=0; i < inputPoints.length-2; i=i + 2)
				{
					for (j=0; j <= 1+0.00001; j=j + 1/bzt)
					{
						if (i != 0 && j == 0)
							continue;
						pos_x=Math.pow((1 - j),2) * inputPoints[i].x + 2 * j * (1 - j) * inputPoints[i + 1].x + Math.pow(j,2) * inputPoints[i + 2].x;
						pos_y=Math.pow((1 - j),2) * inputPoints[i].y + 2 * j * (1 - j) * inputPoints[i + 1].y + Math.pow(j,2) * inputPoints[i + 2].y;
						m_point=new MapPoint(pos_x,pos_y);
						//中轴线的点数
						curvepoints.push(m_point);
					}
				}
				return curvepoints;
			}
			
			/* 获得曲线点组 */
			private function getdbx_geometry(curvepoints:Array,mapWidth:Number,bzt:Number):Array
			{
				var bottomcurepoints:Array=new Array();
				var c_length:Number=curvepoints.length;
				var dis:Number= mapWidth/20.0;
				
				var pos_x:Number;
				var pos_y:Number;
				var pre_pos_x:Number;
				var pre_pos_y:Number;
				var bb:Number;
				var slope:Number;
				var cos_number:Number;
				var sin_number:Number;
				var pre_point:MapPoint;
				var m_point:MapPoint;
				
				
				for (var u:Number=0; u < curvepoints.length; u++)
				{
					if (u == 0)
					{
						continue;
					}
					else
					{
						var bottom_pos_x:Number;
						var bottom_pos_y:Number;
						m_point=curvepoints[u];
						pos_x=m_point.x;
						pos_y=m_point.y;
						pre_point=curvepoints[u - 1];
						pre_pos_x=pre_point.x;
						pre_pos_y=pre_point.y;
						slope=(pos_y - pre_pos_y) / (pos_x - pre_pos_x);
						bb=dis * (1 - u / c_length * 0.9);
						cos_number=Math.cos(Math.atan(slope) - Math.PI / 2);
						sin_number=Math.sin(Math.atan(slope) - Math.PI / 2);
						
						
						if (pre_pos_x <= pos_x && pre_pos_y <= pos_y)
						{
							bottom_pos_x=pre_pos_x + ((bb * cos_number) < 0 ? (-bb * cos_number) : (bb * cos_number));
							bottom_pos_y=pre_pos_y - ((bb * sin_number) < 0 ? (-bb * sin_number) : (bb * sin_number));
						}
						else if (pre_pos_x <= pos_x && pre_pos_y > pos_y)
						{
							bottom_pos_x=pre_pos_x - ((bb * cos_number) < 0 ? (-bb * cos_number) : (bb * cos_number));
							bottom_pos_y=pre_pos_y - ((bb * sin_number) < 0 ? (-bb * sin_number) : (bb * sin_number));
						}
						else if (pre_pos_x >= pos_x && pre_pos_y >= pos_y)
						{
							bottom_pos_x=pre_pos_x - ((bb * cos_number) < 0 ? (-bb * cos_number) : (bb * cos_number));
							bottom_pos_y=pre_pos_y + ((bb * sin_number) < 0 ? (-bb * sin_number) : (bb * sin_number));
						}
						else if (pre_pos_x >= pos_x && pre_pos_y <= pos_y)
						{
							bottom_pos_x=pre_pos_x + ((bb * cos_number) < 0 ? (-bb * cos_number) : (bb * cos_number));
							bottom_pos_y=pre_pos_y + ((bb * sin_number) < 0 ? (-bb * sin_number) : (bb * sin_number));
						}
						var bottom_point:MapPoint=new MapPoint(bottom_pos_x,bottom_pos_y);
						bottomcurepoints.push(bottom_point);
					}
				}
				var rings:Array=new Array();
				rings.push(bottomcurepoints);
				return rings;
			}
		]]>
	</fx:Script>
	<s:BorderContainer width="100%" height="100%">
		<esri:Map id="map">
			<esri:ArcGISTiledMapServiceLayer id="layer" url="http://server.arcgisonline.com/ArcGIS/rest/services/ESRI_StreetMap_World_2D/MapServer"/>
		</esri:Map>
	</s:BorderContainer>
</s:Application>
这样就可以画出一条平滑的贝赛尔曲线了。这是直接利用贝赛尔曲线公式,而没有利用flash.display.Graphics.curveTo()方法,虽然简单了点,但效果还不错。

相关文章

一:display:flex布局display:flex是一种布局方式。它即可以...
1. flex设置元素垂直居中对齐在之前的一篇文章中记载过如何...
移动端开发知识点pc端软件和移动端apppc端软件是什么,有哪些...
最近挺忙的,准备考试,还有其他的事,没时间研究东西,快周...
display:flex;把容器设置为弹性盒模型(设置为弹性盒模型之后...
我在网页上运行了一个Flex应用程序,我想使用Command←组合键...