flex+degrafa自定义曲线ployline绘制

应用程序
<?xml version="1.0" encoding="utf-8"?>
<mx:Application	xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
				xmlns:degrafa="com.degrafa.*"
				xmlns:paint="com.degrafa.paint.*"
				xmlns:geometry="com.degrafa.geometry.*" viewSourceURL="srcview/index.html" 
				 backgroundColor="#ffffff" xmlns:local="*"
				 creationComplete="inipolyline()" xmlns:text="flash.text.*">
				
	<degrafa:Surface id="asur">
	
		<!-- Creating fills. -->
		<degrafa:fills>
			<paint:SolidFill	id="blue"
								color="#62ABCD"/>
		</degrafa:fills>
		
		<!-- Creating Strokes. -->
		<degrafa:strokes>
			<paint:SolidStroke	id="black"
								color="#000000"
								alpha="1"
								weight="3"/>
			<paint:SolidStroke	id="red"
								color="#FF0000"
								alpha="1"
								weight="3"/>
		</degrafa:strokes>
		<!-- Creating Polyline-->
		<!-- Creating a Geometry Group. -->
		<degrafa:GeometryGroup x="0" y="0">
		
			<!-- Creating a Polygon. -->
			<geometry:Polyline stroke="{black}">
				<geometry:data>0,0 0,20 20,20 20,40 40,40 40,60</geometry:data>
			</geometry:Polyline>
			
		</degrafa:GeometryGroup> 
		<!--自定义曲线-->
		<degrafa:GeometryGroup x="0" y="100" id="geopolytl"/>
	</degrafa:Surface>
	<mx:Button  click="deletepolyline()"  label="deletepolyline" x="100" y="0"/>
	<mx:Script>
		<![CDATA[
			import com.degrafa.GraphicText;
			import com.degrafa.IGeometry;
		public function deletepolyline():void
		{
			    for each(var g:GeometryGroup in asur.graphicsCollection.items)
	        {
	            g.target = null;
	            g.visible = false;
	            for each(var o:IGeometry in g.geometryCollection.items)
	            {
	                o.data = "";
	                g.geometryCollection.removeItem(o);
	            }
	            g.geometry.length = 0;
	            g = null;
	        }
	        asur.graphicsCollection.items.length = 0;
		}
		public function inipolyline():void
		{
		    var polytl: DashedPolylinetl= new DashedPolylinetl();
	        polytl.dash=10;
	        polytl.gap=4;
	        polytl.style=2;
	        var datastl:String="0,0 0,20 20,20 20,40 40,40 40,60 60,60 60,0 ";
	        polytl.data=datastl;
	        polytl.colour=0x1f1fd5;
	        geopolytl.geometryCollection.addItem(polytl);         
		}
			
		]]>
	</mx:Script>
</mx:Application>

