[转] n次贝塞尔曲线AS重现

[转] n次贝塞尔曲线AS再现
http://bbs.9ria.com/viewthread.php?tid=71904&extra=page%3D1%26amp;orderby%3Ddateline%26amp;filter%3D86400


新年快到了,再也忍不住几个月不发帖了,这贴主要内容有:
1)n次方贝塞尔曲线(以1-10阶次为例子)
2)n次方贝塞尔曲线(Can Move版)(曲线可以移动,而效率不错哟,包括10次贝塞尔曲线)
3)n次方贝塞尔曲线(等分)(简单版等分,详细在
http://bbs.9ria.com/thread-24082-1-1.html
中,不同的是,俺不使用复杂的公式)

新年系列之——n次贝塞尔曲线AS再现出发!!
以俺的思路讲解,如果有必要的话,看看其他资料,保证对不明白贝塞尔曲线的兄弟们了解提升 一大步。

看看二次、三次的贝塞尔曲线公式:

[转] n次贝塞尔曲线AS重现

其公式主要成分为基函数(贝塞尔曲线计算耗时的原因),基函数推导过程(以二次为例):

[转] n次贝塞尔曲线AS重现


如此类推。。。所有的基函数数值都能计算出来
如果你还是一头汗!!那也没关系,先看看代码,基函数的代码
function BEZ(n:int,k:int,t:Number):Number {//基函数
        return C(n,k)*Math.pow(t,k)*Math.pow(1-t,n-k);
}
function C(n:int,k:int):Number {//组合排序
        var son:int=jie_cheng(n);
        var mother:int=jie_cheng(k)*jie_cheng(n-k);
        return son/mother;
}
function jie_cheng(i:int):int {//阶乘
        var n:int=1;
        for (var j:int=1; j<=i; j++) {
                n*=j;
        }
        return n;
}



二次贝塞尔曲线一个点要计算出6次基函数数值,因此越平滑,越高阶的贝塞尔曲线,会越折磨CPU的。
要画出一个贝塞尔曲线的一个点在上面的第一张图中已经看出了,所以完整的帧代码为:
var points:Array = [];
var sp:Sprite=new Sprite();
var n:int = 5;
addChild(sp);
draw_points(points,n);
function P_BEZ(t:Number,sz:Array):Point {//n次
        var x_p:Number = 0;
        var y_p:Number = 0;
        var n:int = sz.length;
        for (var i:int=0; i<sz.length; i++) {
                var b:Number = BEZ(n - 1,i,t);
                x_p += sz[i].x * b;
                y_p+=sz[i].y*b;
        }
        return (new Point(x_p,y_p));
}
function BEZ(n:int,k:int,t:Number):Number {//基函数
        return C(n,k)*Math.pow(t,k)*Math.pow(1-t,n-k);
}
function C(n:int,k:int):Number {//组合排序
        var son:int=jie_cheng(n);
        var mother:int=jie_cheng(k)*jie_cheng(n-k);
        return son/mother;
}
function jie_cheng(i:int):int {//阶乘
        var n:int=1;
        for (var j:int=1; j<=i; j++) {
                n*=j;
        }
        return n;
}
function draw_points(sz:Array,n:int):void {
        sz.length=0;
        for (var i:int=0; i<=n; i++) {
                sz[i]=new Point(800*Math.random(),500*Math.random());
                draw_point(sz[i]);
        }
        draw_lines(sz);
        sp.graphics.lineStyle(2,0xff0000);
        var p:Point=P_BEZ(0,sz);
        sp.graphics.moveTo(p.x,p.y);
        for (var j:Number=0; j<1; j+=0.01) {
                p=P_BEZ(j,sz);
                sp.graphics.lineTo(p.x,p.y);
        }
        p=P_BEZ(1,sz);
        sp.graphics.lineTo(p.x,p.y);
}
function draw_point(p:Point):void {//画点
        sp.graphics.lineStyle(0);
        sp.graphics.drawCircle(p.x,p.y,3);
}
function draw_lines(sz:Array):void {//画边
        sp.graphics.lineStyle(0,0,0.3);
        sp.graphics.moveTo(sz[0].x,sz[0].y);
        for (var i:int=0; i<sz.length; i++) {
                var p:Point=sz[i];
                sp.graphics.lineTo(p.x,p.y);
        }
}


5阶次的贝塞尔曲线

[转] n次贝塞尔曲线AS重现

10阶次的贝塞尔曲线

[转] n次贝塞尔曲线AS重现

1阶次的贝塞尔曲线

[转] n次贝塞尔曲线AS重现



那么,要移动10阶次的贝塞尔曲线,需要怎么做?
一切都是基函数的问题,就从他入手。
假设需要画100个点(已经可以画出很平滑的曲线了)
var sep:int = 100;
复制代码
如果阶次肯定地话,基函数的数值也就肯定了,如10阶次,一个点x坐标、y坐标分别需要计算出11个基函数数值。
把它保存起来
var datas:Array = [];
复制代码
以后需要的时候使用,这样就会得到意识不到的效果。(当然,3次贝塞尔曲线就足以模拟n次贝塞尔曲线,as3.0也是如此,但是做出实实在在的n次贝塞尔曲线,实在 )
效果图(移动前):

[转] n次贝塞尔曲线AS重现

效果图(移动后):

[转] n次贝塞尔曲线AS重现

效果图: 下载 (41.44 KB)

[转] n次贝塞尔曲线AS重现


初始化时CPU会高一些,此后CPU都十分理想。哈哈,代码会在最后给出。




本帖最后由 shen_0_ 于 2011-1-7 18:37 编辑


http://bbs.9ria.com/thread-24082-1-1.html   帖子已经解答出等分的问题,但是考虑其效果的用途,可以再简单一些
我使用一个点
var p:Point=P_BEZ(0,sz);
复制代码
将曲线大致跟踪了一次(画的同时)
在画的时候不是画出真正的贝塞尔曲线,而是画出其相似的等分线段:

[转] n次贝塞尔曲线AS重现

当然密集时会产生不理想的效果

[转] n次贝塞尔曲线AS重现



这个教程告一段落! 新的一年要更加努力呀!!!!


1 楼 xellosssky 2011-03-07  
感谢楼主分享,最想做连接2点的随机曲线,用了万有引力公式,结果一个点变成另一个点的“卫星”,不断的绕着转了……[转] n次贝塞尔曲线AS重现 。现在可以尝试下贝塞尔曲线公式了