domingo, 14 de agosto de 2011

Espiral de Arquimedes

  Depois de ver a Espiral de Arquimedes , quis entender a matemática que gera a figura. Até chegar no resultado, usei C++, Shell Script e gnuplot.
  Uma vez lido sobre o assunto no link, é preciso entender como converter de coordenadas cartesianas para polares. O assunto foi estendido para realizar uma figura 3D.
  A parte que utiliza C++ é composta de três arquivos: uma classe, a definição da classe e o programa-cliente (main).

A classe


  Apenas uma função que não retorna nada (void) com o nome de Polar e não recebe nenhum parâmetro.

cat espiral.h

#ifndef ESPIRAL_H
#define ESPIRAL_H

class espiral {
public:
  void Polar();
private:

};
#endif /* ESPIRAL_H */

Definição da classe


  Os includes chamam a biblioteca matemática cmath , iostream para imprimir e mudar de linha (cout e endl) e a biblioteca criada espiral.h .
  void espiral::Polar(). É necessário a palavra espiral e duas vezes :: para que o compilador saiba em qual classe foi feita sua declaração.
  Na função há a declaração da constante pi e algumas variáveis. O laço for gera a quantidade de pontos desejada e foi decidido 10 voltas (3600 pontos). Traduzindo o que x e y armazenam, é


x = raio * cos θ
y = raio * sen θ


  É preciso converter de radianos para graus!
  A variável z é incrementada de 0.001 em 0.001.
  O cout << gera a saída para as variáveis.

cat espiral.cpp

#include< cmath >
#include< iostream >
using std::cout;
using std::endl;
#include "espiral.h"

int espiral::Polar()
{
  const double pi=3.141592;
  const int pontos=3600;
  double x[pontos],y[pontos];
  double z, r=1;

  z=0;
  for (int teta=0; teta < pontos; teta++)
  {
    x[teta]=static_cast(r*cos(teta*pi/180));
    y[teta]=static_cast(r*sin(teta*pi/180));
    z+=0.001;
    r+=.1;

    cout << x[teta] << " " << y[teta] << " " << z << endl;
  }

main


  O programa-cliente que ao ser executado é responsável por chamar os métodos em uma determinada ordem.
  espiral é a classe e myespiral é o objeto criado. O software só pode manipular o objeto e por isso cada classe tem seu objeto.
  Assim, o que é visto em seguida é o objeto myespiral chamando o método Polar.

cat main.cpp

#include <cstdlib>
#include "espiral.h"
using namespace std;
int main(int argc, char** argv) {
  espiral myespiral;
  myespiral.Polar();
  return 0;
}

  Agora que os arquivos estão prontos, uma instrução precisa ser passada ao compilador para saber como juntar os códigos-fontes e gerar o código-objeto (a linguagem de máquina). Assim:

$ g++ espiral.cpp main.cpp -o arquimedes.out -ansi

  Ao executar o binário, redirecione para um arquivo-texto:

$ ./arquimedes.out > plot.txt

  A participação do shell script foi a de apontar valores extremos dos eixos X e Y.

$ cat xy.sh

#!/bin/bash
menorX=`cat plot.txt | awk '{printf "%s\n",$1}' | sort -n | head -n 1`
maiorX=`cat plot.txt | awk '{printf "%s\n",$1}' | sort -nr | head -n 1`
menorY=`cat plot.txt | awk '{printf "%s\n",$2}' | sort -n | head -n 1`
maiorY=`cat plot.txt | awk '{printf "%s\n",$2}' | sort -nr | head -n 1`
echo ">X" $menorX
echo "<X" $maiorX
echo ">Y" $maiorY
echo "<Y" $menorY

  Executando o script xy.sh para a massa de dados plot.txt , o resultado foi:
>X -343.048
<X 361
>Y 334.049
<Y -352.046

  Este resultado servirá para entrar com os limites do gráfico (instruções xrange e yrange).
  Finalmente, para gerar a figura, chame o gnuplot:

  $ gnuplot
   G N U P L O T
   Version 4.4 patchlevel 0
   last modified March 2010
   System: Linux 2.6.35-30-generic
  
   Copyright (C) 1986-1993, 1998, 2004, 2007-2010
   Thomas Williams, Colin Kelley and many others
  
   gnuplot home:     http://www.gnuplot.info
   faq, bugs, etc:   type "help seeking-assistance"
   immediate help:   type "help"
   plot window:      hit 'h'
  
  Terminal type set to 'wxt'
  gnuplot> 

Entre com as seguintes instruções no prompt do gnuplot:
  gnuplot> set xrange[-400:400]
  gnuplot> set yrange[-400:400]
  gnuplot> set ticslevel 0
  gnuplot> splot "plot.txt" u 1:2:3 with lines

  Caso queira apenas um figura 2D, remova a variável z da linha cout << x[teta] << " " << y[teta] << " " << z << endl; para que imprima x e y. Os passos seguintes são os mesmo: direcionar a saída para plot.txt e com um comando no gnuplot, o gráfico é gerado:

gnuplot> plot [-400:400][-400:400] "plot.txt" with lines
  Os gráficos feitos pelo gnuplot permitem ser rotacionados. Use o ponteiro do mouse para visualizar milhares de ângulos!
  O resultado pode ser visto na figura abaixo.

Nenhum comentário:

Postar um comentário