AS3 三角形填充

		private var bmd:BitmapData = new BitmapData(800,600, false, 0);
		private var bmp:Bitmap = new Bitmap(bmd);
//		private var clip:Rectangle = new Rectangle(120,150,40,30);
		private var clip:Rectangle = new Rectangle(0,0,800,600);
//		private var clip:Rectangle = new Rectangle(80,0,70,600);
		public function GeometryTest()
		{
			addChild(bmp);
//			flatBottom(new Point(100,200),new Point(50,100),new Point(150,100));
//			flatTop(new Point(50,100), new Point(150,100), new Point(100,0));
//			drawTriangle(new Point(30,200),new Point(50,80),new Point(150,90));
			stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		private var count:int = 0;
		protected function onEnterFrame(event:Event):void
		{
			if(count == 0)
			{
				bmd.fillRect(clip,0);
				count = 10;
				drawTriangle(new Point(Math.random()*800,300),new Point(Math.random()*800,500),new Point(Math.random()*800,200));
			}
			count--;
		}
		
		public function drawTriangle(p1:Point, p2:Point, p3:Point):void
		{
			var x1:Number = p1.x, y1:Number = p1.y;
			var x2:Number = p2.x, y2:Number = p2.y;
			var x3:Number = p3.x, y3:Number = p3.y;
			//三点共线 则不能成为三角形
			if((x1 == x2 && x2 == x3) || (y1 == y2 && y2 == y3))
			{
				return;
			}
			
			//让点按照 P1 P2 P3 的y值从大到小排序
			var tempX:Number;
			var tempY:Number;
			if(y1 < y2)
			{
				tempX = x2;
				x2 = x1;
				x1 = tempX;
				
				tempY = y2;
				y2 = y1;
				y1 = tempY;
			}
			
			if(y1 < y3)
			{
				tempX = x3;
				x3 = x1;
				x1 = tempX;
				
				tempY = y3;
				y3 = y1;
				y1 = tempY;
			}
			
			if(y2 < y3)
			{
				tempX = x3;
				x3 = x2;
				x2 = tempX;
				
				tempY = y3;
				y3 = y2;
				y2 = tempY;
			}
			
			//如果所有定点都在裁剪区域外则不能绘图
			if(y3 > clip.bottom || y1 < clip.top || 
				(x1 < clip.left && x2 < clip.left && x3 < clip.left) ||
				(x1 > clip.right && x2 > clip.right && x3 > clip.right))
			{
				return;
			}
			
			var temp1:Point = new Point(x1, y1);
			var temp2:Point = new Point(x2, y2);
			var temp3:Point = new Point(x3, y3);
			//平顶
			if(y1 == y2)
			{
				flatTop(temp1, temp2, temp3);
			}else if(y2 == y3)//平底
			{
				flatBottom(temp1, temp2, temp3);
			}else
			{
				//要求出 1-3边上的点new_x, 其中 2-new_x 可以将三角性分为平顶三角形和平底三角形
				//公式画图可得,就是求 当走过 y2-y3 个步长时 ,x3 在 1-3边上 所走的距离
				var newX:Number = x3 + (y2 - y3)*(x3 -x1)/(y3 - y1);
				var tempNew:Point = new Point(newX, y2);
				
				flatTop(temp2, tempNew, temp3);
				flatBottom(temp1, tempNew, temp2);
			}
		}
		
		//画平底即底边比顶点的Y值小
		public function flatBottom(p1:Point, p2:Point, p3:Point):void
		{
			bmd.lock();
			//指定p1为底点,p2-p3为平底
			var x1:Number = p1.x, y1:Number = p1.y;
			var x2:Number = p2.x, y2:Number = p2.y;
			var x3:Number = p3.x, y3:Number = p3.y;
			//保证 x2 是左斜边,x3是右斜边
			if(x2 > x3)
			{
				var temp:Number = x2;
				x2 = x3;
				x3 = temp;
			}
			//计算斜率
			var dxyLeft:Number = (x2 - x1)/(y2 - y1);//是通过Y的增加来求X的变化率,所以是斜率的倒数
			var dxyRight:Number = (x3 - x1)/(y3 - y1);
			
			var xs:Number = x2;
			var xe:Number = x3;
			
			if(y1 > clip.bottom)
			{
				xs = xs + dxyLeft*(-y1 + clip.bottom);//当前的点xs + 走过(-y1 + clip.top)步的变化率,就是需要的xs点
				xe = xe + dxyRight*(-y1 + clip.bottom);//当前的点xe + 走过(-y1 + clip.top)步的变化率,就是需要的xe点
				y1 = clip.bottom;
			}
			if(y3 < clip.top)
			{
				y3 = clip.top;
			}
			var y:int;
			var x:int;
			//假如x点都在裁剪区域内
			if(x1 >= clip.left && x1 <= clip.right &&
				x2 >= clip.left && x2 <= clip.right &&
				x3 >= clip.left && x3 <= clip.right)
			{
				for(y = y3; y <= y1; y++)
				{
					//drawLine(new Point(xs, y), new Point(xe, y), 0x00ff00);
					for(x = xs; x <= xe; x++)
					{
						bmd.setPixel32(x, y, 0xffffff*Math.random());
					}
					xs += dxyLeft;
					xe += dxyRight;
				}
			}else//加入有x点不在裁剪区域内则每增加一步,就要判断x是否超出clip范围,如果超出则映射到对应的clip边上(当然也可以直接用这个else的所有内容,而不必写这个if-else, 写if-else 主要是为了让if更快)
			{
				var left:Number = xs;
				var right:Number = xe;
				for(y = y3; y <= y1; y++)
				{
					left = xs;
					right = xe;
					if(left < clip.left)
					{
						left = clip.left;
						if(right < clip.left)
						{
							continue;
						}
					}
					if(right > clip.right)
					{
						right = clip.right;
						if(left > clip.right)
						{
							continue;
						}
					}
//					drawLine(new Point(left, y), new Point(right, y), 0x00ff00);
					for(x = left; x <= right; x++)
					{
						bmd.setPixel32(x, y, 0xff0000);
					}
					xs += dxyLeft;
					xe += dxyRight;
				}
			}
			bmd.unlock();
		}
		
		//画平顶即底边比顶点的Y值大
		public function flatTop(p1:Point, p2:Point, p3:Point):void
		{
			bmd.lock();
			//指定p3为底点,p1-p2为平顶
			var x1:Number = p1.x, y1:Number = p1.y;
			var x2:Number = p2.x, y2:Number = p2.y;
			var x3:Number = p3.x, y3:Number = p3.y;
			//保证 x1 是左斜边,x2是右斜边
			if(x1 > x2)
			{
				var temp:Number = x1;
				x1 = x2;
				x2 = temp;
			}
			//计算斜率
			var dxyLeft:Number = (x1 - x3)/(y1 - y3);//是通过Y的增加来求X的变化率,所以是斜率的倒数
			var dxyRight:Number = (x2 - x3)/(y2 - y3);
			var xs:Number = x3;//如果xs 或者 xe 是 int 型的话,需要加0.5 除去误差,相当于四舍五入到整点,比如1.8 +0.5 = 2.3 ≈ 2 , 1.2 + 0.5 = 1.7 ≈ 1
			var xe:Number = x3;
			
			if(y3 < clip.top)
			{
				xs = xs + dxyLeft*(-y3 + clip.top);
				xe = xe + dxyRight*(-y3 + clip.top);
				y3 = clip.top;
			}
			
			if(y1 > clip.bottom)
			{
				y1 = clip.bottom;
			}
			
			var y:int;
			var x:int;
			//假如x点都在裁剪区域内
			if(x1 >= clip.left && x1 <= clip.right &&
				x2 >= clip.left && x2 <= clip.right &&
				x3 >= clip.left && x3 <= clip.right)
			{
				for(y = y3; y <= y1; y++)
				{
					for(x = xs; x <= xe; x++)
					{
						bmd.setPixel32(x, y, 0xffffff*Math.random());
					}
					
					xs += dxyLeft;
					xe += dxyRight;
				}
			}else
			{
				var left:Number = xs;
				var right:Number = xe;
				for(y = y3; y <= y1; y++)
				{
					left = xs;
					right = xe;
					if(left < clip.left)
					{
						left = clip.left;
						if(right < clip.left)
						{
							continue;
						}
					}
					if(right > clip.right)
					{
						right = clip.right;
						if(left > clip.right)
						{
							continue;
						}
					}
					for(x = left; x <= right; x++)
					{
						bmd.setPixel32(x, y, 0xffff00);
					}
					
					xs += dxyLeft;
					xe += dxyRight;
				}
			}
			bmd.unlock();
		}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值