「プログラムでシダを描画する」をGoで描画する

  • 28
    いいね
  • 2
    コメント
この記事は最終更新日から1年以上が経過しています。

「プログラムでシダを描画する」記事たちに触発されて、Goで書いてみました。

ファイル「shida.png」に出力した結果

shida.png

ソースコード

  • 変数については、見やすさを重視して型を表記しました。
  • 変数 N は、オリジナルを踏襲して大文字のままにしています。
  • 乱数は rand.Float64() としました。
shida.go
package main

import (
    "image"
    "image/color"
    "image/draw"
    "image/png"
    "log"
    "math/rand"
    "os"
    "time"
)

var (
    N  int     = 20
    xm float64 = 0.0
    ym float64 = 0.5
    h  float64 = 0.6
)

var (
    width    int    = 500
    height   int    = 500
    filename string = "shida.png"
)

var (
    bgcolor   color.Color = color.RGBA{255, 255, 255, 255}
    linecolor color.Color = color.RGBA{0, 128, 0, 255}
)

func W1x(x, y float64) float64 {
    return 0.836*x + 0.044*y
}

func W1y(x, y float64) float64 {
    return -0.044*x + 0.836*y + 0.169
}

func W2x(x, y float64) float64 {
    return -0.141*x + 0.302*y
}

func W2y(x, y float64) float64 {
    return 0.302*x + 0.141*y + 0.127
}

func W3x(x, y float64) float64 {
    return 0.141*x - 0.302*y
}

func W3y(x, y float64) float64 {
    return 0.302*x + 0.141*y + 0.169
}

func W4x(x, y float64) float64 {
    return 0
}

func W4y(x, y float64) float64 {
    return 0.175337 * y
}

func f(m *image.RGBA, k int, x, y float64) {
    if 0 < k {
        f(m, k-1, W1x(x, y), W1y(x, y))
        if rand.Float64() < 0.3 {
            f(m, k-1, W2x(x, y), W2y(x, y))
        }
        if rand.Float64() < 0.3 {
            f(m, k-1, W2x(x, y), W2y(x, y))
        }
        if rand.Float64() < 0.3 {
            f(m, k-1, W3x(x, y), W3y(x, y))
        }
        if rand.Float64() < 0.3 {
            f(m, k-1, W4x(x, y), W4y(x, y))
        }
    } else {
        var s float64 = 490.0
        m.Set(int(x*s+float64(width)*0.5), int(float64(height)-y*s), linecolor)
    }
}

func main() {
    rand.Seed(time.Now().Unix())

    m := image.NewRGBA(image.Rect(0, 0, width, height))
    draw.Draw(m, m.Bounds(), &image.Uniform{bgcolor}, image.ZP, draw.Src)

    f(m, N, 0, 0)

    file, err := os.Create(filename)
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    err = png.Encode(file, m)
    if err != nil {
        log.Fatal(err)
    }
}

pngファイルを作成する際に参照したサイト