美文网首页
分形图的绘制

分形图的绘制

作者: 阿昕_ | 来源:发表于2019-01-18 15:11 被阅读14次

    更多算法(语言为JavaScript) 持续更新...

    戳我去GitHub看更多算法问题>>>>目录

    戳我去GitHub看详细代码>>>>分形基础绘制

    Vicsek fractal

    基本正方形在3×3网格中分解为9个较小的正方形,绘制角落处的四个正方形和中间正方形。对于剩余的五个子方格中的每一个,递归地重复该过程。Vicsek分形是在此程序的极限下获得的集合。

    https://en.wikipedia.org/wiki/Vicsek_fractal
    // 绘制图形
        draw(ctx, depth = this.depth, x = 0, y = 0, w = this.width, h = this.width) {
    
          ctx.fillStyle = '#ccc';
    
          if (depth <= 0 && depth != undefined || w <= 1 || h <= 1) {
            // 绘制
            ctx.fillRect(x, y, w, h)
            return
          }
    
          this.depth = depth
    
          // 要绘制的格子容器中的小格子的宽高  将格子容器划分为3 * 3 的矩阵 根据位置分别绘制小格子
          let w_3 = w / 3
          let h_3 = h / 3
    
          // 递归绘制每个格子的5个方向
          this.draw(ctx, depth - 1,x, y, w_3, h_3)
          this.draw(ctx, depth - 1, x + 2 * w_3, y, w_3, h_3)
          this.draw(ctx, depth - 1, x + 2 * w_3, y + 2 * w_3, w_3, h_3)
          this.draw(ctx, depth - 1, x + w_3, y + w_3, w_3, h_3)
          this.draw(ctx, depth - 1, x, y + 2 * w_3, w_3, h_3) 
        }
    
    

    分形结果如下图:


    Vicsek分形.gif

    Sierpinski carpet 分形

    Sierpinski carpet 始于一个正方形"方形几何"。该正方形在3×3网格中被切割成9个一致的子方形,只绘制中心子方,然后,无限制地将相同的过程递归地应用于剩余的8个子方格。


    流程图
    // 绘制图形
       draw(ctx, depth = this.depth, x = 0, y = 0, w = this.width, h = this.width) {
    
         ctx.fillStyle = '#fff';
    
         // 要绘制的格子容器中的小格子的宽高  将格子容器划分为3 * 3 的矩阵 根据位置分别绘制小格子
         let w_3 = w / 3
         let h_3 = h / 3
    
         if (depth <= 0 && depth != undefined || w <= 1 || h <= 1) return
    
         this.depth = depth
    
    
         // 递归绘制9个格子
         for (let i = 0; i < 3; i++) {
           for (let j = 0; j < 3; j++) {
             if (i === 1 && j === 1) {
               // 中心的格子 直接绘制
               ctx.fillRect( x + w_3, y + w_3, w_3, h_3)
             } else {
               // 其他八个角的格子 递归
               this.draw(ctx, depth - 1, x + i * w_3, y + j * w_3, w_3, h_3)
             }
           }
         }
       }
    

    分形结果如下图:


    sierpinski_carpet_分形.gif

    sierpinski triangle 分形

    • 从等边三角形开始。
    • 将其细分为四个较小的全等边三角形并移除中心三角形。
    • 重复步骤2,永远保留每个剩余的较小三角形。


      sierpinski triangle 分形
      思路
        // 绘制图形
        draw(ctx, depth = this.depth, Ax = 0, Ay = this.side, side = this.side, all = this.depth) {
    
          ctx.fillStyle = '#ccc';
          // 计算三角形其余两点坐标
          let Bx = Ax + side
          let By = Ay
          let Cx = Ax + side / 2
          let Cy = Ay - Math.sin( 2 * Math.PI / 360 * 60) * side
    
          if (depth <= 0 && depth != undefined || side <= 1) {
            // 传入三点坐标
            this.triangle(ctx, Ax, Ay,Bx, By, Cx, Cy)
            return
          }
    
          // 递归 在左下角坐标为 (Ax, Ay)且边长为 side 的正方形中绘制三个等边三角形
          this.draw(ctx, depth - 1, Ax, Ay, side / 2, all)
          this.draw(ctx, depth - 1, (Ax + Bx) / 2, (Ay + By) / 2, side / 2, all)
          this.draw(ctx, depth - 1, (Ax + Cx) / 2, (Ay + Cy) / 2, side / 2, all)
    
        }
        // 绘制三角形 传入三点的坐标
        triangle(ctx, x1, y1, x2, y2, x3, y3) {
          ctx.beginPath()
          ctx.moveTo(x1, y1);
          ctx.lineTo(x2, y2);
          ctx.lineTo(x3, y3);
          ctx.closePath();
          ctx.fill();
        }
    

    分形结果如下图:


    sierpinski_triangle_分形.gif

    koch snowflake 分形

    概念:Koch雪花可以通过等边三角形开始构建,然后递归地改变每个线段,如下所示:

    • 将线段划分为三个相等长度的段
    • 绘制一个等边三角形,其中以第1步的中间部分作为基准,并指向外部。
    • 从第2步中删除作为三角形底边的线段。

    在该过程的一次迭代之后,得到的形状是六芒星的轮廓。

    koch snowflake 分形 思路
        // 绘制图形
        draw(ctx, depth = this.depth, x1 = 0, y1 = this.width / 2, side = this.width, deg = 0) {
    
          ctx.strokeStyle = '#fff';
    
          // 要绘制的格子容器中的小格子的宽高  将格子容器划分为3 * 3 的矩阵 根据位置分别绘制小格子
          let w_3 = side / 3
    
          if (depth < 0 && depth != undefined || w_3 <= 1) {
            let x2 = x1 + Math.cos(2 * Math.PI / 360 * deg) * side
            let y2 = y1 - Math.sin(2 * Math.PI / 360 * deg) * side
            this.line(ctx, x1, y1, x2, y2)
            return
          }
    
          let x2 = x1 + Math.cos(2 * Math.PI / 360 * deg) * w_3
          let y2 = y1 - Math.sin(2 * Math.PI / 360 * deg) * w_3
          this.draw(ctx, depth - 1, x1, y1, w_3, deg)
    
          let x3 = x2 + w_3 * Math.cos(2 * Math.PI / 360 * (deg + 60))
          let y3 = y2 - w_3 * Math.sin(2 * Math.PI / 360 * (deg + 60))
          this.draw(ctx, depth - 1, x2, y2, w_3, deg + 60)
    
          let x4 = x3 + w_3 * Math.cos(2 * Math.PI / 360 * (deg - 60))
          let y4 = y3 - w_3 * Math.sin(2 * Math.PI / 360 * (deg - 60))
          this.draw(ctx, depth - 1, x3, y3, w_3, deg - 60)
    
          this.draw(ctx, depth - 1, x4, y4, w_3, deg)
        }
    
        // 绘制线条
        line(ctx, x1, y1, x2, y2) {
          ctx.beginPath();
          ctx.moveTo(x1, y1);
          ctx.lineTo(x2, y2);
          ctx.closePath();
          ctx.stroke();
        }
    

    分形结果如下图:


    koch_snowflake_分形.gif

    分形绘制树🌲

       
       // 绘制图形
       draw(ctx, depth = this.depth, x1 = this.width / 2, y1 = this.width, side = this.width, deg = 0) {
    
         ctx.strokeStyle = '#fff';
         let w_2 = side / 2
    
         if (depth < 0 && depth != undefined || w_2 <= 1) {
           let x2 = x1 - Math.sin(2 * Math.PI / 360 * deg) * side
           let y2 = y1 - Math.cos(2 * Math.PI / 360 * deg) * side
           this.line(ctx, x1, y1, x2, y2)
           return
         }
    
    
         // 获取中点坐标
         let x2 = x1 - Math.sin(2 * Math.PI / 360 * deg) * w_2
         let y2 = y1 - Math.cos(2 * Math.PI / 360 * deg) * w_2
    
         // 下边的树杈
         this.line(ctx, x1, y1, x2, y2)
         // 左边的树杈
         this.draw(ctx, depth - 1, x2, y2, w_2, deg + this.splitDeg / 2)
         // 右边的树杈
         this.draw(ctx, depth - 1, x2, y2, w_2, deg - this.splitDeg / 2)
       }
    
       // 绘制线条
       line(ctx, x1, y1, x2, y2) {
         ctx.beginPath();
         ctx.moveTo(x1, y1);
         ctx.lineTo(x2, y2);
         ctx.closePath();
         ctx.stroke();
       }
    

    分形结果如下图:


    绘制树_分形.gif

    相关文章

      网友评论

          本文标题:分形图的绘制

          本文链接:https://www.haomeiwen.com/subject/zsemdqtx.html