Created
November 17, 2019 22:18
-
-
Save ambuc/a36d007d177c7dd90153dc9ab174ee12 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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