packages feed

spade-0.1.0.3: samples/mandelbrot.spd

graphicswindow(800, 800, false)
let params = {"height":800,"scale":2.63331,"start":{"img":-1.54217315,"real":-2.0421},"step":0.0101525597994770,"width":800}
let params_ref = newref(params)
loop
  let ws = getwindowsize()
  setcolor(0, 0, 0)
  clearscreen()
  let params = readref(params_ref)
  writefile("/tmp/params.json", jsonencode(params))
  let n = drawmandelbrot(params)
  if (n == "exit") then
    break
  endif
endloop

proc drawmandelbrot(params)
  for x = 0 to round((params.width / params.scale))
    let n = drawonecol(params, x)
    if (n == "exit") then
      return n
    elseif (n == "redraw") then
      break
    endif
  endfor
  return "continue"
endproc

proc drawonecol(params, x)
  let real = (params.start.real + (x * params.step))
  for y = 0 to round((params.height / params.scale))
    let n = processkeys(params, getkeypresses())
    if (n !== "continue") then
      return n
    endif
    let current = {img: (params.start.img + (y * params.step)), real: real}
    let ds = isinset(current)
    setcolor((ds * 240), 0, 0)
    point((x * params.scale), (y * params.scale))
  endfor
  return "continue"
endproc

proc modifydict(dict, key, callback)
  let c = dict[key]
  let dict[key] = callback(c)
  return dict
endproc

proc modifykey(ref, key, callback)
  modifyref(ref, fn (x) modifydict(x, key, callback) endfn)
endproc

proc amendscale(params, mult)
  let current_center_x = (params.start.real + ((params.width / (2 * params.scale)) * params.step))
  let current_center_y = (params.start.img + ((params.height / (2 * params.scale)) * params.step))
  let newscale = (params.scale * mult)
  let new_center_x = (params.start.real + ((params.width / (2 * newscale)) * params.step))
  let new_center_y = (params.start.img + ((params.height / (2 * newscale)) * params.step))
  let params.start.real = (params.start.real + (current_center_x - new_center_x))
  let params.start.img = (params.start.img + (current_center_y - new_center_y))
  let params.scale = newscale
  return params
endproc

proc amendstep(params, mult)
  let current_center_x = (params.start.real + ((params.width / (2 * params.scale)) * params.step))
  let current_center_y = (params.start.img + ((params.height / (2 * params.scale)) * params.step))
  let newstep = (params.step * mult)
  let new_center_x = (params.start.real + ((params.width / (2 * params.scale)) * newstep))
  let new_center_y = (params.start.img + ((params.height / (2 * params.scale)) * newstep))
  let params.start.real = (params.start.real + (current_center_x - new_center_x))
  let params.start.img = (params.start.img + (current_center_y - new_center_y))
  let params.step = newstep
  return params
endproc

proc processkeys(range_start, keys)
  if contains(keys, keycodes.q) then
    return "exit"
  elseif contains(keys, keycodes.up) then
    modifykey(params_ref, "start", fn (x) modifydict(x, "img", fn (x) (x + 0.1) endfn) endfn)
    return "redraw"
  elseif contains(keys, keycodes.down) then
    modifykey(params_ref, "start", fn (x) modifydict(x, "img", fn (x) (x - 0.1) endfn) endfn)
    return "redraw"
  elseif contains(keys, keycodes.left) then
    modifykey(params_ref, "start", fn (x) modifydict(x, "real", fn (x) (x - 0.1) endfn) endfn)
    return "redraw"
  elseif contains(keys, keycodes.right) then
    modifykey(params_ref, "start", fn (x) modifydict(x, "real", fn (x) (x + 0.1) endfn) endfn)
    return "redraw"
  elseif contains(keys, keycodes.a) then
    modifyref(params_ref, fn (x) amendscale(x, (1 / 1.1)) endfn)
    return "redraw"
  elseif contains(keys, keycodes.z) then
    modifyref(params_ref, fn (x) amendscale(x, 1.1) endfn)
    return "redraw"
  elseif contains(keys, keycodes.s) then
    modifyref(params_ref, fn (x) amendstep(x, (1 / 1.1)) endfn)
    return "redraw"
  elseif contains(keys, keycodes.x) then
    modifyref(params_ref, fn (x) amendstep(x, 1.1) endfn)
    return "redraw"
  endif
  return "continue"
endproc

proc isinset(c)
  let r = false
  let current = {img: 0, real: 0}
  for i = 0 to 100
    let current = addcomplex(sqcomplex(current), c)
    if (magcomplex(current) > 100) then
      return i
    endif
  endfor
  return 0
endproc

proc magcomplex(c)
  return (pow(c.real, 2) + pow(c.img, 2))
endproc

proc addcomplex(c, d)
  return {img: (c.img + d.img), real: (c.real + d.real)}
endproc

proc sqcomplex(c)
  let real = (pow(c.real, 2) - pow(c.img, 2))
  let img = (2 * (c.real * c.img))
  return {img: img, real: real}
endproc