Visualizing the digits of π


The following program lets you scrub the mouse downward to find more and more precise approximations of π within the red optical sight in the center of the screen.

N = 100  -- spacing between zoom levels
M = N*2  -- spacing between ticks on a single zoom level; enough space to write the tick value to some max precision
y = N  -- current zoom level
Pan = nil
-- 14159265358979323846264338327950288419716939937510
Pi = {3, 3.1, 3.14, 3.141, 3.1415, 3.14159, 3.141592, 3.1415926, 3.14159265, 3.141592653, 3.1415926535}
-- the current approximation of pi
function approx()
  local yint = floor(y/N)
  local yfrac = y - yint*N
  local lo = Pi[yint]
  if yint == #Pi then return lo end
  local hi = Pi[yint+1]
  return lo + yfrac/N*(hi-lo)
end
-- viewport location of number x assuming number 'center' is always at Safe_width/2
function vx(center, scale, x)
  return Safe_width/2 + (x-center)/scale * M
end
-- number at viewport location vx assuming number 'center' is always at Safe_width/2
function sx(center, scale, vx)
  return center + (vx - Safe_width/2)/M * scale
end
function draw_tick(center, scale, x, ly)
  local vx = vx(center, scale, x)
  line(vx, ly, vx, ly+5)
  g.print(x, vx, ly+10)
end
function ticks(level, pi)
  local scale = 10^-(level-1)
  local sxmin = sx(pi, scale, 0)
  local sxmax = sx(pi, scale, Safe_width)
  local ticklo, tickhi = Pi[level], Pi[level]
  if ticklo > sxmin then
    local k = floor((Pi[level]-sxmin)/scale)
    ticklo = Pi[level]-k*scale
  else
    local k = floor((sxmin-Pi[level])/scale)
    ticklo = Pi[level]+k*scale
  end
  if tickhi > sxmax then
    local k = floor((Pi[level]-sxmax)/scale)
    tickhi = Pi[level]-k*scale
  else
    local k = floor((sxmax-Pi[level])/scale)
    tickhi = Pi[level]+k*scale
  end
  assert(ticklo < tickhi)
  return ticklo, tickhi, scale
end
function car.draw()
  -- optical sight
  color(1,0,0)
  line(Safe_width/2, Safe_height/2-80, Safe_width/2, Safe_height/2-10)
  line(Safe_width/2, Safe_height/2+80, Safe_width/2, Safe_height/2+10)
  -- number lines
  local level = floor(y/N)
  local pi = approx()
  for j=1,#Pi do
    color(0.4,0.4,0.4)
    local ly = Safe_height/2 - y + j*N
    line(0, ly, Safe_width, ly)
    local ticklo, tickhi, scale = ticks(j, pi)
    for tick=ticklo,tickhi,scale do
      draw_tick(pi, scale, tick, ly)
    end
    color(0.5,0.5,1)
    circle('fill', vx(pi, scale, Pi[j]), ly, 5)
    color(0.2,0.2,1)
    circle('line', vx(pi, scale, Pi[j]), ly, 5)
  end
end
function car.mousepressed() Pan = true end
function car.mousereleased() Pan = nil end
function car.mousemoved(_x,_y,_dx, dy, ...)
  if not Pan then return end
  y = y-dy
  y = max(y, N)
  y = min(y, #Pi * N)
end

If you try pasting this program into Lua Carousel, remember to first run the abbreviations on one of the example screens. Or if you've deleted that screen, here are the abbreviations I used in this post:

g = love.graphics
line, circle = g.line, g.circle
color = g.setColor
min, max = math.min, math.max
floor, ceil = math.floor, math.ceil

Get Lua Carousel

Leave a comment

Log in with itch.io to leave a comment.