分形--謝爾賓斯基三角形


    大學時候,有上過關於圖像學相關的課程,當時圖像學課程的老師,聽說在學院里都非常的出名,在入學之前就有聽說,當初信誓旦旦的,想好好學習,可以還是擋不過大學里的自由的生活的誘惑,還是沒能堅持下來。

    當初對圖形學相關的印象也是停留在絢麗的圖形圖像上,對於實現感覺就是高深莫測的東西(刁吊的MFC),現在工作也快一年多了,可能是東西做的多了,對做任何東西都有一股自信,所以想把當初的東西撿起來。

原理:(摘自百度百科)

1.取一個實心的三角形。(多數使用等邊三角形)

2.沿三邊中點的連線,將它分成四個小三角形。

3.去掉中間的那一個小三角形。

4.對其余三個小三角形重復1。

取一個正方形或其他形狀開始,用類似的方法構作,形狀也會和謝爾賓斯基三角形相近。

image

 

先貼上js實現效果:

迭代效果

image        image  image     image

關鍵代碼:

頁面:

使用HTML5中的canvas畫布進行圖像的繪制,並提供一個可供輸入的文本框記錄迭代次數。

<body style='margin:0 auto;width:800px;'>
    <div>
        <input type='text' id='Count'/><input type='button' value='運行' id='btn' />
    </div>
    <canvas id='cav' width='500' height='500' style='border:1px solid black;'></canvas>
</body>

 

js實現思路:

定義最大的等邊三角形,每迭代一次,取三角各邊的中點,然后將中間點進行連接,對於中間的三角形不進行二次迭代,使用此取巧的方式代替“挖空”中間三角形的概念,邏輯很簡單。

js:

1、點對象

function point (x,y) {
            this.x = x;
            this.y = y;
        }

2、畫線

function drawLine (ctx,point1,point2,point3) {
            ctx.beginPath();
            ctx.moveTo(point1.x, point1.y);
            ctx.lineTo(point2.x, point2.y);
            ctx.lineTo(point3.x, point3.y);
            ctx.closePath();
            ctx.stroke();
        }

3、取中間點

function getMiddlePoint (pointA,pointB) {
            var x = (pointA.x + pointB.x)/2;
            var y = (pointA.y + pointB.y)/2;
            return new point(x,y);
        }

4、迭代函數

function drawOri (ctx,pointA,pointB,pointC,count) {
            if (count>2) {
                drawLine(ctx,pointA,pointB,pointC);
                var t_A = getMiddlePoint(pointA,pointB);
                var t_B = getMiddlePoint(pointA,pointC);
                var t_C = getMiddlePoint(pointB,pointC);
                count -= 1;
                drawOri(ctx,t_A,pointB,t_C,count);
                drawOri(ctx,t_A,t_B,pointA,count);
                drawOri(ctx,pointC,t_B,t_C,count);
            } else if(count==2){
                drawLine(ctx,pointA,pointB,pointC);
                var t_A = getMiddlePoint(pointA,pointB);
                var t_B = getMiddlePoint(pointA,pointC);
                var t_C = getMiddlePoint(pointB,pointC);
                count -= 1;
                drawOri(ctx,t_A,t_B,t_C,count);
            }else{
                drawLine(ctx,pointA,pointB,pointC);
            }
        }

完整可運行代碼如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset='utf-8'></meta>
    <title>謝爾賓斯基三角形</title>
    <style type="text/css"></style>
    <script type="text/javascript">
    
        function point (x,y) {
            this.x = x;
            this.y = y;
        }

        function drawLine (ctx,point1,point2,point3) {
            ctx.beginPath();
            ctx.moveTo(point1.x, point1.y);
            ctx.lineTo(point2.x, point2.y);
            ctx.lineTo(point3.x, point3.y);
            ctx.closePath();
            ctx.stroke();
        }

        function getMiddlePoint (pointA,pointB) {
            var x = (pointA.x + pointB.x)/2;
            var y = (pointA.y + pointB.y)/2;
            return new point(x,y);
        }

        function drawOri (ctx,pointA,pointB,pointC,count) {
            if (count>2) {
                drawLine(ctx,pointA,pointB,pointC);
                var t_A = getMiddlePoint(pointA,pointB);
                var t_B = getMiddlePoint(pointA,pointC);
                var t_C = getMiddlePoint(pointB,pointC);
                count -= 1;
                drawOri(ctx,t_A,pointB,t_C,count);
                drawOri(ctx,t_A,t_B,pointA,count);
                drawOri(ctx,pointC,t_B,t_C,count);
            } else if(count==2){
                drawLine(ctx,pointA,pointB,pointC);
                var t_A = getMiddlePoint(pointA,pointB);
                var t_B = getMiddlePoint(pointA,pointC);
                var t_C = getMiddlePoint(pointB,pointC);
                count -= 1;
                drawOri(ctx,t_A,t_B,t_C,count);
            }else{
                drawLine(ctx,pointA,pointB,pointC);
            }
        }

        window.onload=function () {
            var cav = document.getElementById('cav');
            var ctx = cav.getContext('2d');
            ctx.strokeStyle="#3333ff";
            drawOri(ctx,new point(230,10),new point(10,450),new point(480,450),7);
            var btn = document.getElementById('btn');
            var val = 0;
            btn.onclick=function () {
                val = document.getElementById('Count').value;
                if (parseInt(val).toString()!='NaN') {
                    ctx.clearRect(0,0,500,500);
                    drawOri(ctx,new point(230,10),new point(10,450),new point(480,450),val);
                } else{
                    alert('error number');
                };
            }
        }
    </script>
</head>
<body style='margin:0 auto;width:800px;'>
    <div>
        <input type='text' id='Count'/><input type='button' value='運行' id='btn' />
    </div>
    <canvas id='cav' width='500' height='500' style='border:1px solid black;'></canvas>
</body>
</html>

編后語:

   可能實現方式上算法不是最好的,大家如果有更好的js實現技巧,歡迎交流指導!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM