Animações do guia de movimentação de palco

Como funciona

Pode-se dizer que se trata de um “sistema multiagente": cada coralista recebe informações sobre o mundo e sobre os demais coralistas, e deve decidir para qual direção ele quer ir. Esse processo acontece iterativamente, para cada bolinha, 30 vezes por segundo.

Formalizando

Seja \(n \in \mathbb{N}\), e \(V\) um conjunto. Defina uma família de digrafos \( \{G_k\}_{k \in \mathbb{N}} \) tal que, para todo \(k \in \mathbb{N}\), tem-se \(G_k := (V, A_k)\) para algum \(A_k \subseteq V^2\). Ainda para cada \(k \in \mathbb{N}\), existe \(p_k(v) \in \mathbb{R}^n\), dita a posição de \(v\) no instante \(k\) (no algoritmo, \(p_0(v)\) é sorteado para todo \(v\)).

Defina

\[ \DeclareMathOperator{\angle}{angle} \DeclareMathOperator{\acos}{acos} \DeclareMathOperator{\out}{out} \angle: (x, y) \in \mathbb{R}^n \times \mathbb{R}^n \mapsto \acos\left(\frac{x \cdot y}{\|x\|\|y\|}\right) \in [0, 2\pi]. \]

Isso é, \(\angle\) dá o ângulo entre dois vetores. Seja \(\alpha \in [0, 2\pi]\). Para todo \(k \in \mathbb{N}\), tem-se que \( vu \in A_k \) se e somente se não existe nenhum \(w \in V\) tal que

\[ \left\| p_k(w) - p_k(v) \right\| < \left\| p_k(u) - p_k(v) \right\| \]

e

\[ \angle(p_k(u) - p_k(v), p_n(w) - p_n(v)) < \alpha. \]

Ou seja, só há um vértice de \(v\) para \(u\) se não existir nenhum outro vértice mais próximo de \(v\) e “angularmente próximo” de \(u\).

Defina agora a função \(r : \mathbb{R}^n \rightarrow \mathbb{R}^n\), que associa cada ponto ao vetor que leva desse ponto até o ponto mais próximo na formação (arco, círculo, etc) desejada. Por exemplo, se \(n = 2\) e a formação desejada é um círculo de raio \(R\) de centro \(c\), então, para todo \(x \in \mathbb{R}^2\), com \(x \neq c\),

\[ r(x) = \frac{(\left\|c - x\right\| - R)}{\left\|c - x \right\|}(c - x). \]

Seja agora, para todo \(k \in \mathbb{N} \setminus\{1\}\), a função \(d_{k}: V \rightarrow \mathbb{R}^n\), definida para todo \(v \in V\) por

\[ \begin{align} d_{k + 1}(v) = & (r(p_{k}(v)) - p_k(v)) + \\\ & \sum_{w \in N^{\out}_{G_{k}}(v)} \frac{-1}{\max(1, \left\|r(p_{k}(v))\right\|) \cdot \left\|p_{k}(w) - p_{k}(v)\right\|} \cdot \frac{w - p_k(v)}{\left\|w - p_k(v)\right\|}, \end{align} \]

sendo \(N^{\out}_G(v)\) o conjunto dos vizinhos de saída (out-neigbors) de \(v\), para todo \(v\) vértice de algum digrafo \(G\).

Essa equação pode ser entendida como o vetor que leva ao destino de um cantor para um instante \(k \in \mathbb{N} \setminus \{ 0 \}\). É nela que estão definidas, ao mesmo tempo, a primeira e a segunda regra. O cantor vai afastar-se de todos os demais cantores, o mais rapidamente quanto mais estiver próximo deles. Ao mesmo tempo, vai aproximar-se da formação desejada, e quanto mais longe estiver dessa formação, menos os outros cantores vão ter impacto sobre a sua posição.

No entanto, os cantores têm velocidade limitada. Sua posição final é dada, para todo \(k \in \mathbb{N}\setminus \{0\}\) por

\[ p_{k}(v) = \begin{cases} p_{k - 1} + \hat{d_k}(v) & \text{ se } \left\|d_k(v)\right\| > 1; \\\ p_{k - 1} + d_k(v) & \text{ caso contrario.} \end{cases} \]

Na implementação usamos \(n = 2\) e \(\alpha = 2\pi/3 \). Omitimos aqui algumas constantes usadas nela (a velocidade de cada cantor, por exemplo), mas o espírito da coisa é esse. Para mais detalhes, a implementação pode ser vista e melhorada aqui.