Форум программистов, компьютерный форум, киберфорум
Python: GUI, графика
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.67/55: Рейтинг темы: голосов - 55, средняя оценка - 4.67
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 245

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

08.01.2021, 17:01. Показов 11524. Ответов 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
Просмотров: 237

Размер: 10.2 Кб

Хочется, чтобы было вот так:
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
08.01.2021, 17:01
Ответы с готовыми решениями:

Как сделать анимацию движения объекта по кругу?
Нужна помощь!:-#Importing required libraries %matplotlib notebook import matplotlib.pyplot as plt import numpy as np from celluloid...

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

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

25
1472 / 827 / 140
Регистрация: 12.10.2013
Сообщений: 5,456
08.01.2021, 20:32
Цитата Сообщение от 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
Сообщений: 245
09.01.2021, 11:29  [ТС]
Это 6 контрольных точек, можно и с двумя, мне главное понять, желательно код с маленькими пояснениями, как на моей кривой нарисовать круг и заставить его двигаться по этой кривой.
0
1472 / 827 / 140
Регистрация: 12.10.2013
Сообщений: 5,456
09.01.2021, 13:56
Цитата Сообщение от 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
5514 / 2867 / 571
Регистрация: 07.11.2019
Сообщений: 4,751
09.01.2021, 15:35
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
Сообщений: 245
09.01.2021, 23:50  [ТС]
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
1472 / 827 / 140
Регистрация: 12.10.2013
Сообщений: 5,456
09.01.2021, 23:51
Цитата Сообщение от Bronzor Посмотреть сообщение
В anaconda ни один код не заработал, нету анимации просто статичная картинка. Как я понимаю, первый код это движение точки по кругу,
Не знаю что такое anaconda.
Я настроил Visual Studio Code для Python 3.8 и коды работают. Первый код движение по кривой Безье. Второй по синусоиде с показом кривой. Плохо что одну и туже задачу можно рисовать 100500 способами .
1
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 245
09.01.2021, 23:58  [ТС]
Да, как оказалось, та же проблема, если вставить этот код и затем вставить ваш, анимация работает, но если вставить код в новый файл, будет статичная картинка, пока не понятно как это исправить.
Кликните здесь для просмотра всего текста

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
5514 / 2867 / 571
Регистрация: 07.11.2019
Сообщений: 4,751
10.01.2021, 00:41
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
Сообщений: 245
10.01.2021, 12:20  [ТС]
u235, После добавления ничего не изменилось. При этом анимация сохраняется и с ней всё хорошо.
0
5514 / 2867 / 571
Регистрация: 07.11.2019
Сообщений: 4,751
10.01.2021, 12:33
Так вы через Jupyter запускаете.. Там работать не будет. Запустите просто из комм.строки анаконды.
1
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 245
10.01.2021, 12:34  [ТС]
u235, Notebook, а почему другая анимация работает, а эта нет?
0
5514 / 2867 / 571
Регистрация: 07.11.2019
Сообщений: 4,751
10.01.2021, 12:48
Bronzor, откуда же я знаю. У меня нет кода другой анамации чтобы сравнить, а у вас есть. Вот и найдите различия.
1
2 / 2 / 0
Регистрация: 13.10.2018
Сообщений: 245
10.01.2021, 13:59  [ТС]
Оказывается два раза сверху не то скопировал, тоже самое всё, но эта анимация работает...
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
5514 / 2867 / 571
Регистрация: 07.11.2019
Сообщений: 4,751
10.01.2021, 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
Сообщений: 245
10.01.2021, 15:31  [ТС]
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
5514 / 2867 / 571
Регистрация: 07.11.2019
Сообщений: 4,751
10.01.2021, 15:49
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
Сообщений: 245
10.01.2021, 16:20  [ТС]
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
Сообщений: 245
10.01.2021, 16:58  [ТС]
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
5514 / 2867 / 571
Регистрация: 07.11.2019
Сообщений: 4,751
10.01.2021, 22:43
Все нормально, только код можно еще сократить. В цикле 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
10.01.2021, 22:43
Помогаю со студенческими работами здесь

Алгоритм вычисления максимального радиуса для сопряжения кривой Безье и отрезка
Здравствуйте! Пытаюсь вычислить максимальный радиус гладкого сопряжения кубической кривой Безье (P0, P1, P2, P3) и отрезка (P3,P4) - на...

Как сделать анимацию передвижения объекта в QT
Как сделать анимацию передвижения виджета слева на право.

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

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

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru