Vamos usar as ideias de transformações lineares para transformar linearmente os vetores que mapeiam um círculo em uma elípse. Em seguida, vamos rotacionar esses vetores transformados para o ângulo que quisermos com uma matriz de rotação.
# importando a biblioteca numpy do python
import numpy
# importando a biblioteca matplotlib do python
import matplotlib.pyplot as plt
%matplotlib inline
# importando a biblioteca 'plot_helper'
from plot_helper import *
Vamos usar uma matriz de transformação para transformar um círculo em uma elipse
# definindo a matriz de transformação matrizA
matrizA = numpy.array([[2,1], [1,2]])
# imprime na tela a matrizA
print("{}".format(matrizA))
[[2 1] [1 2]]
# plota o gráfico da transformação linear, antes e depois
plot_linear_transformation(matrizA)
# definindo um array de 41 vetores, essses que começam em 0 e vão até 2pi
# (completa um círculo trigonomêtrico), aumentando gradativamente
# a função NumPy linspace é uma ferramenta em Python para criar sequências numéricas
alfa = numpy.linspace(0, 2*numpy.pi, 41)
# imprimindo alfa
print("{}".format(alfa))
[0. 0.15707963 0.31415927 0.4712389 0.62831853 0.78539816 0.9424778 1.09955743 1.25663706 1.41371669 1.57079633 1.72787596 1.88495559 2.04203522 2.19911486 2.35619449 2.51327412 2.67035376 2.82743339 2.98451302 3.14159265 3.29867229 3.45575192 3.61283155 3.76991118 3.92699082 4.08407045 4.24115008 4.39822972 4.55530935 4.71238898 4.86946861 5.02654825 5.18362788 5.34070751 5.49778714 5.65486678 5.81194641 5.96902604 6.12610567 6.28318531]
# função zip une elemento a elemento da lista de arrays
coordenadas = zip(numpy.cos(alfa), numpy.sin(alfa))
# adiciona cada par de elementos definidos em coordenadas a uma lista de vetores
vetores = list(coordenadas)
# verificando os pares de coordenadas definidos anteriormente
print("{}".format(vetores))
[(1.0, 0.0), (0.9876883405951378, 0.15643446504023087), (0.9510565162951535, 0.3090169943749474), (0.8910065241883679, 0.45399049973954675), (0.8090169943749475, 0.5877852522924731), (0.7071067811865476, 0.7071067811865476), (0.5877852522924731, 0.8090169943749475), (0.4539904997395468, 0.8910065241883678), (0.30901699437494745, 0.9510565162951535), (0.15643446504023092, 0.9876883405951378), (6.123233995736766e-17, 1.0), (-0.1564344650402308, 0.9876883405951378), (-0.30901699437494734, 0.9510565162951536), (-0.45399049973954675, 0.8910065241883679), (-0.587785252292473, 0.8090169943749475), (-0.7071067811865475, 0.7071067811865476), (-0.8090169943749473, 0.5877852522924732), (-0.8910065241883678, 0.45399049973954686), (-0.9510565162951535, 0.3090169943749475), (-0.9876883405951377, 0.15643446504023098), (-1.0, 1.2246467991473532e-16), (-0.9876883405951378, -0.15643446504023073), (-0.9510565162951536, -0.3090169943749473), (-0.8910065241883679, -0.45399049973954664), (-0.8090169943749475, -0.587785252292473), (-0.7071067811865477, -0.7071067811865475), (-0.5877852522924732, -0.8090169943749473), (-0.4539904997395469, -0.8910065241883678), (-0.30901699437494756, -0.9510565162951535), (-0.15643446504023104, -0.9876883405951377), (-1.8369701987210297e-16, -1.0), (0.15643446504023067, -0.9876883405951378), (0.30901699437494723, -0.9510565162951536), (0.45399049973954664, -0.891006524188368), (0.5877852522924729, -0.8090169943749476), (0.7071067811865474, -0.7071067811865477), (0.8090169943749473, -0.5877852522924734), (0.8910065241883678, -0.45399049973954697), (0.9510565162951535, -0.3090169943749477), (0.9876883405951377, -0.1564344650402311), (1.0, -2.4492935982947064e-16)]
# plotando o gráfico da lista de vetores
plot_vector(vetores)
# título do gráfico
plt.title("Vetores que representam um círculo")
Text(0.5, 1.0, 'Vetores que representam um círculo')
# definindo uma lista de vetores vazios
novosVetores = []
# estrutura de repetição for que inicia do zero até a (quantidade de vetores da lista - 1)
for indice in range(len(vetores)):
# implementa a multiplicação da matriz de transformação matrizA com cada par de
# coordenadas dos vetores
# a lista de vetores vazios
novosVetores.append(matrizA.dot(numpy.array(vetores[indice])))
plot_vector(novosVetores) # plota o gráfico dos novosVetores
plt.title("Vetores após terem sidos transformados") # título do gráfico
Text(0.5, 1.0, 'Vetores após terem sidos transformados')
e dessa forma, após aplicar uma transformação linear com matrizes, podemos transformar um círculo em uma elipse.
Temos os vetores que mapeiam o círculo trigonômetrico
plot_vector(vetores) # plotando o gráfico da lista de vetores
plt.title("Vetores que representam um círculo") # título do gráfico
Text(0.5, 1.0, 'Vetores que representam um círculo')
Vamos usar uma matriz de transformação nesses vetores para formar nossa elipse
Dado a matriz:
$matriz = \begin{bmatrix} 3 & 0 \\ 0 & 1 \\ \end{bmatrix}$
# definindo a matriz de transformação
matriz = numpy.array([[3,0],[0,1]])
# imprimindo a matriz
print("{}".format(matriz))
[[3 0] [0 1]]
# definindo uma lista vazia para os vetores da elipse
elipse = []
# estrutura de reétição for com repetição iniciada em 0 até o valor da quantidade de vetores - 1 : [0,41)
for indice in range(len(vetores)):
# aplica a transformação e adiciona a lista de vetores elipse
elipse.append(matriz.dot(numpy.array(vetores[indice])))
# imprime os vetores que mapeiam a elipse
print("{}".format(elipse))
[array([3., 0.]), array([2.96306502, 0.15643447]), array([2.85316955, 0.30901699]), array([2.67301957, 0.4539905 ]), array([2.42705098, 0.58778525]), array([2.12132034, 0.70710678]), array([1.76335576, 0.80901699]), array([1.3619715 , 0.89100652]), array([0.92705098, 0.95105652]), array([0.4693034 , 0.98768834]), array([1.8369702e-16, 1.0000000e+00]), array([-0.4693034 , 0.98768834]), array([-0.92705098, 0.95105652]), array([-1.3619715 , 0.89100652]), array([-1.76335576, 0.80901699]), array([-2.12132034, 0.70710678]), array([-2.42705098, 0.58778525]), array([-2.67301957, 0.4539905 ]), array([-2.85316955, 0.30901699]), array([-2.96306502, 0.15643447]), array([-3.0000000e+00, 1.2246468e-16]), array([-2.96306502, -0.15643447]), array([-2.85316955, -0.30901699]), array([-2.67301957, -0.4539905 ]), array([-2.42705098, -0.58778525]), array([-2.12132034, -0.70710678]), array([-1.76335576, -0.80901699]), array([-1.3619715 , -0.89100652]), array([-0.92705098, -0.95105652]), array([-0.4693034 , -0.98768834]), array([-5.5109106e-16, -1.0000000e+00]), array([ 0.4693034 , -0.98768834]), array([ 0.92705098, -0.95105652]), array([ 1.3619715 , -0.89100652]), array([ 1.76335576, -0.80901699]), array([ 2.12132034, -0.70710678]), array([ 2.42705098, -0.58778525]), array([ 2.67301957, -0.4539905 ]), array([ 2.85316955, -0.30901699]), array([ 2.96306502, -0.15643447]), array([ 3.0000000e+00, -2.4492936e-16])]
# plota o gráfico da elipse
plot_vector(elipse)
Observe como foi a transformação linear:
# plota o gráfico da transformação linear
plot_linear_transformation(matriz)
Vamos fazer algo legal com nossos conhecimentos em trigonometria
Podemos rotacionar esses vetores que mapeiam a elipse:
Dada a matriz de rotação:
$rotacao = \begin{bmatrix} cos(teta) & -sen(teta) \\ sen(teta) & cos(teta) \\ \end{bmatrix}$
# vamos rotacionar 45° os vetores que mapeiam a elipse
teta = numpy.pi/4
# definindo a matriz de transformação linear para a rotação
matrizRotacao = numpy.array([[numpy.cos(teta), -numpy.sin(teta)],[numpy.sin(teta), numpy.cos(teta)]])
Temos o gráfico da transformação linear:
# plota o gráfico da matriz de rotação
plot_linear_transformation(matrizRotacao)
# função responsável por rotacionar os vetores que mapeiam algum objeto.
# entrada: ângulo de rotação, lista de vetores que mapeiam um objeto
def giro(teta,vetores):
# definindo a matriz de rotação
matrizRotacao = numpy.array([[numpy.cos(teta), -numpy.sin(teta)],[numpy.sin(teta), numpy.cos(teta)]])
rotacao = [] # lista vazia para rotacionar os vetores da elipse no ângulo informado
# estrutura de repetição for que inicia em 0 e termina até a quantidade de vetores da lista: [0,lista)
for indice in range(len(vetores)):
# aplica a transformação em cada vetor e implementa na lista
rotacao.append(matrizRotacao.dot(numpy.array(vetores[indice])))
# retorna o gráfico plotado da rotação dos vetores da lista por um angulo teta, em rad
return plot_vector(rotacao)
giro(teta,elipse) # executa a função de rotação
Observe que a elipse rotacionou 45°, como esperado
# vamos rotacionar 90° os vetores que mapeiam a elipse
teta = numpy.pi / 2
# executa a função de rotação
giro(teta,elipse)
# vamos rotacionar 30° os vetores que mapeiam a elipse
teta = numpy.pi / 6
# executa a função de rotação
giro(teta,elipse)
# vamos rotacionar 180° os vetores que mapeiam a elipse
teta = numpy.pi
# executa a função de rotação
giro(teta,elipse)