terça-feira, 22 de janeiro de 2013

Animação de hipocicloides com HTML5 e Javascript


Hipocicloide ou hypocycloid (inglês) são curvas que podem ser produzidas por meio de dois círculos, sendo um externo de raio maior e outro interno de raio menor, além dos círculos é utilizada uma constante que é geralmente representada por k, caso a constante seja um número inteiro, ela determina a quantidade de cúspides na curva.
Fig 1: Hipocicloide obtida com K=2.1

O círculo de raio menor rola em volta do círculo de raio maior com um ponto fixo, as coordenadas que esse ponto fixo intercepta, são utilizadas como pontos da curva. O ponto inicial sempre é completado (juntado com outro) no final das iterações.

O que mais chama a atenção são os desenhos que é possível gerar simplesmente variando o valor da constante k, como podemos observar nas figura 1.

Para obter os pontos das curvas é utilizada a seguinte equação.


Onde r é o raio do círculo menor, a letra grega teta é o passo da circunferência e k é a constante que define o modelo da curva.

Para reproduzir computacionalmente a equação anterior, foi utilizada a linguagem Javascript junto com Canvas 2D que faz parte do padrão HTML5. Podemos observar o trecho de código que calcula as coordenadas.
 function calculateCoordinates(theta)
 {
   canvas = document.getElementById("hypocycloid");
   width = canvas.width; 
   height = canvas.height;
   r = width/(k*3);
   x = width/2 + r * (k - 1) * Math.cos(theta) + r * Math.cos((k-1)*theta);
   y = height/2 + r * (k - 1) * Math.sin(theta) - r * Math.sin((k-1)*theta);
   return [x,y];
 }    

Na implementação o raio (r) foi obtido dividindo a largura da área do canvas (área de desenho) pela constante k*3, pois com valor fixo do raio e dependendo do tamanho da área, parte do desenho poderia ser ocultado.

A seguir podemos observar o trecho de código que é responsável pelas iterações e atualização do desenho e animação.
 function animate() 
 {
   reqFrame = window.mozRequestAnimationFrame    ||
              window.msRequestAnimationFrame     ||              
              window.webkitRequestAnimationFrame ||
              window.oRequestAnimationFrame;
   theta=theta+0.006;
   coord = calculateCoordinates(theta);
   x = coord[0];
   y = coord[1];
   draw();
          
   reqFrame(animate);
 }

O trecho que desenha cada ponto no Canvas 2D é mostrado a seguir.
 function draw()
 {
   canvas = document.getElementById("hypocycloid");
   ctx = canvas.getContext("2d");
   ctx.fillRect(x,y,1,1);
 } 

Os principais trechos do código são os que foram expostos anteriormente, é claro que para a animação funcionar é necessário inicializar as variáveis, tratar os valores de entrada e etc. O código completo pode ser visto neste link. Outro detalhe foi que para tornar o código mais didático, não tratei a condição de parada do desenho.

Abaixo é possível ver o funcionamento do código, basta clicar no botão "Gerar Curvas". É necessário o navegador ser compatível com HTML5.

Valor de K
Valores interessantes de K: 2.1, 3, 3.1, 3.15, 3.2, 4, 4.15, 4.5, 6, 12 ...

Um comentário:

Postar um comentário

quinta-feira, 10 de janeiro de 2013

Introdução ao Visualization Toolkit (VTK)


Figura 1: Exemplo de pipeline
Visualization Toolkit (VTK) é uma biblioteca para visualização, processamento de imagens e computação gráfica. Multiplataforma (Linux, Mac OS X e Windows) de código fonte aberto, ela dispõe de fácil integração com bibliotecas de interface gráfica como Qt, GTK, wxPython, MFC, entre outras. Além de C++, por meio de wrapper ela suporta outras linguagens de programação como Python, Java e TCL.

Para processar imagens, superfícies ou outros dados suportados pelo VTK, é possível utilizar uma das centenas de filtros disponíveis nele, a documentação é dividida por classes e a grande maioria é repleta de exemplos.

Como ilustra a figura 1, o VTK trabalha com o conceito de pipeline, aonde a entrada (input) de uma determinada funcionalidade recebe a saída de uma funcionalidade anterior (output).

No exemplo abaixo será mostrada a criação e visualização de um cubo, lembrando que nesse caso a linguagem de programação utilizada será Python. Podemos observar o resultado na figura 2.

# -*- coding: utf-8 -*- 

#Importar o módulo vtk
import vtk

#Criar a representação poligonal de um cubo de 10x10x10
cube = vtk.vtkCubeSource()
cube.SetXLength(10)
cube.SetYLength(10)
cube.SetZLength(10)

#Mapear o dado poligonal para primitivas gráficas
cube_mapper = vtk.vtkPolyDataMapper()
cube_mapper.SetInputConnection(cube.GetOutputPort())

#Representar o objeto em uma cena
cube_actor = vtk.vtkActor()
cube_actor.SetMapper(cube_mapper)
cube_actor.SetPosition(0.0,0,0)
cube_actor.GetProperty().SetColor(0,0,1)

#Adicionar objetos e definir a cor
#de fundo da cena no renderizador.
ren = vtk.vtkRenderer()
ren.AddActor(cube_actor)
ren.SetBackground(.8, .8, .8)

#Adicionar o renderizador na interface gráfica 
#do utilizador (GUI)
ren_win = vtk.vtkRenderWindow()
ren_win.AddRenderer(ren)
ren_win.SetSize(600,600)

#Adicionar recursos de interação na GUI
interactor = vtk.vtkRenderWindowInteractor()
interactor.SetRenderWindow(ren_win)

#Atualizar toda a cena
interactor.Render()

#Manter a janela (GUI) em um loop
interactor.Start()

Figura 2: Cubo renderizado com VTK


3 comentários:

Postar um comentário