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 |
[Please log in to post a comment]




