Essa seção fornece um módulo externo extremamente simples que mostra uma malha oscilando. Para experimentar esse exemplo, faça uma cópia do arquivo example1.c (esse arquivo é distribuído com Geomview no subdiretio doc) em seu diretório e compile example1.c com o comando
cc -o example1 example1.c -lm
A seguir coloque a linha
(emodule-define "Example 1" "./example1")
em um arquivo chamado .geomview no seu diretório atual. A seguir chame o Geomview; É importante que você compile o programa exemplo, crie o arquivo .geomview e chame o Geomview a partir do mesmo diretório. Você pode ver "Example 1" no navegador de módulos (Modules) do painel principal (Main) do Geomview; clique sobre essa entrada no navegador para iniciar o módulo. Uma superfície deve aparecer na sua janela de câmera e deve estar oscilando. Você pode parar o módulo clicando sobre a linha "[1] Example 1" no navegador de módulos (Modules).
/* * example1.c: oscillating mesh * * 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 more details. * * This module creates an oscillating mesh. */ #include <math.h> #include <stdio.h> /* 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)); } main(argc, argv) char **argv; { int xdim, ydim; float xmin, xmax, ymin, ymax, dx, dy, t, dt; 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 */ /* Geomview setup. We begin by sending the command * (geometry example { : foo}) * to Geomview. This tells Geomview to create a geom called * "example" which is an instance of the handle "foo". */ printf("(geometry example { : foo })\n"); fflush(stdout); /* Loop until killed. */ for (t=0; ; t+=dt) { UpdateMesh(xmin, xmax, ymin, ymax, xdim, ydim, t); } } /* UpdateMesh sends one mesh iteration to Geomview. This consists of * a command of the form * (read geometry { define foo * MESH * ... * }) * where ... is the actual data of the mesh. This command tells * Geomview to make the value of the handle "foo" be the specified * mesh. */ 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 módulo inicia-se definindo uma função F(x,y,t)
que
especifica uma superfície va-riando com o tempo. O propósito do módulo é
animar essa superfície com o passar do tempo.
O programa principal começa definindo algumas variáveis que especificam os parâmetros com os quais a função é para ser mostrada.
O próximo pedaço de código no programa principal envia a seguinte linha para a saída padrão
(geometry example { : foo })
Isso diz ao Geomview para criar um geom chamado example
que é uma
instância do manipulador foo
. Manipuladores são uma parte do
formato de arquivo OOGL que permite a você nomear uma peça do objeto geométrico cujo valor
pode ser especificado em seu lugar (e nesse caso atualizado muitas vezes); para
maiores informações sobre manipuladores, veja Formatos dos Arquivos da OOGL. Nesse caso,
example
é o título através do qual o usuário irá ver o objeto no
navegador de objeto do Geomview, e foo
é o nome interno do
manipulador para o qual o objeto aponta.
Nós então fazemos fflush(stdout)
para garantir que Geomview
receba esse comando imediatamente. Em geral, uma vez que pipes podem ser
colocados em uma área de memória temporária de armazenamento, um módulo externo deve fazer isso sempre que esse módulo externo tenha que
garantir que Geomview tenha atualmente recebido tudo que tenha sido mostrado na saída.
A última coisa no programa principal é um ciclo infinito que circula
através de chamadas ao procedimento UpdateMesh
com incremento dos
valores de t
. UpdateMesh
envia ao Geomview um comando
da forma
(read geometry { define foo MESH 24 24 ... })
onde ...
é uma longa lista de números. Esse comando diz ao Geomview
fazer os valores do manipulador foo
ser a malha especificada. Tão
breve quanto Geomview receba esse comando, o geom sendo mostrado
muda para refletir o novo objeto geométrico.
A malha é fornecida no formato de uma OOGL MESH. Esse formato começa com
a palavra chave MESH
. A seguir temos dois números que fornecem as dimensões
x e y da malha; nesse caso elas são ambas 24. Essa linha é
seguida por 24 linhas, cada linha contendo 24 trios de números. Cada um
desses trios representa um ponto sobre superfície. Então finalmente existe uma linha
com "})
" nesse formato que termina o "{
" que iniciou a
declaração define
e o "(
" que iniciou o comando. Para
mais detalhes sobre o formato de dados MESH, veja MESH.
Esse módulo pode ser escrito sem o uso de manipuladores escrevendo comandos da forma
(geometry example { MESH 24 24 ... })
Nesse primeiro tempo Geomview recebe um comando e dessa forma pode criar
um geom chamado example
com os dados fornecidos da MESH
.
Subsequentemente comandos (geometry example ...)
podem fazer com que
Geomview substitua a geometria do geom example
com os novos
dados da MESH
. Se realizado dessa forma pode não ser necessário enviar
o comando inicial (geometry example { : foo })
como dito acima. A
técnica do manipulador é útil, todavia, porque essa técnica pode ser usada em situações
mais gerais onde um manipulador representa somente parte de um complexo
geom, permitindo a um módulo externo substituir somente aquela parte sem
ter que retransmitir o geom completo. Para mais informações sobre manipuladores,
veja GCL. Veja Referencias. Veja (hdefine ...)
. Veja (read ...)
.
O módulo entra em ciclos através de chamadas a UpdateMesh
que fornece como saída
comandos da forma acima um após o outro tão rápido quanto possível.
O ciclo continua indefinidamente; o módulo irá terminar quando o
usuário fizer isso clicando sobre sua linha de instância no navegador de
módulos (Modules), ou em caso contrário quando Geomview for encerrado.
Algumas vezes quando você encerra o módulo clicando sobre sua entrada de instância no navegador de módulos (Modules), Geomview irá encerrá-lo enquanto o módulo está no meio de um comando ao Geomview. Geomview irá então receber somente uma peça de um comando e irá mostrar uma crítica mas inofensiva mensagem de erro sobre isso. uando um módulo tiver um painel de interface com o usuário o usuário pode usar um botão "Quit" para fornecer uma forma mais elegante para o usuário encerrar o módulo. Veja o exemplo seguinte.
Você pode usar esse módulo em uma janela de shell sem o Geomview para ver os comando que o módulo mostra como saída. Você irá ter que encerrá-lo com ctrl-C para que ele pare.