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]