Заставьте фигуру вращаться с помощью матрицы вращения, используя matplotlib

Я хочу повернуть фигуру (состоящую из линий) в 2D-пространстве. Я использую эту технику: (1) я перевожу фигуру в начало координат. Точка вращения находится в (0,0) (2) я выполняю вращение (3) я возвращаю фигуру обратно

Проблема связана с моей функцией вращения. Не знаю, почему это не работает, так как я использовал матрицу вращения. Вам не обязательно просматривать весь код, просто посмотрите на функцию «вращение» и функцию «анимация». Вы увидите, что я оставляю комментарии, чтобы помочь вам.

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

Если вы не сделаете вращение, а просто переместите дважды (шаг (1) и шаг (3) моей процедуры), вы увидите, что вся фигура не движется (это ожидаемо, так как я перемещаю ее в центр и возвращаю туда, где это было) и вы можете увидеть, как выглядит фигура. Таким образом, единственная проблема связана с функцией вращения.

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
import pylab as pl
import math

#Deplacement de la base pour pouvoir utiliser la matrice de rotation
def center(x,y,c):
    for i in range(len(x)):
        x[i] = x[i] - c[0]
    for i in range(len(y)):
        y[i] = y[i] - c[1]
    return None

#Remettre la base à sa place
def recenter(x,y,c):
    for i in range(len(x)):
        x[i] = x[i] + c[0]
    for i in range(len(y)):
        y[i] = y[i] + c[1]
    return None

#Rotation
def rotation(x,y,angle):
    my_list = [[],[]]
    for i in range(len(x)):
        my_list[0].append(x[i]*math.cos(angle) + y[i]*math.sin(angle))
    for j in range(len(y)):
        my_list[1].append(x[i]*math.sin(angle)*(-1) + y[i]*math.cos(angle))
    return my_list

#Here is the rotation matrix
#cos sin
#-sin cos

# First set up the figure, the axis, and the plot element we want to animate
fig = plt.figure()
ax = plt.axes(xlim=(-125, 125), ylim=(-250, 250))
line, = ax.plot([], [], lw=2)

#Les lignes du tableau
plt.plot([0, 125], [50, 50], color='k', linestyle='-', linewidth=2)
plt.plot([0, 125], [200, 200], color='k', linestyle='-', linewidth=2)
plt.plot([17.5, 107.5], [80, 80], color='k', linestyle='-', linewidth=2)
plt.plot([17.5, 107.5], [110, 110], color='k', linestyle='-', linewidth=2)
plt.plot([17.5, 107.5], [140, 140], color='k', linestyle='-', linewidth=2)
plt.plot([17.5, 107.5], [170, 170], color='k', linestyle='-', linewidth=2)
plt.plot([17.5, 17.5], [80, 170], color='k', linestyle='-', linewidth=2)
plt.plot([17.5, 17.5], [80, 170], color='k', linestyle='-', linewidth=2)
plt.plot([47.5, 47.5], [80, 170], color='k', linestyle='-', linewidth=2)
plt.plot([77.5, 77.5], [80, 170], color='k', linestyle='-', linewidth=2)
plt.plot([107.5, 107.5], [80, 170], color='k', linestyle='-', linewidth=2)

# initialization function: plot the background of each frame
def init():
    line.set_data([], [])
    return line,

# animation function. This is called sequentially
def animate(i):
    c1 = 62.5
    c2 = 10
    pt_rot = (c1, c2) #Point from which I want to rotate
    x = [47.5, 47.5, 77.5, 77.5, 47.5, 62.5, c1, 57.5, 67.5]
    y = [15, 45, 45, 15, 15, 15, c2, 10, 10]

    center(x,y,pt_rot)
    #Uncomment these 3 following lines to test the double translation
    my_list = rotation(x,y,(i/180))
    x = my_list[0]
    y = my_list[1]
    recenter(x, y, pt_rot)

    line.set_data(x,y)

    return line,

# call the animator.  blit=True means only re-draw the parts that have changed.
anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=200, interval=20, blit=True)

plt.show()

person A. Neo    schedule 16.12.2016    source источник
comment
Что делает функция angle_position? Он никогда не вызывается в вашем сценарии. Последний абзац вашего вопроса кажется важным. Однако он также наименее понятен. Почему он должен быть хорошим, если перевод ничего не двигает? А в чем собственно вся проблема? Если линия вращается, она делает то, что должна, верно? Когда я запускаю ваш код, я не вижу вращения. Попробуйте уточнить, написав в своем вопросе Ожидаемое поведение: ‹некоторые предложения› и Наблюдаемое поведение: ‹некоторые предложения›.   -  person ImportanceOfBeingErnest    schedule 16.12.2016
comment
Извините, я внесу изменения в вопрос, чтобы быть более точным.   -  person A. Neo    schedule 16.12.2016
comment
Думаю, я отвечу на все ваши вопросы:   -  person A. Neo    schedule 16.12.2016


Ответы (1)


В вашем сценарии есть две основные проблемы:

  1. В функции вращения вы позволяете циклу j, но устанавливаете x и y с точки зрения i, который является константой после первого цикла.

  2. Вы устанавливаете угол поворота в градусах. Однако для тригонометрических функций требуется угол, заданный в радиантах. Так что в основном вам нужно умножить угол на 2pi.

Третий момент, который на самом деле не является проблемой, но затрудняет чтение сценария, заключается в том, что вы возвращаете None в функциях перевода. Мне легче читать, если каждая функция возвращает некоторые значения, и можно было бы вернуть эти значения следующей функции.

Вот полный исполняемый скрипт.

import numpy as np
from matplotlib import pyplot as plt
from matplotlib import animation
import math


def center(x,y,c):
    for i in range(len(x)):
        x[i] = x[i] - c[0]
    for i in range(len(y)):
        y[i] = y[i] - c[1]
    # return x,y  <--------------------- here 
    return x,y

def recenter(x,y,c):
    for i in range(len(x)):
        x[i] = x[i] + c[0]
    for i in range(len(y)):
        y[i] = y[i] + c[1]
    # return x,y  <--------------------- here 
    return x,y

def rotation(x,y,angle):
    my_list = [[],[]]
    for i in range(len(x)):
        my_list[0].append(x[i]*math.cos(angle) + y[i]*math.sin(angle))
    for j in range(len(y)):
        #Big mistake here, replace i by j <--------------------- here 
        my_list[1].append(x[j]*math.sin(angle)*(-1.) + y[j]*math.cos(angle))
    return my_list[0], my_list[1]



fig = plt.figure()
ax = plt.axes(xlim=(10, 110), ylim=(-40, 60))
ax.set_aspect('equal')
line, = ax.plot([],[], lw=2)

def init():
    line.set_data([],[])
    return line,

def animate(i):
    c1 = 62.5
    c2 = 10
    pt_rot = (c1, c2)
    x = [47.5, 47.5, 77.5, 77.5, 47.5, 62.5, c1, 57.5, 67.5]
    y = [15, 45, 45, 15, 15, 15, c2, 10, 10]

    x,y = center(x,y,pt_rot)  # <--------------------- here 
    x,y = rotation(x,y,(i/180.)*np.pi) # <------------ here 
    x,y = recenter(x, y, pt_rot) # <------------------ here 

    line.set_data(x,y)
    return line,


anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=359, interval=20, blit=True)

plt.show()
person ImportanceOfBeingErnest    schedule 16.12.2016
comment
Спасибо. Это была глупая ошибка. Последую вашему совету по поводу возврата None. - person A. Neo; 17.12.2016