はじめに
このページでは以下の作品について説明します。
文字数超過のため、つぶやきProcessing ならず。残念。あと 35 文字削減しないといけない。
— Koji Saito (@KojiSaito) June 29, 2020
今日の作品は「ご近所を探せ!」です。
5,000 個のランダムな点に対し、最近点と線を結ぶ様子を収めたものです。#dailycodingchallenge #プログラミング #generativeart pic.twitter.com/BJCMKtnFWd
この作品はランダムに生成した 5,000 個の点 \( p_i \ (i=1,\cdots,5000) \) に対し、 最も近くに存在する点 \( p_j \ (j \ne i) \) と線を結ぶという作品です。
ソースコード
N=5000
P=[[random(500),random(500),int(random(N)),1e9] for i in [0]*N]
def setup():size(500,500)
def draw():
clear();stroke(-1)
for i in range(N):
t=(i+int(random(N-1))+1)%N
d=dist(P[i][0],P[i][1],P[t][0],P[t][1])
if P[i][3]>d:
P[i][2]=t
P[i][3]=d
t=P[i][2]
line(P[i][0],P[i][1],P[t][0],P[t][1])
解説
変数 P の使い方が分かれば、特に難しいところはないので、 その部分を中心に説明します。
i 番目の点 \( p_i \) の情報は P[i] に格闘されています。 \( p_i \) の座標を \( (x_i,y_i) \) とすると、 P[i][0] および P[i][1] にはそれぞれ \( x_i, y_i \) が 格納されています。
P[i][2] には \( p_i \) の、 現時点で見つかっている最近点 \( p_{n_i} \) のインデックス値 \( n_i \) が 格納されています。
そのため、描画では t=P[i][2] として、
line(P[i][0],P[i][1],P[t][0],P[t][1])
という処理を行っています (これで、現時点で最も近いと思われている点との間に線分が描画されます)。
P[i][3] には、現時点での \( p_i \) 最近点 \( p_{n_i} \) との距離 \( d_i \) が格納されています。
各フレームごとに全ての点 \( p_i \) に対し、 適当に乱数でインデックス t を決め、 \( p_i, p_t \) 間の距離を計算します。
その距離が \( d_i \) つまり P[i][3] よりも小さければ、 より近い点を見つけたこととなりますので、 P[i][2] および P[i][3] を更新します。
毎フレーム毎にこのような処理を行うと、 冒頭で挙げたようなアニメーションが生成できます。
まとめ
このページでは、最近点を探して線分で結ぶ「ご近所を探せ」という作品について 解説しました。 ソースコードも掲載し、その中でも重要な情報を格納している変数 P について説明しました。
ツィートでも書いているのですが、プログラムの圧縮に失敗しており、 1 ツィート内に収めることができませんでした。 やっている内容はそんなに難しくないので、 もう少し短く記述できそうなのですが、 上手く言っていません。
つぶやき Processing するためには、 別のアプローチ方法が必要なのかもしれません (が、現時点では全くアイデアがありません)。