Форум программистов, компьютерный форум, киберфорум
Python: GUI, графика
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 5.00/11: Рейтинг темы: голосов - 11, средняя оценка - 5.00
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 44
1

Как сделать анимацию движения объекта по кривой (алгоритм Безье)

08.01.2021, 17:01. Просмотров 2104. Ответов 25

Смог написать программу для рисования кривой используя алгоритм Безье (anaconda), можете пожалуйста помочь, что нужно добавить, чтобы получилась анимация движения, например круга по этой кривой. Просят использовать ffmpeg, celluloid, matplotlib для анимации и Tkinter или что-то похожее для графического интерфейса, читал про библиотеки, но пока туго с пониманием того, как добиться нужного результата, надеюсь на вашу помощь.

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import numpy as np               
import matplotlib.pyplot as plt  
 
img = np.ones((600,600,3))
 
def DrawBezier(x0,y0,x1,y1,x2,y2,x3,y3,x4,y4,x5,y5):
    
    x = x0
    y = y0
    t = 0
    ts = 0.001
 
    while t <= 1.0:
        
        B0 = (1-t)*(1-t)*(1-t)*(1-t)*(1-t)
        B1 = 5*t*(1-t)*(1-t)*(1-t)*(1-t)
        B2 = 10*t*t*(1-t)*(1-t)*(1-t)
        B3 = 10*t*t*t*(1-t)*(1-t)
        B4 = 5*t*t*t*t*(1-t)
        B5 = t*t*t*t*t
        
        x = int(x0*B0 + x1*B1 + x2*B2 + x3*B3 + x4*B4 + x5*B5)
        y = int(y0*B0 + y1*B1 + y2*B2 + y3*B3 + y4*B4 + y5*B5)
        
        img[y,x] = (1,0,0)
        t=t+ts 
        
    return
   
DrawBezier(180,290,140,335,50,170,10,15,360,240,140,67)
    
%matplotlib notebook
plt.figure(figsize=(10,8), dpi = 100, facecolor='w')
plt.imshow(img)
plt.gca().invert_yaxis()
plt.show()
Название: jr.JPG
Просмотров: 108

Размер: 10.2 Кб

Хочется, чтобы было вот так:
Как сделать анимацию движения объекта по кривой (алгоритм Безье)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.01.2021, 17:01
Ответы с готовыми решениями:

Как сделать анимацию движения велосипеда?
Не понимаю как сделать анимацию движения велосипеда. Вот мой проект(без анимации):

Как сделать анимацию движения по трассе
Всем привет! Очень нужна консультацию по такому вопросу: нужно сделать анимацию движения, скажем,...

Directx. Как сделать анимацию объекта
Нашел пример программы при помощи которой можно открыть 3д модель в формате .x. Так же имеется файл...

