sábado, 7 de novembro de 2009

Rotações Altamente

Em post anterior referi um conjunto de princípios enunciados por George Polya e que nos podem ajudar a resolver problemas. Vamos ver se consigo exemplificar com um problema que nos vai interessar proximamente.

Admitamos que queremos implementar um programa para pegar numa imagem e rodá-la um certo número de graus. Como fazer? Se pensarmos um pouco chegamos à conclusão que uma imagem digital não é mais do que um conjunto de pontos, cada um designado por pixel - do inglês picture element, possuindo determinadas características. Quantos mais pixeis numa imagem, maior a sua resolução. Ter uma máquina fotográfica com 12 milhões de pixeis é melhor do que ter uma só com 1.2 Megapixeis. Estas questões no entanto não nos vão ocupar agora. O que nos interessa é discutir é saber como resolver o problema da rotação. Dito de outro modo: dado um ponto no espaço para onde é que ele vai parar quando lhe aplicamos uma rotação? Para ajudar um pequeno desenho.




E agora mãos à obra!
Comecemos então pelo princípio. e no princípio é a fase de compreender o problema. Qual é a incógnita? As novas coordenadas do ponto, depois da rotação. Na figura, os valores de (w,z). Quais são os dados? Uma vez mais é simples: as coordenadas iniciais do ponto ((x,y)) e o ângulo de rotação (Θ).

Passemos a um plano para resolver o problema. Várias são as questões que podemos colocar nesta fase. Admitamos que não nos conseguimos lembrar de nenhum problema semelhante já resolvido no passado e cuja solução pudéssemos adaptar. Acontece com frequência! Será que conseguimos relacionar a incógnita com os dados? Aqui aparece o método! Dos nossos conhecimentos de trignometria sabemos que as coordenadas de um ponto se podem relacionar com o seno e o coseno do ângulo que forma com a origem dos eixos de coordenadas. Assim podemos relacionar (w,z) com Θ2. Parece que não avançámos muito pois temos mais uma incógnita. Mas será mesmo assim? É que este ângulo é a soma dos outros dois (Θ e Θ1). O primeiro ... é dado! E o segundo? Bem, uma vez mais este relaciona-se com as coordenadas (x,y) através das funções seno e coseno. E pronto. Temos um plano para partir dos dados em direcção às incógnitas.

Vamos então à terceira fase: executar o plano. Vamos aos cálculos! Serão feitos no pressuposto de que a circunferência tem raio 1. Comecemos a relacionar coisas.




Agora vem o passo normalmente conhecido por eureka, e que aqui se resume a saber um pouco de trignometria. Exprimir o coseno de uma soma:




Ficamos apenas com a questão de exprimir Θ1 em função de (x,y). Nada que o nosso saber trignométrico não resolva:




Continuemos a juntar as peças do puzzle.




Ou ainda de outro modo:




Usando o mesmo raciocínio para Z teremos:




Quem souber um pouco de álgebra sabe que estas relações se podem colocar na forma matricial. Vamos a isso.



A última fase da resolução de problemas diz respeito à reflexão sobre o que fizemos. Uma das questões é a verificação do resultado. Tentemos com um ângulo de 90 graus. Neste caso o seno é 1 e o coseno 0. É só substituir e aplicar a um ponto qualquer.




Mas agora podemos desenvolver um programa para resolver o problema da rotação encarado como produto de uma matriz por um vector! É o que vem a seguir.


def prod_escalar(vect1, vect2):
"""
Produto escalr de dois vectores representados por listas.
"""
prod = [vect1[i] * vect2[i] for i in range(len(vect1))]
return sum(prod)

def prod_matriz_vector(mat,vec):
"""
Produto de uma matriz m x n por um vector 1 x n
"""
res = [prod_escalar(mat[i],vec) for i in range(len(mat))]
return res


Nesta solução duas notas. Primeiro, o facto de termos usado uma definição auxiliar que nos faz o produto escalar de dois vectores. Aplicou-se o princípio da construção descendente de programas, por camadas de abstracção. Segundo, recorremos às listas por compreensão, o que nos permitiu tornar o programa mais legível.

E pronto. Já está!

Sem comentários:

Enviar um comentário