分形--谢尔宾斯基地毯

     谢尔宾斯基地毯的构造与谢尔宾斯基三角形相似,区别仅在于谢尔宾斯基地毯是以正方形而非等边三角形为基础的。将一个实心正方形划分为的9个小正方形,去掉中间的小正方形,再对余下的小正方形重复这一操作便能得到谢尔宾斯基地毯。

    js实现思路和我之前写的分形--谢尔宾斯基三角形的类似。

js效果:

imageimage

贴关键代码:

1、画点

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

2、画线

function drawLine (ctx,point1,point2) {
        ctx.beginPath();
        ctx.moveTo(point1.x,point1.y);
        ctx.lineTo(point2.x,point2.y);
        ctx.closePath();
        ctx.stroke();
    }
3、画矩形
function drawRect (ctx,point1,point2,point3,point4) {
        ctx.beginPath();
        ctx.moveTo(point1.x,point1.y);
        ctx.lineTo(point2.x,point2.y);
        ctx.lineTo(point3.x,point3.y);
        ctx.lineTo(point4.x,point4.y);
        ctx.closePath();
        ctx.stroke();
    }

4、取矩形各边的3等分点的两个中间点坐标

///获取3等分的两个中间点坐标
    function getTwoMiddlePoint (point1,point2) {
        var temp1 = new point(0,0);
        var temp2 = new point(0,0);
        if (point1.x == point2.x) {
            var indentX = Math.abs(point1.y - point2.y)/3;
            if (point1.y>point2.y) {
                temp1.x = point2.x;
                temp1.y = point2.y + indentX;
                temp2.x = point1.x;
                temp2.y = point2.y + indentX*2;
            } else{
                temp1.x = point1.x;
                temp1.y = point1.y + indentX*2;
                temp2.x = point2.x;
                temp2.y = point1.y + indentX;
            }
        } else if (point1.y == point2.y) {
            var indentY = Math.abs(point1.x - point2.x)/3;
            if (point1.x>point2.x) {
                temp1.x = point2.x + indentY;
                temp1.y = point2.y;
                temp2.x = point2.x + indentY*2;
                temp2.y = point1.y;
            } else{
                temp1.x = point1.x + indentY*2;
                temp1.y = point1.y;
                temp2.x = point1.x + indentY;
                temp2.y = point2.y;
            }
        }
        return new doublePoint(temp1,temp2);
    }

5、迭代函数

function drawMengo(ctx,pointa,pointb,pointc,pointd,count) {
        if (count>=2) {
            drawRect(ctx,pointa,pointb,pointc,pointd);
            var double_ab = getTwoMiddlePoint(pointa,pointb);
            console.log(double_ab);
            var double_bc = getTwoMiddlePoint(pointb,pointc);
            var double_cd = getTwoMiddlePoint(pointd,pointc);
            console.log(double_cd);
            var double_da = getTwoMiddlePoint(pointa,pointd);
            {
                drawLine(ctx,double_ab.point1,double_cd.point1);
                drawLine(ctx,double_ab.point2,double_cd.point2);
                drawLine(ctx,double_da.point1,double_bc.point1);
                drawLine(ctx,double_da.point2,double_bc.point2);
                count -= 1;
                drawMengo(ctx,pointa,double_ab.point2,new point(double_ab.point2.x, double_da.point2.y),double_da.point2,count);
                drawMengo(ctx,double_ab.point2,double_ab.point1,new point(double_ab.point1.x, double_da.point2.y),
                    new point(double_ab.point2.x, double_da.point2.y),count);
                drawMengo(ctx,double_ab.point1,pointb,double_bc.point2,new point(double_ab.point1.x, double_bc.point2.y),count);

                drawMengo(ctx,double_da.point2,new point(double_ab.point2.x, double_da.point2.y),
                    new point(double_ab.point2.x, double_da.point1.y),double_da.point1,count);
                drawMengo(ctx,new point(double_ab.point1.x, double_bc.point2.y),double_bc.point2,double_bc.point1,
                    new point(double_ab.point1.x,double_bc.point1.y),count);

                drawMengo(ctx,double_da.point1,new point(double_ab.point2.x,double_da.point1.y),double_cd.point2,pointd,count);
                drawMengo(ctx,new point(double_ab.point2.x,double_da.point1.y),new point(double_ab.point1.x,double_da.point1.y),double_cd.point1,double_cd.point2,count);
                drawMengo(ctx,new point(double_ab.point1.x,double_da.point1.y),double_bc.point1,pointc,double_cd.point1,count);
            }
        } else{
            drawRect(ctx,pointa,pointb,pointc,pointd);
        }
    }

完整可运行代码:

