Шары и их движение; Свет и ее путь всегда очаровывали меня. Я изучил анимацию в R несколько дней назад. Я не мог больше сопротивляться. Итак, я сделал один. :)

У всего этого проекта есть три аспекта.

Математическая часть - координатная геометрия

Физическая часть - трение

Алгоритм - здравый смысл

Кодирование - Go-Go Animate (gganimate): P

Математическая часть

  1. Закрепите границы доски.
  2. Найдите уравнение отраженной линии вдоль границ.

Здесь мы сохранили границы как прямые, соединяющие точки {(0,0), (0,1), (1,0), (1,1)}.

Результат 1:

Если вы отразите линию y = mx + c через y = 1, y = 0, x = 0 или x = 1, наклон новой линии станет -m.

Результат 2:

  1. Через строку y = 1 y = mx + c становится y = -mx + (2-c).
  2. Через строку y = 0 y = mx + c становится y = -mx + -c.
  3. Через строку x = 1 y = mx + c становится y = -mx + (2m + c).
  4. Через строку x = 0 y = mx + c становится y = -mx + c.

Часть алгоритма

Выберите начальную точку. (X =?, Y =?)

Выберите направление по оси X. (d = + 1 / -1)

Выберите линию движения (m =?, C =?)

Наблюдение

Когда мяч отскакивает от стены x = 0, направление меняется на d = +1. (положительная ось X)

Когда мяч отскакивает от стены x = 1, направление меняется на d = -1. (отрицательная ось X)

Поэтому необходимо иметь в виду следующее.

Каждый раз, когда мяч попадает в X-стену, наклон, точка пересечения и направление линии движения меняются.

Каждый раз, когда мяч попадает в Y-образную стену, изменяется только наклон и точка пересечения линии движения.

Часть кода

Код, как всегда, дается после гифки.

#starting point
x = 0.5
y = 0.2
m = -pi
c = 0.2
#direction
d = +1 
#number of discrete steps
n = 90
#length of discrete steps
l = 0.01 
#dummy 
X = x 
Y = y
#The Algorithm
for (i in t)
 {
  X = X + d*l
  Y = m*X + c
if (X < 0) #Reflection along X = 0
{
    X = 0
    Y = m*X + c
       y = c(y,Y)
       x = c(x,X)
c = c
       m = -m
       d = +1
X = X + d*l
       Y = m*X + c
   }
if (X > 1) #Reflection along X = 1
{
    X = 1
    Y = m*X + c
       y = c(y,Y)
       x = c(x,X)
c = 2*m + c
       m = -m
       d = -1
X = X + d*l
       Y = m*X + c
   }
if (Y < 0) #Reflection along Y = 0
    {
     Y = 0
    X = (Y-c)/m
       y = c(y,Y)
       x = c(x,X)
c = -c
       m = -m
X = X + d*l
       Y = m*X + c
    }
if (Y > 1) #Reflection along Y = 1
    {
     Y = 1
    X = (Y-c)/m
       y = c(y,Y)
       x = c(x,X)
c = 2-c
       m = -m
X = X + d*l
       Y = m*X + c
    }
   
   y = c(y,Y)
   x = c(x,X)
}
t = 1:length(x)
#engineering the boundary and the animation
seq = 1:2
a = c(0,1,1,1,1,0,0,0)
b = c(0,0,0,1,1,1,1,0)
T = rep(seq,4)
d = c(1,1,2,2,3,3,4,4)
boundary = data.frame(a,b,d,T)
billiard = data.frame(x,y,t)
anim <- 
 ggplot(billiard, aes(x, y)) + 
    geom_path(size = 2) +
   geom_path(size = 1, colour = "red")+
    geom_point(colour = "blue", size = 8) +
    geom_path(boundary, mapping = aes(a, b, group=d), size = 3)+
    theme_minimal() + 
    labs(title = 'Simulation of the motion of a Ball in a Billard Table. ')+
    transition_reveal(t)
animate(anim, nframes = 100, type="cairo")

Я не добавил здесь трений. Итак, добавим трений.

Часть физики - трение

animatecarrom <- function(theta)
  {
library("ggplot2")
library("gganimate")
library("babynames")
library("hrbrthemes")
library("gifski")
library("png")
#starting point
x = 0.5
y = 0.5
m = tan(theta)
c = y - m*x
#direction
if (theta > -pi/2 && theta <= pi/2)
      {
        d = +1
      }
if (theta <= 1.5*pi && theta > pi/2)
      {
        d = -1
      }
#number of discrete steps
#length of discrete steps
l = 0.3
alpha = 0.01
#dummy 
X = x 
Y = y
up = 0
right = 0
down = 0
left = 0
tstop =  floor(l/alpha)
deltat = 0.1
seq = seq(0,tstop,deltat)
for (i in seq)
  {
    X = X + d*deltat*(l-alpha*i)
    Y = m*X + c
if (X < 0)
{
        X = 0
        Y = m*X + c
          y = c(y,Y)
          x = c(x,X)
c = c
          m = -m
          d = +1
X = X + d*deltat*(l-alpha*i)
          Y = m*X + c
left = left + 1
      }
if (X > 1)
{
        X = 1
        Y = m*X + c
          y = c(y,Y)
          x = c(x,X)
c = 2*m + c
          m = -m
          d = -1
X = X + d*deltat*(l-alpha*i)
          Y = m*X + c
right = right + 1
      }
if (Y < 0)
      {
        Y = 0
        X = (Y-c)/m
          y = c(y,Y)
          x = c(x,X)
c = -c
          m = -m
X = X + d*deltat*(l-alpha*i)
          Y = m*X + c
down = down + 1
      }
if (Y > 1)
      {
        Y = 1
        X = (Y-c)/m
          y = c(y,Y)
          x = c(x,X)
c = 2-c
          m = -m
X = X + d*deltat*(l-alpha*i)
          Y = m*X + c
up = up + 1
      }
y = c(y,Y)
      x = c(x,X)
}
t = 1:length(x)
#engineering the boundary
seq = 1:2
a = c(0,1,1,1,1,0,0,0)
b = c(0,0,0,1,1,1,1,0)
T = rep(seq,4)
d = c(1,1,2,2,3,3,4,4)
boundary = data.frame(a,b,d,T)
billiard = data.frame(x,y,t)
anim <- 
  ggplot(billiard, aes(x, y)) + 
    geom_path(size = 2) +
    geom_path(size = 1, colour = "red")+
    geom_point(colour = "blue", size = 8) +
    geom_path(boundary, mapping = aes(a, b, group=d), size = 3)+
    theme_minimal() + 
    labs(title = 'Simulation of the motion of a Ball in a Billard Table. ')+
    transition_reveal(t)
animate(anim, nframes = 100, type="cairo")
anim_save("billiards.gif", type="cairo")
}

Спасибо, что зашли.

Если вы узнаете что-то новое из этой статьи, хлопните в ладоши и поделитесь ею со своими коллегами и сообществом, чтобы они получили удовольствие и поигрались с ней.

Быть в курсе! Оставайтесь благословенными!

Сриджит.

© SrijitMukherjee2020