¡Vaya, es un efecto muy bonito! Lo que sucede es esto:
- En primer lugar, se gira la luna alrededor del planeta en algún ángulo, digamos, α .
- Entonces se gira el planeta alrededor del sol en algún ángulo, digamos, β .
- Ahora, trata de girar la luna alrededor del planeta por el ángulo α de nuevo... ¡pero el planeta se ha movido mientras tanto!
Así, se obtiene el efecto que se ve en tu demostración: la velocidad absoluta de la luna es proporcional a su distancia del planeta, por lo que cuando la luna está cerca, se mueve más lentamente que el planeta y por lo tanto se queda atrás. Pero eso la aleja del planeta y la hace moverse más rápido, por lo que la alcanza de nuevo, pero entonces su órbita la lleva delante del planeta, por lo que sus trayectorias convergen y se acercan de nuevo. De este modo, se obtienen estas trayectorias en forma de espirógrafo.
Variar la proporción α/β cambia la trayectoria; α/β>1 da efectos similares a los observados, mientras que si α/β=1 La luna se escapa al infinito y nunca vuelve. Para 0<α/β<1 el planeta alcanza a la luna después de completar una rotación extra alrededor del sol, mientras que α/β<0 hace que la luna se sumerja hacia dentro, más cerca del sol (y, por −1<α/β<0 para trazar patrones cuasi-poligonales nítidos mientras lo hace).
De todos modos, la solución es bastante simple: después de girar el planeta alrededor del sol, gire también la luna alrededor del sol en el mismo ángulo ( jsFiddle ):
function do_rotation() {
moon.attr(rotate(get_point(moon), get_point(earth), 5));
earth.attr(rotate(get_point(earth), get_point(sun), 1));
moon.attr(rotate(get_point(moon), get_point(sun), 1)); // <- NEW
setTimeout(do_rotation, 1000 / 60);
}
Así, el planeta y la luna se mantienen a la misma distancia el uno del otro. Como efecto secundario, la velocidad de rotación de la luna alrededor del planeta, desde un punto de vista no rotatorio, se convierte en α+β en lugar de sólo α . Si no quieres eso, simplemente resta el ángulo de rotación del planeta al de la luna.