はじめに
この作品は 2020 年 4 月 1 日から 5 月 14 日にかけて開催された、 #dailycodingchallenge の 4 月 25 日のお題「残す」についての作品です。
#つぶやきProcessing 残す
— Koji Saito (@KojiSaito) April 25, 2020
def setup():size(500,500);background(-1)
R=random;r=100
def draw():
x1=R(500);y1=R(500)
x2=R(500);y2=R(500)
dx=x2-x1;dy=y2-y1
ex=x1-250;ey=y1-250
p=ex*ex;q=ey*ey
b=dx*ex+dy*ey
if b*b-(dx*dx+dy*dy)*(p+q-r*r)<0:line(x1,y1,x2,y2)#dailycodingchallenge https://t.co/C2QIMBcqna pic.twitter.com/g2o6tLXx05
ツィートにある動画を再生してもらうと分かるのですが、 中央部分に円形の領域が残される作品です。
ソースコードと仕組み
この作品は、つぶやき Processing としてもツィートされていますので、 ソースコードも公開されています。 また、コンパクトな作品なので、比較的、ソースコードも原型をとどめていますが、 以下に清書したものも記しておきます:
def setup():size(500,500);background(-1)
R=random
r=100
def draw():
x1=R(500); y1=R(500)
x2=R(500); y2=R(500)
dx=x2-x1;dy=y2-y1
ex=x1-250;ey=y1-250
p=ex*ex;q=ey*ey
b=dx*ex+dy*ey
if b*b-(dx*dx+dy*dy)*(p+q-r*r)<0:
line(x1,y1,x2,y2)
この作品の仕組ですが、乱数により、 まず描画候補の直線の端点の座標 (x1,y1) と (x2,y2) を決めます。
あとは、この直線と、 中心 (250,250) 半径 100 の円との交点があるかどうかを調べ、 もし、交点がないのであれば、その直線を描画します。
円と直線の交点の数ですが、 点 (x1,y1) と (x2,y2) を通る直線 L は 媒介変数 t を用いて次のように書けます:
$$ \left( \begin{array}{c} x \newline y \end{array} \right) = \left( \begin{array}{c} x_1 \newline y_1 \end{array} \right) +t \left( \begin{array}{c} x_2-x_1 \newline y_2-y_1 \end{array} \right) $$
なお上式で表される点 (x,y) は L 上の点を表します。
これで、L 上の点が変数 t により表現されましたので、 あとはこの x と y を、 点 (250,250) を中心とする半径 100 (これを r とする)の円 C を表す次の式に代入します:
$$ (x-250)^2+(y-250)=r^2 $$
すると、この式は結局 t の 2 次式となり、 この 2 次式が解を持たなければ直線 L と円 C は交わらないこととなります。
2 次式において解を持つ・持たないは判別式により計算されますので、 判別式を計算し、判別式の値が負である=解を持たない時にのみ、 直線 L を描画するようにします。
これが、この作品で行われている処理の概要となります。