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();
}
AS3 三角形填充
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.