zemax では hexapolar(六極)でサンプリング点を生成するモードがあります.
zemax 使ったことがないので正確かどうかは不明ですが, ring が増えるごとに,
0, 1 (中心は 1 点)
1, 6
2, 12
3, 18
...
と 6 点ずつ増やしていくようなパターンです.
こんな感じでしょうか.
batoid に参考となるコードがあります.
ただ, batoid の asPolar
関数では, 必ずしも任意の ring(naz)で点の数が 6 の倍数にはなりませんでした...
強制的に 6 の倍数にするように修正してみました.
import numpy as np
import matplotlib.pyplot as plt
def asPolar(outer: float, inner: float, nrad: int, naz: int, nrandom = None):
if nrandom is None:
nphis = []
rhos = np.linspace(outer, inner, nrad)
#print(rhos)
#for rho in rhos:
# nphi = int((naz*rho/outer)//6)*6
# if nphi == 0:
# nphi = 6
# nphis.append(nphi)
#if inner == 0.0:
# nphis[-1] = 1
for i in range(nrad):
nphi = 6 * (nrad - i - 1)
nphis.append(nphi)
nphis[-1] = 1
print(nphis)
reversed_nphis = list(reversed(nphis))
print(reversed_nphis)
# test
for i in range(len(reversed_nphis)):
if i == 0:
assert reversed_nphis[i] == 1
else:
assert reversed_nphis[i] == i * 6
th = np.empty(np.sum(nphis))
rr = np.empty(np.sum(nphis))
idx = 0
for rho, nphi in zip(rhos, nphis):
rr[idx:idx+nphi] = rho
th[idx:idx+nphi] = np.linspace(0, 2*np.pi, nphi, endpoint=False)
idx += nphi
if inner == 0.0:
rr[-1] = 0.0
th[-1] = 0.0
else:
rr = np.sqrt(np.random.uniform(inner**2, outer**2, size=nrandom))
th = np.random.uniform(0, 2*np.pi, size=nrandom)
r = np.empty((len(rr), 3), order='F')
x = r[:, 0]
y = r[:, 1]
z = r[:, 2]
x[:] = rr*np.cos(th)
y[:] = rr*np.sin(th)
del rr, th
print(len(x))
return x, y
def main():
outer = 1.0
inner = 0.0
for n in range(1, 32):
nrad = n
naz = nrad * 6 # nrad * 6 = zemax config(1, 6, 12, 18, 24, 30, ...)
nrandom = None # Uniform sampling
x, y = asPolar(outer=outer, inner=inner, nrad=nrad, naz=naz, nrandom=nrandom)
plt.plot(x, y, 'o')
plt.show()
main()
Voila!
円内にそこそこ面積一様でサンプル点を作るのによさそうでしょうか?