Log In  

This function uses bresenham's algorithm mirrored to the 8 octants, filtered by angle for the desired arc angles. It's so slow as to be useless; there are much better arc functions on the BBS already. I'm posting it for posterity and future reference, and because it inspired me to come up with a handy octant-range asin() approximation that might actually be useful

-- approximation of asin(d) for 0<=d<=.7071
-- exact at d==0, d==sin(1/16), d==sin(1/8)
-- max error .0021 at d==sin(3/32) in given range
-- error within that max beyond bounds up to d==sin(.137)
function delta2angle(d)
 return d * 0x.29cf + (d > 0x.61f8 and (d - 0x.61f8) * 0x.0785 or 0)
end

function arc(x, y, r, a1, a2, ...)
 a1 %= 1
 a2 %= 1
 if (a1 == a2) pset(x + r * cos(a1), y - r * sin(a1), ...) return
 a2 = a2 + (a1 > a2 and 1 or 0) -- ensure a2>a1
 dx, dy = r, 0
 while dy <= dx do
  a = delta2angle(dy / r)
  for flip_x = -1, 1, 2 do
   for flip_y = -1, 1, 2 do
    for diag_mirror = 1, 2 do
     local ta = flip_x < 0 and .5 - a or a
     ta = flip_y<0 and -ta or ta
     ta = diag_mirror>1 and (flr(ta * 4) + 1) / 4 - ta % 0.25 or ta
     ta = ta == .5 + flip_y * .25 and .5 - flip_y * .25 or ta % 1
     if (ta + 1 - a1) % 1 < a2 - a1 then
      local flips = {flip_x, flip_y}
      local d = {dx * flips[diag_mirror], dy * flips[3 - diag_mirror]}
      pset(x + d[diag_mirror], y + d[3 - diag_mirror], ...)
     end
    end
   end
  end
  dy += 1
  if (dy * dy + dx * dx > (r + .5) * (r + .5)) dx = dx - 1
 end
end
P#73025 2020-02-12 16:59


[Please log in to post a comment]

Follow Lexaloffle:          
Generated 2024-03-29 15:27:12 | 0.004s | Q:6