
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();
}