Skip to content

Instantly share code, notes, and snippets.

@marmakoide
Created July 18, 2022 15:24
Show Gist options
  • Save marmakoide/fc8316a4a1642e5d6db0372122b4cfdc to your computer and use it in GitHub Desktop.
Save marmakoide/fc8316a4a1642e5d6db0372122b4cfdc to your computer and use it in GitHub Desktop.
Generates a very accurate antialiased disk, without super sampling a very large bitmap. Works correctly only for even values of N.
import numpy
import scipy.integrate as integrate
def get_disk_mask(N):
def F(x):
return (1 - x ** 2) ** .5
# Build a quarter
M = N // 2
quarter = numpy.zeros((M, M))
for i in range(M):
max_slice_len = F((i + 0) / M)
min_slice_len = F((i + 1) / M)
j_max = int(numpy.floor(M * max_slice_len))
j_min = int(numpy.floor(M * min_slice_len))
if i <= j_max:
column_area, err = integrate.quad(F, i / M, (i + 1) / M)
delta = column_area - j_min / M ** 2
fraction = delta * M ** 2
if j_max == j_min:
quarter[i,:j_min], quarter[i,j_min] = 1, fraction
quarter[:j_min, i], quarter[j_min,i] = 1, fraction
else:
if fraction < 1:
quarter[i,:j_min], quarter[i,j_min] = 1, fraction
quarter[:j_min,i], quarter[j_min,i] = 1, fraction
else:
quarter[i,:j_max], quarter[i,j_max] = 1, fraction - 1
quarter[:j_max,i], quarter[j_max,i] = 1, fraction - 1
# Assemble the quarters
ret = numpy.zeros((N, N))
ret[M:,M:] = quarter
ret[:M,M:] = numpy.flip(quarter, axis = 0)
ret[M:,:M] = numpy.flip(quarter, axis = 1)
ret[:M,:M] = numpy.flip(quarter, axis = (0, 1))
# Job done
return ret
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment