Esse mundo virtual foi modelado em VRML, sendo necessário a inserção de
scripts, desenvolvidos na linguagem JavaScript que permite realizar tarefas complexas
com mais facilidade através do uso de funções matemáticas predefinidas.
No mundo virtual encontra-se o objeto chave que é utilizado para abrir ou fechar o circuito. Este objeto possui um sensor, chamado TouchSensor que permite ao usuário clicar com o mouse na chave (Figura 5.1), fazendo com que ela seja aberta ou fechada dependendo do estado em que ela se encontra. Por exemplo, se o usuário clicar na chave
e ela estiver aberta, ela fechará.
Figura 5.1: Chave Fechada
A seguir, apresenta-se um trecho do código VRML, utilizado no desenvolvimento da chave, através de Proto.
#criação de um PROTO, cujo nome é chaveProto PROTO chaveProto [
#aqui é definido a interface da chaveProto, ou seja, #o que será visível para outros nodos que utilizarão #este PROTO
eventOut SFBool resultadoChave ] {
#criação do Transform, cujo nome é chave. Sempre que se desejar #mudar o objeto, fazer alguma transformação nele. Isso será #feito através do Transform
DEF chave Transform { children [
#início do bloco onde são declaradas as variáveis que #serão usadas nas funções script.
DEF ChaveScript Script {
eventOut SFBool bln IS resultadoChave eventOut SFTime ligado
eventOut SFTime desligado eventIn SFTime inicio field SFBool estado FALSE
#início do bloco onde as funções script são #implementadas
#quando utilizadas com o VRML,
#as funções JavaScript recebem dois argumentos. #O primeiro é o valor que recebe o eventIn, o #segundo é um valor que contém o tempo em #que a função foi chamada, esse tempo é #um valor absoluto
function Comutar(value, time) {
#variável booleana que, a cada vez que é chamada, #comuta de estado (verdadeiro para falso e
#vice-versa) estado = !estado;
#bln recebe o valor de estado. Como bln está #conectada ao eventOut resultadoChave. Se bln #mudar, resultadoChave também muda
bln = estado;
#se estado for verdadeiro então a variável
#ligado vai receber o tempo absoluto que a função #Comutar foi chamada. Caso contrário,
#desligado vai receber if (estado) { ligado = time; } else { desligado = time; } }
#a função inicio chama a função comutar com os #mesmos argumentos que ela recebe
function inicio(value, time) { Comutar(value, time); }"
}
# Código para a modelagem da chave #trecho de código que contém a criação #dos sensores
DEF MovChave Transform { children [
#sensor que possibilica o clique na chave DEF SensorMovChave TouchSensor {
Group {
children [
DEF DescerChave Group {
children DEF TSDescChav TimeSensor { cycleInterval 0.25
} }
DEF OrDescChav OrientationInterpolator { key [1.0] keyValue [ 0.0 0.0 1.0 0.79 ] } ] } Group { children [
DEF SubirChave Group {
children DEF TSSubChav TimeSensor { cycleInterval 0.25
} }
DEF OrSubChav OrientationInterpolator { key [1.0] keyValue [ 0.3 1.55 0.0 0.0 ] } ] } ] } ] }
#linha que servirá de gatilho, chamando a função inicio ROUTE SensorMovChave.touchTime TO ChaveScript.inicio
#quando a variável desligado for alterada, ela passará #seu valor (tempo) para o TimeSensor TSDescChav que #se iniciará
#assim que o TSDescChav se iniciar, o fraction_changed #ficará gerando novas frações de tempo. A cada fração #de tempo gerada, o valor é passado para
#OrSubChav.set_fraction que gera novos valores #para rotação
ROUTE TSDescChav.fraction_changed TO OrSubChav.set_fraction #os novos valores para rotação são passados para
#MovChave.set_rotation através do eventOut #OrSubChav.value_changed
ROUTE OrSubChav.value_changed TO MovChave.set_rotation #quando a variável ligado for alterada, ela passará #seu valor (tempo) para o TimeSensor TSSubChav que #se iniciará
ROUTE ChaveScript.ligado TO TSSubChav.set_startTime }
Para verificar se a chave está aberta ou fechada, utiliza-se o eventOut resultadoChave que devolve valores booleanos. Sendo True se a chave estiver aberta, e False se a chave estiver fechada. Este evento é importante, pois é sempre chamado antes do circuito ser analisado.
No multímetro, quando o usuário seleciona um instrumento de medição (amperímetro, voltímetro ou ohmímetro), o botão referente ao instrumento acenderá para que o usuário saiba qual o equipamento está habilitado. A seguir, apresenta-se o script JavaScript que controla o acender do botão.
#função que recebe como argumento um valor booleano #é chamada quando o usuário clica no amperímetro, #voltímetro ou ohmímetro
function set_booleanLuz(bool) {
#se bool for verdadeiro, vai entrar no if if (bool) {
#se o usuário clicar no botão que corresponde #ao amperímetro, então AmpSensor.isActive #será Verdadeiro, entrando no if
if (AmpSensor.isActive) {
#acendendo a luz do botão que corresponde ao #amperímetro
valorAmp = !valorAmp; luzAmp.on = valorAmp;
#função chamada para atualizar a posição dos fios #de medição
atualizarFiosAmp();
#apagando a luz do botão que corresponde ao #ohmímetro
valorOhm = false; luzOhm.on = valorOhm;
#apagando a luz do botão que corresponde ao #voltímetro
valorVolt = false; luzVolt.on = valorVolt;
#saindo da função set_booleanLuz return;
if (OhmSensor.isActive) { valorOhm = !valorOhm; luzOhm.on = valorOhm; atualizarFiosVoltOhm(); valorAmp = false; luzAmp.on = valorAmp; valorVolt = false; luzVolt.on = valorVolt; return; } if (VoltSensor.isActive) { valorVolt = !valorVolt; luzVolt.on = valorVolt; atualizarFiosVoltOhm(); valorOhm = false; luzOhm.on = valorOhm; valorAmp = false; luzAmp.on = valorAmp; return; } } }
Veja que, dentro da função set_booleanLuz, estão sendo chamadas outras funções: atualizarFiosAmp e atualizarFiosVoltOhm. A primeira posiciona os fios quando se está medindo a intensidade. A segunda posiciona os fios quando se está medindo a tensão ou a resistência. Importante salientar que existem duas funções diferentes, pois o amperímetro deve ser inserido em série no circuito, e o voltímetro/ohmímetro devem ser inseridos em paralelo.
Para auxiliar o usuário na montagem do circuito, algumas “dicas” são mostradas em um quadro branco que aparece quando o usuário passa o mouse sobre o botão “?” que está no painel de controle. Este botão é mostrado na Figura 5.2. Se o usuário tirar o mouse
do botão, ele desaparece. Isso acontece, pois esse é um botão exploratório, e o usuário somente deve buscá-lo em casos de dúvida. A seguir, apresenta-se a implementação VRML para o quadro.
Figura 5.2: Botão Exploratório #inicio do bloco que contém o código onde o #quadro onde as mensagens de ajuda são mostradas DEF quadro Switch {
#como o quadro só é mostrado quando o usuário
#passa o \emph{mouse} sobre ele usou-se o whichChoice = -1 #isto quer dizer que inicialmente ele não é
#mostrado. só é mostrado se o whichChoice for zero whichChoice -1 choice [ Transform { translation -2.8 -1.8 -6.8 scale 0.045 0.045 0.045 children [ #fundo branco# Transform { translation -25.0, 25.0, 0.0 scale 20.0 20.0 1.0 children [ Shape { appearance Appearance { material Material { diffuseColor 1.0 1.0 1.0 } } geometry IndexedFaceSet { solid FALSE coord Coordinate {
point [ -1.0 1.0 0.0, 1.0 1.0 0.0, 1.0 -1.0 0.0, -1.0 -1.0 0.0 ] } coordIndex [ 0, 1, 2, 3, 0 ] } } ] }, #texto basico# Transform { translation -40.0 40.0 0.1 scale 4.0 4.0 1.0 children [ Shape { appearance Appearance { material Material { diffuseColor 0.0 0.0 0.0 } }
geometry DEF msg_ajuda Text {
#campo que conterá os textos que #serão mostrados para o usuário string [""]
#formatação da fonte do texto fontStyle FontStyle { style "BOLD" size 1.5 justify "LEFT" } } } ] } ] } ] }
Para controlar o aparecimento/desaparecimento do quadro, usa-se o código JavaScript mostrado a seguir.
recebe um valor booleano. quando o usuário #passa o \emph{mouse} sobre a ajuda, esta função recebe #verdadeiro. Caso contrário, falso function set_boolean1(s){
if(s){
#este comando que faz o quadro de ajuda aparecer quadro.whichChoice = 0;
}else{
#este comando faz o quadro de ajuda desaparecer quadro.whichChoice = -1;
} }
As mensagens do quadro são atualizadas a cada ação do usuário. Para controlar as trocas de mensagens, o conteúdo do quadro deve ser apagado antes que ele receba uma nova mensagem. A função usada para apagar o conteúdo do quadro é mostrada a seguir.
function LimpaAjuda() { for (i=0; i<=9; i++) {
#limpando o vetor que contém o texto de #ajuda ao usuário
msg_ajuda.string[i] = ´; }
}