<html>
<head>
    <title>门格海绵--谢尔宾斯基地毯</title>
    <meta charset='utf-8'/>
    <script type="text/javascript">
    function point(x,y){
        this.x = x;
        this.y = y;
    }

    function doublePoint (point1,point2) {
        this.point1 = point1;
        this.point2 = point2;
    }

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

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

    ///获取3等分的两个中间点坐标
    function getTwoMiddlePoint (point1,point2) {
        var temp1 = new point(0,0);
        var temp2 = new point(0,0);
        if (point1.x == point2.x) {
            var indentX = Math.abs(point1.y - point2.y)/3;
            if (point1.y>point2.y) {
                temp1.x = point2.x;
                temp1.y = point2.y + indentX;
                temp2.x = point1.x;
                temp2.y = point2.y + indentX*2;
            } else{
                temp1.x = point1.x;
                temp1.y = point1.y + indentX*2;
                temp2.x = point2.x;
                temp2.y = point1.y + indentX;
            }
        } else if (point1.y == point2.y) {
            var indentY = Math.abs(point1.x - point2.x)/3;
            if (point1.x>point2.x) {
                temp1.x = point2.x + indentY;
                temp1.y = point2.y;
                temp2.x = point2.x + indentY*2;
                temp2.y = point1.y;
            } else{
                temp1.x = point1.x + indentY*2;
                temp1.y = point1.y;
                temp2.x = point1.x + indentY;
                temp2.y = point2.y;
            }
        }
        return new doublePoint(temp1,temp2);
    }

    function drawMengo(ctx,pointa,pointb,pointc,pointd,count) {
        if (count>=2) {
            drawRect(ctx,pointa,pointb,pointc,pointd);
            var double_ab = getTwoMiddlePoint(pointa,pointb);
            console.log(double_ab);
            var double_bc = getTwoMiddlePoint(pointb,pointc);
            var double_cd = getTwoMiddlePoint(pointd,pointc);
            console.log(double_cd);
            var double_da = getTwoMiddlePoint(pointa,pointd);
            {
                drawLine(ctx,double_ab.point1,double_cd.point1);
                drawLine(ctx,double_ab.point2,double_cd.point2);
                drawLine(ctx,double_da.point1,double_bc.point1);
                drawLine(ctx,double_da.point2,double_bc.point2);
                count -= 1;
                drawMengo(ctx,pointa,double_ab.point2,new point(double_ab.point2.x, double_da.point2.y),double_da.point2,count);
                drawMengo(ctx,double_ab.point2,double_ab.point1,new point(double_ab.point1.x, double_da.point2.y),
                    new point(double_ab.point2.x, double_da.point2.y),count);
                drawMengo(ctx,double_ab.point1,pointb,double_bc.point2,new point(double_ab.point1.x, double_bc.point2.y),count);

                drawMengo(ctx,double_da.point2,new point(double_ab.point2.x, double_da.point2.y),
                    new point(double_ab.point2.x, double_da.point1.y),double_da.point1,count);
                drawMengo(ctx,new point(double_ab.point1.x, double_bc.point2.y),double_bc.point2,double_bc.point1,
                    new point(double_ab.point1.x,double_bc.point1.y),count);

                drawMengo(ctx,double_da.point1,new point(double_ab.point2.x,double_da.point1.y),double_cd.point2,pointd,count);
                drawMengo(ctx,new point(double_ab.point2.x,double_da.point1.y),new point(double_ab.point1.x,double_da.point1.y),double_cd.point1,double_cd.point2,count);
                drawMengo(ctx,new point(double_ab.point1.x,double_da.point1.y),double_bc.point1,pointc,double_cd.point1,count);
            }
        } else{
            drawRect(ctx,pointa,pointb,pointc,pointd);
        }
    }
    window.onload=function  () {
        var cav = document.getElementById('cav');
        var ctx = cav.getContext('2d');
        ctx.strokeStyle = 'green';//rgba(100,200,100,50);
        var count = document.getElementById('num');
        drawMengo(ctx,new point(10,10),new point(709,10),new point(709,709),new point(10,709),count.value);

        var btn = document.getElementById('clk');
        btn.onclick=function  () {
            ctx.clearRect(0,0,800,800);
            drawMengo(ctx,new point(10,10),new point(709,10),new point(709,709),new point(10,709),count.value);
        }
    }
    </script>
</head>
<body>
    <div style='margin:0 auto;'>
        <div>
            <input type='text' id='num' value='6'/>
            <input type='button' id='clk' value='run'/>
        </div>
        <canvas id='cav' width='750' height='750' style='border:1px solid red;'></canvas>
    </div>
</body>
</html>

编后语:

     迭代函数的逻辑其实不复杂,主要是靠细心,注意对应点的连接,最后可以得到最终效果,算法很挫,还请指教。

posted @ 2015-10-20 23:52  zhanfuShi  阅读(1575)  评论(0编辑  收藏  举报