PLplot 02: O primeiro gráfico
A criação de gráficos utilizando a PLplot é bastante simples na maior parte do tempo. O conjunto de funções da biblioteca pode, a grosso modo, ser visto como dois conjuntos separados. Um conjunto de funções que definem as propriedades do gráfico — cor de fundo, tipo de linha, uso ou não de grades, escala, etc — e um conjunto de funções responsáveis pela plotagem do gráfico em si. Neste artigo, criaremos um gráfico básico com a PLplot.
Seja então f(x) a função que queremos plotar. Consideremos, a título de exemplo, f(x) como sendo definida por
O programa abaixo é uma implementação para que possamos gerar o gráfico dessa função. Praticamente nenhuma personalização é feita, deixando que a biblioteca utilize os parâmetros default para a maior parte das opções disponíveis.
O download do código-fonte pode ser feito aqui.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 |
/* exemplo01.c: * Exemplo básico de uso da biblioteca PLPlot. * Este programa simplesmente plota na tela o gráfico da função * * f(x) = x/(1 + x^2) * * praticamente nenhuma personalização é feita, deixando que a biblioteca * utilize os parâmetros default. */ #include <plplot.h> /* Número de pontos em que iremos calcular o valor de f(x) dentro do intervalo * definido abaixo. Vamos utilizar um ponto adicional para ligar o último ponto * calculado com outro calculado quando x = XMAX (definido abaixo). O número de * pontos, ou melhor, o intervalo de amostragem que será utilizado dependerá de * cada função. Fique esperto. */ #define NUMPONTOS 200 /* O intervalo em que a função será exibida. Isto quer dizer que teremos um * ponto a cada intervalo dt, tal que dt = (XMAX - XMIN)/NUMPONTOS. Os limites * para o eixo Y também estão definidos. */ #define XMIN -10 #define XMAX 10 #define YMIN -1.0 #define YMAX 1.0 /* A função função f(x). O tipo de dado PLFLT é, por padrão, uma variável do * tipo float. Isso pode ser modificado definido uma variável de nome PL_DOUBLE * ou somente DOUBLE utilizando a diretiva define do pré-processador. Isso deve * ser feito antes de incluir a biblioteca no programa. No nosso caso, está * perfeito do jeito que está, não precisamos alterar isso. * A função abaixo recebe um valor x do tipo PLFLT como argumento e retorna o * valor da função, tal como definimos na descrição desse programa. Esse * procedimento é necessário porque a biblioteca não recebe uma função * matemática como parâmetro e a plota, mas um conjunto de pontos que serão * conectados entre si de alguma forma */ PLFLT f(PLFLT x) { return x/(1 + x*x); } int main (int argc, const char *argv[]) { PLFLT x[NUMPONTOS + 1]; /* Vetor com os pontos do eixo x */ PLFLT y[NUMPONTOS + 1]; /* Vetor com os pontos do eixo y */ PLFLT dt; /* Intervalo de amostragem */ PLINT i; /* Calcula o valor de f(x) em NUMPONTOS, com um intervalo de espaçamento dt * e guardando esses valores nos vetores x e y para que possamos utilizá-los * mais à frente */ dt = (PLFLT)(XMAX - XMIN)/NUMPONTOS; for (i = 0; i < NUMPONTOS; i++) { x[i] = XMIN + (PLFLT)i*dt; y[i] = f(x[i]); } x[NUMPONTOS] = XMAX; y[NUMPONTOS] = f(XMAX); /* Inicializa PLplot. Essa função irá perguntar qual o dispositivo que * você quer utilizar para plotar o gráfico. Se você deixar o campo em * branco, a biblioteca irá selecionar o primeiro dispositivo na lista * exibida */ plinit (); /* Definindo limites do gráfico. A função plenv é responsável por criar a * janela de exibição e desenhar uma caixa dentro dela, representando os * eixos do nosso gráfico. Os limites do eixo x são definidos através de * XMIN e XMAX. Os limites do eixo Y por YMIN e YMAX. O penúltimo diz * respeito a escala do gráfico. O último parâmetro está associado as * propriedades dos eixos e a caixa ao redor do gráfico. Iremos utilizar * aqui o valor 1 para o penúltimo parâmetro, indicando que queremos que as * escalas dos eixos x e y sejam as mesmas. Para o último, utilizamos o * valor -1, indicando para o programa que desenhe apenas uma caixa ao redor * do gráfico. Para maiores informações a respeito de valores que podem ser * utilizados e o que cada um significa, leia a documentação da biblioteca * presente no site oficial da mesma */ plenv (XMIN, XMAX, YMIN, YMAX, 0, -1); /* Inserindo rótulos no gráfico. A função pllab permite a definição de * rótulos no nosso gráfico. O primeiro argumento é rótulo do eixo x, o * segundo é o rótulo do eixo y com algumas sequências de escape para * podermos obter um sobrescrito como potência. O último é o título do * gráfico. Dependendo do driver utilizado, pode não ser uma boa ideia o uso * de acentos nas strings */ pllab ("x", "x/(1 + x#u2#d)", "Olá mundo dos gráficos!"); /* Plotando o gráfico. A função plline recebe três argumentos: o primeiro * é o número de pontos que queremos plotar. O segundo é um vetor com as * coordenadas do eixo x. O terceiro é um vetor com as coordenadas do eixo * y. Essa função simplesmente desenha uma linha reta entre pontos * consecutivos, assim como a maior parte dos softwares que plotam funções * e exibem o resultado na tela. É ela a responsável por realmente desenhar * o nosso gráfico */ plline (NUMPONTOS + 1, x, y); /* Pronto, terminamos! A função plend é responsável por encerrar a PLplot, * fazendo todos os ajustes necessários para que tudo ocorra como esperado e * você tenha o seu gráfico ao final */ plend (); return 0; } |
Simples e rápido, não? Antes de compilarmos esse código, vamos dar uma olhada melhor nele. Note que qualquer programa que queira utilizar essa biblioteca deve adicionar o arquivo de cabeçalho plplot.h. É onde estão definidas todas as funções do quais iremos precisar para gerar os nossos gráficos.
Como foi dito no código, a PLplot não é capaz de receber uma expressão matemática como parâmetro e gerar um gráfico a partir disso, mas nada impede que você implemente uma função capaz de fazê-lo. Nesse caso, a biblioteca libmatheval seria de grande utilidade. Em artigos futuros, tentaremos implementar esse recurso.
Vamos compilar esse código e ver o que obtemos. Abra um terminal, navegue até o diretório onde colocou o programa e compile-o com o comando
|
1 |
$ gcc exemplo01.c `pkg-config --libs --cflags plplotd` -o exemplo01 |
Isso deverá gerar um executável de nome exemplo01 em seu diretório de trabalho. Vamos executá-lo:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
$ ./exemplo01 Plotting Options: < 1> xwin X-Window (Xlib) < 2> tk Tcl/TK Window < 3> ps PostScript File (monochrome) < 4> psc PostScript File (color) < 5> xfig Fig file < 6> null Null device < 7> tkwin New tk driver < 8> mem User-supplied memory device < 9> wxwidgets wxWidgets Driver <10> svg Scalable Vector Graphics (SVG 1.1) <11> bmpqt Qt Windows bitmap driver <12> jpgqt Qt jpg driver <13> pngqt Qt png driver <14> ppmqt Qt ppm driver <15> tiffqt Qt tiff driver <16> svgqt Qt SVG driver <17> qtwidget Qt Widget <18> epsqt Qt EPS driver <19> pdfqt Qt PDF driver <20> extqt External Qt driver <21> memqt Memory Qt driver <22> xcairo Cairo X Windows Driver <23> pdfcairo Cairo PDF Driver <24> pscairo Cairo PS Driver <25> svgcairo Cairo SVG Driver <26> pngcairo Cairo PNG Driver <27> memcairo Cairo Memory Driver <28> extcairo Cairo External Context Driver Enter device number or keyword: |
Opa, mas o que diabos… Ah sim, o driver! Quando você executa o programa, a função plinit é chamada (linha 63). Ela verifica se um driver foi definido e em caso negativo, exibe a lista acima perguntando ao usuário qual utilizar. Note que temos várias opções. Se a opção escolhida for salvar o arquivo no disco, na forma de uma imagem (drivers ps, png, svg, pdfcairo, svgcairo, etc), o programa irá perguntar o nome da imagem que deverá ser utilizado e então salvar o arquivo nela. Mas vamos escolher a opção xcairo, número 22 na lista acima. Digite isso e dê um ENTER para visualizar o gráfico na tela:
Perfeito! Mas cadê as marcas nos eixos? Lembra que na linha 77, utilizamos a função plenv, onde o último parâmetro estava associado as propriedades dos eixos, bem como o desenho de uma caixa ao redor do gráfico? Pois é, fica como tarefa pra você: Leia a documentação dessa função no site oficial e veja quais são as outras opções possíveis. Modifique-as e recompile o seu programa para ver qual é o resultado. Teste também os diferentes drivers que podem ser utilizados e verifique quais são as diferenças entre eles.
No próximo artigo, iremos definir algumas propriedades do nosso gráfico como a cor de fundo, cor da linha utilizada para o gráfico, espessura, etc. Isso fará com que tenhamos algo mais personalizado.
Última atualização: 17/12/2012


