高斯帕曲線 Gosper curve理解與js實現

    最近看threejs相關的知識點,發現一個 比較有趣的曲線-Gosper curve,如圖所示:

是由無數個基本圖像組成

    類似的曲線還有很多,比如龍曲線(Dragon curve)、Koch曲線(Koch curve)、摩爾定律曲線(Moore curve)、謝爾賓斯基曲線(Sierpiński curve)、奧斯古德曲線(Osgood curve)等等,這些曲線的共有特性爲降維,以Gosper爲例,當曲線足夠長時,它可以充滿一個二維的矩形,此時通過曲線的長度就可以表示二維矩形的某一點,同理可以上升爲三維。這些曲線的實際應用之一就是作爲地圖的索引,詳情請點擊點擊打開鏈接

    廢話這麼多,來看此曲線的定義和僞代碼,粘貼自wiki點擊打開鏈接

    The Gosper curve can be represented using an L-System with rules as follows:

    

Angle: 60°
Axiom: {\displaystyle A} A
Replacement rules:
{\displaystyle A\mapsto A-B--B+A++AA+B-} A\mapsto A-B--B+A++AA+B-
{\displaystyle B\mapsto +A-BB--B-A++A+B} B\mapsto +A-BB--B-A++A+B

    In this case both A and B mean to move forward, + means to turn left 60 degrees and - means to turn right 60 degrees - using a "turtle"-style program such as Logo.

    上面代碼中+代表加60,-代表減60,兩個--代表減120。

to rg :st :ln
make "st :st - 1
make "ln :ln / sqrt 7
if :st > 0 [rg :st :ln rt 60 gl :st :ln  rt 120 gl :st :ln lt 60 rg :st :ln lt 120 rg :st :ln rg :st :ln lt 60 gl :st :ln rt 60]
if :st = 0 [fd :ln rt 60 fd :ln rt 120 fd :ln lt 60 fd :ln lt 120 fd :ln fd :ln lt 60 fd :ln rt 60]
end

to gl :st :ln
make "st :st - 1
make "ln :ln / sqrt 7
if :st > 0 [lt 60 rg :st :ln rt 60 gl :st :ln gl :st :ln rt 120 gl :st :ln rt 60 rg :st :ln lt 120 rg :st :ln lt 60 gl :st :ln]
if :st = 0 [lt 60 fd :ln rt 60 fd :ln fd :ln rt 120 fd :ln rt 60 fd :ln lt 120 fd :ln lt 60 fd :ln]
end

   js代碼如下:(代碼參照Three.js開發指南)

function gosper(a, b) {

            var turtle = [0, 0, 0];
            var points = [];
            //var count = 0;

            rg(a, b, turtle);


            return points;

            function rt(x) {
                turtle[2] += x;
            }

            function lt(x) {
                turtle[2] -= x;
            }

            function fd(dist) {
                points.push({x: turtle[0], y: turtle[1], z: Math.sin(count) * 5});
                //var dir = turtle[2] * (Math.PI / 180);
                //turtle[0] += Math.cos(dir) * dist;
                //turtle[1] += Math.sin(dir) * dist;
                //points.push({x: turtle[0], y: turtle[1], z: Math.sin(count) * 5});
            }

            function rg(st, ln, turtle) {
                st--;
                ln = ln / 2.6457;
                if (st > 0) {
                    rg(st, ln, turtle);
                    rt(60);
                    gl(st, ln, turtle);
                    rt(120);
                    gl(st, ln, turtle);
                    lt(60);
                    rg(st, ln, turtle);
                    lt(120);
                    rg(st, ln, turtle);
                    rg(st, ln, turtle);
                    lt(60);
                    gl(st, ln, turtle);
                    rt(60);
                }
                if (st == 0) {
                    fd(ln);
                    rt(60);
                    fd(ln);
                    rt(120);
                    fd(ln);
                    lt(60);
                    fd(ln);
                    lt(120);
                    fd(ln);
                    fd(ln);
                    lt(60);
                    fd(ln);
                    rt(60)
                }
            }

            function gl(st, ln, turtle) {
                st--;
                ln = ln / 2.6457;
                if (st > 0) {
                    lt(60);
                    rg(st, ln, turtle);
                    rt(60);
                    gl(st, ln, turtle);
                    gl(st, ln, turtle);
                    rt(120);
                    gl(st, ln, turtle);
                    rt(60);
                    rg(st, ln, turtle);
                    lt(120);
                    rg(st, ln, turtle);
                    lt(60);
                    gl(st, ln, turtle);
                }
                if (st == 0) {
                    lt(60);
                    fd(ln);
                    rt(60);
                    fd(ln);
                    fd(ln);
                    rt(120);
                    fd(ln);
                    rt(60);
                    fd(ln);
                    lt(120);
                    fd(ln);
                    lt(60);
                    fd(ln);
                }
            }
        }
    其中fd方法就獲得曲線的某一個點值
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章