代码改变世界

AS3 通过多点绘制光滑曲线

2009-06-25 10:33  宝宝合凤凰  阅读(514)  评论(0编辑  收藏  举报

AS3 通过多点绘制光滑曲线

标签AS3  多点  绘制  光滑曲线  2009-05-31 10:30

问题:有n个随机点,需要用光滑曲线将起连接起来,曲线看上去要有一定的曲度?

思路1:从第一个点穿过第二个点到第三个点绘制曲线,然后再穿过第四个点到第五个点绘制曲线,穿过第六个点到第七个点。。。这样可以看出来,点的个数n比为奇数,才可以画到终点,暂设置n=9。

var numPoints = n;//n必为奇数,暂设为9
//创建随机点构成的一个数组
var points:Array = new Array();
for(var i=0;i<numPoints;i++){
   points[i] = {};
   points[i].x = Math.random()*stage.width;
   points[i].y = Math.random()*stage.height;
}
//设置笔触样式
lineStyle(1);
//移动笔到第一个点
moveTo(points[0].x,points[0].y);
//循环每一个相邻的后续对画曲线
for(i=1;i<numPoints;i+=2){
   curveTo(points[i].x,points[i].y,points[i+1].x,points[i+1].y); 

}
思路2:在每两个点之间插入一个新的点,位于原两点之间,用所插入的点为每条曲线的起始点和终点,用原来的点作为控制点画曲线,这样没有点的个数必为奇数的限制,且画出来的曲线比第一种方法的曲线更加“好看”。如下图:

 

 

空心白点为原来的点,黑色实心点为插入的新点(图片来源:http://www.b4en.com/home/link.php?url=http://lovejulia.cn%2Fblog%2Farticle.asp%3Fid%3D107,参考:http://www.b4en.com/home/link.php?url=http://lovejulia.cn%2Fblog%2Farticle.asp%3Fid%3D107http://www.b4en.com/home/link.php?url=http://blog.sina.com.cn%2Fs%2Fblog_3ecb9b1101008z9g.html

从图上看出,第一个插入的点,与最后一个插入的点没有用到,也就是说没有用来作为任何控点和终点,所以只需要在第二个点和倒数第二个点之间插入新点,算法如下:

var numPoints = n;
var points:Array = new Array();
for(var i=0;i<numPoints;i++){
   points[i] = {};
   points[i].x = Math.random()*stage.width;
   points[i].y = Math.random()*stage.height;
}
lineStyle(1);
moveTo(points[0].x,points[0].y);
//在第二个点与倒数第二个点间插入新点,并绘制曲线
for(i=1;i<numPoints-2;i++){
   var xc = (points[i].x+points[i+1].x)/2;
   var yc = (points[i].y+points[i+1].y)/2;
   //i从1开始的,即第一个控点是原来的第二个点,终点(xc,yc)为原第二个点与第三个点间插入的新点,即第一个插入的点。。。循环结束i=numPoints-2,即还剩下两个点没有画线
   curveTo(points[i].x,points[i].y,xc,yc);
}
//追加最后一条曲线(倒数第二个点为控点,最后一个点为终点)
curveTo(points[i].x,points[i].y,points[i+1].x,points[i+1].y); 


总结:思路1中是经过每个原始点画曲线,但必须要求点的个数为奇数,且最小给定点个数为 三,画出来的曲线可以看出明显的衔接,曲度不够,不是要求的曲线;思路2中的曲线只是经过了第一个点和最后一个点,中间的点是根据原有点来插入的点,也就 是说并没有经过给出的点,而是经过由给出点所得出的新点,这种方法得出的曲线没有点数必为奇数的限制,且曲度也可以达到要求。

 
PS:我整理了一下,完整代码:
package {
 import flash.display.Sprite;
 import flash.display.StageAlign;
 import flash.display.StageScaleMode;
 
 [SWF(frameRate='30',width=600,height=400)]
 public class DD extends Sprite
 {
  public function DD()
  {
   stage.scaleMode=StageScaleMode.NO_SCALE;
   stage.align=StageAlign.TOP_LEFT;
   var numPoints:uint = 9;
   var points:Array = new Array();
   
   for(var i:int=0;i<numPoints;i++){
      points[i] = {};
      points[i].x = Math.random()*stage.stageWidth;
      points[i].y = Math.random()*stage.stageHeight;
   }
   this.graphics.lineStyle(2);
   this.graphics.moveTo(points[0].x,points[0].y);
   
   //在第二个点与倒数第二个点间插入新点,并绘制曲线
   for(i=1;i<numPoints-2;i++){
      var xc:Number = (points[i].x+points[i+1].x)/2;
      var yc:Number = (points[i].y+points[i+1].y)/2;
      //i从1开始的,即第一个控点是原来的第二个点,终点(xc,yc)为原第二个点与第三个点间插入的新点,即第一个插入的点。。。循环结束i=numPoints-2,即还剩下两个点没有画线
      this.graphics.curveTo(points[i].x,points[i].y,xc,yc);
   }
   
   //追加最后一条曲线(倒数第二个点为控点,最后一个点为终点)
   this.graphics.curveTo(points[i].x,points[i].y,points[i+1].x,points[i+1].y);
  }
 }
}