Escolar Documentos
Profissional Documentos
Cultura Documentos
INTRODUÇÃO A ROBÓTICA
Historia da robótica
rob tica
O precursor do termo robô (Groover, 1988) foi Karel Capek, novelista e escritor
de uma peca teatral da Tchecoslovaquia, que usou pela primeira vez, em 1920,
a palavra “robota” (serviço compulsório, atividade forcada) originando a palavra
“robot” em inglês e traduzido para o português como “robô”. Diversos filmes de
ficção cientifica mostraram robôs produzidos com o comportamento e a forma
humana, levando muitos jovens a pesquisar e desenvolver robôs para o mundo
real. Com o surgimento dos computadores na metade do século, iniciaram-se
especulações em termos da capacidade de um robô pensar e agir como um ser
humano. No entanto, os robôs foram, neste período, criados especialmente
para executarem tarefas difíceis, perigosas e impossíveis para um ser humano.
Por outro lado, eles não eram projetados com a capacidade de criar ou
Executar processos que não lhes foram ensinados ou programados. Assim
sendo, foram às indústrias que mais se beneficiaram com o desenvolvimento
da robótica, aumentando a produção e eliminando tarefas perigosas, antes
executadas por seres humanos.
Na robótica moderna, ha pesquisas e desenvolvimentos de robôs intitulados
humanóides ou antropomórficos. Estes são criados com a semelhança humana
e com capacidade de interagir com o ambiente, como o A sim o construído pela
montadora japonesa Honda Motor Co. Citam-se ainda diversos brinquedos
articulados com feições que lembram animais de estimação como cães, por
exemplo, e que se destinam ao entretenimento. Contudo, tais robôs são
incapazes de realizar quaisquer tipos de tarefas, e apenas respondem a
estímulos externos. Estes equipamentos não fazem parte do propósito deste
documento, que visa exclusivamente estudar e compreender os robôs
industriais. Estes, por sua vez, caracterizam se por serem capazes de realizar
tarefas, podem ser programados, e possuem forca elevada.
Automação
Automa o
Automação e uma tecnologia que faz uso de sistemas mecânicos, elétricos,
eletrônicos e de computação para efetuar controle de processos produtivos.
Alguns exemplos de processos de automação nas indústrias são:
a) Automação
Automa o fixa
b) – Automação
Automa o flexível
flex vel
Nomenclatura
robô
braço mecânico
mecanismo robótico
manipulador
manipulador mecânico
manipulador robótico
Anatomia
Volume de trabalho
Sistemas de acionamentos
Sistema de controle
Desempenho e precisão
Órgãos terminais
Sensores
Programação
Anatomia dos braços
bra os mecânicos
mec nicos industriais
Juntas
A junta prismática
prism tica ou linear: Move em linha reta. São compostas de duas
hastes que deslizam entre si;
A junta rotacional: Gira em torno de uma linha imaginaria estacionaria
chamada de eixo de rotação. Ela gira como uma cadeira giratória e abrem e
fecham como uma dobradiça;
A junta esférica:
esf rica: Funciona com a combinação de três juntas de rotação,
realizando a rotação em torno de três eixos;
A junta
junta cilíndrica:
cil ndrica: E composta por duas juntas, uma rotacional e uma
prismática;
A junta planar: E composta por duas juntas prismáticas, realiza movimentos
em duas direções;
A junta parafuso: E constituída de um parafuso que contem uma porca ao
qual executa um movimento semelhante ao da junta prismática, porem, com
movimento no eixo central (movimento do parafuso).
Rotativa de torção
tor o ou torcional T: O elo de entrada e de saída tem a mesma
Direção do eixo de rotação da junta.
Rotativa rotacional R: Os elos de entrada e de saída são perpendiculares ao
eixo de rotação da junta.
Rotativa revolvente V: O elo de entrada possui a mesma direção do eixo de
rotação, mas o elo de saída e perpendicular a este.
Representação
Representa o esquemática
esquem tica de juntas
Roll ou rolamento
rolamento - rotação do punho em torno do braço
Pitch ou arfagem - rotação do punho para cima ou para baixo
Yaw ou guinada - rotação do punho para a esquerda e para a direita.
Cadeias cinemáticas
cinem ticas:
ticas:
Representação
Representa o esquemática
esquem tica de braço
bra o robótico
rob tico com cadeia cinemática
cinem tica
Parcialmente fechada.
Representação
Representa o esquemática
esquem tica de articulações
articula es não
n o motoras
Configuração
Configura o dos robôs
rob s
A configuração física dos robôs (Groover, 1988) esta relacionada com os tipos
de juntas que ele possui. Cada configuração pode ser representada por um
esquema de notação de letras, como visto anteriormente. Considera-se
Esquema de notação
nota o para designar configurações
configura es de robôs
rob s
Configura
Configuração rob – braço
igura o do robô bra o e corpo Símbolo
mbolo
Esquema de notação
nota o para designar configurações
configura es do pulso
Configuração rob – (pulso)
Configura o do robô Símbolo
mbolo
Configuração
Configura o de um punho TRT na forma compacta. Embora todas as
juntas sejam resolventes, este punho tem denominação
denomina o TRT.
Robô
Rob cartesiano
cartesiano
Robô
Rob cartesiano (LLL)
Robô
Rob cilíndrico
cil ndrico
Este braço possui na base uma junta prismática, sobre a qual apóia uma junta
rotativa (resolvente ou torcional). Uma terceira junta do tipo prismática e
conectada na junta rotativa formando uma configuração LVL. Este braço
apresenta um volume de trabalho cilíndrico, e pode-se apresentar também na
configuração TLL.
Braço
Bra o robótico
rob tico cilíndrico
cil ndrico
Robô
Rob esférico
esf rico ou polar
Este tipo de braço robótico foi projetado para suportar grandes cargas e ter
grande alcance. E bastante utilizado para carga e descarga de maquinas,
embora o braço revoluto seja mais comum nestas aplicações. Ele conta com
duas juntas rotativas seguidas de uma junta prismática. A primeira junta move o
braço ao redor de um eixo vertical, enquanto que a segunda junta gira o
conjunto ao redor de um eixo horizontal. O volume de trabalho e um setor
esférico, de onde este manipulador obteve seu nome. A denominação “polar”
deve-se as coordenadas polares de sistemas de eixos cartesianos,
caracterizadas por duas coordenadas angulares (juntas rotativas) e uma
coordenada radial (junta prismática). Este tipo de braço esta em desuso, sendo
substituídos pelos braços revolutos.
Robô
Rob polar em configuração
configura o VVL.
Robô
Rob SCARA
Este e também um braço bastante utilizado, pois e compacto, tem grande
precisão e repetibilidade, embora com um alcance limitado. Estas
características o tornam próprios para trabalhos em montagem mecânica ou
eletrônica que exigem alta precisão. Possui duas juntas rotativas e uma junta
linear, que atua sempre na vertical, como visto na Figura 3.16. O volume de
trabalho deste braço e cilíndrico, porem, como utiliza juntas rotativas, e também
considerado articulado. O nome e um acrônimo de Selective Compliance
Assembly Robot Arm, ou Braço Robótico de Montagem com Complacência
Seletiva.
Robô
Rob com articula
articulação
icula o horizontal SCARA.
Robô
Rob articulado ou revoluto
Estes tipos de robôs (Groover, 1988, Adade Filho, 1992), possuem 3 juntas
rotativas, conforme ilustrada a Figura 3.17. Eles são os mais usados nas
indústrias, por terem uma configuração semelhante ao do braço humano,
(braço, antebraço e pulso). O pulso e unido a extremidade do antebraço, o que
propicia junta adicional para orientação do órgão terminal. Este modelo de
configuração e o mais versátil dos manipuladores, pois assegura maiores
movimentos dentro de um espaço compacto.
Os braços
bra os revolutos podem ser de dois tipos:
Robô
Rob articulado ou revoluto
Robô
Rob paralelo
Estes tipos de manipuladores possuem juntas que transformam movimentos de
rotação em translação, ou usam diretamente juntas prismáticas. Sua principal
característica e um volume de trabalho reduzido, porem uma alta velocidade, o
que o torna propicio para certas atividades de montagem. Outra característica
destes braços e que eles não possuem cinemática com cadeia aberta, como a
maioria dos robôs industriais. Os quatro ou seis atuadores destes braços unem
a base diretamente ao punho.
Um robô
rob do tipo pórtico
p rtico (“
(“gantry”
gantry”), a esquerda, fabricado pela BMI, e um robô
rob
Cilíndrico
Cil ndrico feito pela ST
ST Robotics, a direita.
Órg
rgão
rg o terminal
Na robótica, órgão terminal (Groover, 1988) e usado para descrever a Mao ou
Ferramenta que esta conectada ao pulso, como por exemplo, uma pistola de
solda, garras, pulverizadores de tintas, entre outros. O órgão terminal e o
responsável por realizar a manipulação de objetos em diferentes tamanhos,
Sensores
Sensores são dispositivos cuja finalidade e obter informações sobre o ambiente
em que se encontram, e são utilizados como componentes do sistema de
controle de realimentação do robô. Ha diversos tipos de sensores que podem
ser classificados de acordo com os princípios físicos sobre os quais eles estão
baseados.
Sensor de posição
posi o
Sensor de toque
Sensor de pressão
press o
Sistemas de acionamento
Acionadores hidráulicos
hidr ulicos
Acionadores elétricos
el tricos
Geralmente robôs de tamanho pequeno a médio utilizam acionadores elétricos.
Os acionadores elétricos mais comuns em uso nos robôs são: motor de
corrente continua ou DC, servo-motor e motor de passo. Esses tipos de
acionadores não propiciam muita velocidade ou potencia, quando comparados
com acionadores hidráulicos, porem atingem maior precisão. Em geral são
dotados de redutores para reduzir a velocidade e aumentar o torque.
Acionamentos elétricos podem ser utilizados em juntas prismáticas, com a
transformação do movimento rotativo do motor em movimento linear por meio
de um fuso. Motores elétricos lineares não são utilizados, pois produzem forcas
de pequena intensidade. O custo do acionamento elétrico cresce com o torque
necessário para acionar o braço mecânico, já o tamanho do motor e
praticamente proporcional ao conjugado produzido. Por outro lado, a simples
redução da velocidade, por meio de redutor, embora propicie maior precisão e
Custo de braços
bra os robóticos
rob ticos em função
fun o da capacidade de carga, para
acionamento hidráulico
hidr ulico e elétrico.
el trico.
Servo-
Servo-motor
Servos-motores são compostos por motores DC e um redutor de velocidades,
junto com um sensor de posição e um sistema de controle re-alimentado. Em
outras palavras, os servos-motores podem ser considerados como sendo
motores comandados em posição (angular ou linear), já que, do ponto de vista
de quem os utiliza, o controle interno em malha fechada e irrelevante. Os
servos-motores são pequenos, com ampla variação de torques. O mecanismo
de posicionamento ajusta a posição angular por meio de um sinal codificado
que lhe e enviado. Enquanto esse código estiver na entrada, o servo ira manter
a sua posição angular. Em geral o sinal e do tipo PWM (Pulse Width
Modulation), ou seja, a posição angular ira depender da largura do pulso
enviado.
Motor de passo
Acionadores pneumáticos
pneum ticos
Os acionadores pneumáticos são semelhantes aos acionadores hidráulicos,
porem a diferença e a utilização de ar ao invés de óleo. Entretanto o ar e
altamente compressível, o que causa uma baixa precisão e forca, mas estes
acionadores possuem alta velocidade. Acionadores pneumáticos lineares
(cilindros) requerem sistemas sofisticados e complexos para controlarem a
posição em pontos ao longo do curso. Justamente por isso, são pouco
utilizados em aplicações que tenham tal necessidade. Porem, diversas tarefas
de produção podem ser automatizadas com atuadores pneumáticos lineares
trabalhando entre os extremos de posição, ou seja, totalmente recolhido ou
totalmente estendido, que apresentam boa repetibilidade. Estas tarefas em
geral são simples, consistindo de movimentação de material, fixação de pecas e
separação de objetos, chamadas genericamente de operações “pega-e-poe”. O
baixo custo dos acionadores pneumáticos e da geração de ar-comprimido faz
com que a automação pneumática seja a mais adequada se o trabalho a ser
realizado for simples. Pode-se utilizar o acionamento pneumático em juntas
rotativas de forma direta (acionadores rotativos) ou com redutores (motores
pneumáticos de lóbulos ou palhetas). Tais aplicações são, contudo, muito
especificas e indicadas apenas quando houver restrições quanto ao
acionamento elétrico ou hidráulico. A programação de sistemas pneumáticos
pode ser realizada com controladores lógicos programáveis (PLC), ou mesmo
por chaves distribuidoras e chaves fim-de-curso. Este tipo de programação
permite certa flexibilidade na seqüência de acionamentos, porem e bastante
limitada no que se refere a mudanças na forma e no tipo de tarefa executada.
Pode-se dizer, portanto, que sistemas pneumáticos estão mais próximos de
uma automação fixa do que da automação programável.
Métodos
todos de acionamento
Acionamento indireto
Uma vez que os atuadores das juntas são pesados, os fabricantes tentam
introduzir alterações no projeto que permitam redução do peso nas juntas
próximas ao pulso e transferir este peso, quando possível, para a base. Desta
forma consegue-se uma capacidade de carga maior para o braço. Este tipo de
acionamento e denominado indireto, já que o atuador fica afastado da junta
movida por ele. Neste tipo de acionamento, e necessário usar algum tipo de
transmissão de potencia, como polias, correntes, rodas dentadas,
engrenagens, parafusos e correias, ou seja, o acionador e adaptado longe da
junta pretendida do manipulador. Entretanto este método sofre efeitos
indesejados no desempenho do robô, devido a folga nas engrenagens, flexão
dos vínculos do manipulador, escorregamento dos sistemas de polias.
Acionamento direto
Neste método, o acionador e adaptado diretamente na junta, o que, em
determinados casos, proporciona melhor precisão e rendimento de potencia em
relação ao acionamento indireto. Contudo, devido ao baixo torque por unidade
de peso alcançado pelos motores elétricos, costuma-se utilizá-los em conjunto
com redutores de engrenagens, que aumentam o torque, porem reduzem a
velocidade. Neste caso, se o acionador estiver fixado no elo motor, o
acionamento e considerado direto. Nas juntas rotativas com acionamento
direto, o sensor de posição angular (“encoder”) fornece o angulo relativo entre o
elo motor e o elo movido. No acionamento indireto esta leitura fornece o angulo
do elo movido em relação a um outro elo, anterior ao elo motor.
Volume de trabalho
O volume de trabalho (Groover, 1988) e o termo que se refere ao espaço que
um determinado braço consegue posicionar seu pulso. Este volume, em geral,
e estabelecido conforme os limites impostos pelo projeto estrutural do braço, ou
( rea) útil
Volume (área) til do manipulador RS40B. (Fonte: Staubli Robotics)
Sistema de Controle
controle fará os ajustes necessários para que o erro seja reduzido a zero. Um
esquema simples de malha fechada e apresentado em diagrama de blocos.
Programação
Programa o de robôs
rob s
Braços
Bra os mecânicos
mec nicos são
s o programados de diversas formas:
Dinâmica
Din mica do braço
bra o robótico
rob tico
Precisão
Precis o dos movimentos
Resolução espacial
Precisão
Repetibilidade.
Transmissão
Transmiss o de potencia
vale:
Precisão
Precis o cartesiana em juntas robóticas
rob ticas
Supondo-se que sejam conhecidas as precisões (ou resolução do controle) em
cada uma das juntas de um braço mecânico, deseja-se saber qual será a
precisão cartesiana, isto e, qual será a precisão do braço num determinado
ponto de trabalho. E evidente que a precisão cartesiana depende do ponto de
operação, pois os erros de juntas rotativas são mais acentuados quando o
braço estiver estendido do que quando estiver recolhido. Será feita agora uma
analise simples para um braço de apenas uma junta rotativa, e, a seguir, um
braço composto de duas juntas rotativas movendo-se num plano. Considera-se
um braço articulado movendo-se no plano xy, tal que a origem do sistema
coincida com o eixo de rotação, conforme mostra a figura 3.30. Ao passar da
posição P para a posição P', movendo-se do incremento mínimo (resolução da
junta), as novas coordenadas cartesianas do ponto passam a ser x' e y'. Como
o vetor de deslocamento v possui modulo a , e lembrando que PP' e
perpendicular ao elo a em P para pequenos valores do ângulo , tem-se que:
Se o braço possuir uma junta prismática, como visto abaixo, então segue
imediatamente que a projeção do erro _a nos eixos cartesianos devido ao
movimento linear da junta J2 e dado por.
Deslocamento de um braço
bra o com 2GL e juntas
juntas RL.
Percebe-se nos exemplos mostrados que passando o incremento ao limite,
tem-se que,
Transformações
Transforma es entre variáveis
vari veis de junta e variáveis
vari veis cartesianas
robótico. Os elos são rotulados por L , novamente sendo 1 o elo mais próximo
n
Geometria do manipulador RR
Pode-se igualmente obter a expressão acima pela aplicação da lei dos co-
senos ao triangulo formado pelo centro da junta 1, centro da junta 2 e ponto P
na extremidade da garra. Neste caso, o angulo conhecido e o angulo entre os
elos, que e igual a 180 –
o . Nota-se que a inversão do co-seno fornece dois
valores possíveis para o angulo , que correspondem a duas situações nas
quais existe uma solução para o problema. Na primeira delas com > 0, tem-
se a solução normal, com cotovelo para baixo. Na segunda solução, igualmente
valida, a junta 2 situa-se acima tal que o angulo e negativo. Nota-se também
que o valor de e diferente nas duas situações.
As duas soluções
solu es possíveis
poss veis para a cinemática
cinem tica inversa do
do manipulador RR
Nota-se que a cinemática inversa não pode ser resolvida, pois ha apenas duas
equações com 3 incógnitas (os três ângulos das juntas). De fato, pode-se
mostrar facilmente que existem infinitas soluções de ângulos que satisfazem a
condição do órgão terminal atingir um dado ponto no plano. E necessário
assumir uma condição a mais e esta condição já foi estabelecida no enunciado
do problema ao se fixar a orientação da junta J com o angulo ∏ (com relação a
3
Derivando as equações
equa es da cinemática
cinem tica direta e substituindo na expressão
express o acima
tem-
tem-se
movendo-se num plano vertical, dado que a orientação do ultimo elo com
relação a horizontal e um angulo conhecido.
Geometria do manipulador
manipulador RLR em movimento plano vertical
A cinemática direta deste braço e idêntica a do primeiro exemplo, uma vez que
ambos possuem a mesma geometria. Assim,
Isto permite escrever a cinemática direta para a posição desta junta, ou seja:
Algumas
Algumas soluções
solu es possíveis
poss veis para a cinemática
cinem tica inversa
Como x e y são conhecidos, pode-se resolver este sistema para as variáveis
3 3
E finalmente
Que resulta:
Braço
Bra o revoluto TRR em movimento no espaço
espa o
a vista lateral pode também ser calculada por meio da hipotenusa do triangulo
retângulo PQR:
180 caso esteja em graus, para colocá-lo no quadrante correto. Para o calculo
o
Manipulador esférico
esf rico TRL:R
ter uma solução. Uma vez que a cinemática direta fornece 3 equações, será
lateral, que:
Nota-se que tanto d quanto z podem ser calculados, uma vez que se
4 4
Notação de Denavit-Hartenberg
Os parâmetros de Denavit-Hartenberg permitem obter o conjunto de equações
que descreve a cinemática de uma junta com relação a junta seguinte e vice-
versa. São 4 os parâmetros: o angulo de rotação da junta , o angulo de torção
da junta t, o comprimento do elo a e o deslocamento da junta d. Considera-se
uma seqüência de juntas robóticas de revolução como indicado na figura
abaixo. Para obter os parâmetros de Denavit-Hartenberg para a junta Jn, aplica-
se os seguintes procedimentos:
Mostra-se, como no exemplo da figura 5.3, uma junta prismática onde a direção
do eixo da junta foi transferida para o ponto On, onde ocorre a interseção desta
direção com o eixo da junta n+1. Nesta situação o comprimento do elo an torna-
se nulo (na verdade e adicionado a an −1). Nota-se também que a direção de xn
e obtida como sendo perpendicular simultaneamente a direção de
deslocamento da junta prismática (eixo zn 1), e ao eixo da junta Jn+1.
Parâmetros
Par metros de Denavit-
Denavit-Hartenberg em juntas prismáticas.
prism ticas.
A matriz de rotacao entre os sistemas n 1 e n+1 sera dada entao por uma
rotacao do sistema n 1 em torno do eixo zn 1, seguida de uma translacao de dn
na direcao de zn 1, 5.1 - Sistemas de coordenadas da base e do orgao terminal.
O sistema de coordenadas da base e o sistema de coordenadas do orgao
terminal são especiais, uma vez que nao existem restricoes para que o sistema
Dado um vetor no sistema n, ele pode ser expresso no sistema n−1 por meio
da matriz que relaciona ambos os sistemas.
Exemplo
Exemplo de aplicação
aplica o num manipulador VVR:VR.
Este exemplo mostra a obtenção dos parâmetros de Denavit-Hartenberg no
manipulador. Admite-se conhecidos os comprimentos de todos os elos.. Deve-
se relacionar os sistemas de coordenadas de cada junta e preencher a tabela
de parâmetros.
Manipulador robótico
rob tico esquemático
esquem tico para obtenção
obten o dos parâmetros
par metros de Denavit-
Denavit-
Hartenberg.
Tabela de parâmetros
par metros de Denavit-
Denavit-Hartemberg
Trigonometria
Semelhança
Semelhan a de triângulos
tri ngulos
Dois triângulos são semelhantes quando possuem dois ângulos iguais. Como a
soma dos ângulos internos de um triangulo e sempre igual a 180o, então todos
os ângulos de triângulos semelhantes são iguais.
Teorema de Pitágoras
Pit goras
Seno, co-
co-seno e tangente
Complementos de ângulos
ngulos
Supondo conhecidos o seno e o co-seno do angulo , deseja-se saber o valor
do seno e co-seno do angulo complementar 180 o . Conforme
indica a figura abaixo, estes podem ser obtidos da semelhança entre os
triângulos OAC e OBD:
Ângulos
ngulos complementares.
Da mesma figura pode-se ainda verificar que, da semelhança entre os
triângulos OAC e OEA,
Angulos reciprocos.
Figuras semelhantes a essas podem ser desenhadas para se obter as
igualdades:
diferen a de ângulos
Soma e diferença ngulos
Em geometria e comum a necessidade de se conhecer o seno ou o co-seno da
soma de dois ângulos. Pode-se relacionar o seno (ou o co-seno) da soma com
Embora seja também possível obter uma solução geométrica para a tangente
da soma, e mais fácil neste ponto calcular pela relação entre o seno e o co-
seno, ou seja:
Transformações
Transforma es de Coordenadas
Coordenadas
Em diversos problemas físicos e mecânicos existe a necessidade de se
expressar determinada grandeza vetorial em um ou mais sistemas de
coordenadas distintos. Em geral um destes sistemas encontra-se parado
enquanto o outro e o sistema móvel. Por exemplo, a posição de um guindaste
num navio pode ser conhecida com relação a um sistema de eixos fixados a
embarcação, ou, similarmente, ser conhecida com relação a um sistema de
coordenadas fixadas ao ancoradouro. Navios, aeronaves, foguetes, satélites,
veículos em geral, alem de uma grande serie de fenômenos apresentam o
mesmo tipo de problema. Vamos apresentar uma forma de sistematizar estas
transformações de coordenadas.
Rotações
Rota es de coordenadas
entre os eixos c e i.
Conclui-se, também, que as direções dos eixos (x, y, z), quando representadas
nos sistema Q serão dadas respectivamente por x = (u , v , w ), y = (u , v , w ),
x x x y y y
- Rotação
Rota o no sistema de coordenadas Q de um angulo ao redor do eixo x.
Uma rotação
rota o de um angulo ao redor do eixo cartesiano
cartesiano x ira levar a seguinte
matriz de rotação:
rota o:
Translações
Transla es de coordenadas
Muitas vezes os eixos coordenados não possuem origens coincidentes. Nestes
casos, para obter a posição de um dado vetor ou objeto num dos sistemas será
necessário efetuar, alem da transformação de orientação entre os sistemas,
também uma translação. Considere então o sistema Q com sua origem
Translação
Transla o entre sistemas de eixos coordenados.
Nesta situação, se a posição de um ponto P do espaço for dada pelo vetor r , e
o
então a posição deste ponto P no sistema Q será dada pela soma vetorial:
Transformações
Transforma es compostas
Num caso mais geral, os eixos dos sistemas O e Q não são paralelos, e nem
suas origens são coincidentes. Para analisar este caso, pode-se supor que
exista um sistema de eixos intermediário, cujos eixos são paralelos ao do
sistema O, porem sua origem e coincidente com o sistema Q. Percebe-se
então que a transformação entre os dois sistemas reduz-se entre uma
translação de O para o sistema intermediário, seguido de uma rotação entre
este ultimo e o sistema Q.
Transformação
Transforma o composta de rotação
rota o e translação
transla o
Sabe-se que a transformação que relaciona um vetor no sistema intermediário I
com seu correspondente no sistema Q e dada por:
Transformações
Transforma es homogêneas
homog neas
Relações
Rela es inversas
Anexo 1
INTRODUÇÃO A LINGUAGEM C
ESTRUTURA BÁSICA DE UM PROGRAMA C
Exemplo:
#include <stdio.h>
Robótica Teoria e Prática
Robótica Teoria e Prática
main ()
{
printf ( " Programa Inicial " );
}
Variáveis
Uma variável é um espaço reservado na memória do computador para armazenar certos
tipos de dados.
#include <stdio.h>
main ()
{
int num;
num = 2;
printf("Numero = %d",num);
Int num;
Tipo da variável Nome da variável
num = 2;
A função printf()
O printf() é de fato uma função assim como o main(). Os parênteses contêm a sentença
a ser apresentada na tela. Esta sentença deve ser limitada por aspas (“ “), e o conteúdo
de variáveis também podem ser exibidas pelo printf conforme o exemplo abaixo:
#include <stdio.h>
main()
{
int a = 1;
char tipo = ‘c’;
float valor = 22.53;
printf("inteiro= %d char= %c float= %f \n",a,tipo,valor);
}
%c ---------- Caracter
%s ---------- String
%d ---------- Inteiro
%f ---------- Float (notação decimal)
%e ---------- Float (notação exponencial)
%g ---------- Float
%u ---------- Inteiro sem sinal
%x ---------- Hexadecimal inteiro
%o ---------- Octal inteiro
%ld ------------------- Long
%lu ------------------- Long
%lx ------------------- Long
%lo ------------------- Long
Ainda no último exemplo, observe que o ultimo caracter do printf era “\n”. Este caracter
de controle indica que queremos inserir uma nova linha. Existem outros caracteres de
controle, e todos iniciam com um \ “, conforme a tabela abaixo:
\n ---------- Nova linha
\t ----------- Tabulação
\b ---------- Backspace
\’ ---------- Aspas simples
\” ---------- Dupla aspas
\\ ----------- Barra
No exemplo abaixo ilustraremos alguns resultados obtidos com o comando printf (Os
retângulos abaixo de cada comando printf ilustra o resultado obtido na tela do
computador):
#include <stdio.h>
Robótica Teoria e Prática
Robótica Teoria e Prática
main()
{
int i = 52;
float x = 28.534;
printf("i = %2d\n",i);
i = 52
printf("i = %4d\n",i);
i = 52
printf("x = %8.3f\n",x);
x=28.534
printf("x = %-8.3f\n",x);
x = 28.53 4
}
A função scanf()
Esta função é responsável pela entrada de dados via teclado. Existem várias funções de
entrada e saída em C, porém o printf e o scanf são as mais comuns. Examine o exemplo
abaixo:
#include <stdio.h>
main()
{
int i,j;
float x,y;
double a,b;
scanf("%d",&i);
scanf("%f",&x);
scanf("%lf",&a);
j = i % 2;
y = x * 2;
b = a / 2;
printf("i= %3d j= %3d \n",i,j);
printf("x= %.3f y= %.3f \n",x,y);
printf("a= %g b= %g \n",a,b);
}
Operadores
Os operadores aritméticos sobre as variáveis são os seguintes:
Robótica Teoria e Prática
Robótica Teoria e Prática
+ --------- Soma
- --------- Subtração
* -------- Multiplicação
/ --------- Divisão
% ------- Resto da divisão
A operação de incremento de uma unidade tem também um formato reduzido, ou seja, o
comando:
i = i + 1;
é freqüentemente representado por:
i++;
Da mesma forma i = i-1; pode ser escrito como i--;
#include <stdio.h>
#include <math.h>
main()
{
float a,b,c;
float x1,x2;
printf("Entre a,b,c:");
scanf("%f %f %f",&a,&b,&c);
x1=(-b+sqrt(b*b-4*a*c))/(2*a);
x2=(-b-sqrt(b*b-4*a*c))/(2*a);
printf("\n x1 = %f x2 = %f\n",x1,x2);
}
Comentários
É possível introduzir comentários dentro de um programa C, bastando para isso colocá-
los no seguinte formato:
/* Comentario */
/* * * * * * * * * * * * * * * * * * * * * * * * */
#include <math.h>
main()
{
/* Definicao das variaveis */
float a,b,c; /* Coeficientes do polinomio */
float x1,x2; /* Solucoes desejadas */
/* Entrada de Dados */
printf("Entre a,b,c:");
scanf("%f %f %f",&a,&b,&c);
/* Calculo das raizes */
x1=(-b+sqrt(b*b-4*a*c))/(2*a);
x2=(-b-sqrt(b*b-4*a*c))/(2*a);
/* Impressao dos dados finais */
printf("\n x1 = %f x2 = %f\n",x1,x2);
}
LAÇOS (LOOPS)
Existem três formatos básicos de laços:
1 – do {} while();
2 - while() {}
3 - for( ; ;) { }
Comando for( ; ; ) {}
O for é um comando apropriado quando queremos executar um conjunto de operações
um número fixo de vezes. O exemplo abaixo imprime os números de 0 até 9:
#include <stdio.h>
main()
{
int n;
10
for(n=0; n<10; n++) {
printf("n = %d\n",n);
}
}
O resultado será:
n=0
n=1
n=2
n=3
n=4
n=5
n=6
n=7
n=8
n=9
Expressão de inicialização
Inicializa a variável do laço. A inicialização é feita uma única vez quando o laço inicia.
Expressão de teste
Esta expressão testa (a cada vez que o conjunto de comandos no interior do for finaliza),
se o laço deve ser encerrado. Enquanto a expressão for verdadeira o laço é repetido.
Para realizar teste utilizamos os operadores relacionais. Os principais operadores são:
< Menor
> Maior
<= Menor ou igual
>= Maior ou igual
== Igual
!= Diferente
&& e
! negação
|| ou
Expressão de incremento
A cada repetição do laço, o terceiro argumento (n++) incrementa a variável n.
/* * * * * * * * * * * * * * * * * * * * */
/* Integracao Numerica: Ponto a Esquerda */
/* * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
main()
{
int i;
int n;
float w;
float dx ;
float a,b ;
float soma;
printf("\nEntre o extremo inferior do intervalo: ");
scanf("%f",&a);
printf("\nEntre o extremo superior do intervalo: ");
scanf("%f",&b);
Comando do {} while();
Este segundo tipo de laço é adequado para situações onde não sabemos ao certo quantas
vezes o laço deve ser repetido. O exemplo abaixo ilustra a utilização do comando:
#include <stdio.h>
main()
{
int n;
n = 0;
do {
printf("n = %d\n",n);
n++;
} while (n < 10);
}
No exemplo acima o programa entra dentro do laço faz o primeiro printf, incrementa n
de uma unidade e só então verifica a condição while (n < 10). Caso a condição seja
verdadeira, a execução do programa retorna a primeira linha do laço (printf("n =
%d\n",n);) e prossegue até que a condição seja falsa. O programa sempre entra
executando os comando no interior do laço, para somente no final realizar o teste.
/* Metodo de Newton */
#include <stdio.h>
Robótica Teoria e Prática
Robótica Teoria e Prática
#include <math.h>
main()
{
int i ;
double xn, x0,xn_1;
double erro ;
printf(" Entre com a condicao inicial: ");
scanf("%lf",&x0);
printf("\n Erro maximo: ");
scanf("%lf",&erro);
xn = x0;
i = 0;
do {
xn_1 = xn;
xn = xn_1 - (xn_1 * xn_1 - 2) / (2 * xn_1);
i++;
printf("\nx[%2d] = %20.17f",i,xn);
} while (fabs(xn - xn_1) > erro);
printf ("\n A raiz obtida foi: %20.17f\n",xn);
}
#include <stdio.h>
main()
{
int n;
n = 0;
while (n < 10){
printf("n = %d\n",n);
n++;
}
}
Neste exemplo, primeiro é feito o teste (while (n < 10)) e somente em caso verdadeiro
os comandos dentro do while são executados. Assim se a condição for falsa a primeira
vez, em nenhum momento os comandos dentro do laço serão executados. Já no do{}
while(); pelo menos a primeira vez os comandos dentro do laço serão executados.
#include <stdio.h>
main()
Robótica Teoria e Prática
Robótica Teoria e Prática
{
int n;
n = 0;
while (n < 10){
printf("n = %d\n",n);
if (n > 3)
break;
n++;
}
printf (“Fim do programa \n”);
}
n=0
n=1
n=2
n=3
n=4
Fim do programa
O comando continue; transfere a execução do programa para o teste do laço, que pode
ou não prosseguir conforme a condição seja verdadeira ou falsa.
DECISÕES
Comando if () {}
/* * * * * * * * * * * * * * * * * * */
/* Testa se um numero e par ou impar */
/* * * * * * * * * * * * * * * * * * */
#include <stdio.h>
main()
{
int i,n;
printf("Entre com n = ");
scanf("%d", &n);
i = n % 2;
if (i == 0) {
printf("\n n e um numero par\n");
}
else {
printf("\n n e um numero impar\n");
}
}
Neste exemplo a variável i armazena o resto da divisão de n por 2. Caso seja zero, então
o programa passa a execução do comando printf("\n n e um numero par\n"). Se a
Robótica Teoria e Prática
Robótica Teoria e Prática
condição falha, o comando else indica que o programa deve executar o comando
printf("\n n e um numero impar\n"). Observe que o else é um comando opcional. Caso
você não o inclua, o programa segue para o próximo comando após o if.
/* * * * * * * * * * * * * * * * * * */
/* Metodo da Bissecao */
/* * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
main()
{
float a,b,c;
float erro;
float fa,fb,fc;
printf("\nEntre com a = ");
scanf("%f",&a);
printf("\nEntre com b = ");
scanf("%f",&b);
printf("\nEntre com o erro = ");
scanf("%f",&erro);
fa = a*a - 2;
fb = b*b - 2;
if ((fa * fb) > 0) {
printf("\nCondicao inicial nao contem raiz !\n");
exit(0);
}
while(fabs(a-b) > erro) {
c = (a+b)/2.0;
fc = c*c - 2.0;
if (fa * fc < 0) {
b = c;
}
else {
if (fb * fc < 0)
a = c;
else
break;
}
printf("\n Raiz parcial = %f ",c);
}
printf("\n\n Raiz obtida = %f \n",c);
Robótica Teoria e Prática
Robótica Teoria e Prática
FUNÇÕES
Introdução
As funções cumprem como primeiro papel, evitar repetições desnecessárias de código.
No exemplo anterior precisamos calcular o valor y=x*x-2 em diversas partes do
programa. Se desejássemos trocar a função, seria necessário alterar várias partes do
código. Para evitar isso, utilizaremos uma função como no exemplo abaixo:
/* * * * * * * * * * * * * * * * * * * */
/* Metodo da Bisssecao */
/* * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
float f(float x)
{
return(x*x-2);
}
void main()
{
int i = 0;
float a,b,c;
float erro;
float fa,fb,fc;
printf("Entre com os extremos do intervalo [a, b]: ");
scanf("%f,%f",&a,&b);
printf("\nErro: ");
scanf("%f",&erro);
fa = f(a);
fb = f(b);
if ((fa * fb) > 0) {
printf("Condicao inicial nao contem raiz !\n");
exit(0);
}
while(fabs(a-b) > erro) {
i++;
c = (a+b)/2.0;
fc = f(c) ;
if (fa * fc < 0)
b = c;
else
if (fb * fc < 0)
a = c;
else
break;
printf("Raiz parcial no passo %d = %f \n",i,c);
}
printf("\n Raiz obtida = %f \n",c);
Robótica Teoria e Prática
Robótica Teoria e Prática
float f (float x)
Define o tipo Nome da Função Argumentos retornado pela função de entrada
{
float y;
y = x * x - 2;
return(y); /*Valor a ser retornado*/
}
Uma observação importante é que as variáveis dentro da função não são conhecidas fora
da função e vice versa.
/* * * * * * * * * * * * * * * * * * */
/* Metodos de Integracao Numerica */
/* * * * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <conio.h>
float f(float x)
{
float y;
y = 1/(1+x*x);
return(y);
}
float Integra_Ponto_a_esquerda(float a,float b,int n)
{
int i ;
float soma ;
float dx ;
soma = 0.0;
dx = (b-a)/n;
for(i=1; i<= n; i++) {
soma = soma + f(a + (i-1)*dx) * dx;
printf("\nSoma parcial = %f ",soma);
}
return(soma);
}
float Integral_Trapezio(float a,float b,int n)
{
int i ;
Robótica Teoria e Prática
Robótica Teoria e Prática
float soma ;
float dx ;
dx = (b-a)/n;
soma = f(a);
for(i=1; i < n; i++) {
soma = soma + 2*f(a + i*dx);
printf("\nSoma parcial = %f ",soma);
18
}
soma = dx/2 * (soma + f(b));
return(soma);
}
float Integral_Simpson(float a,float b,int n)
{
int i ;
float soma ;
float dx ;
dx = (b-a)/n;
soma = f(a);
for(i=1; i < n; i++) {
if ((i%2) == 1)
soma = soma + 4*f(a + i*dx);
else
soma = soma + 2*f(a + i*dx);
printf("\nSoma parcial = %f ",soma);
}
soma = dx/3 * (soma + f(b));
return(soma);
}
main()
{
int i;
int n;
char c;
float a,b ;
float soma;
do {
printf("Selecione um do metodos de integracao \n");
printf("1- Ponto a esquerda \n");
printf("2- Trapezio \n");
printf("3- Simpson \n");
printf("Opcao: ");
scanf("%d",&i);
printf("\nEntre o extremo inferior do intervalo: ");
scanf("%f",&a);
printf("\nEntre o extremo superior do intervalo: ");
scanf("%f",&b);
printf("\nEntre com o numero de particoes: ");
scanf("%d",&n);
switch(i)
Robótica Teoria e Prática
Robótica Teoria e Prática
{
case 1:
soma = Integra_Ponto_a_esquerda(a,b,n);
break;
case 2:
soma = Integral_Trapezio(a,b,n);
break;
case 3:
soma = Integral_Simpson(a,b,n);
break;
}
printf("\nIntegral = %15.9f ",soma);
printf("\n Continua (s/n) ");
c = getche();
} while((c != 'n') && (c != 'N'));
VETORES E MATRIZES
Vetores
Quando você deseja representar uma coleção de dados semelhantes, pode ser muito
inconveniente utilizar um nome de variável diferente para cada dado. Para ilustrar
vamos considerar o seguinte exemplo: Montar um programa que armazena as notas de
15 alunos e calcula a média obtida pela turma. As notas serão armazenadas em uma
variável do tipo float, porém ao invés de criarmos 15 variáveis, utilizamos uma variável
do tipo vetor, definida como abaixo:
float notas[15];
#include <stdio.h>
main()
{
int i ;
float media ;
float soma ;
float notas[15];
for(i=0;i < 15;i++) {
printf("\n Aluno %2d ",i+1);
scanf("%f",¬as[i]);
}
for(i=0;i<15;i++)
soma = soma + notas[i];
media = soma / 15;
printf("\n A media final foi: %f",media);
}
Declaração
n[3] = 29;
29
n[0] n[1] n[2] n[3] n[4]
Inicializando vetores
Assim como é possível inicializar uma variável simples na mesma linha da declaração,
o mesmo pode ser feito para vetores. Observe o exemplo abaixo:
/* * * * * * * * * * * * * * * * * * * * * */
/* Metodo da Bolha (ordenacao de um vetor) */
/* * * * * * * * * * * * * * * * * * * * * */
#define MAX 10
#include <stdio.h>
main()
{
int i ;
int flag;
float swap;
float n[MAX];
/* Entrada de Dados */
printf("Entre com os numeros para ordenacao \n");
for(i=0;i<MAX;i++)
{
printf("\n numero %2d: ",i);
scanf("%f",&(n[i]));
}
/* Ordena a sequencia de numeros */
flag = 1;
while(flag == 1) {
Robótica Teoria e Prática
Robótica Teoria e Prática
flag = 0;
for(i=0;i<(MAX-1);i++)
{
if (n[i] > n[i+1])
{
swap = n[i] ;
n[i] = n[i+1];
n[i+1] = swap ;
flag = 1 ;
}
}
}
/* Imprime a sequencia de numeros ordenada */
printf("\nSequencia ordenada : ");
for(i=0; i<MAX; i++)
printf("\n %10.5f ",n[i]);
printf("\n");
}
Matrizes
Para representar uma matriz 3x4 (3 linha e 4 colunas) de números reais utilizamos a
seguinte declaração:
float A[3][4];
Assim fica reservado um espaço de memória conforme a figura abaixo:
/* * * * * * * * * * * * * * * * * * * * * * */
/* Multiplicacao de um vetor por uma matriz */
/* * * * * * * * * * * * * * * * * * * * * * */
#include <stdio.h>
main()
{
int i,j;
float A[3][3] = {{1.0, 1.5, 2.1}, {3.4, 2.2, 9.1}, {-1.2, -3.4, 0.9}};
float v[3] = {2.0, 1.0, 0.5};
float p[3];
for(i=0;i<3;i++) {
p[i] = 0;
for(j=0;j<3;j++) {
p[i] += A[i][j] * v[j];
}
}
Robótica Teoria e Prática
Robótica Teoria e Prática
for(i=0;i<3;i++) {
printf("\n[");
for(j=0;j<3;j++) {
printf("% 5.3f ",A[i][j]);
}
printf(" ] ");
printf(" [ %5.3f ]",v[i]);
}
for(i=0;i<3;i++)
printf("\n p[%1d] = %10.4f",i,p[i]);
}
PONTEIROS
Considere o seguinte programa:
#include <stdio.h>
int teste(int i)
{
i = i + 20;
printf("Dentro da funcao i = %d \n",i);
return(i);
}
void main()
{
int i,j;
i = 1;
printf("Fora da funcao i = %d \n",i);
j = teste(i);
printf("Fora da funcao i = %d \n",i);
printf("Fora da funcao j = %d \n",j);
}
Observe que o valor da variável i não tem seu conteúdo alterado pela função. Isto ocorre
porque quando uma função é chamada durante o programa, todas as variáveis presentes
Robótica Teoria e Prática
Robótica Teoria e Prática
na função são criadas neste. Quando a função finaliza, todas as variáveis da função são
apagadas da memória. Muitas vezes gostaríamos que os argumentos de entrada da
função pudessem ter seus valores alterados quando a função finalizasse. Esta será uma
das aplicações do conceito de ponteiros.
O que é um ponteiro?
#include <stdio.h>
void main()
{
int i;
printf("Endereco de i = %x\n",&i);
}
Para armazenar o endereço de uma variável (por exemplo &i) em outra variável, é
necessário criar um tipo especial de variável denominada apontador. Exemplo:
#include <stdio.h>
void main()
{
int i ;
int *pi;
pi = &i;
printf("Endereco de i = %x ou %x\n",&i,pi);
}
A variável pi é uma variável do tipo ponteiro para inteiro (ou seja, ela recebe o endereço
de uma variável do tipo inteiro). Para informar que esta variável é do tipo apontador
colocamos um asterisco (*) na frente da variável no momento da sua declaração:
int * pi
Tipo de ponteiro Indica ponteiro Nome da variável
Observe o exemplo:
#include <stdio.h>
void main()
{
int i ;
int j ;
int *pi;
pi = &i;
i = 25;
j = *pi + 8; /* equivalente a j = i + 8 */
printf("Endereco de i = %x \n",pi);
printf("j = %d \n",j);
}
O operador unário * trata seu operando como um endereço e acessa este endereço para
buscar o conteúdo da variável. Observe que o * tem dupla função:
No nosso exemplo, para alterar o valor da variável i, temos duas alternativas (totalmente
equivalentes) :
i = 5;
*pi = 5;
Como sabemos, uma função não consegue alterar diretamente uma variável utilizada
como argumento. Com o auxílio dos ponteiros podemos encontrar uma alternativa para
esta situação. No exemplo do programa de ordenação, foi preciso permutar dois
elementos do vetor que estavam fora de ordem. Não seria possível permutar dois valores
através de uma função como abaixo:
/* * * * * * * * * * * * * * * * * * * * * * * * * */
/* Este programa NÃO consegue permutar os valores */
#include <stdio.h>
x = 1.2 e y = 56.89
/* * * * * * * * * * * * * * * * * * * * * * * * * */
/* Este programa permutar os valores das variaveis */
#include <stdio.h>
void troca(float *x, float *y)
{
float auxiliar;
auxiliar = *x;
*x = *y;
*y = auxiliar;
}
main()
{
float x = 1.2;
float y = 56.89;
troca(&x,&y);
printf("x = %6.2f e y = %6.2f\n",x,y);
}
O uso comum de argumentos do tipo ponteiro ocorre em funções que devem retornar
mais de um valor. No exemplo acima, a função retornou dois valores.
#include <stdio.h>
void troca(float *x, float *y)
{
float auxiliar;
auxiliar = *x;
*x = *y;
*y = auxiliar;
}
void ordena(float *px)
{
int i ;
int flag;
/* Ordena a sequencia de numeros */
flag = 1;
while(flag == 1) {
flag = 0;
for(i=0;i<(MAX-1);i++)
{
if (px[i] > px[i+1])
{
troca(&(px[i]),&(px[i+1]));
flag = 1;
}
}
}
}
main()
{
int i ;
float n[MAX];
/* Entrada de Dados */
printf("Entre com os numeros para ordenacao \n");
for(i=0;i<MAX;i++)
{
printf("\n numero %2d: ",i);
scanf("%f",&(n[i]));
}
ordena(n);
/* Imprime a sequencia de numeros ordenada */
printf("\nSequencia ordenada : ");
for(i=0; i<MAX; i++)
printf("\n %10.5f ",n[i]);
printf("\n");
}
Uma das restrições do nosso programa de ordenação é que o usuário não pode definir a
princípio quantos elementos ele pretende ordenar. Isto ocorre porque precisamos
informar na declaração do vetor qual será a sua dimensão. Vamos retirar essa restrição.
Para isso utilizaremos um novo comando: malloc(). Vamos utilizar um exemplo:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
void main()
{
int i;
int n;
float *v;
printf("Entre com a dimensao do vetor desejada = ");
scanf("%d",&n);
v = (float *) malloc(n * sizeof(float));
for(i=0;i<n;i++)
scanf("%f",&(v[i]));
for(i=0;i<n;i++)
printf("v[%2d]=%f\n",i,v[i]);
free(v);
}
1. O vetor que será alocado foi declarado como um ponteiro: float *v;
2. O comando malloc(n * sizeof(float)) reserva n espaços de memória, cada um do
tamanho de um float.
3. A função malloc retorna o endereço do primeiro elemento do vetor: (float *) malloc()
4. A função free, libera o espaço de memória reservado para o vetor.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
float **matalloc(int n,int m)
{
int j;
float **A;
28
Robótica Teoria e Prática
Robótica Teoria e Prática
Determinando a matriz L e U
Nosso objetivo inicial é aplicar um conjunto de operações elementares sobre a matriz
dos coeficientes de tal forma que ao final do processo obtemos A = LU, ou seja, a
matriz A pode ser escrita como o produto de duas matrizes onde:
Obtemos então uma matriz triangular superior. Esta matriz é matriz U desejada. Para
obter a matriz L, observamos que cada uma das operações elementares aplicadas pode
ser representada por uma matriz. Vamos acompanhar pelo exemplo.
3. Substituição da i-ésima linha pela i-ésima linha acrescida de K vezes a j-ésima linha
(Li = Li + K Lj ):Partindo da matriz identidade, coloque o valor K na i-ésima linha e j-
ésima coluna.
Ex: L2 = L2 + 4 L3. Partindo da matriz identidade, coloque na segunda linha e na
terceira coluna o valor 4:
A Tela do Computador
A tela do computador pode ser considerada uma matriz de células discretas (Pixels),
cada qual pode estar acesa ou apagada.
640 x 480
800 x 600
1024 x 768
1280 x 1024
Cores
A cada pixel associamos uma cor. Para obter uma cor, o monitor envia certa
combinação de vermelho, verde e azul (RGB). O número de cores possíveis varia
conforme o hardware. Cada pixel tem uma mesma quantidade de memória para
armazenar suas cores. O buffer de cores (Color Buffer) é uma porção da memória
reservada para armazenar as cores em cada pixel. O tamanho deste buffer é usualmente
medido em bits. Um buffer de 8 bits pode exibir 256 cores diferentes simultaneamente.
Conforme a capacidade da placa gráfica podemos ter:
Existem duas formas básica de acessar as cores no OpenGL: RGB e Modo Indexado.
Trabalharemos sempre em formato RGB. No formato RGB você deve informar as
intensidades de Vermelho, Verde e Azul desejadas. Estas intensidades devem variar
entre 0.0 a 1.0. A tabela abaixo mostra como obter as cores básicas:
Cores R G B R G B
Introdução ao OpenGL
O sistema gráfico OpenGL (GL significa Graphics Library) é uma biblioteca (de
aproximadamente 350 comandos) para aplicações gráficas. O OpenGL foi desenvolvido
pela Silicon Graphics (SGI) voltado para aplicações de computação gráfica 3D, embora
possa ser usado também em 2D. As rotinas permitem gerar primitivas (pontos, linhas,
polígonos, etc) e utilizar recursos de iluminação 3D. O OpenGL é independente do
sistema de janelas, ou seja, suas funções não especificam como manipular janelas. Isto
permite que o OpenGL possa ser implementado para diferentes sistemas: X Window
System (Unix), Windows 95 e NT, OS/2 , Macintosh, etc.
#include <gl\glut.h>
void redesenha()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
glBegin(GL_POINTS);
glVertex2f(200.0,200.0);
glEnd();
glFlush();
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400); /* Antes do glutCreateWIndow */
glutInitWindowPosition(1,1);
glutCreateWindow("Ponto");
gluOrtho2D(0,399,399,0); /* Apos CreateWindow */
glutDisplayFunc(redesenha); /* Esta funcao e necessaria, caso
contrario o opengl nao consegue
criar a janela */
glutMainLoop();
}
glutInit(&argc,argv);
É utilizado para iniciar a biblioteca GLUT.
Exercícios:
void redesenha()
{
static int i = 0;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
Robótica Teoria e Prática
Robótica Teoria e Prática
glColor3f(1.0,0.0,0.0);
glBegin(GL_POINTS);
glVertex2f(200.0,200.0);
glEnd();
glFlush();
printf(" %d ",i++);
}
Algoritmo ingênuo
A primeira idéia de como resolver este problema é proposto pelo programa abaixo. Este
é um exemplo ingênuo de como desenhar a reta que passa por dois pontos dados.
Vamos discutir a seguir os principais problemas deste programa e as possíveis soluções.
/* -------------------------------------------------------------- */
/* Exemplo ingênuo de como plotar a reta definida por dois pontos */
/* -------------------------------------------------------------- */
#include <gl\glut.h>
#include <stdio.h>
int pontos;
float x0,y0,x1,y1;
float Reta_dois_pontos(float x)
{
float y;
y = (y1-y0)/(x1-x0)*(x-x0) - y0;
return(y);
}
void display()
{
int i ;
float x,y;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
for (i=0;i<pontos;i++)
{
x = x0 + i * (x1 - x0)/pontos;
y = Reta_dois_pontos(x);
glBegin(GL_POINTS);
glVertex2f(x,y);
Robótica Teoria e Prática
Robótica Teoria e Prática
glEnd();
}
glFlush();
glutSwapBuffers();
}
void main(int argc, char **argv)
{
printf("x0 = ");
scanf("%f",&x0);
printf("\ny0 = ");
scanf("%f",&y0);
printf("\nx1 = ");
scanf("%f",&x1);
printf("\ny1 = ");
scanf("%f",&y1);
printf("\nPontos = ");
scanf("%d",&pontos);
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
glOrtho(0,399,399,0,-1,1);
glutDisplayFunc(display);
glutMainLoop();
}
1) Este método requer operações em ponto flutuante (float ou double) para cada pixel.
Isto acarreta em um algoritmo lento, se comparado a um algoritmo que opera somente
com números inteiros. Para o caso da reta, existe um tal algoritmo que utiliza somente
aritmética com números inteiros. Este algoritmo foi desenvolvido por Jack E.
Bresenham na década de 60 e será descrito adiante.
2) O usuário estabelece o número de pontos da reta a serem plotados entre os dois
pontos. Podem ocorrer dois casos: faltarem pontos (a reta fica pontilhada), sobrarem
pontos (neste caso o algoritmo faz contas desnecessárias). O ideal é o próprio programa
se encarregar de determinar o número de pontos necessários e suficientes para resolver
o problema.
3) O caso particular da reta vertical x = K (onde K é constante) não pode ser plotado.
Algoritmo de Bresenham
Para os casos em que a inclinação não está entre 0 e 1, utilizamos a mesma solução
considerando simetrias. O algoritmo completo deve considerar oito casos:
D1 = y – Ay e D2 = Ay + 1 – y
P1 = D1 – D2
= y – Ay – (Ay + 1) + y
= 2y – 2Ay -1
Substituindo y = m (Ax + 1) + b, obtemos
P1 = 2m(Ax + 1) + 2b – 2Ay -1
• A expressão
2 dY (Ax + 1) + 2 b dX – 2Ay dX - dX
é o teste que estamos procurando, pois ele envolve somente números inteiros
(dY,dX,Ax,Ay,b). Porém ainda podemos melhorar o algoritmo, pois esta avaliação
ficaria demasiada cara para ser feita a cada novo pixel da reta.
• Neste passo vamos tentar calcular a variável de decisão P2 para o próximo pixel,
utilizando a informação que adquirimos no passo anterior para estimar P1. De forma
geral para dois passos subseqüentes temos que:
P2 – P1 = 2dY(Ax + 2) +2b dX –2Ay dX –dX – (2dY(Ax + 1) +2b dX –2Ay dX - dX)
= 2 dY -2 (Ay – Ay) dX
Temos duas possibilidades: ou Ay = Ay ou Ay = Ay+1, o que se resume a:
P2 – P1 = 2 dY ,caso em que escolhemos o ponto (Ax+1,Ay)
P2 – P1 = 2 dY -2 dX ,caso em que escolhemos o ponto (Ax+1,Ay+1)
Assim uma vez que calculamos a variável de decisão P1 para o primeiro pixel, nos
pixels subseqüentes, basta incrementar 2 dY ou (2 dY – 2 dX), conforme o pixel
escolhido no passo anterior.
#include <gl\glut.h>
#include <stdio.h>
//=============================================================
=======
// b r e s l i n e . c
//
// VERSION 1: draws only from one end and calculates both x and y.
//
// Programmer: Kenny Hoff
// Date: 10/25/95
// Purpose: To implement the Bresenham's line drawing algorithm
for
// all slopes and line directions (using minimal
routines).
//=============================================================
======
// EXTERNALLY DEFINED FRAMEBUFFER AND FRAMEBUFFER
DIMENSIONS (WIDTH))
// extern int WIDTH;
//=============================================================
=======
=
// Fills the intermediate points along a line between the two given
// endpoints using Bresenham's line drawing algorithm. NOTE: this
// routine does no clipping so the coordinate values must be within
the
// FrameBuffer bounds.
// NOTE: USE (Ax,Ay) as the starting point (values that are
// incremented)
//=============================================================
=======
void BresLine(int Ax, int Ay, int Bx, int By)
{
//--------------------------------------------------------------
-
// INITIALIZE THE COMPONENTS OF THE ALGORITHM THAT ARE NOT
// AFFECTED BY THE SLOPE OR DIRECTION OF THE LINE
//--------------------------------------------------------------
int dX = abs(Bx-Ax); // store the change in X and Y of the
// line endpoints
int dY = abs(By-Ay);
//--------------------------------------------------------------
// DETERMINE "DIRECTIONS" TO INCREMENT X AND Y (REGARDLESS OF
// DECISION)
Robótica Teoria e Prática
Robótica Teoria e Prática
//--------------------------------------------------------------
-
int Xincr, Yincr;
if (Ax > Bx) { Xincr=-1;} else { Xincr=1;}//which direction in
X?
if (Ay > By) { Yincr=-1;} else { Yincr=1;}//which direction in
Y?
//--------------------------------------------------------------
// DETERMINE INDEPENDENT VARIABLE (ONE THAT ALWAYS
INCREMENTS BY
// 1 (OR -1) )AND INITIATE APPROPRIATE LINE DRAWING ROUTINE
// (BASED ON FIRST OCTANT ALWAYS). THE X AND Y'S MAY BE FLIPPED
//IF Y IS THE INDEPENDENT VARIABLE.
//--------------------------------------------------------------
{
int dPr = dY<<1; // amount to increment decision
// if right is chosen (always)
int dPru = dPr - (dX<<1); // amount to increment
// decision if up is chosen
int P = dPr - dX; // decision variable start
value
for (; dX>=0; dX--) // process each point in the line
// one at a time (just use dX)
{
glBegin(GL_POINTS);
glVertex2d(Ax, Ay); // plot the pixel
glEnd();
if (P > 0) // is the pixel going right AND up?
{
Ax+=Xincr; // increment independent variable
Ay+=Yincr; // increment dependent variable
P+=dPru; // increment decision (for up)
}
else // is the pixel just going right?
{
Ax+=Xincr; // increment independent variable
P+=dPr; // increment decision (for right)
}
}
}
else // if Y is the independent variable
{
int dPr = dX<<1; // amount to increment decision if
// right is chosen (always)
int dPru = dPr - (dY<<1); // amount to increment
// decision if up is chosen
int P = dPr - dY; // decision variable start value
for (; dY>=0; dY--) // process each point in the line
// one at a time (just use dY)
Robótica Teoria e Prática
Robótica Teoria e Prática
{
glBegin(GL_POINTS);
glVertex2d(Ax, Ay); // plot the pixel
glEnd();
if (P > 0) // is the pixel going up AND right?
{
Ax+=Xincr; // increment dependent variable
Ay+=Yincr; // increment independent variable
P+=dPru; // increment decision (for up)
}
else // is the pixel just going up?
{
Ay+=Yincr; // increment independent variable
P+=dPr; // increment decision (for right)
}
}
}
}
void display()
{
int i;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
BresLine(0,0,400,400);
glFlush();
glutSwapBuffers();
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
glOrtho(0,399,0,399,-1,1);
glutDisplayFunc(display);
glutMainLoop();
}
Retas no Opengl
O OpenGL dispõe em sua biblioteca interna de um comando que plota uma reta por dois
pontos dados.
Este comando é descrito abaixo:
void display()
{
float x,y;
glClearColor(0.0,0.0,0.0,0.0);
Robótica Teoria e Prática
Robótica Teoria e Prática
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex2f(x0,y0);
glVertex2f(x1,y1);
glEnd();
glFlush();
}
#include <gl\glut.h>
#include <stdio.h>
float funcao(float x)
{
return(x*x);
}
void display()
{
float x,y;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glColor3f(1.0,0.0,0.0);
for(x=-1;x<1;x+=0.01)
{
y = funcao(x);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
}
glFlush();
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
gluOrtho2D(-1,1,-1,1);
glutDisplayFunc(display);
glutMainLoop();
}
/* * * * * * * * * * * * * */
/* Modulo: Funcao01.cpp */
/* * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "funcao02.h"
void redesenha()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
plota_funcao();
glFlush();
glutSwapBuffers();
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
glutDisplayFunc(redesenha);
gluOrtho2D(-5,5,-5,5);
glutMainLoop();
}
/* * * * * * * * * * * * * */
/* Modulo: funcao02.cpp */
/* * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
#define PI 3.1415926535897932384626433832795
float xmin = -5.0;
float xmax = 5.0;
float ymin = -5.0;
float ymax = 5.0;
int pontos = 400;
/* -------------------------------- */
float funcao(float x)
/* -------------------------------- */
{
return(sin(x));
}
Robótica Teoria e Prática
Robótica Teoria e Prática
/* -------------------------------- */
void plota_eixo()
/* -------------------------------- */
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
/* -------------------------------- */
void plota_funcao()
/* -------------------------------- */
{
int i ;
float dx ;
float x,y;
dx = (xmax - xmin)/pontos;
glColor3f(1.0,0.0,0.0);
x = xmin;
for(i=0;i<pontos;i++)
{
y = funcao(x);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
x = x + dx;
}
}
/* funcao02.h */
float funcao(float x);
void plota_eixo();
void plota_funcao();
O usuário pode interagir com o programa de duas formas principais: através do Mouse
ou Teclado. Para isso o GLUT dispõe de dois tipos de funções (que denominamos
Callbacks) específicas para habilitar a utilização do teclado e do mouse. Vamos
descrevê-las a seguir.
Teclado
Para registrar ocorrências no teclado o GLUT dispõe da função:
void glutKeyboardFunc(void (*func)(unsigned char key, int x, int y)) , Esta função
determina que quando uma tecla for pressionada, o controle do programa deve passar a
função definida no campo (*func) e esta função receberá como parâmetros de entrada, a
Robótica Teoria e Prática
Robótica Teoria e Prática
tecla pressionada (unsigned char key), e a posição do mouse (int x, int y). O exemplo
abaixo exemplifica uma aplicação para o programa funções.
- funcao011.h: Este módulo deve ter apenas o cabeçalho das funções do programa
funcao011.cpp.
A seguir apresentamos o código de cada um destes módulos.
Módulo funcao011.h
/* * * * * * * * * * * * * * */
/* Modulo: funcao011.h */
/* * * * * * * * * * * * * * */
float funcao(float x);
void plota_eixo();
void plota_funcao();
void entra_dominio();
Módulo funcao010.cpp
Este módulo contém as rotinas básicas do OpenGL e a abertura do programa (void
main()). Observe que a função glutKeyboardFunc(le_tecla); informa que quando
alguma tecla é pressionada o controle do programa deve passar a rotina void
le_tecla(unsigned char key, int x, int y).
/* * * * * * * * * * * * * * */
/* Modulo: funcao010.cpp */
/* * * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "funcao011.h"
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
Robótica Teoria e Prática
Robótica Teoria e Prática
plota_eixo();
plota_funcao();
glFlush();
}
void le_tecla(unsigned char key, int x, int y)
{
switch(key)
{
case 'D':
case 'd':
entra_dominio();
display();
break;
}
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
glutDisplayFunc(display);
glutKeyboardFunc(le_tecla);
glutMainLoop();
}
Módulo funcao011.cpp
Neste módulo separamos as rotinas que trabalham com a função ser desenhada.
/* * * * * * * * * * * * * * */
/* Modulo: funcao011.cpp */
/* * * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
float xmin,ymin,xmax,ymax,incremento;
float funcao(float x)
{
return(sin(x));
}
void plota_eixo()
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
Robótica Teoria e Prática
Robótica Teoria e Prática
}
void plota_funcao()
{
float x,y;
glColor3f(1.0,0.0,0.0);
for(x=xmin;x<xmax;x+=incremento)
{
y = funcao(x);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
}
}
void entra_dominio()
{
int pontos;
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
Mouse
O GLUT é capaz de obter três tipos de ocorrências diferentes a partir do mouse. Vamos
descrevê-las a seguir.
glutMouseFunc
void glutMouseFunc(void (*func)(int button, int state, int x, int y)) Este evento detecta
quando algum botão do mouse foi pressionado. Quando isto ocorre, o programa executa
a rotina definida em void (*func). Os parâmetros desta rotina podem receber os
seguintes valores:
- button : informa qual botão do mouse foi pressionado, sendo atribuído com um dos
seguintes valores: GLUT_LEFT_BUTTON, GLUT_MIDDLE_BUTTON,
GLUT_RIGHT_BUTTON.
- state: informa quando o botão foi pressionado e quando o botão foi solto, sendo
atribuído com dois possíveis valores: GLUT_DOWN ou GLUT_UP.
- X,y: informa a posição do mouse na janela quando o botão foi pressionado.
Como exemplo, vamos alterar o programa função anterior, e acrescentar outra forma de
interrupção para alterar o domínio. Assim se o usuário pressionar o botão esquerdo do
/* * * * * * * * * * * * * * */
/* Modulo: funcao010.cpp */
/* * * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "funcao011.h"
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
plota_funcao();
glFlush();
}
void le_tecla(unsigned char key, int x, int y)
{
switch(key)
{
case 'D':
case 'd':
entra_dominio();
display();
break;
}
}
void le_botao_mouse(int b,int state,int x, int y)
{
switch(b) {
case GLUT_RIGHT_BUTTON:
switch(state) {
case GLUT_DOWN:
entra_dominio();
display();
break;
case GLUT_UP:
printf(" x = %d y = %d \n",x,y);
break;
}
break;
}
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
glutDisplayFunc(display);
glutKeyboardFunc(le_tecla);
glutMouseFunc(le_botao_mouse);
glutMainLoop();
}
glutMotionFunc
void glutMotionFunc(void (*func)(int x, int y))
Este evento detecta o movimento do mouse enquanto algum botão do mouse está
pressionado. Quando isto ocorre, o programa executa a rotina definida em void (*func)
e informa em x,y a posição do mouse na janela. No exemplo abaixo, a rotina
le_botao_movimento_mouse(int x, int y) imprime a posição do mouse enquanto
mantemos um de seus botões pressionados.
/* * * * * * * * * * * * */
/* Programa mouse01.cpp */
/* * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glFlush();
}
void le_botao_movimento_mouse(int x, int y)
{
printf("Botao+movimento x = %d y = %d \n",x,y);
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Mouse");
glutDisplayFunc(display);
glutMotionFunc(le_botao_movimento_mouse);
glutMainLoop();
}
glutPassiveMotionFunc
/* * * * * * * * * * * * */
/* Programa mouse02.cpp */
/* * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glFlush();
}
void le_movimento_mouse(int x, int y)
{
printf("Movimento x = %d y = %d \n",x,y);
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Mouse");
glutDisplayFunc(display);
glutPassiveMotionFunc(le_movimento_mouse);
glutMainLoop();
}
CURVAS PARAMÉTRICAS
Introdução
Considere uma curva C representando a trajetória de uma partícula P, de tal forma que a
posição P(x,y) da partícula é conhecida em cada instante de tempo t. Assim as
coordenadas x e y são conhecidas como funções da variável t de modo que:
x = x(t)
y = y(t)
Estas são as equações paramétricas da curva C e t é denominado parâmetro. Como
exemplo de curvas temos:
a) Circunferência de centro na origem e raio 1:
x = cos(t)
y = sen(t) onde 0 <= t <= 2*Pi
b) Ciclóide (curva traçada por um ponto da circunferência quando o círculo rola sobre
uma reta):
x = t - sen(t)
y = 1 - cos(t)
/* * * * * * * * * * * * * */
/* Modulo: Curvas010.cpp */
/* * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "curvas011.h"
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
plota_curva();
glFlush();
}
void le_tecla(unsigned char key, int x, int y)
{
switch(key)
{
case 'D':
case 'd':
entra_dominio();
display();
break;
}
}
void le_botao_mouse(int b,int state,int x, int y)
{
switch(b) {
case GLUT_RIGHT_BUTTON:
switch(state) {
case GLUT_DOWN:
entra_dominio();
display();
Robótica Teoria e Prática
Robótica Teoria e Prática
break;
case GLUT_UP:
break;
}
break;
}
}
void main(int argc, char **argv)
{
22
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
glutDisplayFunc(display);
glutKeyboardFunc(le_tecla);
glutMouseFunc(le_botao_mouse);
glutMainLoop();
}
Módulo curvas011.cpp
Neste módulo implementamos o desenho do gráfico das curvas paramétricas. As
funções plota_eixo e entra_domínio não sofrem alterações.
/* * * * * * * * * * * * * */
/* Modulo: Curvas011.cpp */
/* * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
#define PI (4.0*atan(1.0))
float xmin = -1.0;
float ymin = -1.0;
float xmax = 1.0;
float ymax = 1.0;
float incremento = 0.01;
/* -------------------------------- */
void curva(float t,float *x,float *y)
/* float t (entrada) */
/* float *x (saida) */
/* float *y (saida) */
{
*x = cos(t);
*y = sin(t);
}
void plota_eixo()
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
void plota_curva()
{
float x,y,t;
glColor3f(1.0,0.0,0.0);
for(t=0;t < 2*PI; t+=incremento)
{
curva(t,&x,&y);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
}
}
void entra_dominio()
{
int pontos;
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
Módulo curvas011.h
Exercício
Como exercício implemente:
1) Curva ciclóide (t assume qualquer valor real).
2) x(t) = 3*t*t, y(t)=4*t*t*t (t assume qualquer valor real).
3) x(t) = cos(2*t), y(t)= sin(2*t) (0 <= t <= 2*PI) (Qual a diferença para a curva do
programa ?)
Para formar as coordenadas polares considere um ponto fixo O, denominado origem (ou
polo) e um eixo partindo de O, denominado eixo polar. A cada ponto P do plano
podemos associar uma par de coordenadas polares (r,theta) onde:
r: distância orientada da origem ao ponto P.
theta: ângulo entre o eixo polar e o segmento OP.
0=m
r = sin0
d) Cardióide
r = a(1+ cos(0))
e) Espiral
r = a0
f) Rosácea
r = asen(n0 )
Para visualizar as curvas polares, podemos utilizar o mesmo programa das curvas
paramétricas. Para isso, considere uma curva dada na forma polar:
r = f (0)
Assim temos uma curva na forma paramétrica. Como exemplo vamos visualizar a curva
do cardióide, alterando apenas a rotina curva do programa anterior:
/* -------------------------------- */
void curva(float t,float *x,float *y)
/* float t (entrada) */
/* float *x (saida) */
/* float *y (saida) */
/* -------------------------------- */
/* -------------------------------- */
{
*x = (1+cos(t))*cos(t);
*y = (1+cos(t))*sin(t);
}
Exercícios
1) Como exercício visualize as demais curvas dadas em coordenadas polares.
2) Visualize a curva dada em coordenadas polares por r = sec(theta).
Além de pontos e retas, o OpenGL possui no total 10 tipos de primitivas úteis. Todos os
modelos da tabela abaixo devem ser utilizados iniciando com glBegin(...) e finalizando
com glEnd(...),
por exemplo para o GL_LINES temos:
glBegin(GL_LINES);
glVertex2f(1.0,1.0);
glVertex2f(1.0,2.0);
glVertex2f(2.0,-2.0);
...
glEnd();
GL_POINTS Pontos individuais.
GL_LINES Reta entre dois pontos.
GL_POLYGON Polígono convexo .
GL_TRIANGLES Tripla de vértices é interpretado como um
triângulo.
GL_QUADS Conjunto de quatro vértices interpretado como
quadrilátero.
GL_LINE_STRIP Sequência de retas.
GL_LINE_LOOP Idêntico ao anterior, porém com uma reta unindo o
primeiro e último vértice.
GL_TRIANGLE_STRIP Lista de triângulos.
GL_TRAINGLE_FAN Lista de triângulos com o primeiro vértice em
comum.
GL_QUAD_STRIP Lista de quadriláteros.
Como exemplo de aplicação dos novos objetos vamos visualizar alguns métodos
numéricos de integração: ponto à direita, ponto à esquerda e trapézio.
Módulo Intvis01.c
/* * * * * * * * * * * * * * */
/* Modulo: Intvis01.c */
/* * * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "Intvis02.h"
#include "Intvis03.h"
extern int tipo,visual;
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
plota_funcao();
plota_integral();
glFlush();
glutSwapBuffers();
}
void le_tecla(unsigned char key, int x, int y)
{
switch(key)
{
case 'D':
case 'd':
entra_dominio();
display();
break;
case 'I':
case 'i':
entra_limites();
display();
break;
case '0':
tipo = 0;
display();
break;
case '1':
tipo = 1;
display();
break;
}
}
Módulo Intvis02.cpp
/* * * * * * * * * * * * * * */
/* Modulo: Intvis02.cpp */
/* * * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
float xmin = -10.0;
float ymin = -10.0;
float xmax = 10.0;
float ymax = 10.0;
float incremento = 0.01;
float funcao(float x)
{
return(sin(x));
}
void plota_eixo()
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
Robótica Teoria e Prática
Robótica Teoria e Prática
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
void plota_funcao()
{
float x,y;
glColor3f(1.0,0.0,0.0);
for(x=xmin;x<xmax;x+=incremento)
{
y = funcao(x);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
}
}
void entra_dominio()
{
int pontos;
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
Módulo Intvis03.cpp
Neste módulo separamos as rotinas que responsáveis pela visualização dos numéricos
métodos de integração.
/* * * * * * * * * * * * * * */
/* Modulo: Intvis03.cpp */
/* * * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include "Intvis02.h"
float a = 0;
float b = 1;
int tipo = 0;
int visual = 0;
int divisoes = 5;
Robótica Teoria e Prática
Robótica Teoria e Prática
void Integral_retangulo()
{
int i ;
float x,y;
float dx;
dx = (b-a)/divisoes;
for(i=0; i < divisoes; i++)
{
x = a+ i*dx;
y = funcao(x);
glColor3f(1.0,1.0,0.0);
if (visual == 0)
glBegin(GL_LINE_LOOP);
else
glBegin(GL_POLYGON);
glVertex2f(x,y);
glVertex2f(x+dx,y);
glVertex2f(x+dx,0);
glVertex2f(x,0);
glEnd();
}
}
void Integral_trapezio()
{
int i ;
float x,y1,y2;
float dx;
dx = (b-a)/divisoes;
for(i=0; i < divisoes; i++)
{
x = a+ i*dx;
y1 = funcao(x);
y2 = funcao(x + dx);
glColor3f(1.0,1.0,0.0);
if (visual == 0)
glBegin(GL_LINE_LOOP);
else
glBegin(GL_POLYGON);
31
glVertex2f(x,y1);
glVertex2f(x+dx,y2);
glVertex2f(x+dx,0);
glVertex2f(x,0);
glEnd();
}
}
void plota_integral()
{
switch(tipo) {
case 0:
Robótica Teoria e Prática
Robótica Teoria e Prática
Integral_retangulo();
break;
case 1:
Integral_trapezio();
break;
}
}
void entra_limites()
{
printf("Limites de Integracao \n");
printf("a = ");
scanf("%f",&a);
printf("\nb = ");
scanf("%f",&b);
printf("\ndivisoes = ");
scanf("%d",&divisoes);
}
/* * * * * * * * * * * * * * * * * */
/* Modulo: Funcao.cpp (com zoom) */
/* * * * * * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "plota.h"
int mov = 0; /* Detecta o movimento do mouse */
int xv1,xv2,yv1,yv2; /* Domínio da nova janela */
void redesenha()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
plota_funcao();
if (mov == 1)
plota_retangulo(xv1,yv1,xv2,yv2);
glFlush();
Robótica Teoria e Prática
Robótica Teoria e Prática
glutSwapBuffers();
}
void le_botao_movimento_mouse(int x,int y)
{
xv2 = x;
yv2 = y;
redesenha();
}
void le_botao_mouse(int b,int state,int x,int y)
{
switch(b) {
case GLUT_LEFT_BUTTON:
switch(state) {
case GLUT_DOWN:
xv1 = x;
yv1 = y;
mov = 1;
break;
case GLUT_UP:
mov = 0;
xv2 = x;
yv2 = y;
recalcula_dominio(xv1,yv1,xv2,yv2);
redesenha();
break;
}
break;
}
}
void le_tecla(unsigned char key, int x, int y)
{
switch(key)
{
case 'D':
case 'd':
entra_dominio();
redesenha();
break;
}
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
glutDisplayFunc(redesenha);
glutKeyboardFunc(le_tecla);
glutMouseFunc(le_botao_mouse);
Robótica Teoria e Prática
Robótica Teoria e Prática
glutMotionFunc(le_botao_movimento_mouse);
glutMainLoop();
}
/* * * * * * * * * * * * * * * * */
/* Modulo: plota.cpp (com zoom) */
/* * * * * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
#include "funcao.h"
#define PI 3.1415926535897932384626433832795
float xmin = -1.0;
float ymin = -1.0;
float xmax = 1.0;
float ymax = 1.0;
int pontos = 400;
/* -------------------------------- */
float funcao(float x)
/* -------------------------------- */
{
return(sin(50*PI*x));
}
/* -------------------------------- */
void plota_eixo()
/* -------------------------------- */
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
/* -------------------------------- */
void plota_funcao()
/* -------------------------------- */
{
int i ;
float dx ;
float x,y;
dx = (xmax - xmin)/pontos;
glColor3f(1.0,0.0,0.0);
x = xmin;
for(i=0;i<pontos;i++)
{
y = funcao(x);
glBegin(GL_POINTS);
glVertex2f(x,y);
glEnd();
Robótica Teoria e Prática
Robótica Teoria e Prática
x = x + dx;
}
}
/* -------------------------------- */
void plota_retangulo(int x,int y,int xv1,int yv1)
/* -------------------------------- */
{
float t;
float retxmin,retxmax,retymin,retymax;
t = (float)xv1 / 400.0;
retxmin = xmin + t * (xmax-xmin);
t = (float)x / 400.0;
retxmax = xmin + t * (xmax-xmin);
t = (float)y / 400.0;
retymin = ymax - t * (ymax-ymin);
t = (float)yv1 / 400.0;
retymax = ymax - t * (ymax-ymin);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINE_LOOP);
glVertex2f(retxmin,retymin);
glVertex2f(retxmin,retymax);
glVertex2f(retxmax,retymax);
glVertex2f(retxmax,retymin);
glEnd();
}
/* -------------------------------- */
void entra_dominio()
/* -------------------------------- */
{
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
}
/* --------------------------------------------------------------- */
void recalcula_dominio(float xv_1,float yv_1,float xv_2,float yv_2)
/* --------------------------------------------------------------- */
{
float t;
float xmin1,xmax1;
float ymin1,ymax1;
t = (float)xv_1 / 400;
Robótica Teoria e Prática
Robótica Teoria e Prática
CURVAS IMPLÍCITAS
Introdução
Já aprendemos na seção 3 como representar curvas na forma paramétrica. Vamos
discutir agora outro tipo de representação muito utilizada para curvas: a representação
implícita. A equação implícita de uma curva descreve uma relação entre as coordenadas
x e y dos pontos que pertencem a curva. Assim no plano xy a equação implícita de uma
curva tem a forma :
f (x, y) = 0
Observe que não é simples exibir um conjunto de pontos que pertençam a esta curva.
Vamos definir uma função de duas variáveis z = f (x, y) utilizando a equação acima, da
seguinte forma:
- Se V1 * V2 < 0, então a função se anula em um ponto entre V1 e V2. Este ponto pode
ser
aproximado linearmente.
- Se V1 * V3 < 0, então a função se anula em um ponto entre V1 e V3.
- Se V2 * V3 < 0, então a função se anula em um ponto entre V2 e V3.
- Se V1 = 0, então a função se anula exatamente sobre o vértice V1.
- Se V2 = 0, então a função se anula exatamente sobre o vértice V2.
- Se V3 = 0, então a função se anula exatamente sobre o vértice V3.
- Considerando que exatamente duas das condições acima se verificaram
simultaneamente, aproximamos a curva nesse triângulo por um segmento de reta unindo
os dois pontos obtidos.
/* * * * * * * * * * * * * */
/* Modulo: impl010.cpp */
/* * * * * * * * * * * * * */
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "impl011.h"
extern float xmin,xmax,ymin,ymax;
void display()
{
glClearColor(1.0,1.0,1.0,1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
plota_curva_implicita();
glFlush();
glutSwapBuffers();
}
void le_tecla(unsigned char key, int x, int y)
{
switch(key)
{
case 'D':
case 'd':
entra_dominio();
display();
break;
}
}
void le_botao_mouse(int b,int state,int x, int y)
{
switch(b) {
case GLUT_RIGHT_BUTTON:
switch(state) {
case GLUT_DOWN:
break;
case GLUT_UP:
printf(" x = %d y = %d \n",x,y);
break;
}
break;
}
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(400,400);
glutInitWindowPosition(50,50);
glutCreateWindow("Ponto");
glutDisplayFunc(display);
gluOrtho2D(xmin,xmax,ymin,ymax);
Robótica Teoria e Prática
Robótica Teoria e Prática
glutKeyboardFunc(le_tecla);
glutMouseFunc(le_botao_mouse);
glutMainLoop();
}
Módulo impl011.cpp
Neste módulo implementamos o desenho do gráfico das curvas implícitas. As funções
plota_eixo e entra_domínio não sofrem alterações.
/* * * * * * * * * * * * * */
/* Modulo: impl011.cpp */
/* * * * * * * * * * * * * */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
float xmin = -2.0;
float ymin = -2.0;
float xmax = 2.0;
float ymax = 2.0;
float incremento = 0.1;
float funcao(float x,float y)
{
return(sqrt(x*x+y*y)-((x*x-y*y)/(x*x+y*y))+sin(x*y));
}
void plota_eixo()
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
void triangulo(float x1,float y1,float x2,float y2,float x3,float y3)
{
int i = 0;
float t;
float x[3],y[3];
float s1,s2,s3;
glColor3f(0.0,0.0,1.0);
glBegin(GL_LINE_LOOP);
glVertex2f(x1,y1);
glVertex2f(x2,y2);
glVertex2f(x3,y3);
glEnd();
s1 = funcao(x1,y1);
s2 = funcao(x2,y2);
s3 = funcao(x3,y3);
if ((s1 * s2) < 0) {
Robótica Teoria e Prática
Robótica Teoria e Prática
t = -s1/(s2-s1);
x[i] = x1 + t * (x2-x1);
y[i] = y1;
i++;
}
if ((s1 * s3) < 0) {
t = -s1/(s3-s1);
x[i] = x1 ;
y[i] = y1 + t * (y3-y1);
i++;
}
if ((s2 * s3) < 0) {
t = -s2/(s3-s2);
x[i] = x2 + t * (x3-x2);
y[i] = y2 + t * (y3-y2);
i++;
}
if (s1 == 0) {
x[i] = x1;
y[i] = y1;
i++;
}
if (s2 == 0) {
x[i] = x2;
y[i] = y2;
i++;
}
if (s3 == 0) {
x[i] = x3;
y[i] = y3;
39
i++;
}
if (i == 2) {
glLineWidth(2.0);
glColor3f(1.0,0.0,0.0);
glBegin(GL_LINES);
glVertex2f(x[0],y[0]);
glVertex2f(x[1],y[1]);
glEnd();
glLineWidth(1.0);
}
}
void plota_curva_implicita()
{
float x,y;
glColor3f(1.0,0.0,0.0);
for(x=xmin;x<xmax;x+=incremento)
{
for(y=ymin;y<ymax;y+=incremento)
Robótica Teoria e Prática
Robótica Teoria e Prática
{
triangulo(x,y,x+incremento,y,x,y+incremento);
triangulo(x+incremento,y+incremento,x,y+incremento,x+incremento,y);
}
}
}
void entra_dominio()
{
int pontos;
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Divisoes =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
Módulo impl011.h
void plota_eixo();
void plota_curva_implicita();
void entra_dominio();
FRACTAIS
Exemplos de fractais
Alguns dos principais exemplos que apresentaremos nesta seção foram gerados
utilizando composição de transformações de rotação e escala seguido de uma possível
translação. O formato geral da função é dado por:
Triângulo de Sierpinski
Para obter o triângulo de Sierpinski, utilizaremos uma aplicação que a partir de um
triângulo, obtém três novos triângulos conforme a figura abaixo:
Módulo frac010.cpp
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include "fract011.h"
extern float xmax,xmin,ymax,ymin;
extern float incremento;
extern int pontos;
int xp[2],yp[2];
int tamx = 400;
int tamy = 400;
int st = -1;
void display()
{
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_funcao(0.0,0.0,1.0,0.0,0.0,1.0,6);
glFlush();
glutSwapBuffers();
}
void le_tecla(unsigned char key, int x, int y)
{
switch(key)
{
case 'I':
case 'i':
entra_dominio();
break;
}
}
void botao_mouse(int b,int state,int x, int y)
{
float t;
float xmin1,xmax1,ymin1,ymax1;
switch(b) {
case GLUT_LEFT_BUTTON:
switch(state) {
case GLUT_DOWN:
xp[0] = x;
yp[0] = y;
st = 0;
printf("down %d %d ",x,y);
break;
case GLUT_UP:
xp[1] = x;
yp[1] = y;
printf("up %d %d ",x,y);
t = (float)xp[0] / tamx;
xmin1 = xmin + t * (xmax-xmin);
t = (float)xp[1] / tamx;
xmax1 = xmin + t * (xmax-xmin);
xmin = xmin1;
xmax = xmax1;
t = (float)yp[1] / tamy;
ymin1 = ymax - t * (ymax-ymin);
t = (float)yp[0] / tamy;
ymax1 = ymax - t * (ymax-ymin);
ymin = ymin1;
ymax = ymax1;
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
display();
break;
}
break;
}
}
void mov_mouse(int x, int y)
{
float t;
float xmin1,xmax1,ymin1,ymax1;
t = (float)xp[0] / tamx;
xmin1 = xmin + t * (xmax-xmin);
t = (float)x / tamx;
xmax1 = xmin + t * (xmax-xmin);
t = (float)y / tamy;
ymin1 = ymax - t * (ymax-ymin);
t = (float)yp[0] / tamy;
ymax1 = ymax - t * (ymax-ymin);
display();
glDrawBuffer(GL_FRONT);
Robótica Teoria e Prática
Robótica Teoria e Prática
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINE_STRIP);
glVertex2f(xmin1,ymin1);
glVertex2f(xmin1,ymax1);
glVertex2f(xmax1,ymax1);
glVertex2f(xmax1,ymin1);
glVertex2f(xmin1,ymin1);
glEnd();
glDrawBuffer(GL_BACK);
glFlush();
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(tamx,tamy);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
glutDisplayFunc(display);
gluOrtho2D(xmin,xmax,ymin,ymax);
glutKeyboardFunc(le_tecla);
glutMouseFunc(botao_mouse);
glutMotionFunc(mov_mouse);
glutMainLoop();
}
Módulo frac011.cpp
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
float xmin = -2;
float ymin = -2;
float xmax = 2;
float ymax = 2;
float incremento = 0.01;
int pontos = 1000;
void funcao(float *x,float *y,float e,float f)
{
*x = *x/2 + e;
*y = *y/2 + f;
}
void plota_eixo()
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
Robótica Teoria e Prática
Robótica Teoria e Prática
glVertex2f(0,ymax);
glEnd();
}
void plota_funcao(float x0,float y0,
float x1,float y1,
float x2,float y2,
int n)
{
int i,j;
float x[3][3],y[3][3];
float e[3] = {0.0, 0.5, 0.0};
float f[3] = {0.0, 0.0, 0.5};
for(i=0;i<3;i++) {
x[i][0] = x0;
y[i][0] = y0;
x[i][1] = x1;
y[i][1] = y1;
x[i][2] = x2;
y[i][2] = y2;
}
for(i=0;i<3;i++)
for (j=0;j<3;j++)
funcao(&(x[j][i]),&(y[j][i]),e[j],f[j]);
if (n == 0) {
for (i=0;i<3;i++) {
glColor3f(1.0,0.0,0.0);
glBegin(GL_POLYGON);
glVertex2f(x[i][0],y[i][0]);
glVertex2f(x[i][1],y[i][1]);
glVertex2f(x[i][2],y[i][2]);
glEnd();
}
return;
}
else {
for(i=0;i<3;i++)
plota_funcao(x[i][0],y[i][0],x[i][1],y[i][1],
x[i][2],y[i][2],n-1);
}
}
void entra_dominio()
{
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
Robótica Teoria e Prática
Robótica Teoria e Prática
Módulo frac011.h
void funcao(float *x,float *y,float e,float f);
void plota_eixo();
void plota_funcao(float x0,float y0,float x1,float y1,
float x2,float y2,int n);
void entra_dominio();
…….
#include <math.h>
#include "fract021.h"
........
void display()
{
........
plota_funcao(1.5,-1.8);
........
}
.........
Módulo frac021.cpp
/* * * * * * * * * * * * * * * * * **/
/* Triangulo Sierpinski Monte Carlo */
/* fract021.cpp */
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <gl\glut.h>
float xmin = -2;
float ymin = -2;
float xmax = 2;
float ymax = 2;
float incremento = 0.01;
int pontos = 1000;
void funcao(float *x,float *y,float e,float f)
{
*x = *x/2 + e;
*y = *y/2 + f;
}
void plota_eixo()
{
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINES);
glVertex2f(xmin,0);
glVertex2f(xmax,0);
glVertex2f(0,ymin);
glVertex2f(0,ymax);
glEnd();
}
void plota_funcao(float x0,float y0)
{
int i,j;
float x[3][4],y[3][4];
float e[3] = {0.0, 0.5, 0.0};
float f[3] = {0.0, 0.0, 0.5};
srand( (unsigned)time( NULL ) );
for(i=0;i<20000;i++) {
j = (int) (3.0 * ((float)rand())/ RAND_MAX);
j = ( j > 2) ? 2 : j;
funcao(&x0,&y0,e[j],f[j]);
glColor3f(1.0,0.0,0.0);
Robótica Teoria e Prática
Robótica Teoria e Prática
glBegin(GL_POINTS);
glVertex2f(x0,y0);
glEnd();
}
}
void entra_dominio()
{
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
…………
#include "fract031.h"
…………………
void display()
{
int i;
float x[4] = {0.0,1.0,1.0,0.0};
float y[4] = {0.0,0.0,1.0,1.0};
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_funcao(x,y,8);
glFlush();
}
....................
Módulo frac031.cpp
/* * * * * * * * * * * */
/* Fractal Fern */
/* fract031.cpp */
#include <stdio.h>
#include <math.h>
#include <gl\glut.h>
float xmin = -0.2;
float ymin = -0.2;
float xmax = 2;
float ymax = 2;
float incremento = 0.01;
int pontos = 1000;
void T(float a11,float a12,float a21,float a22,float e,float f,float
*x1,float *y1)
{
float xx;
float yy;
49
xx = a11 * *x1 + a12 * *y1 + e;
yy = a21 * *x1 + a22 * *y1 + f;
*x1 = xx;
*y1 = yy;
}
void plota_funcao(float *x,float *y,int n)
{
int i,j;
float xx[4][4],yy[4][4];
for(i=0;i<4;i++)
for(j=0;j<4;j++)
{
xx[i][j] = x[j];
yy[i][j] = y[j];
}
if (n == 0) {
glColor3f(0.0,1.0,0.0);
glBegin(GL_LINE_LOOP);
glVertex2f(x[0],y[0]);
glVertex2f(x[1],y[1]);
glVertex2f(x[2],y[2]);
glVertex2f(x[3],y[3]);
glEnd();
return;
}
else {
for(i=0;i<4;i++) {
T( 0.20,-0.26, 0.23, 0.22,0.400,
0.045,&(xx[0][i]),&(yy[0][i]));
T( 0.85, 0.04,-0.04, 0.85,0.075,
0.180,&(xx[1][i]),&(yy[1][i]));
T( 0.00, 0.00, 0.00, 0.16,0.500,
0.000,&(xx[2][i]),&(yy[2][i]));
T(-0.15, 0.28, 0.26, 0.24,0.575,-
0.086,&(xx[3][i]),&(yy[3][i]));
}
plota_funcao(xx[0],yy[0],n-1);
plota_funcao(xx[1],yy[1],n-1);
plota_funcao(xx[2],yy[2],n-1);
plota_funcao(xx[3],yy[3],n-1);
}
Robótica Teoria e Prática
Robótica Teoria e Prática
}
void entra_dominio()
{
printf("xmin = ");
scanf("%f",&xmin);
printf("\nymin = ");
scanf("%f",&ymin);
printf("\nxmax = ");
scanf("%f",&xmax);
printf("\nymax = ");
scanf("%f",&ymax);
printf("\n Total de pontos =");
scanf("%d",&pontos);
glLoadIdentity();
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
Curva de Koch
Módulo frac040.cpp
#include <gl\glut.h>
#include <stdio.h>
#include <math.h>
#include <conio.h>
#include "fract041.h"
extern float xmax,xmin,ymax,ymin;
extern float incremento;
extern int pontos;
int xp[2],yp[2];
int tamx = 400;
int tamy = 400;
int st = -1;
void display()
{
int i;
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_eixo();
for(i=0;i<7;i++) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
plota_funcao(-1.0,1.0,1.0,1.0,i);
plota_funcao( 1.0,1.0,0.0,-1.0,i);
plota_funcao(0.0,-1.0,-1.0,1.0,i);
glFlush();
glutSwapBuffers();
getch();
}
glFlush();
glutSwapBuffers();
}
Robótica Teoria e Prática
Robótica Teoria e Prática
float t;
float xmin1,xmax1,ymin1,ymax1;
t = (float)xp[0] / tamx;
xmin1 = xmin + t * (xmax-xmin);
t = (float)x / tamx;
xmax1 = xmin + t * (xmax-xmin);
t = (float)y / tamy;
ymin1 = ymax - t * (ymax-ymin);
t = (float)yp[0] / tamy;
ymax1 = ymax - t * (ymax-ymin);
display();
glDrawBuffer(GL_FRONT);
glColor3f(1.0,1.0,1.0);
glBegin(GL_LINE_STRIP);
glVertex2f(xmin1,ymin1);
glVertex2f(xmin1,ymax1);
glVertex2f(xmax1,ymax1);
glVertex2f(xmax1,ymin1);
glVertex2f(xmin1,ymin1);
glEnd();
glDrawBuffer(GL_BACK);
glFlush();
}
void main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(tamx,tamy);
glutInitWindowPosition(50,50);
glutCreateWindow("Funcao");
glutDisplayFunc(display);
gluOrtho2D(xmin,xmax,ymin,ymax);
glutKeyboardFunc(le_tecla);
glutMouseFunc(botao_mouse);
glutMotionFunc(mov_mouse);
glutMainLoop();
}
Módulo frac041.cpp
/* * * * * * * * * * * */
/* Fractal Curva Koch */
/* fract041.cpp */
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <gl\glut.h>
float xmin = -2;
float ymin = -2;
float xmax = 2;
float ymax = 2;
Robótica Teoria e Prática
Robótica Teoria e Prática
gluOrtho2D(xmin,xmax,ymin,ymax);
incremento = fabs(xmax-xmin)/pontos;
}
Bibliografia:
Estrato de aulas do curso de Mecatrônica da Escola Politécnica de Minas Gerais
POLIMIG – Matéria Robótica Industrial Prof. Orlando Laoboissier
Sites:
www.robotrom.com
www.nasa.gov
www.bionix.com
www.rogeriodumba.com.br