Алгоритм движения касательной по кривой
у меня не получается перевести с Canvas в Chart(((((((( помогите кто знает как это сделать(можно и...

25
1080 / 692 / 114
Регистрация: 12.10.2013
Сообщений: 4,587
08.01.2021, 20:32 2
Цитата Сообщение от Bronzor Посмотреть сообщение
B0 = (1-t)*(1-t)*(1-t)*(1-t)*(1-t)
B1 = 5*t*(1-t)*(1-t)*(1-t)*(1-t)
B2 = 10*t*t*(1-t)*(1-t)*(1-t)
B3 = 10*t*t*t*(1-t)*(1-t)
B4 = 5*t*t*t*t*(1-t)
B5 = t*t*t*t*t
Никогда такого не видел. На википедии формула в одну строку, что это за монстр и зачем?
Это наверно высокой степени. Их вроде как никто не использует. Набирают кривую из кусков квадратичной кривой. Можно легко сделать сложной формы и замкнуть.
Как правильно задать систему урАвнений для кубических сплайнов?
Для анимации по таймеру на каждом кадре увеличиваете параметр t, подставляете в формулу кривой получаете координаты точки меняются по времени. Когда будет 2 кривых вместе то нужно будет завести два параметра, один общий t0 от 0 до 2 и второй t должен расти от 0 до 1 смотря какому диапазону принадлежит t0.Чтобы точка на кривой прошла сначала одну кривую затем вторую.
0
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 44
09.01.2021, 11:29  [ТС] 3
Это 6 контрольных точек, можно и с двумя, мне главное понять, желательно код с маленькими пояснениями, как на моей кривой нарисовать круг и заставить его двигаться по этой кривой.
0
1080 / 692 / 114
Регистрация: 12.10.2013
Сообщений: 4,587
09.01.2021, 13:56 4
Цитата Сообщение от Bronzor Посмотреть сообщение
желательно код с маленькими пояснениями
В гугле "point animation python"
Включил “картинки” смотрю где 1 точка а не 100500.
https://stackoverflow.com/ques... f-a-circle
Поменял строку
Python
1
 return np.array([r*np.cos(phi), r*np.sin(phi)])
и добавил опорные точки.

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = 4,3
from matplotlib.animation import FuncAnimation
 
p0x=0.0
p0y=-0.5
p1x=0.0
p1y=0.5
p2x=0.5
p2y=0.0
 
r = 1 # radius of circle
def circle(phi):
    #return np.array([r*np.cos(phi), r*np.sin(phi)])
    return np.array([
        (1.0-phi)**2*p0x + 2*phi*(1.0-phi)*p1x + phi**2*p2x,
        (1.0-phi)**2*p0y + 2*phi*(1.0-phi)*p1y + phi**2*p2y,
        ])
 
# create a figure with an axes
fig, ax = plt.subplots()
# set the axes limits
ax.axis([-1.5,1.5,-1.5,1.5])
# set equal aspect such that the circle is not shown as ellipse
ax.set_aspect("equal")
# create a point in the axes
point, = ax.plot(0,1, marker="o")
 
# Updating function, to be repeatedly called by the animation
def update(phi):
    # obtain point coordinates 
    x,y = circle(phi)
    # set point's coordinates
    point.set_data([x],[y])
    return point,
 
# create animation with 10ms interval, which is repeated,
# provide the full circle (0,2pi) as parameters
ani = FuncAnimation(fig, update, interval=30, blit=True, repeat=True,
                    frames=np.linspace(0,2*np.pi,360, endpoint=False))
 
plt.show()

Тут другой с экспортом в mp4.
https://medium.com/@kirthi.tej... 0e075e5c6e
закоментил экспорт и добавил
Python
1
 plt.show()

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
 
TWOPI = 2*np.pi
 
fig, ax = plt.subplots()
 
t = np.arange(0.0, TWOPI, 0.001)
s = np.sin(t)
l = plt.plot(t, s)
 
ax = plt.axis([0,TWOPI,-1,1])
 
redDot, = plt.plot([0], [np.sin(0)], 'ro')
 
def animate(i):
    redDot.set_data(i, np.sin(i))
    return redDot,
 
# create animation using the animate() function
myAnimation = animation.FuncAnimation(fig, animate, frames=np.arange(0.0, TWOPI, 0.1),interval=10, blit=True, repeat=True)
 
plt.show()
 
# myAnimation.save('sine.mp4', fps=30, extra_args=['-vcodec', 'libx264'])
1
837 / 555 / 155
Регистрация: 07.11.2019
Сообщений: 1,304
09.01.2021, 15:35 5
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from matplotlib import pyplot as plt
from celluloid import Camera
import numpy as np
 
tau=np.linspace(0,1,1000)
P=np.array([[180, 290],
           [140, 335],
           [50,  170],
           [10,   15],
           [360, 240],
           [140,  67]
           ])
 
def Bezier(t, P):
    # Bezier Matrix:
    Mb=np.matrix([
        [ -1,   5, -10,  10, -5, 1],
        [  5, -20,  30, -20,  5, 0],
        [-10,  30, -30,  10,  0, 0],
        [ 10, -20,  10,   0,  0, 0],
        [ -5,   5,   0,   0,  0, 0],
        [  1,   0,   0,   0,  0, 0]
                 ])
    # T matrix
    xx, yy=np.meshgrid(np.arange(5, -1, -1), t)
    xx=np.matrix(xx)
    yy=np.matrix(yy)
    T_mat=np.power(yy, xx)
    B=T_mat*Mb*P
    return B
    
 
fig = plt.figure(figsize=(10,8), dpi = 100, facecolor='w')
plt.axis('equal')
plt.axis([0,600,0,600])
X,Y=Bezier(tau, P)[:,0],Bezier(tau, P)[:,1]
 
camera = Camera(fig)
for i in range(100):
    coord=Bezier(i/100, P)
    plt.plot(X,Y,color = '#ff0000')
    plt.scatter(coord[0,0], coord[0,1], color = '#00ff00' , marker='o')
    camera.snap()
animation = camera.animate()
animation.save('animation.mp4')
https://youtu.be/WSB_Smh6aIw
1
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 44
09.01.2021, 23:50  [ТС] 6
Excalibur921, В anaconda ни один код не заработал, нету анимации просто статичная картинка. Как я понимаю, первый код это движение точки по кругу, а второй по синусоиде, а как передвигать по точкам кривой Безье?
u235, Всё работает, большое спасибо за код, но можно побольше объяснений, откуда взялась матрица 6 на 6, почему именно такие значения, зачем нужна T матрица, meshgrid? какой параметр отвечает за ускорение/замедление передвижения маркера?

Добавлено через 17 минут
u235, Анимация почему-то работает, только если добавить строчку %matplotlib qt, а затем удалить её, если просто скопировать код и запустить, отображается просто координатная система без линии и анимации.
Запускаю этот код
Кликните здесь для просмотра всего текста

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from matplotlib import pyplot as plt
from celluloid import Camera
import numpy as np
import ffmpeg
tau=np.linspace(0,1,1000)
P=np.array([[180, 290],
           [140, 335],
           [50,  170],
           [10,   15],
           [360, 240],
           [140,  67]
           ])
 
def Bezier(t, P):
    # Bezier Matrix:
    Mb=np.matrix([
        [ -1,   5, -10,  10, -5, 1],
        [  5, -20,  30, -20,  5, 0],
        [-10,  30, -30,  10,  0, 0],
        [ 10, -20,  10,   0,  0, 0],
        [ -5,   5,   0,   0,  0, 0],
        [  1,   0,   0,   0,  0, 0]
                 ])
    # T matrix
    xx, yy=np.meshgrid(np.arange(5, -1, -1), t)
    xx=np.matrix(xx)
    yy=np.matrix(yy)
    T_mat=np.power(yy, xx)
    B=T_mat*Mb*P
    return B
 
fig = plt.figure(figsize=(10,8), dpi = 100, facecolor='w')
plt.axis('equal')
plt.axis([0,600,0,600])
X,Y=Bezier(tau, P)[:,0],Bezier(tau, P)[:,1]
camera = Camera(fig)
for i in range(100):
    coord=Bezier(i/100, P)
    plt.plot(X,Y,color = '#ff0000')
    plt.scatter(coord[0,0], coord[0,1], color = '#00ff00' , marker='o')
    camera.snap()
animation = camera.animate(interval = 200, repeat = True,
                           repeat_delay = 500)

Всё работает, перезагружаю kernel, всё работает, анимация показывается, вставляю ваш код, анимация работает, перезагружаю kernel снова просто координатная плоскость, иначе говоря, если в новый файл вставить ваш код анимация не работает, почему?
0
1080 / 692 / 114
Регистрация: 12.10.2013
Сообщений: 4,587
09.01.2021, 23:51 7
Цитата Сообщение от Bronzor Посмотреть сообщение
В anaconda ни один код не заработал, нету анимации просто статичная картинка. Как я понимаю, первый код это движение точки по кругу,
Не знаю что такое anaconda.
Я настроил Visual Studio Code для Python 3.8 и коды работают. Первый код движение по кривой Безье. Второй по синусоиде с показом кривой. Плохо что одну и туже задачу можно рисовать 100500 способами .
1
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 44
09.01.2021, 23:58  [ТС] 8
Да, как оказалось, та же проблема, если вставить этот код и затем вставить ваш, анимация работает, но если вставить код в новый файл, будет статичная картинка, пока не понятно как это исправить.
Кликните здесь для просмотра всего текста

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
from matplotlib import pyplot as plt
from celluloid import Camera
import numpy as np
import ffmpeg
tau=np.linspace(0,1,1000)
P=np.array([[180, 290],
           [140, 335],
           [50,  170],
           [10,   15],
           [360, 240],
           [140,  67]
           ])
 
def Bezier(t, P):
    # Bezier Matrix:
    Mb=np.matrix([
        [ -1,   5, -10,  10, -5, 1],
        [  5, -20,  30, -20,  5, 0],
        [-10,  30, -30,  10,  0, 0],
        [ 10, -20,  10,   0,  0, 0],
        [ -5,   5,   0,   0,  0, 0],
        [  1,   0,   0,   0,  0, 0]
                 ])
    # T matrix
    xx, yy=np.meshgrid(np.arange(5, -1, -1), t)
    xx=np.matrix(xx)
    yy=np.matrix(yy)
    T_mat=np.power(yy, xx)
    B=T_mat*Mb*P
    return B
 
fig = plt.figure(figsize=(10,8), dpi = 100, facecolor='w')
plt.axis('equal')
plt.axis([0,600,0,600])
X,Y=Bezier(tau, P)[:,0],Bezier(tau, P)[:,1]
camera = Camera(fig)
for i in range(100):
    coord=Bezier(i/100, P)
    plt.plot(X,Y,color = '#ff0000')
    plt.scatter(coord[0,0], coord[0,1], color = '#00ff00' , marker='o')
    camera.snap()
animation = camera.animate(interval = 200, repeat = True,
                           repeat_delay = 500)
0
837 / 555 / 155
Регистрация: 07.11.2019
Сообщений: 1,304
10.01.2021, 00:41 9
Bronzor, Матрица 6х6 это матрица Безье, если из ваших B0-B5 сделать полиномы (раскрыть скобки ), то матрица Безье это коэффициенты при t^5.. t^0 степени.
Матрица T - матрица степеней вектора времени. Если вектор t=0.5 (одна точка) T=[0.5**5, 0.5**4, 0.5**3,..0.5**0]
Если вектор t=[0, 0.5, 1] (три точки), то матрица T=[[0**5, 0**4,..0**0], [0.5**5, 0.5**4,..0.5**0],[1**5, 1**4,..1**0]].
См. https://ru.wikipedia.org/wiki/... 1%8C%D0%B5
Т.о. мы ускоряем код, используя быстрое умножение матриц numpy, а не циклы.

Добавлено через 20 минут
Попробуйте добавить в конец скрипта
Python
1
 plt.show()
1
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 44
10.01.2021, 12:20  [ТС] 10
u235, После добавления ничего не изменилось. При этом анимация сохраняется и с ней всё хорошо.
Как сделать анимацию движения объекта по кривой (алгоритм Безье)
0
837 / 555 / 155
Регистрация: 07.11.2019
Сообщений: 1,304
10.01.2021, 12:33 11
Так вы через Jupyter запускаете.. Там работать не будет. Запустите просто из комм.строки анаконды.
1
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 44
10.01.2021, 12:34  [ТС] 12
u235, Notebook, а почему другая анимация работает, а эта нет?
0
837 / 555 / 155
Регистрация: 07.11.2019
Сообщений: 1,304
10.01.2021, 12:48 13
Bronzor, откуда же я знаю. У меня нет кода другой анамации чтобы сравнить, а у вас есть. Вот и найдите различия.
1
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 44
10.01.2021, 13:59  [ТС] 14
Оказывается два раза сверху не то скопировал, тоже самое всё, но эта анимация работает...
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#Importing required libraries
%matplotlib notebook
import matplotlib.pyplot as plt
import numpy as np
from celluloid import Camera
import ffmpeg
 
 
#Creating Data
x = np.linspace(0, 10, 100)
 
#defining a function to return sine of input values.
def fun(i):
    y = np.sin(i)
    return y
 
x_y = fun(x)
 
#Creating matplotlib figure and camera object
fig = plt.figure()
plt.xlim(0,10)
plt.ylim(-2,2)
camera = Camera(fig)
 
#Looping the data and capturing frame at each iteration
for i in x:
    plt.plot(x,x_y , color = 'green' , lw = 0.8)
    f = plt.scatter(i, fun(i) , color = 'red' , s = 200)
    plt.title('tracing a sin function')
    camera.snap()
 
#Creating the animation from captured frames
animation = camera.animate(interval = 200, repeat = True,
                           repeat_delay = 500)
Добавлено через 8 минут
u235, Вставил %matplotlib qt5 перед созданием координатной плоскости (верно? fig = plt.figure()) и теперь анимация работает в отдельном окне.
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
from matplotlib import pyplot as plt
from celluloid import Camera
import numpy as np
 
tau=np.linspace(0,1,1000)
P=np.array([[180, 290],
           [140, 335],
           [50,  170],
           [10,   15],
           [360, 240],
           [140,  67]
           ])
 
def Bezier(t, P):
    # Bezier Matrix:
    Mb=np.matrix([
        [ -1,   5, -10,  10, -5, 1],
        [  5, -20,  30, -20,  5, 0],
        [-10,  30, -30,  10,  0, 0],
        [ 10, -20,  10,   0,  0, 0],
        [ -5,   5,   0,   0,  0, 0],
        [  1,   0,   0,   0,  0, 0]
                 ])
    # T matrix
    xx, yy=np.meshgrid(np.arange(5, -1, -1), t)
    xx=np.matrix(xx)
    yy=np.matrix(yy)
    T_mat=np.power(yy, xx)
    B=T_mat*Mb*P
    return B
%matplotlib qt5
fig = plt.figure()
plt.xlim(0,600)
plt.ylim(0,600)
X,Y=Bezier(tau, P)[:,0],Bezier(tau, P)[:,1]
camera = Camera(fig)
 
for i in range(100):
    coord=Bezier(i/100, P)
    plt.plot(X,Y,color = '#ff0000')
    plt.scatter(coord[0,0], coord[0,1], color = '#00ff00' , marker='o')
    camera.snap()
    
animation = camera.animate(interval = 200, repeat = True,
                           repeat_delay = 500)
Добавлено через 53 минуты
Осталось понять как работает код.
tau (что это за сокращение, кстати?) это одномерный массив состоящий из 1000 элементов от 0 до 1?
P это двумерный массив, где хранятся координаты x,y моих контрольных точек.
Mb это двумерный массив, где хранятся коэффициенты при t,
Затем создаём прямоугольную сетку используя одномерные массивы xx и yy (от -5 до -1 с шагом -1), и зачем нужен параметр t здесь? не понял 25 строку.
xx = матрица размерностью хх
yy = матрица размерностью yy
28 снова не понял, но это возведение элемента массива yy в степень элемента массива xx?
Затем создаём объект figure без осей
Затем устанавливаем пределы x и y осей
35 не понял что происходит, но что-то присваивается переменным x и y
Затем в цикле получаем координаты точек, отображаем их на графике красным цветом
Добавляем маркер зелёного цвета (что значит coord[0,0], coord[0,1] ? и какие параметры отвечают за размер кружка, можно ли вместо маркера создать круг и его двигать?)
Затем снимок камеры
После того, как все кадры были получены, создаём анимацию?
0
837 / 555 / 155
Регистрация: 07.11.2019
Сообщений: 1,304
10.01.2021, 15:15 15
tau - параметр кривой Безье - меняется от 0 до 1 , 1000 - число точек из которых она состоит. Если сделать не 1000, а, например, 20, то на кривой будут изломы.
25 строка - (от 5 до 0 включительно) это степени, в которые будет возводится t. Посмотрите примеры np.meshgrid на оф. сайте numpy. На входе - два вектора, на выходе две матрицы-сетки.
28 - да, так и есть.

35 - Получаем два вектора координат X и Y из вектор tau - для статичного графика
coord[0,0], coord[0,1] - координаты точки кривой, соответствующие параметру i/100 - центр кружка.
Python
1
plt.scatter(coord[0,0], coord[0,1], color = '#00ff00' , marker='o', s=10)
s - размер кружка
1
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 44
10.01.2021, 15:31  [ТС] 16
u235, вроде стало понятнее, а как переделать код в 3 контрольные точки? попробовал удалить координаты 3 точек, и последние три строки матрицы, но не заработало, видимо не всё так просто, также а как отобразить закрасить контрольные точки?
Нашёл вот такой идеальный код, мне бы анимировать точку и добавить возможность ввода конечной точки всё.
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import matplotlib.pyplot as plt
import numpy as np
from celluloid import Camera
 
tau=np.linspace(0,1,1000)
P0, P1, P2=np.array([[0, 0],
           [2, 4],
           [5, 3],
           ])
 
P = lambda t: (1 - t)**2 * P0 + 2 * t * (1 - t) * P1 + t**2 * P2
points = np.array([P(t) for t in np.linspace(0, 1, 50)])
 
# get x and y coordinates of points separately
x, y = points[:,0], points[:,1]
 
%matplotlib qt5
fig = plt.figure()
plt.xlim(-1,6)
plt.ylim(-1,6)
camera = Camera(fig)
 
for i in range(100):
    plt.plot(x,y,color = '#ff0000')
    plt.plot(*P0, 'b.')
    plt.plot(*P1, 'b.')
    plt.plot(*P2, 'b.')
    camera.snap()
    
animation = camera.animate(interval = 20, repeat = True,
                           repeat_delay = 0)
0
837 / 555 / 155
Регистрация: 07.11.2019
Сообщений: 1,304
10.01.2021, 15:49 17
Bronzor, Для 3х контрольных точек нужна другая матрица Безье, 3x3, а не 5x5. Как ее считать я уже говорил.
Контрольные точки лучше хранить единой матрицей P, , а не в виде P0, P1... тогда
достаточно вызвать что-то типа:
Python
1
plt.scatter(P[:,0], P[:,1], color = '#ffff00' , marker='o')
чтобы отобразить сразу все контрольные точки за одну команду без циклов.
Работайте с матрицами и векторами как с единым целым, а не поэлементно.
Почитайте хорошую книжку Роджерс Д., Адамс Дж. Математические основы машинной графики.
1
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 44
10.01.2021, 16:20  [ТС] 18
u235, Спасибо за разъяснения, пока что такой результат, осталось добавить возможность, чтобы пользователь вводил координаты последней контрольной точки P3.
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from matplotlib import pyplot as plt
from celluloid import Camera
import numpy as np
 
tau=np.linspace(0,1,1000)
P=np.array([[0, 0],
           [2, 4],
           [5, 3],
           ])
 
def Bezier(t, P):
    # Bezier Matrix:
    Mb=np.matrix([
        [1, -2, 1],
        [-2, 2, 0],
        [1, 0, 0],
                 ])
    # T matrix
    xx, yy=np.meshgrid(np.arange(2, -1, -1), t)
    xx=np.matrix(xx)
    yy=np.matrix(yy)
    T_mat=np.power(yy, xx)
    B=T_mat*Mb*P
    return B
%matplotlib qt5
fig = plt.figure()
plt.xlim(-2,6)
plt.ylim(-2,6)
X,Y=Bezier(tau, P)[:,0],Bezier(tau, P)[:,1]
camera = Camera(fig)
 
for i in range(100):
    coord=Bezier(i/100, P)
    plt.plot(X,Y,color = '#ff0000')
    plt.scatter(P[:,0], P[:,1], color = '#0000FF' , marker='o')
    plt.scatter(coord[0,0], coord[0,1], color = '#00ff00' , marker='o', s=100)
    camera.snap()
    
animation = camera.animate(interval = 20, repeat = True,
                           repeat_delay = 0)
animation.save('1.mp4')
1
Миниатюры
Как сделать анимацию движения объекта по кривой (алгоритм Безье)  
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 44
10.01.2021, 16:58  [ТС] 19
u235, Добавил ввод, может перемудрил и как-то иначе можно? Правильно ли написал комментарии?
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
## Импортирование библиотек
from matplotlib import pyplot as plt
from celluloid import Camera
import numpy as np
 
## Создание одномерного массива, значения от 0 до 1, количество точек - 1000 (параметр кривой Безье)
tau=np.linspace(0,1,1000)
print('Введите х координату:')
x_end = input()
print('Введите y координату:')
y_end = input()
P=np.array([[0, 0],  # Координаты контрольны точек записанные в виде двумерного массива
           [2, 4],
           [x_end, y_end],
           ])
P=P.astype(float)
# Алгоритм Безье
def Bezier(t, P):
    # Базисная матрица Безье (коэффициенты при t^2,t^1,t^0)
    Mb=np.matrix([
        [1, -2, 1],
        [-2, 2, 0],
        [1, 0, 0],
                 ])
    # Т матрица (матрица степеней вектора времени)
    xx, yy=np.meshgrid(np.arange(2, -1, -1), t) # Степени, в которые будет возводится t (На входе - два вектора, на выходе две матрицы-сетки)
    xx=np.matrix(xx)
    yy=np.matrix(yy)
    T_mat=np.power(yy, xx) # Возведение элемента массива yy в степень элемента массива xx
    B=T_mat*Mb*P # Получаем координаты точки
    return B # Возвращаем координаты точки
 
# Открытие всплывающего окна (GUI)
%matplotlib qt 
fig = plt.figure() # Создание объекта-фигуры без осей
plt.xlim(-2,6) #Создание и задание пределов оси Х
plt.ylim(-2,6) #Создание и задание пределов оси Y
X,Y=Bezier(tau, P)[:,0],Bezier(tau, P)[:,1] # Получаем два вектора координат X и Y из вектор tau - для статичного графика
camera = Camera(fig) 
 
for i in range(100):
    coord=Bezier(i/100, P)
    plt.plot(X,Y,color = '#ff0000') # Отображение координатной плоскости
    plt.scatter(P[:,0], P[:,1], color = '#0000FF') # Отображение контрольных точек
    plt.scatter(coord[0,0], coord[0,1], color = '#00ff00' , marker='o', s=100) # Координаты точки кривой, соответствующие параметру i/100 - центр кружка.
    camera.snap() # Снимок камеры
    
animation = camera.animate(interval = 20, repeat = True, repeat_delay = 0) # Создание анимации
animation.save('1.mp4') # Сохранение анимации
Введите х координату:
5
Введите y координату:
-1

Как сделать анимацию движения объекта по кривой (алгоритм Безье)
1
837 / 555 / 155
Регистрация: 07.11.2019
Сообщений: 1,304
10.01.2021, 22:43 20
Все нормально, только код можно еще сократить. В цикле for не считать coord заново, а просто брать скажем каждый 10ый элемент из X , Y

Добавлено через 1 минуту
типа
Python
1
plt.scatter( X[i*10, 0], Y[i*10, 0], color = '#00ff00' , marker='o', s=200)
а 42 строку убрать.
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
10.01.2021, 22:43

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Алгоритм движения касательной по кривой
Никак не могу реализовать алгоритм движения касательной по кривой (у меня есть разные кривые sin,...

Сделать анимацию движения нескольких эллипсов
Нужно сделать анимацию движения 8-10 эллипсов в разных направлениях при загрузке формы с помощью...

Сделать анимацию движения хвоста у мышки
сделать анимацию движения хвоста у мышки,вот есть код

Нужно сделать анимацию движения нарисованного стула
Здравствуйте! Я написал программу, рисующую стул, и нужно сделать так, чтобы этот стул просто...

Как сделать эффект движения объекта относительно заднего фона
Например, в игре марио, когда персонаж идет, задний фон как бы движется в противроположную сторону...

Как при построении кривой Безье уменьшить разброс точек?
Для построения кривой Безье за основу взял предлагаемое решение для C++Builder:...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.