Desenhar uma catenária
Ao fazer as cordas entre os balões em Balloon Platform Defense, tive que descobrir como desenhar uma corda pendurada entre dois pontos, a forma mais conhecida como catenária. Todos os exemplos que encontrei na internet ou impunham restrições ao problema, como os dois pontos estarem na mesma altura, ou pressupunham informações que aqui não estavam disponíveis, como o ângulo em que a corda começa: só se conhecem os pontos inicial e final da corda e o comprimento dela. A Wikipédia traz muitas informações sobre as equações da catenária, e foi meu ponto de partida. A equação da catenária é:y=a\cosh \left (\frac{x}{a} \right )=\frac{a\left ( e^{\frac{x}{a}}+e^{-\frac{x}{a}} \right )}{2}
Isso supõe que o ponto mais baixo da corda está onde ela cruza o eixo y. Na prática, a equação terá constantes somadas às variáveis x e y, ambas ainda a determinar, já que não sabemos onde estará o ponto mais baixo – um dos fatores que tornam isto mais complicado do que todos os exemplos de livro didático. (Já reparou que os problemas de matemática da vida real são sempre muito mais complicados do que os exemplos dos livros? Ainda estou esperando o problema da vida real com uma integral que possa ser resolvida analiticamente.) Mas isso vai ter que esperar, porque primeiro precisamos determinar o valor de a, a constante da equação que decide basicamente o quão estreita ou larga é a curva. Cuidado: se os pontos estiverem na mesma posição do eixo x, a será infinito, então esse caso deve ser tratado antes de chegar aqui – ou mesmo o caso em que estão muito próximos e a é incalculavelmente grande. (Lembre-se de que “incalculavelmente grande” aqui é qualquer número que, usado como argumento da função exponencial, a faria retornar NaN ou infinito na precisão de ponto flutuante que você estiver usando.) E, claro, evite que o seu código chegue até aqui se os dois pontos estiverem mais distantes do que o comprimento da corda – o resultado será ruim.
Calcular o fator de escala
Para calcular a, a Wikipédia dá a equação (baseada numa propriedade da catenária: enquanto cosh dá a posição da curva, sinh dá o comprimento da curva):\sqrt{s^{2}-v^{2}}=2a\sinh \left ( \frac{h}{2a} \right )
onde s é o comprimento da corda, e h e v são as distâncias horizontal e vertical (em valor absoluto) entre os pontos inicial e final. Todos esses valores são conhecidos, sobrando só uma incógnita, mas ela precisa ser encontrada numericamente. Primeiro tentei fazer isso sem me preocupar muito com o valor inicial, e convergir ou não era questão de sorte. Felizmente, é fácil encontrar um bom valor inicial. A série de Taylor do seno hiperbólico é:
\sinh x=x+\frac{x^{3}}{3!}+\frac{x^{5}}{5!}+\cdots
Fazendo as substituições u = \frac{1}{4a^{2}} e c = \sqrt{s^{2}-v^{2}}, a equação a resolver fica:
c=\frac{1}{\sqrt{u}}\sinh \left ( h\sqrt{u} \right )
que, tomando os três primeiros termos da série de Taylor de sinh e simplificando, dá:
c=\frac{1}{\sqrt{u}}\left (h\sqrt{u}+\frac{\left ( h\sqrt{u} \right )^{3}}{3!} +\frac{\left ( h\sqrt{u} \right )^{5}}{5!} \right )
c=\frac{1}{\sqrt{u}}\left (h\sqrt{u}+\frac{h^{3}u\sqrt{u}}{3!} +\frac{h^{5}u^{2}\sqrt{u}}{5!} \right )
c=h+\frac{h^{3}u}{3!} +\frac{h^{5}u^{2}}{5!}
que, rearranjada, fica:
\frac{h^{5}}{120}u^{2}+\frac{h^{3}}{6}u+\left ( h-c \right )=0
É uma simples equação quadrática em u, e substituir seus coeficientes na fórmula quadrática da escola x = \frac{-b\pm \sqrt{b^{2}-4ac}}{2a}
nos dá um bom ponto de partida para u e, por consequência, para a.
u = \frac{-\frac{1}{6}h^{3}+ \sqrt{\frac{1}{36}h^{6}-\frac{1}{30}h^{5}\left ( h-c \right )}}{\frac{1}{60}h^{5}}, onde a=\frac{1}{2\sqrt{u}}
Esse ponto de partida é próximo o bastante para encontrar uma solução com o método de Newton. Colocando na forma f\left ( a \right )=0
temos f\left ( a \right )=2a \sinh \left ( \frac{h}{2a} \right )-c
e {f}'\left ( a \right )=2 \sinh \left ( \frac{h}{2a} \right )-\frac{h}{a}\cosh \left ( \frac{h}{2a} \right )
Como a_{n+1}=a_{n}-\frac{f\left ( a_{n} \right )}{{f}'\left ( a_{n} \right )}
,
a_{n+1}=a_{n}-\frac{2a \sinh \left ( \frac{h}{2a} \right )-c}{2 \sinh \left ( \frac{h}{2a} \right )-\frac{h}{a}\cosh \left ( \frac{h}{2a} \right )}=a_{n}-\frac{a \sinh \left ( \frac{h}{2a} \right )-0.5c}{ \sinh \left ( \frac{h}{2a} \right )-\frac{h}{2a}\cosh \left ( \frac{h}{2a} \right )}
Atualmente verifico se a sequência converge para menos de 0,001 do valor anterior, o que costuma acontecer em 2 a 4 iterações, embora às vezes leve mais de dez quando as coordenadas x estão mais próximas. Métodos de Householder de ordem superior provavelmente seriam possíveis sem muito mais cálculo, já que a maior parte do trabalho está em calcular as funções hiperbólicas, e as derivadas seguintes da função só devem resultar em mais múltiplos delas. Agora que conhecemos a escala, podemos calcular a translação.
Calcular a translação
Como a equação padrãoy=a\cosh \left (\frac{x}{a} \right )
supõe que a catenária é simétrica em relação ao eixo y e tem o ponto mais baixo em (0,a), enquanto a que estamos desenhando pode estar em qualquer lugar da tela, precisamos calcular uma translação (p,q) que a leve para a posição correta, e a equação fica:
y-q=a\cosh \left (\frac{x-p}{a} \right )
(Lembrando: a já é conhecido a esta altura, x e y são variáveis, então só p e q continuam desconhecidos.) Minha primeira ideia foi substituir na equação os valores conhecidos de x e y – ou seja, as duas extremidades da corda. Embora funcione na teoria, as equações resultantes, apesar dos meus esforços para simplificá-las, muitas vezes geravam valores durante o cálculo com os quais variáveis de ponto flutuante de precisão dupla não conseguiam lidar. Acabei tendo que encontrar outra abordagem, que no fim se mostrou mais eficiente.
Lembre-se de que trocar cosh por sinh na equação da catenária dá o comprimento da curva. Substituindo nessa forma as coordenadas x das extremidades esquerda e direita, junto com o comprimento desejado da corda (s), obtemos a equação:
a\sinh \left (\frac{x_{right}-p}{a} \right )-a\sinh \left (\frac{x_{left}-p}{a} \right )=s
Uma das identidades das funções hiperbólicas diz que:
\sinh x - \sinh y=2\cosh\left ( \frac{x+y}{2} \right ) \sinh \left ( \frac{x-y}{2} \right )
Portanto:
\sinh \left (\frac{x_{right}-p}{a} \right )-\sinh \left (\frac{x_{left}-p}{a} \right )=2\cosh\left ( \frac{x_{right}+x_{left}-2p}{2a} \right ) \sinh \left ( \frac{x_{right}-x_{left}}{2a} \right )
No argumento do cosh, as coordenadas x direita e esquerda são somadas e divididas por 2, o que dá a coordenada do meio, então podemos substituí-la diretamente. A subtração no argumento do sinh dá o mesmo valor que antes chamamos de h, de modo que esse sinh também pode ser calculado como uma quantidade conhecida, e a equação original se rearranja para:
\cosh\left ( \frac{x_{middle}-p}{a} \right ) = \frac{s}{2a\sinh \left ( \frac{h}{2a}\right )}
Agora podemos encontrar p com o arco cosseno hiperbólico, mas é preciso cuidado. Como cosh é uma função par, sempre obteremos uma resposta positiva, mas também existe uma resposta negativa, o que dá dois valores possíveis para p.
p =x_{middle}\pm a\cosh^{-1}\left ( \frac{s}{2a\sinh \left ( \frac{h}{2a}\right )} \right )
Para saber qual valor queremos, podemos verificar as coordenadas y das extremidades. Fazendo uma experiência com um pedaço de barbante, você verá que, para o mesmo comprimento e as mesmas coordenadas x, o ponto mais baixo da curva (se estiver entre as coordenadas x) estará à direita do meio (e portanto corresponderá ao arco cosseno positivo) se a coordenada y direita for mais baixa que a esquerda, e vice-versa.
Outro problema que pode surgir é que, quando as coordenadas y são iguais, o ponto mais baixo da curva deveria estar exatamente no meio, então o argumento do cosh deveria ser zero e o valor do qual se calcula o arco cosseno deveria ser um. Por causa das imprecisões do ponto flutuante, ele muitas vezes fica um pouco abaixo de um, causando um erro ao calcular o arco cosseno. É prudente verificar se as coordenadas y são iguais (ou quase iguais) antes de iniciar esse cálculo, para economizar cálculo e evitar esse erro, e nesse caso simplesmente supor que p está exatamente no meio do caminho entre as extremidades.
Agora que a e p são conhecidos, q pode ser calculado substituindo os valores de x e y de uma das extremidades na equação
y-q=a\cosh \left (\frac{x-p}{a} \right )
e rearranjando para:
q=y-a\cosh \left (\frac{x-p}{a} \right )
Calcule q com isso e você terá a equação final com a qual desenhar a curva.
y=a\cosh \left (\frac{x-p}{a} \right )+q
Desenhar a curva agora é simples. Usei o cálculo mais preciso possível das funções hiperbólicas na maioria das etapas do cálculo dos parâmetros, porque era difícil saber como qualquer imprecisão se propagaria. Mas nesta última etapa, que exige a maior parte dos cálculos, você saberá o tamanho do argumento que está usando e quanta imprecisão pode tolerar, e poderá prever se uma série de Taylor até certa potência será precisa o suficiente – e, na minha experiência, na maioria das vezes vale a pena usá-la.