Skip to content

Instantly share code, notes, and snippets.

@ambuc
Created November 17, 2019 22:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ambuc/a36d007d177c7dd90153dc9ab174ee12 to your computer and use it in GitHub Desktop.
Save ambuc/a36d007d177c7dd90153dc9ab174ee12 to your computer and use it in GitHub Desktop.
package main
// Renders a series of julia_n.pngs which can be zipped together into a gif.
//
// Example usage:
// go run julia.go
// convert /tmp/julia*.png -loop 0 animation.gif
import (
"fmt"
"github.com/fogleman/gg"
"image/color"
"math"
"math/cmplx"
)
const (
// Variables for the Julia set.
kConst complex128 = -0.8 + 0.156i
kThreshold float64 = 1.9
// The scaling factor between pixels and floating point coordinates. A higher
// number means a more zoomed-in image.
kScaling float64 = 600.0
// The dimensions of the image.
kDim int = 500
// The number of frames to render at the most.
kSteps int = 50
)
// Computes a fractional |mu|-value given the integer number of steps |i| and
// the complex value |z|.
func Mu(i int, z complex128) float64 {
return float64(i) + 1.0 - math.Log(math.Log(cmplx.Abs(z)))/math.Log(2.0)
}
// Computes the shade for each pixel in a 2D array and returns the maximum
// mu-value (shade analogue) encountered during the aforementioned process.
func Compute(pixels *[kDim][kDim]float64, steps int) float64 {
var max_mu float64 = 0.0
for x := 0; x < kDim; x++ {
a := float64(x) / kScaling
for y := 0; y < kDim; y++ {
b := float64(y) / kScaling
z := complex(a, b)
for i := 0; i < steps; i++ {
z = cmplx.Pow(z, 2) + kConst
if cmplx.Abs(z) > kThreshold {
var mu float64 = Mu(i, z)
if mu > max_mu {
max_mu = mu
}
pixels[x][y] = mu
break
}
}
}
}
return max_mu
}
// Maps a floating-point number between 0 and 1 to a grayscale color between 0
// and 255.
func Shade(n float64) color.Color {
return color.Gray{uint8(n * (math.MaxInt8 - 1))}
}
// Renders a 2D array of pixels to a gg.Context object.
func Render(max_mu float64, pixels [kDim][kDim]float64) *gg.Context {
dc := gg.NewContext(kDim, kDim)
for x := 0; x < kDim; x++ {
for y := 0; y < kDim; y++ {
dc.SetColor(Shade(pixels[x][y] / max_mu))
dc.SetPixel(x, y)
}
}
dc.SetRGB(0, 0, 0)
dc.Fill()
return dc
}
func main() {
for f := 0; f < kSteps; f++ {
fmt.Printf("Step %v\n", f)
var pixels [kDim][kDim]float64
max_mu := Compute(&pixels, f /*steps*/)
Render(max_mu, pixels).SavePNG(fmt.Sprintf("/tmp/julia_%v.png", f))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment