Nota de tradução: Este exemplo é muito antigo e não compila nas máquinas atuais. Até o momento de digitação destas linhas de tradução ele não tinha sido atualizado permanecendo portanto inoperante.
Essa seção fornece uma nova versão do módulo acima — uma versão que inclue uma interface de usuário para controlar a velocidade da oscilação. Usamos a biblioteca FORMS criada por Mark Overmars para o painel de controle. A biblioteca FORMS é uma coleção de ferramentas para interface de usuário de domínio público para IRISes.
Para experimentar esse exemplo, faça uma cópia do arquivo example2.c (distribuído com Geomview no subdiretório doc) no seu diretório e compile-o com o comando
cc -I/u/gcg/ngrap/include -o example2 example2.c \ -L/u/gcg/ngrap/lib/sgi -lforms -lfm_s -lgl_s -lm
Você pode
substituir a sequência de caracteres /u/gcg/ngrap acima com o nome do caminho do
diretório de distribuição do Geomview em seu sistema. (A biblioteca forms é
distribuída com Geomview e as opções -I
e -L
acima
dizem ao compilador onde encontrá-las.)
Então coloque a linha
(emodule-define "Example 2" "./example2")
em um arquivo chamado .geomview no diretório e chame Geomview do mesmo diretório. Clique sobre a entrada "Example 2" no navegador de módulos (Modules) para chamar o módulo. Um pequeno painel de controle deverá aparecer. Você pode então controlar a velocidade da oscilação da malha movendo o botão deslizante.
/* * example2.c: oscillating mesh with FORMS control panel * * This example module is distributed with the Geomview manual. * If you are not reading this in the manual, see the "External * Modules" chapter of the manual for an explanation. * * This module creates an oscillating mesh and has a FORMS control * panel that lets you change the speed of the oscillation with a * slider. */ #include <math.h> #include <stdio.h> #include <sys/time.h> /* for struct timeval below */ #include "forms.h" /* for FORMS library */ FL_FORM *OurForm; FL_OBJECT *VelocitySlider; float dt; /* F is the function that we plot */ float F(x,y,t) float x,y,t; { float r = sqrt(x*x+y*y); return(sin(r + t)*sqrt(r)); } /* SetVelocity is the slider callback procedure; FORMS calls this * when the user moves the slider bar. */ void SetVelocity(FL_OBJECT *obj, long val) { dt = fl_get_slider_value(VelocitySlider); } /* Quit is the "Quit" botão callback procedure; FORMS calls this * when the user cliques the "Quit" botão. */ void Quit(FL_OBJECT *obj, long val) { exit(0); } /* create_form_OurForm() creates the FORMS panel by calling a bunch of * procedures in the FORMS library. This code was generated * automatically by the FORMS designer program; normally this code * would be in a separate file which you would not edit by hand. For * simplicity of this example, however, we include this code here. */ create_form_OurForm() { FL_OBJECT *obj; FL_FORM *form; OurForm = form = fl_bgn_form(FL_NO_BOX,380.0,120.0); obj = fl_add_box(FL_UP_BOX,0.0,0.0,380.0,120.0,""); VelocitySlider = obj = fl_add_valslider(FL_HOR_SLIDER,20.0,30.0, 340.0,40.0,"Velocity"); fl_set_object_lsize(obj,FL_LARGE_FONT); fl_set_object_align(obj,FL_ALIGN_TOP); fl_set_call_back(obj,SetVelocity,0); obj = fl_add_button(FL_NORMAL_BUTTON,290.0,75.0,70.0,35.0,"Quit"); fl_set_object_lsize(obj,FL_LARGE_FONT); fl_set_call_back(obj,Quit,0); fl_end_form(); } main(argc, argv) char **argv; { int xdim, ydim; float xmin, xmax, ymin, ymax, dx, dy, t; int fdmask; static struct timeval timeout = {0, 200000}; xmin = ymin = -5; /* Set x and y */ xmax = ymax = 5; /* plot ranges */ xdim = ydim = 24; /* Set x and y resolution */ dt = 0.1; /* Time increment is 0.1 */ /* Forms panel setup. */ foreground(); create_form_OurForm(); fl_set_slider_bounds(VelocitySlider, 0.0, 1.0); fl_set_slider_value(VelocitySlider, dt); fl_show_form(OurForm, FL_PLACE_SIZE, TRUE, "Example 2"); /* Geomview setup. */ printf("(geometry example { : foo })\n"); fflush(stdout); /* Loop until killed. */ for (t=0; ; t+=dt) { fdmask = (1 << fileno(stdin)) | (1 << qgetfd()); select(qgetfd()+1, &fdmask, NULL, NULL, &timeout); fl_check_forms(); UpdateMesh(xmin, xmax, ymin, ymax, xdim, ydim, t); } } /* UpdateMesh sends one mesh iteration to Geomview */ UpdateMesh(xmin, xmax, ymin, ymax, xdim, ydim, t) float xmin, xmax, ymin, ymax, t; int xdim, ydim; { int i,j; float x,y, dx,dy; dx = (xmax-xmin)/(xdim-1); dy = (ymax-ymin)/(ydim-1); printf("(read geometry { define foo \n"); printf("MESH\n"); printf("%1d %1d\n", xdim, ydim); for (j=0, y = ymin; j<ydim; ++j, y += dy) { for (i=0, x = xmin; i<xdim; ++i, x += dx) { printf("%f %f %f\t", x, y, F(x,y,t)); } printf("\n"); } printf("})\n"); fflush(stdout); }
O Código inicia-se pela inclusão de alguns arquivos de cabeçalho necassários para o evento cíclico
e para a biblioteca FORMS. O código então declara variáveis globais para manter um
ponteiro para o objeto FORMS do tipo botão deslizante e a velocidade dt
. Essas duas variáveis
são do tipo global porque elas são necessárias no procedimento de retorno do botão deslizante
chamado SetVelocity
, que faz todas as chamadas a cada vez que o usuário move a
barra do botão deslizante. SetVelocity
atualiza o valor da variável dt
com o novo valor do
botão deslizante.
Quit
é o procedimento de chamada de retorno para o botão Quit;
esse botão fornece um caminho elegante para o usuário encerrar o programa.
O procedimento create_panel
chama um conjunto de procedimentos da biblioteca
FORMS para ajustar o painel de controle com o botão deslizante e o botão simples. Para mais
informação sobre o uso de FORMS para criar painéis de interface veja a documentação de
FORMS. Em particular, FORMS vem com um desenhista de painel gráfico
que conduz você a desenhar seus painéis de forma interativa e a gerar
códigos como o código em create_panel
.
Esse programa principal exemplo é similar ao exemplo anterior, mas inclui codificação extra para lidar com ajustes e gerenciamento o painel FORMS.
Para ajustar o painel chamamos o procedimento GL foreground
para fazer com que
o processo execute em primeiro plano. Por padrão programas GL executam em
segundo plano, e por várias razões módulos externos que usam FORMS
(que é baseado em GL) precisa executar em primeiro plano. Chamamos então
create_panel
para criar o painel e fl_set_slider_value
para ajustar o valor inicial do botão deslizante. A chamada a fl_show_form
faz com que o painel apareça na tela.
As primeiras três linhas do ciclo principal, iniciam-se com
fdmask = (1 << fileno(stdin)) | (1 << qgetfd());
monitora e conduz os eventos no painel. A chamada a select
impõe uma espera a cada passagem pelo ciclo principal. Essa chamada retorna
ou após uma espera de 1/5 de segundo ou quando o evento GL seguinte ocorrer, ou
quando dados aparecerem na entrada padrão, o que acontecer primeiro. A
variável timeout
especifica a quantidade de tempo a esperar nessa
chamada; o primeiro número (0 nesse exemplo) fornece o número de segundos,
e o segundo número (200000 nesse exemplo) fornece o número de
microsegundos. Finalmente, fl_check_forms()
procura e executa
quaisquer eventos FORMS que tenham ocorridos; nesse caso isso significa uma chamada a
SetVelocity
se o usuário iver movido o botão deslizante ou uma chamada a
Quit
se o usuário tiver clicado no botão Quit.
O propósito da espera no ciclo é para prevenir que o programa use excessivamente o tempo da CPU executando seu ciclo pincipal quando não hoverem eventos a serem processados. Isso não é tão crucial nesse exemplo, e de fato pode tornar a animação mais lenta até certo ponto, mas em geral com módulos extrnos que possuirem eventos cíclicos essa espera é importante para do something like this because otherwise the module will needlessly take que os ciplos da CPU sigam adiante para outros programamas que estejam sendo executados (tais como Geomview!) mesmo quando estes não estiverem fazendo nada.
A última linha do ciclo principal ensse exemplo, a chamada a
UpdateMesh
, é a mesma que no exemplo anterior.