Fractals... in Typst?

Hi, yall! I’m new to this but I thought I’d try to put Typst through its paces a bit and this is what I came up with. Takes several seconds to render for me, but beats drawing it by hand. :slight_smile:

#let pagewidth = 11 // in
#let pageheight = 8.5 // in

#set page(
    width: pagewidth * 1in,
    height: pageheight *1in,
)

#let pxsize = 2  // points
#let xpixels = int((pagewidth - 2)*72/pxsize)  // pixels horizontally
#let ypixels = int((pageheight - 2)*72/pxsize) // pixels vertically

#let bitmapWidth = xpixels * pxsize
#let bitmapHeight = ypixels * pxsize

#let complexPlaneWidth = 3.0
#let complexPlaneLeftEdgeCoord = -0.7

#let complexPlaneHeight = 2.17
#let complexPlaneTopEdgeCoord = 0

#let maxcount = 100

#let computeRealPartFromX(x) = {
    let f = x / bitmapWidth
    let realPart = f * complexPlaneWidth + complexPlaneLeftEdgeCoord

    return realPart
}

#let computeImaginaryPartFromY(y) = {
    let f = y / bitmapHeight
    let imaginaryPart = complexPlaneTopEdgeCoord - f * complexPlaneHeight

    return imaginaryPart
}

#let escapeTime(cReal, cImg) = {
    let zReal = 0.0
    let zImg = 0.0
    
    let count = 0

    while ((zReal*zReal + zImg*zImg) < 4) and (count < maxcount) {
        let nextZReal = zReal*zReal - zImg*zImg
        let nextZImg = 2*zReal*zImg

        zReal = nextZReal + cReal
        zImg = nextZImg + cImg

        count += 1
    }

    return count
}

#let mapColor(t) = {
    if t == maxcount {
        return black
    }

    let r = (127 + calc.sin(t / 11.0) * 127) * 1.0;
	let g = (127 + calc.sin(t / 7.0) * 127) * 1.0;
	let b = (127 + calc.sin(t / 5.0) * 127) * 1.0;

    if r < 0 { r = 0 }
    if g < 0 { g = 0 }
    if b < 0 { b = 0 }

    if r > 255 { r = 255 }
    if g > 255 { g = 255 }
    if b > 255 { b = 255 }

    return rgb(int(r), int(g), int(b))
}

#for yindex in range(ypixels) [
    #for xindex in range(xpixels) [
        #let x = (xindex * pxsize) - (bitmapWidth / 2)
        #let y = (yindex * pxsize) - (bitmapHeight / 2)
        #let cReal = computeRealPartFromX(x)
        #let cImg = computeImaginaryPartFromY(y)
        #let et = escapeTime(cReal, cImg)
        #let color = mapColor(et)

        #place(
            dx: 0pt + (xindex*pxsize) * 1pt,
            dy: 0pt + (yindex*pxsize) * 1pt,
        )[
            #square(size: pxsize * 1pt + 0.2pt,  fill:color)
        ]
    ]
]
8 Likes

Wow this is cool! :typstguy:

You can’t just post that without showing off the results – so here, the output of the above:

7 Likes

Hi. FYI, there is a package for creating fractals: fractusist – Typst Universe.

1 Like

You can also do that in Lilaq with the colormesh very easily, which is also very fast at it:

Example:

2 Likes