折线算法

前提: 

 

 1. 节点具有方向,上/下/左/右 四个方向

 

 2. 节点移动时,必须及时计算出新的方向,

 

先上效果图


折线算法_第1张图片

 

 

 

package com.donkey.workflow.comp.line
{
	import com.donkey.workflow.comp.Anchor;
	import com.donkey.workflow.comp.OutlineForLine;
	import com.donkey.workflow.event.AnchorDragEvent;
	import com.donkey.workflow.event.NodeDragEvent;
	
	import flash.display.Graphics;
	import flash.geom.Point;

	public class BrokenLine extends Line
	{
		
		private static const FIX_LENGTH:int = 20;
		
		private var _sourceDirection:Number;
		
		private var _targetDirection:Number;
		
		private var _straight:int = 1;
		
		public function BrokenLine()
		{
		}
		
		override protected function createChildren():void
		{
			super.createChildren();
		}
		
		
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
		{
			super.updateDisplayList(unscaledWidth, unscaledHeight);
			
			var g:Graphics = graphics;
			g.clear();
			
			var backgroundColor:Number = selected ? getStyle("selectedColor") : getStyle("backgroundColor");
			
			linePoints = [];
			generatePoint(sourcePoint, sourceDirection, targetPoint, targetDirection);
			
			for each (var line:LinePoints in linePoints)
			{
				// 画直线
				g.lineStyle(2, backgroundColor);
				g.moveTo(line.sourcePoint.x, line.sourcePoint.y);
				g.lineTo(line.targetPoint.x, line.targetPoint.y);
			}
			
			var endLine:LinePoints = linePoints[linePoints.length - 1];
			
			if(arrow && null != endLine)
			{
				// 画箭头
				var radius:Number = 8.5;
				var angle:int= GetAngle(endLine.sourcePoint.x, endLine.sourcePoint.y, endLine.targetPoint.x, endLine.targetPoint.y);  
				var centerX:int=endLine.targetPoint.x - radius * Math.cos(angle *(Math.PI/180)) ;  
				var centerY:int=endLine.targetPoint.y + radius * Math.sin(angle *(Math.PI/180)) ;  
				var topX:int=endLine.targetPoint.x;  
				var topY:int=endLine.targetPoint.y;  
				var leftX:int=centerX + radius * Math.cos((angle +120) *(Math.PI/180))  ;  
				var leftY:int=centerY - radius * Math.sin((angle +120) *(Math.PI/180))  ;  
				
				var rightX:int=centerX + radius * Math.cos((angle +240) *(Math.PI/180))  ;  
				var rightY:int=centerY - radius * Math.sin((angle +240) *(Math.PI/180))  ;  
				
				this.graphics.beginFill(backgroundColor, 1);  
				this.graphics.lineStyle(1,backgroundColor, 1);  
				this.graphics.moveTo(topX,topY);  
				this.graphics.lineTo(leftX,leftY);  
				this.graphics.lineTo(centerX,centerY);  
				this.graphics.lineTo(rightX,rightY);  
				this.graphics.lineTo(topX,topY);  
				this.graphics.endFill();
			}
			
			outLine.line = this;
		}
		
		private function GetAngle(startX:Number,startY:Number,endX:Number,endY:Number):int  
		{  
			var tmpx:int=endX - startX ;  
			var tmpy:int=startY -endY ;  
			var angle:int= Math.atan2(tmpy,tmpx)*(180/Math.PI);  
			return angle;  
		}
		
		/**
		 * 生成节点
		 **/
		private function generatePoint(source:Point, sourceD:int, target:Point, targetD:int):void
		{
			smoothPoint(source);
			smoothPoint(target);
			
			var startPoint:Point = offsetPoint(source, sourceD);
			var line:LinePoints = new LinePoints();
			line.sourcePoint = source;
			line.targetPoint = startPoint;
			linePoints.push(line);
			
			var endPoint:Point = offsetPoint(target, targetD);
			
			if (startPoint.y <= endPoint.y)
			{
				this.calculatePoint(startPoint, sourceD, endPoint, targetD);
			}
			else
			{
				this.calculatePoint(endPoint, targetD, startPoint, sourceD);
			}
			
			line = new LinePoints();
			line.sourcePoint = endPoint;
			line.targetPoint = target;
			linePoints.push(line);
		}
		
		/**
		 * 去除误差 
		 * @param source
		 */		
		private function smoothPoint(source:Point):void
		{
			source.x = Math.round(source.x);
			source.y = Math.round(source.y);
			
			if(source.x % 2 == 1)
			{
				source.x = source.x + 1;
			}
			if(source.y % 2 == 1)
			{
				source.y = source.y + 1;
			}
		}
		
		
		/**
		 * 生成开始/结束节点偏移
		 **/
		private function offsetPoint(source:Point, sourceD:int):Point
		{
			var gap:Number;
			var nextSourcePoint:Point = null;
			
			if (Math.abs(sourceD) == 1)
			{
				gap = sourceD > 0 ? FIX_LENGTH : 0 - FIX_LENGTH;
				nextSourcePoint = new Point(source.x + gap, source.y);
			}
			else if (Math.abs(sourceD) == 2)
			{
				gap = sourceD > 0 ? FIX_LENGTH : 0 - FIX_LENGTH;
				nextSourcePoint = new Point(source.x , source.y + gap);
			}
			
			return nextSourcePoint;
		}
		
		/**
		 * 计算
		 **/
		private function calculatePoint(source:Point, sourceD:int, target:Point, targetD:int):void
		{
			if (Math.abs(source.x - target.x) <= 1 && Math.abs(source.y - target.y) <= 1)
			{
				return;
			}
			
			var line:LinePoints = null;
			
			var nextPoint:Point = findNextPoint(source, sourceD, target, targetD);
			
			var nextPointDirection:int = 0;
			if(nextPoint == null)
			{
				nextPoint = new Point(Math.round(source.x + target.x)/2, Math.round(source.y + target.y)/2 );
				if(Math.abs(sourceD) == Math.abs(targetD))
				{
					if(Math.abs(sourceD) == 1)
					{
						nextPointDirection = source.y <= nextPoint.y ? 2 : -2;
					}
					else
					{
						nextPointDirection = source.x <= nextPoint.x ? 1 : -1;
					}
				}
				else
				{
					if(Math.abs(sourceD) == 1)
					{
						nextPointDirection = source.y <= nextPoint.y ? -2 : 2;
					}
					else
					{
						nextPointDirection = source.x <= nextPoint.x ? -1 : 1;
					}
				}
				
				calculatePoint(source, nextPointDirection, nextPoint, sourceD);
				
				calculatePoint(nextPoint, 0 - sourceD, target, targetD);
			}
			else
			{
				// 加入
				line = new LinePoints();
				line.sourcePoint = source;
				line.targetPoint = nextPoint;
				linePoints.push(line);
				
				line = new LinePoints();
				line.sourcePoint = nextPoint;
				line.targetPoint = target;
				linePoints.push(line);
			}
		}
		
		private function findNextPoint(source:Point, sourceD:int, target:Point, targetD:int):Point
		{
			var x:int = 0;
			var y:int = 0;
			
			if(Math.abs(sourceD) == 1)
			{
				if (sourceD > 0)
				{
					if (source.x <= target.x)
					{
						x = target.x;
						y = source.y;
					}
					else if (source.x > target.x)
					{
						x = source.x;
						y = target.y;
					}
				}
				else
				{
					if (source.x <= target.x)
					{
						x = source.x;
						y = target.y;
					}
					else if (source.x > target.x)
					{
						x = target.x;
						y = source.y;
					}
				}
			}
			else
			{
				if (sourceD > 0)
				{
					if (source.y <= target.y)
					{
						x = source.x;
						y = target.y;
					}
					else if (source.y > target.y)
					{
						x = target.x;
						y = source.y;
					}
				}
				else
				{
					if (source.y <= target.y)
					{
						x = target.x;
						y = source.y;
					}
					else if (source.y > target.y)
					{
						x = source.x;
						y = target.y;
					}
				}
			}
			
			var nextPoint:Point = new Point(x, y);
			var directionS:int = calculateDirection(source, nextPoint, sourceD);
			var directionT:int = calculateDirection(nextPoint, target, targetD);
			
			var find:Boolean = false;
			if ((Math.abs(directionS) != Math.abs(sourceD)) || directionS == sourceD)
			{
				//方向相同或者垂直
				if ((Math.abs(directionT) != Math.abs(targetD)) || directionT == 0 - targetD)
				{
					find = true;
				}
				else
				{
					if(directionT == targetD)
					{
						if (Math.abs(targetD) == 1)
						{
							if ((nextPoint.x > target.x && targetD > 0) || (nextPoint.x < target.x && targetD < 0))
							{
								find = true;
							}
						}
					}
				}
			}
			if (find)
			{
				return nextPoint;
			}
			return null;
		}
		
		/**
		 * 计算两个坐标的方向
		 */
		private function calculateDirection(source:Point, target:Point, direction:int):int
		{
			if (source.y == target.y)
			{
				return source.x <= target.x ? 1 : -1;
			}
			else
			{
				return source.y <= target.y ? 2 : -2;
			}
		}

		/**
		 * 根据两个节点之间的位置重新计算开始位置和结束位置
		 **/
		/*override protected function changePoint():void
		{
			if (this.sourceDirection == 1)
			{
				this.sourcePoint.x = this.sourcePoint.x + sourceNode.width / 2;
			}
			if (this.sourceDirection == -1)
			{
				this.sourcePoint.x = this.sourcePoint.x - sourceNode.width / 2;
			}
			
			if (this.sourceDirection == 2)
			{
				this.sourcePoint.y = this.sourcePoint.y + sourceNode.height / 2;
			}
			
			if (this.sourceDirection == -2)
			{
				this.sourcePoint.y = this.sourcePoint.y - sourceNode.height / 2;
			}
			
			// 目标节点
			if (this.targetDirection == 1)
			{
				this.targetPoint.x = this.targetPoint.x + targetNode.width / 2;
			}
			
			if (this.targetDirection == -1)
			{
				this.targetPoint.x = this.targetPoint.x - targetNode.width / 2;
			}
			
			if (this.targetDirection == 2)
			{
				this.targetPoint.y = this.targetPoint.y + targetNode.height / 2;
			}
			
			if (this.targetDirection == -2)
			{
				this.targetPoint.y = this.targetPoint.y - targetNode.height / 2;
			}
		}*/
		
		override protected function changePoint(point:Point, anchor:Anchor):void
		{
			point.x = point.x + anchor.initPoint.x;
			point.y = point.y + anchor.initPoint.y;
		}
		
		override protected function startNodeMoveHandle(event:NodeDragEvent):void{
			updatePoint(sourcePoint, sourceDirection, event, sourceAnchor);
			invalidateDisplayList();
		}
		
		override protected function endNodeMoveHandle(event:NodeDragEvent):void{
			updatePoint(targetPoint, targetDirection, event, targetAnchor);
			invalidateDisplayList();
		}
		
		/**
		 * 更新起始坐标
		 **/
		/*private function updatePoint(point:Point, direction:int, event:NodeDragEvent):void
		{
			if (direction == 1)
			{
				point.x = event.node.x + event.node.width;
				point.y = event.node.y + event.node.height / 2;
			}
			if (direction == -1)
			{
				point.x = event.node.x;
				point.y = event.node.y + event.node.height / 2;
			}
			
			if (direction == 2)
			{
				point.x = event.node.x + event.node.width / 2;;
				point.y = event.node.y + event.node.height;
			}
			
			if (direction == -2)
			{
				point.x = event.node.x + event.node.width / 2;;
				point.y = event.node.y;
			}
		}*/
		
		private function updatePoint(point:Point, direction:int, event:NodeDragEvent, anchor:Anchor):void
		{
			point.x = event.node.x + anchor.initPoint.x;
			point.y = event.node.y + anchor.initPoint.y;
		}
		
		/**
		 * 1. 直线
		 * 2. 曲线
		 * 3. 折线
		 */
		public function get straight():int
		{
			return _straight;
		}
		
		/**
		 * @private
		 */
		public function set straight(value:int):void
		{
			_straight = value;
		}
		
		
		public function get targetDirection():Number
		{
			return _targetDirection;
		}
		
		public function set targetDirection(value:Number):void
		{
			_targetDirection = value;
		}
		
		public function get sourceDirection():Number
		{
			return _sourceDirection;
		}
		
		public function set sourceDirection(value:Number):void
		{
			_sourceDirection = value;
		}

	}
}

 

整体的流程图如下:

 

 


折线算法_第2张图片

 

你可能感兴趣的:(Flex)