自定义的类dashpolylinet1
package  
{   
	import com.degrafa.core.collections.GraphicPointCollection;
	import com.degrafa.geometry.Polyline;
	
	import flash.display.Graphics;
	import flash.geom.Rectangle;
	
	import mx.events.PropertyChangeEvent;
public class DashedPolylinetl extends Polyline
{   
	/**
	 * 构造函数,其中定义了style属性的change事件
	 * */
	public function DashedPolylinetl(points:Array=null)
	{
		super(points);
		addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,redraw);
	}
   /**
   * commandstack用于存储直线绘制信息,主要是moveto和lineto命令 
   **/
    public var	commandstack:Array = new Array();
    private var _points:GraphicPointCollection;
    public var _bounds:Rectangle=new Rectangle();
   
   	override	public function get points():Array{
			if(!_points){_points = new GraphicPointCollection();}
			return _points.items;
		}
	override	public function set points(value:Array):void{			
			if(!_points){_points = new GraphicPointCollection();}
			_points.items = value;
						
			//add a listener to the collection
			if(_points && enableEvents){
				_points.addEventListener(PropertyChangeEvent.PROPERTY_CHANGE,propertyChangeHandler);
			}
			
			invalidated = true;
		
		}
        
        /**
        * 计算dashpolyline的外接矩形
		**/
		  private function calcBounds():void{
		
			var boundsMaxX:Number =0;
			var boundsMaxY:Number =0;
			var boundsMinX:Number =Number.MAX_VALUE;
			var boundsMinY:Number =Number.MAX_VALUE;
						
			for (var i:int = 0;i< _points.items.length; i++) 
			{
				boundsMaxX = Math.max(boundsMaxX, _points.items[i].x);
				boundsMaxY = Math.max(boundsMaxY, _points.items[i].y);
				
				boundsMinX= Math.min(boundsMinX, _points.items[i].x);
				boundsMinY= Math.min(boundsMinY, _points.items[i].y);
				
			}

			_bounds = new Rectangle(boundsMinX,boundsMinY,boundsMaxX-boundsMinX,boundsMaxY-boundsMinY);

		}	
   
   public var length:Number;

   private var _dash:Number;
    /**
     * 每段直线的长度,默认值为0
     **/
    public function get dash():Number
    {
    	if (!_dash)
    		return 0;
		return _dash;
    }
    public function set dash(value:Number):void
    {
		if (_dash != value)
		{
			_dash = value;
			if (gap == 0)
				gap = value;			
			invalidated = true;
        }
    }
    
    private var _style:int;
    
    public function get style():int
    {   if(!_style)
            return 0;
    	return _style;
    }
    
    /**
    * 在style属性change之后分发PropertyChangeEvent事件
    **/
    public function set style(value:int):void
    { 
    	
     if(_style != value)
     {
     	_style=value;
     	invalidated= true;
     }	
     dispatchEvent(new PropertyChangeEvent(PropertyChangeEvent.PROPERTY_CHANGE,false,false, null,int,null,null,this.style));
    }
    
    private var _gap:Number;
  
    /**
     *每段直线之间的距离,默认值为0
     **/
    public function get gap():Number
    {
    	if (!_gap)
    		return 0;
		return _gap;
    }
    public function set gap(value:Number):void
    {
		if (_gap != value)
		{
			_gap = value;
			invalidated = true;
        }
    }
    private var _colour:uint;
  
    /**
     *线的颜色
     **/
    public function get colour():uint
    {
    	if (!_colour)
    		return 0;
		return _colour;
    }
    public function set colour(value:uint):void
    {
		if (_colour != value)
		{
			_colour = value;
			invalidated = true;
        }
    }

	/**
     * 用于绘制之前的指令算法存储至commandstack数组中
     * 根据style值,重组绘制线的数据;
     * style=4,线形为直线,无论如何设置dash,gap,都按照原始data两点一连画直线;
     * style=0,线形为虚线,dash为虚线线段长,gap为虚线间隔,根据二者对原始data进行重组,新的data数据点数大于原始data点个数;
     *         要保证虚线效果,dash+gap必须小于线任意两点间隔或最小距离两点间的距离
     * style=2,线形为虚线并且间隔中有两点,dash为虚线线段长,gap为虚线间隔,根据二者对原始data进行重组,新的data数据点数大于原始data点个数;
     *         要保证效果,该线形适用于数据点任意两点距离大于20的data,线中dash+gap必须小于线任意两点间隔或最小距离两点间的距离,
     *         gap中画了两个点,其位置和gap,dash都有关系,两点距离为20时,dash=10,gap=10,能看到两点效果;算法需要继续改进
     * style=3,线形为虚线并且间隔中有一点,dash为虚线线段长,gap为虚线间隔,根据二者对原始data进行重组,新的data数据点数大于原始data点个数;
     *         要保证效果,该线形适用于数据点任意两点距离大于20的data,线中dash+gap必须小于线任意两点间隔或最小距离两点间的距离,
     *         gap中画了一个点,其位置和gap,dash都有关系,两点距离为20时,dash=5,gap=5,能看到效果;算法需要继续改进
     * style=1,线形为铁路线,算法有问题,无法画出来效果图
      **/
    override public function preDraw():void
    {
		if(invalidated)
		{  
	    	super.preDraw();
          if(points.length==0){ return;}
            commandstack.length=0;                                            
			commandstack.push({type:"m",x:points[0].x+x,y:points[0].y+y});
			//如果style=4,即使设置了dash,gap,它们也不起作用
			if (style==4)
			{    
				for (var i:int = 0;i < points.length; i++)
				{
					commandstack.push({type:"l",x:points[i].x+x,y:points[i].y+y});
				}  
			}
			else
			{   
			   for (var j:int = 0;j < points.length-1; j++)
				switch(style)
				{
				case 0:
					addDashCommands0(commandstack, points[j].x+x, points[j].y+y,points[j+1].x+x, points[j+1].y+y);
				    break;
				case 1:
					  addDashCommands1(commandstack, points[j].x+x, points[j].y+y,points[j+1].x+x, points[j+1].y+y);
                      break;
				case 2:
				case 3:
					addDashCommands2(commandstack, points[j].x+x, points[j].y+y,points[j+1].x+x, points[j+1].y+y);
				      	break;
				default: break;      
				}
			}
                        
			/**
			 * 用于封闭的polyline
			 * */
			if(autoClose)
			{
				commandstack.push({type:"l",x:points[0].x+x,y:points[0].y+y});
			}
	    	calcBounds();
			invalidated = false;
	    }
            
    }
    
    protected var leftOver:int = 0;
    protected var leftOverCount:int = 0;
    
    /**
    *绘制虚线的commandstack命令
    **/
    protected function addDashCommands0(commandstack:Array, x1:int, y1:int, x2:int, y2:int):void
    {
		var length:Number = Math.abs(Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2)));  //线段长度
		var count:int = leftOverCount;
		var currentLength:int = 0;  //当前长度
		var ratio:Number = 1;       //比例
		while (currentLength < length)
		{
			
			// 绘制直线
			if (count % 2 == 0)
			{
				currentLength += dash - leftOver;
				ratio = Math.min(1,(currentLength / length));
				commandstack.push({type:"l",x:x1 + ((x2-x1)*ratio),y:y1 + ((y2-y1)*ratio)});
			}
			else
			{
				currentLength += gap - leftOver;
				ratio = Math.min(1,(currentLength / length));
				
				commandstack.push({type:"m",x:x1 + ((x2-x1)*ratio),y:y1 + ((y2-y1)*ratio)});
			}
			if (currentLength > length)
			{
				leftOver = ((count % 2 == 0) ? dash : gap) - (currentLength - length);
				leftOverCount = count;
			}
			else
			{
				leftOver = 0;
				leftOverCount = 0;
			}
			count++;
		}     	
    }
    
        /**
        * 绘制铁路线的commandstack命令
        **/ 
         protected function addDashCommands1(commandStack:Array, x1:int, y1:int, x2:int, y2:int):void
    {
		var length:Number = Math.abs(Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2)));  //线段长度
		var count:int = leftOverCount;
		var currentLength:int = 0;  //当前长度
		var ratio:Number = 1;       //比例
		while (currentLength < length)
		{
			
			// dash
			if (count % 2 == 0)
			{
				currentLength += dash - leftOver;
				ratio = Math.min(1,(currentLength / length));
				commandStack.push({type:"l",x:x1 + ((x2-x1)*ratio),y:y1 + ((y2-y1)*ratio)});
			}
			else
			{
				currentLength += gap - leftOver;
				ratio = Math.min(1,(currentLength / length));
				
				commandStack.push({type:"mm",x:x1 + ((x2-x1)*ratio),y:y1 + ((y2-y1)*ratio)});
			}
			if (currentLength > length)
			{
				leftOver = ((count % 2 == 0) ? dash : gap) - (currentLength - length);
				leftOverCount = count;
			}
			else
			{
				leftOver = 0;
				leftOverCount = 0;
			}
			count++;
		}    	
    }
    
    /**
    * 绘制单点线或者双点线的commandstack命令
    **/  
            protected function addDashCommands2(commandstack:Array, x1:int, y1:int, x2:int, y2:int):void
    {
		length= Math.abs(Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2)));  //线段长度
		var count:int = leftOverCount;
		var currentLength:int = 0;  //当前长度
		var ratio:Number = 1;       //比例
		while (currentLength < length)
		{
			
			// dash
			if (count % 2 == 0)
			{
				currentLength += dash - leftOver;
				ratio = Math.min(1,(currentLength / length));
				commandstack.push({type:"l",x:x1 + ((x2-x1)*ratio),y:y1 + ((y2-y1)*ratio),x0:x2-x1,y0:y2-y1,xd:((x2-x1)*ratio),yd:((y2-y1)*ratio)});
			}
			else
			{
				currentLength += gap - leftOver;
				ratio = Math.min(1,(currentLength / length));
				
				commandstack.push({type:"m",x:x1 + ((x2-x1)*ratio),y:y1 + (y2-y1)*ratio});
			}
			if (currentLength > length)
			{
				leftOver = ((count % 2 == 0) ? dash : gap) - (currentLength - length);
				leftOverCount = count;
			}
			else
			{
				leftOver = 0;
				leftOverCount = 0;
			}
			count++;
		}     	
    }
           /**
           * 根据style参数来绘制不同的线型
           **/
           
           	private var item:Object;
			private var lengths:Number;
			private var sin:Number;
			private var cos:Number;
			private var xx0:Number;
			private var yy0:Number;
			private var xx:Number;
			private var yy:Number;
			private var dx:Number;
			private var dy:Number;

	   		override public function draw(graphics:Graphics,rc:Rectangle):void{
					
		 	preDraw();
		 							
			if(!rc)				
				super.draw(graphics,_bounds);	
			else
				super.draw(graphics,rc);
			
			for each (item in commandstack)
			{
			graphics.lineStyle(0.1,colour,1);	
			lengths=Math.abs(Math.sqrt(Math.pow(item.x0, 2) + Math.pow(item.y0, 2))) 	
        	sin=item.x0/lengths;//直线的sin值
        	cos=item.y0/lengths;  //直线的cos值 	
        	xx0=item.x+dash*sin/4;               //单点直线的x-coordinate起始位置
        	yy0=item.y+dash*cos/4;               //单点直线的y-coordinate结束位置
        	xx=item.x+dash*sin/2;                //双点直线的x-coordinate起始位置
        	yy=item.y+dash*cos/2;                //双点直线的y-coordinate结束位置
        	dx=(item.x0==0?0:(item.x0)/Math.abs(item.x0));//中间变量,即点的x-coordinate移动距离(取值为0,1,-1)
        	dy=(item.y0==0?0:(item.y0)/Math.abs(item.y0));//中间变量,即点的y-coordinate移动距离(取值为0,1,-1)
        	if(item.type=="m")
        	graphics.moveTo(item.x,item.y);
			else 
			switch(style)
			{
			//绘制虚线的算法	
			case 0:
			//绘制实线的算法
			case 4:
			  {
        		
        		graphics.lineTo(item.x,item.y);
        	    break;
			  }
			case 1:  //绘制铁路线(或者变色线的算法)
			  {
        		  	//graphics.moveTo(item.x,item.y);
        		    if(item.type=="mm")
        		    {
        	         graphics.lineStyle(1,0xff0000,1,true);
        	         graphics.lineTo(item.x,item.y);
        	        }
        		   else 
        		  {
        		    graphics.lineStyle(1,0x000000,1,true);	
        			graphics.lineTo(item.x,item.y);
        		  }
        	    break;
			  }
			  
			case 2:   //绘制双点线型的算法
			  { 
        		graphics.lineTo(item.x,item.y);      
        		 if((Math.abs(xx+dx)<=Math.max(Math.abs(item.x),Math.abs(item.x+item.x0-item.xd)))&&(Math.abs(yy+dy)<=Math.max(Math.abs(item.y),Math.abs(item.y+item.y0-item.yd))))
        		 {        		
        		graphics.moveTo(xx0,yy0);
        		graphics.lineTo(xx0+dx,yy0+dy);//绘制单点,即利用lineto来绘制直线
        		graphics.moveTo(xx,yy);
        		graphics.lineTo(xx+dx,yy+dy);  //绘制双点,即利用lineto来绘制直线
                 }
			  	break;
			  }
			case 3:  //绘制单点线型的算法
			   {
        		graphics.lineTo(item.x,item.y);              //设置线条样式,绘制直线
        		//判断点的绘制是否执行,当点直线x-coordinate和y-coordinate的起始位置在直线之内则绘制单点
        		if((Math.abs(xx)<=Math.max(Math.abs(item.x),Math.abs(item.x+item.x0-item.xd)))&&(Math.abs(yy)<=Math.max(Math.abs(item.y),Math.abs(item.y+item.y0-item.yd))))
        		{        		
        		graphics.moveTo(xx,yy);
        		graphics.lineTo(xx+dx,yy+dy); //绘制单点,即利用lineto来绘制直线
                }
			   	 break;
			   }
			}
			}
			super.endDraw(graphics);
			
			
		}
		  /**
		  * 当style属性发生change则调用重绘函数,能够及时的响应线型改变进行重绘(由于会产生bug导致暂时屏蔽重绘功能,因为会报ss引用为Null)
		  * */
		    public  function redraw(e:PropertyChangeEvent):void
    {
    	    
//    	    draw(ss.graphics,null);
    }
    public function commandstackclear():void
    {
      
    }
	
}

}

你可能感兴趣的:(算法,Flex,Flash,J#)