Académique Documents
Professionnel Documents
Culture Documents
Contedo
1
Introduo
1.1 Linguagens de Programao . . . . . . . . . . . . . . . . . . .
1.2 Lisp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1.3 Exerccios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
2
5
6
7
7
7
8
9
9
10
11
13
15
15
16
17
20
22
22
23
27
30
32
33
35
35
36
36
36
37
37
38
38
39
40
41
43
Modelao Geomtrica
3.1 Coordenadas . . . . . . . . . . . . . . . . . . . .
3.2 Listas . . . . . . . . . . . . . . . . . . . . . . . .
3.3 Operaes com Coordenadas . . . . . . . . . .
3.4 Abstraco de Dados . . . . . . . . . . . . . . .
3.5 Tipos Abstractos . . . . . . . . . . . . . . . . . .
3.6 Coordenadas Bidimensionais . . . . . . . . . .
3.7 Coordenadas em AutoCad . . . . . . . . . . . .
3.8 Coordenadas Polares . . . . . . . . . . . . . . .
3.9 A funo command . . . . . . . . . . . . . . . .
3.10 Variantes de Comandos . . . . . . . . . . . . .
3.11 ngulos em Comandos . . . . . . . . . . . . . .
3.12 Efeitos Secundrios . . . . . . . . . . . . . . . .
3.13 Sequenciao . . . . . . . . . . . . . . . . . . .
3.14 A Ordem Drica . . . . . . . . . . . . . . . . . .
3.15 Parametrizao de Figuras Geomtricas . . . .
3.16 Documentao . . . . . . . . . . . . . . . . . . .
3.17 Depurao . . . . . . . . . . . . . . . . . . . . .
3.17.1 Erros Sintticos . . . . . . . . . . . . . .
3.17.2 Erros Semnticos . . . . . . . . . . . . .
3.18 Modelao Tridimensional . . . . . . . . . . . .
3.18.1 Slidos Tridimensionais Pr-Definidos .
3.18.2 Coordenadas Cilndricas . . . . . . . . .
3.18.3 Coordenadas Esfricas . . . . . . . . . .
3.18.4 Modelao de Colunas Dricas . . . . .
Funes
4.1 Variveis Locais . . . . . . . . . . . .
4.1.1 Declarao . . . . . . . . . . .
4.1.2 Atribuio . . . . . . . . . . .
4.2 Variveis Globais . . . . . . . . . . .
4.3 Variveis Indefinidas . . . . . . . . .
4.4 Propores de Vitrvio . . . . . . . .
4.5 Recurso . . . . . . . . . . . . . . . .
4.6 Recurso em Arquitectura . . . . . .
4.7 Depurao de Programas Recursivos
4.7.1 Trace . . . . . . . . . . . . . .
4.8 Templos Dricos . . . . . . . . . . . .
4.9 A Ordem Jnica . . . . . . . . . . . .
4.10 Recurso na Natureza . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
44
44
45
46
47
50
52
53
54
56
62
63
65
65
68
72
75
79
79
81
83
83
88
90
92
.
.
.
.
.
.
.
.
.
.
.
.
.
94
94
96
96
97
99
99
106
111
115
116
120
131
138
Atribuio
5.1 Aleatoriedade . . . . . . . . . . . . . . . . .
5.2 Nmeros Aleatrios . . . . . . . . . . . . .
5.3 Estado . . . . . . . . . . . . . . . . . . . . .
5.4 Estado Local e Estado Global . . . . . . . .
5.5 Escolhas Aleatrias . . . . . . . . . . . . . .
5.5.1 Nmeros Aleatrios Fraccionrios .
5.5.2 Nmeros Aleatrios num Intervalo
5.6 Planeamento Urbano . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
143
143
144
147
148
149
152
153
157
Listas
6.1 Pares . . . . . . . . . . . . . . . .
6.2 Representao Grfica de Pares .
6.3 Tipos Recursivos . . . . . . . . .
6.4 Recurso em Listas . . . . . . . .
6.5 Predicados sobre Listas . . . . . .
6.6 Enumeraes . . . . . . . . . . . .
6.7 Comparao de Listas . . . . . .
6.8 Comparao de Smbolos . . . .
6.9 Comparao Estrutural de Listas
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
165
167
168
169
170
174
176
178
180
181
Carregamento de Ficheiros
7.1 Carregamento de Dependncias .
7.2 Mdulos . . . . . . . . . . . . . .
7.3 Carregamento Automtico . . . .
7.4 Interpretao e Compilao . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
182
183
184
189
189
Listas de Coordenadas
8.1 Polgonos . . . . . . . . . . . . . .
8.1.1 Estrelas Regulares . . . .
8.1.2 Polgonos Regulares . . .
8.2 Iterao em Listas . . . . . . . . .
8.3 Linhas Poligonais e Splines . . . .
8.4 Trelias . . . . . . . . . . . . . . .
8.4.1 Desenho de Trelias . . .
8.4.2 Gerao de Coordenadas
8.4.3 Trelias Espaciais . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
191
191
192
196
197
200
204
205
212
216
Manipulao de Entidades
9.1 Listas de Associaes . . .
9.2 A funo assoc . . . . . .
9.3 Modificao de Entidades
9.4 Criao de Entidades . . .
9.5 Listas de Propriedades . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
221
223
225
226
226
229
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
9.6
9.7
9.8
9.9
9.10
9.11
9.12
9.13
9.14
9.15
9.16
9.17
9.18
9.19
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
236
237
237
238
239
241
241
244
245
246
247
247
257
260
266
276
277
279
Introduo
A transmisso de conhecimento um dos problemas que desde cedo preocupou a humanidade. Sendo o homem capaz de acumular conhecimento
ao longo de toda a sua vida, com desnimo que enfrenta a ideia de que,
com a morte, todo esse conhecimento se perca.
Para evitar esta perda, a humanidade inventou toda uma srie de mecanismos de transmisso de conhecimento. O primeiro, a transmisso oral,
consiste na transmisso do conhecimento de uma pessoa para um grupo reduzido de outras pessoas, de certa forma transferindo o problema da perda
de conhecimento para a gerao seguinte. O segundo, a transmisso escrita, consiste em registar em documentos o conhecimento que se pretende
transmitir. Esta forma tem a grande vantagem de, por um lado, poder chegar a muitas mais pessoas e, por outro, de reduzir significativamente o
risco de se perder o conhecimento por problemas de transmisso. De facto,
a palavra escrita permite preservar por muito tempo e sem qualquer tipo
de adulterao o conhecimento que o autor pretendeu transmitir.
graas palavra escrita que hoje conseguimos compreender e acumular um vastssimo conjunto de conhecimentos, muitos deles registados h
milhares de anos atrs.
Infelizmente, nem sempre a palavra escrita conseguiu transmitir com
rigor aquilo que o autor pretendia. A lngua natural tem inmeras ambiguidades e evolui substancialmente com o tempo, o que leva a que a interpretao dos textos seja sempre uma tarefa subjectiva. Quer quando escrevemos um texto, quer quando o lemos e o interpretamos, existem omisses,
imprecises, incorreces e ambiguidades que podem tornar a transmisso
de conhecimento falvel. Se o conhecimento que se est a transmitir for
simples, o receptor da informao, em geral, consegue ter a cultura e imaginao suficientes para conseguir ultrapassar os obstculos. No caso da
transmisso de conhecimentos mais complexos j isso poder ser muito
mais difcil.
Quando se exige rigor na transmisso de conhecimento, fazer depender a compreenso desse conhecimento da capacidade de interpretao de
quem o recebe pode ter consequncias desastrosas e, de facto, a histria
da humanidade est repleta de acontecimentos catastrficos cuja causa ,
to somente, uma insuficiente ou errnea transmisso de conhecimento,
ou uma deficiente compreenso do conhecimento transmitido.
Para evitar estes problemas, inventaram-se linguagens mais rigorosas.
A matemtica, em particular, tem-se obssessivamente preocupado ao longo
dos ltimos milnios com a construo de uma linguagem onde o rigor seja
absoluto. Isto permite que a transmisso do conhecimento matemtico seja
muito mais rigorosa que nas outras reas, reduzindo ao mnimo essencial a
capacidade de imaginao necessria de quem est a absorver esse conhecimento.
5
1.1
Linguagens de Programao
programao empregue o Auto Lisp, um dialecto de uma famosa linguagem de programao denominada Lisp.
Apesar de a linguagem GDL parecer ser muito diferente da linguagem
Auto Lisp, os conceitos fundamentais so muito semelhantes. sobre estes
conceitos fundamentais da programao que nos iremos debruar, embora,
por motivos pedaggicos, seja conveniente particulariz-los numa nica
linguagem. Neste texto iremos explicar os fundamentos da programao
atravs da utilizao da linguagem Auto Lisp, no s pela sua facilidade de
aprendizagem, mas tambm pela sua aplicabilidade prtica. No entanto,
uma vez apreendidos esses fundamentos, o leitor dever ser capaz de os
traduzir para qualquer outra linguagem de programao.
1.2
Lisp
1.3
Exerccios
Nesta seco vamos descrever a linguagem de programao Lisp que iremos usar ao longo deste texto. Antes, porm, vamos discutir alguns aspectos que so comuns a todas as linguagens.
2.1
2.2
Quando comparada com a grande maioria das outras linguagens de programao, a linguagem Lisp possui uma sintaxe extraordinariamente simples baseada no conceito de expresso.1
Uma expresso, em Lisp, pode ser construda empregando elementos
primitivos como, por exemplo, os nmeros; ou combinando outras expresses entre si como, por exemplo, quando somamos dois nmeros. Como
iremos ver, esta simples definio permite-nos construir expresses de complexidade arbitrria. No entanto, convm relembrar que a sintaxe restringe
aquilo que podemos escrever: o facto de podermos combinar expresses
para produzir outras expresses mais complexas no nos autoriza a escrever qualquer combinao de subexpresses. As combinaes obedecem a
regras sintticas que iremos descrever ao longo do texto.
semelhana do que acontece com a sintaxe, tambm a semntica da
linguagem Lisp , em geral, substancialmente mais simples que a de outras
linguagens de programao. Como iremos ver, a semntica determinada
pelos operadores que as nossas expresses iro empregar. Um operador de
soma, por exemplo, serve para somar dois nmeros. Uma combinao que
junte este operador e, por exemplo, os nmeros 3 e 4 tem, como significado, a soma de 3 com 4, i.e., 7. No caso das linguagens de programao, a
semntica de uma expresso dada pelo computador que a vai avaliar.
1
11
2.3
O Avaliador
2.4
Elementos da Linguagem
2.5
Nmeros
_$ 0.1
0.1
_$ .1
; error: misplaced dot on input
2.6
Combinaes
Uma combinao uma expresso que descreve a aplicao de um operador aos seus operandos. Por exemplo, na matemtica, os nmeros podem
ser combinados usando operaes como a soma ou o produto. Como exemplo de combinaes matemticas, temos 1+2 e 1+23. A soma e o produto
de nmeros so exemplos de operaes extremamente elementares consideradas procedimentos primitivos.
Em Lisp, cria-se uma combinao escrevendo uma sequncia de expresses entre um par de parnteses. Uma expresso um elemento primitivo
ou uma outra combinao. A expresso (+ 1 2) uma combinao dos
elementos primitivos 1 e 2 atravs do procedimento primitivo +. J no
caso (+ 1 (* 2 3)) a combinao entre 1 e (* 2 3), sendo esta ltima
expresso uma outra combinao. Note-se que cada expresso deve ser
separada das restantes por um ou mais espaos. Assim, embora a combinao (* 2 3) possua as trs expresses *, 2 e 3, a combinao (*2 3) s
possui duas*2 e 3sendo que a primeira delas no tem qualquer significado pr-definido.
Por agora, as nicas combinaes com utilidade so aquelas em que as
expresses correspondem a operadores e operandos. Por conveno, o Lisp
considera que o primeiro elemento de uma combinao um operador e os
restantes so os operandos.
A notao que o Lisp utiliza para construir expresses (operador primeiro e operandos a seguir) designada por notao prefixa por o operador ocorrer prviamente aos operandos. Esta notao costuma causar alguma perplexidade a quem inicia o estudo da linguagem, que espera uma
notao mais prxima da que aprendeu em aritmtica e que usada habitualmente nas outras linguagens de programao. Nestas, a expresso
(+ 1 (* 2 3)) usualmente escrita na forma 1 + 2 * 3 (designada notao infixa, por o operador ocorrer entre os operandos) que, normalmente,
14
15
2.7
Indentao
A desvantagem da notao prefixa est na escrita de combinaes complexas. Por exemplo, a expresso 1+2*3-4/5*6 l-se com relativa facilidade
mas, quando escrita na sintaxe do Lisp,(- (+ 1 (* 2 3)) (* (/ 4 5) 6)),
fica com uma forma que, para quem no est ainda habituado, pode ser
mais difcil de perceber devido acumulao de parnteses.
Para tornarmos estas expresses mais fceis de entender, podemos (e
devemos) empregar a tcnica da indentao. Esta tcnica baseia-se no uso
de diferentes alinhamentos na disposio textual dos programas de modo a
facilitar a sua leitura. Assim, ao invs de escrevermos as nossas expresses
todas numa linha ou com arranjos arbitrrios entre linhas, escrevemo-las
ao longo de vrias linhas e com um alinhamento entre linhas que mostre o
relacionamento das vrias subexpresses com a expresso que as contm.
A regra para indentao de combinaes Lisp extremamente simples:
numa linha coloca-se o operador e o primeiro operando; os restantes operandos vm alinhados por debaixo do primeiro, usando-se um nmero suficiente de espaos em branco esquerda para que os operandos fiquem
correctamente arrumados. No caso de uma expresso ser curta, podemos
escrev-la numa s linha, com os operandos logo a seguir ao operador, com
um espao em branco entre cada um. Usando estas duas regras, podemos
reescrever a expresso anterior na seguinte forma, onde usamos linhas verticais imaginrias para salientar a indentao:
(- (+ 1
(* 2 3))
(* (/ 4 5)
6))
(um-operador (um-operador-com-um-nome-muito-grande
1 2 3 4)
(outro-operador 5
6
(e-ainda-outro 7
8))
(e-o-ultimo-operador 9 10))
17
2.8
Avaliao de Combinaes
Como j vimos, o Lisp considera que o primeiro elemento de uma combinao um operador e os restantes so os operandos.
O avaliador determina o valor de uma combinao como o resultado de
aplicar o procedimento especificado pelo operador ao valor dos operandos.
O valor de cada operando designado de argumento do procedimento.
Assim, o valor da combinao (+ 1 (* 2 3)) o resultado de somar o
valor de 1 com o valor de (* 2 3). Como j se viu, 1 vale 1 e (* 2 3)
uma combinao cujo valor o resultado de multiplicar o valor de 2 pelo
valor de 3, o que d 6. Finalmente, somando 1 a 6 obtemos 7.
_$ (* 2 3)
6
_$ (+ 1 (* 2 3))
7
2.9
Cadeias de Caracteres
As cadeias de caracteres (tambm denominadas strings) so outro tipo de dados primitivo. Um carcter uma letra, um dgito ou qualquer outro smbolo grfico, incluindo os smbolos grficos no visveis como o espao, a
tabulao e outros. Uma cadeia de caracteres especificada atravs de uma
sequncia de caracteres delimitada por aspas. Tal como com os nmeros, o
valor de uma cadeia de caracteres a prpria cadeia de caracteres.
18
Sequncia
\\
\"
\e
\n
\r
\t
\nnn
Resultado
o carcter \ (backslash)
o carcter " (aspas)
o carcter escape
o carcter de mudana de linha (newline)
o carcter de mudana de linha (carriage return)
o carcter de tabulao (tab)
o carcter cujo cdigo octal nnn
Sendo uma string delimitada por aspas fica a dvida sobre como criar
uma string que contm aspas. Para isso, e para outros caracteres especiais,
existe um carcter que o Auto Lisp interpreta de forma distinta: quando,
na criao de uma string, aparece o carcter \ ele assinala que o prximo
carcter tem de ser processado de forma especial. Por exemplo, para se a
criar a string correspondente frase
O Manuel disse Bom dia! ao Pedro.
temos de escrever:
"O Manuel disse \"Bom dia!\" ao Pedro."
2.10
Operadores de Strings
Para alm dos operadores que j vimos para nmeros, existem operadores
para strings. Por exemplo, para concatenar vrias strings, existe o operador
strcat. A concatenao de vrias strings produz uma s string com todos
os caracteres dessas vrias strings e pela mesma ordem:
19
2.11
Definio de Funes
Para alm das operaes bsicas aritmticas, a matemtica disponibilizanos um vastssimo conjunto de outras operaes que se definem custa
daquelas. Por exemplo, o quadrado de um nmero uma operao (tambm
designada por funo) que, dado um nmero, produz o resultado de multiplicar esse nmero por ele prprio. Matematicamente falando, define-se o
quadrado de um nmero pela funo x2 = x x.
20
Tal como em matemtica, pode-se definir numa linguagem de programao a funo que obtm o quadrado de um nmero. Em Lisp, para
obtermos o quadrado de um nmero qualquer, por exemplo, 5, escrevemos a combinao (* 5 5). No caso geral, dado um nmero qualquer x,
sabemos que obtemos o seu quadrado escrevendo (* x x). Falta apenas
associar um nome que indique que, dado um nmero x, obtemos o seu quadrado avaliando (* x x). Lisp permite-nos fazer isso atravs da operao
defun (abreviatura de define function):
_$ (defun quadrado (x) (* x x))
QUADRADO
prprio (* x x). Esta definio associa a palavra quadrado a um procedimento, i.e., a uma descrio do modo de produzir o resultado pretendido.
Note-se que este procedimento possui parmetros, permitindo o seu uso
com diferentes argumentos. Para se utilizar este procedimento, podemos
avaliar as seguinte expresses:
_$ (quadrado 5)
25
_$ (quadrado 6)
36
(quadrado (* 3 3))
(quadrado 9)
(* 9 9)
81
Em resumo, para se invocar uma funo, necessrio construir uma
combinao cujo primeiro elemento seja uma expresso que avalia para a
funo que se pretende invocar e cujos restantes elementos so expresses
que avaliam para os argumentos que se pretende passar funo. O resultado da avaliao da combinao o valor calculado pela funo para
aqueles argumentos.
A avaliao de uma combinao deste gnero processa-se nos seguintes
passos:
22
2.12
Smbolos
23
24
2.13
Todas as funes que definimos at este momento possuem um nico parmetro. Vamos agora considerar funes com mais do que um parmetro.
Por exemplo, a rea A de um tringulo de base b e altura c define-se
matematicamente por
bc
A(b, c) =
2
.
Em Lisp, teremos:
(defun A (b c) (/ (* b c) 2))
Quando o nmero de definies aumenta torna-se particularmente importante para quem as l que se perceba rapidamente o seu significado e,
por isso, de crucial importncia que se faa uma boa escolha de nomes.
Exercicio 2.15 Defina uma funo que calcula o volume de um paralelippedo a partir do
seu comprimento, altura e largura. Empregue nomes suficientemente claros.
Exercicio 2.16 Defina a funo media que calcula o valor mdio entre dois outros valores.
Por exemplo (media 2 3)2.5.
2.14
Encadeamento de Funes
(area-circulo 2)
(* pi (quadrado 2))
(* 3.14159 (quadrado 2))
(* 3.14159 (* 2 2))
(* 3.14159 4)
12.5664
Exercicio 2.17 Defina a funo que calcula o volume de um cilindro com um determinado
raio e comprimento. Esse volume corresponde ao produto da rea da base pelo comprimento do cilindro.
2.15
Funes Pr-Definidas
A possibilidade de se definirem novas funes fundamental para aumentarmos a flexibilidade da linguagem e a sua capacidade de se adaptar aos
problemas que pretendemos resolver. As novas funes, contudo, precisam
de ser definidas custa de outras que, ou foram tambm por ns definidas
ou, no limite, j estavam pr-definidas na linguagem.
Isto mesmo se verifica no caso da funo area-circulo que definimos acima: ela est definida custa da funo quadrado (que foi tambm
por ns definida) e custa da operao de multiplicao. No caso da funo quadrado, ela foi definida com base na operao de multiplicao. A
operao de multiplicao que, em ltima anlise, a base do funcionamento da funo area-circulo , na realidade, uma funo pr-definida
do Lisp.
Como iremos ver, o Lisp providencia um conjunto razoavelmente grande
de funes pr-definidas. Em muitos casos, so suficientes para o que pretendemos, mas no nos devemos coibir de definir novas funes sempre
que acharmos necessrio.
A Tabela 2 apresenta uma seleco de funes matemticas pr-definidas
do Auto Lisp. Note-se que, devido s limitaes sintticas do Auto Lisp (e
que so comuns a todas as outras linguagens de programao), h vrios
casos em que uma funo em Auto Lisp emprega uma notao diferente
daquela que usual em matemtica. Por exemplo, a funo raiz quadrada
x escreve-se como (sqrt x). O nome sqrt uma contraco do Ingls square root e contraces semelhantes so empregues para vrias outras funes. Por exemplo, a funo valor absoluto |x| escreve-se (abs x)
(de absolute value), a funo parte inteira bxc escreve-se (fix x) (de fixed
point) e a funo potncia xy escreve-se (expt x y) (de exponential). A Tabela 3 mostra as equivalncias mais relevantes entre invocaes de funes
em Auto Lisp e as correspondentes invocaes na Matemtica.
A Tabela 4 apresenta uma seleco de funes sobre strings pr-definidas
do Auto Lisp. medida que formos apresentando novos tpicos do Auto
Lisp iremos explicando outras funes pr-definidas que sejam relevantes
para o assunto.
26
Funo
+
-
Argumentos
Vrios nmeros
Vrios nmeros
Vrios nmeros
Vrios nmeros
Um nmero
Um nmero
Um nmero
Um nmero
Um nmero
Um ou dois
nmeros
*
/
1+
1abs
sin
cos
atan
Um nmero
Um nmero
Dois nmeros
Um nmero
Vrios nmeros
Vrios nmeros
Dois ou mais
nmeros
sqrt
exp
expt
log
max
min
rem
fix
float
Um nmero
Um nmero
Resultado
A adio de todos os argumentos. Sem argumentos, zero.
Com apenas um argumento, o seu simtrico.
Com mais de um argumento, a subtraco ao
primeiro de todos os restantes. Sem argumentos, zero.
A multiplicao de todos os argumentos. Sem
argumentos, zero.
A diviso do primeiro argumento por todos
os restantes. Sem argumentos, zero.
A soma do argumento com um.
A substraco do argumento com um.
O valor absoluto do argumento.
O seno do argumento (em radianos).
O cosseno do argumento (em radianos).
Com um argumento, o arco tangente do argumento (em radianos). Com dois argumentos,
o arco tangente da diviso do primeiro pelo
segundo (em radianos). O sinal dos argumentos usado para determinar o quadrante.
A raiz quadrada do argumento.
A exponencial de base e.
O primeiro argumento elevado ao segundo argumento.
O logaritmo natural do argumento.
O maior dos argumentos.
O menor dos argumentos.
Com dois argumentos, o resto da diviso do
primeiro pelo segundo. Com mais argumentos, o resto da diviso do resultado anterior
pelo argumento seguinte.
O argumento sem a parte fraccionria.
O argumento convertido em nmero real.
27
Auto Lisp
(+ x0 x1 ...
(+ x)
(+)
(- x0 x1 ...
(- x)
(-)
(* x0 x1 ...
(* x)
(*)
(/ x0 x1 ...
(/ x)
(/)
(1+ x)
(1- x)
(abs x)
(sin x)
(cos x)
(atan x)
(atan x y)
(sqrt x)
(exp x)
(expt x y)
(log x)
(fix x)
xn )
xn )
xn )
xn )
Matemtica
x0 + x1 + . . . + xn
x
0
x0 x1 . . . xn
x
0
x0 x1 . . . xn
x
0
x0 /x1 / . . . /xn
x
0
x+1
x1
|x|
sin x
cos x
atan x
atan xy
x
ex
xy
log x
bxc
1 x2
acos x = atan
x
Exercicio 2.21 A funo fix permite truncar um nmero real, produzindo o nmero inteiro que se obtm pela eliminao da parte fraccionria desse real. Defina a funo round
que permite arredondar um nmero real, i.e., produzir o inteiro que mais prximo desse
nmero real.
Exercicio 2.22 Para alm da funo round que arredonda para o inteiro mais prximo e da
28
Funo
strcat
Argumentos
Vrias strings
strlen
Vrias strings
substr
Uma string,
um inteiro (o
ndice) e, opcionalmente,
outro inteiro
(o nmero de
caracteres)
Uma string e
um boleano
opcional
strcase
atof
Uma string
atoi
Uma string
itoa
rtos
Um nmero
Um, dois ou
trs nmeros
Resultado
A concatenao de todos os argumentos.
Sem argumentos, a string vazia .
O nmero de caracteres da concatenao
das strings. Sem argumentos, devolve zero.
A parte da string que comea no ndice
dado e que tem o nmero de caracteres
dado ou todos os restantes caracteres no
caso de esse nmero no ter sido dado.
cos4 2
atan 3
1
2
3 + sin 2 2
Exercicio 2.24 Traduza as seguintes expresses Auto Lisp para a notao matemtica:
1. (log (sin (+ (expt 2 4) (/ (fix (atan pi)) (sqrt 5)))))
2. (expt (cos (cos (cos 0.5))) 5)
3. (sin (/ (cos (/ (sin (/ pi 3)) 3)) 3))
Exercicio 2.25 Defina a funo impar? que, dado um nmero, testa se ele mpar, i.e., se
o resto da diviso desse nmero por dois um. Para calcular o resto da diviso de um
nmero por outro, utilize a funo pr-definida rem.
29
2.16
Vimos que o Auto Lisp disponibiliza, para alm dos operadores aritmticos
usuais, um conjunto de funes matemticas. No entanto, h que ter em
conta que existem diferenas substanciais entre o significado matemtico
destas operaes e a sua implementao no Auto Lisp.
Um primeiro problema importante tem a ver com a gama de inteiros.
Em Auto Lisp, os inteiros so representados com apenas 32 bits de informao.5 Isto implica que apenas se conseguem representar inteiros desde
5
Em AutoCad, a gama de inteiros ainda mais pequena pois a sua representao s usa
16 bits, permitindo apenas representar os inteiros de 32768 a 32767. Isto no afecta o Auto
Lisp, excepto quando este tem de passar inteiros para o AutoCad.
30
2147483648
+
2 1 0 +1 +2
1 0 +1
2147483648
+2147483647
+2
+2147483647
Curiosamente, a maioria dos dialectos de Lisp (mas no o Auto Lisp) no apresenta este
comportamento, preferindo representar nmeros inteiros com dimenso to grande quanto
for necessrio.
31
_$ (* (/ 1 3) 3)
0
Note-se que estamos apenas a falar da leitura de nmeros. Como j vimos, as operaes
aritmticas usuais no apresentam este comportamento.
8
Este exemplo mostra que, em Auto Lisp, h um inteiro que no pode ser lido mas que
pode ser produzido como resultado de operaes aritmticas. importante salientar que
este comportamento verdadeiramente bizarro exclusivo do Auto Lisp e no se verifica em
mais nenhum dialecto de Lisp.
32
_$ (- -2147483647 1)
-2147483648
_$ (- -2147483648 1)
-2.14748e+009
_$ (- -2147483647 2)
2147483647
Exercicio 2.30 A rea A de um pentgono regular inscrito num crculo de raio r dada pela
frmula
q
5
A = r2 10 + 2 5
8
Defina uma funo Auto Lisp que calcule essa rea.
Exercicio 2.31 Defina uma funo que calcula o volume de um elipside de semi-eixos a, b
e c. Esse volume pode ser obtido pela frmula V = 34 abc.
2.17
Em relao aos reais, o seu comportamento mais prximo do que se considera matematicamente correcto mas, ainda assim, h vrios problemas
com que preciso lidar.
A gama dos reais vai desde 4.94066 10324 at 1.79769 10+308 . Se o
Auto Lisp tentar ler um nmero real que excede esta gama ele imediatamente convertido para um nmero especial que representa o infinito:
_$ 2e400
1.#INF
_$ -2e400
-1.#INF
Como se pode ver, nem usando inteiros, nem usando reais, se consegue
obter o resultado correcto. No caso dos inteiros, o problema causado pela
diviso inteira de 4 por 3 que produz 1. No caso dos reais, o problema
causado por erros de arrendondamento: 4/3 no representvel com um
nmero finito de dgitos. Este erro de arrendondamento ento propagado
nas restantes operaes produzindo um valor que, embora no seja zero,
est muito prximo.
Obviamente, como o resultado da avaliao com reais suficientemente
pequeno, podemos convert-lo para o tipo inteiro (aplicando-lhe uma truncatura com a funo fix) e obtemos o resultado correcto:
_$ (fix (- (* (- (/ 4.0 3.0) 1.0) 3.0) 1.0))
0
5.1)
51367.7)
176498634.7)
1209983553611.9)
19843566622234755.9)
553774558711019983333.9)
Exercicio 2.34 Pretende-se criar um lano de escada com n espelhos capaz de vencer uma
determinada altura a em metros. Admitindo que cada degrau tem uma altura do espelho h
e uma largura do cobertor d que verificam a proporo
2h + d = 0.64
defina uma funo que, a partir da altura a vencer e do nmero de espelhos, calcula o
comprimento do lano de escada.
2.18
Avaliao de Smbolos
2.19
1)
"Bom dia!")
pi)
quadrado)
+)
36
mento: INT para inteiros, STR para strings, REAL para reais, etc.
Mas o que so estes resultadosINT, STR, REAL, etc que foram devolvidos pela funo type? Que tipo de valores so? Para responder
questo, o melhor usar a mesmssima funo type:
_$ (type pi)
REAL
_$ (type (type pi))
SYM
SYM a abreviatura de symbol, indicando que o valor REAL que foi devolvido pela funo type um smbolo. Note-se que, contrariamente ao
que acontece com o smbolo pi que est associado ao nmero 3.14159 . . . ,
os smbolos REAL, INT, STR, etc., no esto associados a nada, eles apenas so usados como representao do nome de um determinado tipo de
dados.
Se os valores devolvidos pela funo type so objectos do tipo smbolo,
ento dever ser possvel design-los, tal como designamos os nmeros ou
as strings. Mas qual ser o modo de o fazermos? Uma hiptese (errada) seria escrev-lo tal como escrevemos nmeros ou strings. Acontece que isto
possvel no caso dos nmeros e strings pois eles avaliam para eles prprios.
J no caso dos smbolos, sabemos que no avaliam para eles prprios, antes avaliando para as entidades a que esto associados naquele momento.
Assim, se quisermos designar o smbolo pi, no bastar escrev-lo numa
expresso, pois o que ir resultar aps a sua avaliao no ser um smbolo
mas sim o nmero 3.14159 . . . que o valor desse smbolo.
Para ultrapassar este problema precisamos de, por momentos, alterar a
semntica habitual que o Lisp atribui aos smbolos. Essa semntica, recordemos, a de que o valor de um smbolo a entidade a que esse smbolo
est associado nesse momento e esse valor surge sempre que o Lisp avalia
o smbolo. Para alterarmos essa semntica, precisamos de indicar ao Lisp
que no queremos que avalie um determinado smbolo, i.e., queremos que
trate o smbolo como ele , sem o avaliar. Para isso, o Lisp disponibiliza
a forma quote. Esta forma, que recebe um nico argumento, tem uma
semntica simplicssima: devolve o argumento sem este ter sido avaliado.
Reparemos na seguinte interaco:
_$ pi
3.14159
_$ (quote pi)
PI
_$ (+ 1 2 3)
6
_$ (quote (+ 1 2 3))
(+ 1 2 3)
2.20
Expresses Condicionais
Existem muitas operaes cujo resultado depende da realizao de um determinado teste. Por exemplo, a funo matemtica |x|, que calcula o valor
absoluto do nmero x, equivale ao simtrico do nmero, se este for negativo, ou ao prprio nmero, caso contrrio. Usando a moderna notao da
matemtica, temos:
(
x, se x < 0
|x| =
x,
caso contrrio.
Esta funo ter, portanto, de testar se o seu argumento negativo e
escolher uma de duas alternativas: ou avalia para o prprio argumento, ou
avalia para o seu simtrico.
Estas expresses, cujo valor depende de um ou mais testes a realizar
previamente, so designadas expresses condicionais.
2.21
Expresses Lgicas
38
2.22
Valores Lgicos
2.23
Predicados
No caso mais usual, uma expresso lgica uma invocao de funo com
determinados argumentos. Nesta situao, a funo usada como teste
denominada predicado e o valor do teste interpretado como sendo verdadeiro ou falso. O predicado , consequentemente, uma funo que devolve
apenas verdade ou falso.
Apesar da adopo dos smbolos t e nil, convm alertar que nem todos os predicados devolvem t ou nil exclusivamente. Alguns h que,
quando querem indicar verdade, devolvem valores diferentes de t (e de
nil, obviamente).
2.24
Predicados Aritmticos
Os operadores relacionais matemticos <, >, =, , e 6= so um dos exemplos mais simples de predicados. Estes operadores comparam nmeros
entre si e permitem saber se um nmero menor que outro. O seu uso em
Lisp segue as regras da notao prefixa e escrevem-se, respectivamente, <,
>, =, <=, >= e /=. Eis alguns exemplos:
10
39
_$ (> 4 3)
t
_$ (< 4 3)
nil
_$ (<= (+ 2 3) (- 6 1))
t
2.25
Operadores Lgicos
2.26
Uma propriedade importante dos predicados aritmticos <, >, =, <=, >= e
/= aceitarem qualquer nmero de argumentos. No caso em que h mais
do que um argumento, o predicado aplicado sequencialmente aos pares
de argumentos. Assim, (< e1 e2 e3 ... en1 en ) equivalente a escrever (and (< e1 e2 ) (< e2 e3 ) ... (< en1 en )). Este comportamento
visvel nos sequintes exemplos.
40
_$ (< 1 2 3)
T
_$ (< 1 2 2)
nil
Um caso particular que convm ter em ateno que, embora a expresso (= e1 e2 ... en ) teste se os elementos e1 e2 . . . en so todos iguais,
(/= e1 e2 ... en ) no testa se os elementos e1 e2 . . . en so todos diferentes: uma vez que o teste aplicado sucessivamente a pares de elementos, perfeitamente possvel que existam dois elementos iguais, desde que
no sejam consecutivos. Esse comportamento visvel no seguinte exemplo:11
_$ (/= 1 2 3)
T
_$ (/= 1 2 1)
T
2.27
"pois" "pois")
2.28
Reconhecedores
"pois" "poisar")
"pois" "poisar")
"abcd" "abce")
41
_$ (zerop 1)
nil
_$ (zerop 0)
t
2.29
Reconhecedores Universais
Um outro conjunto importante de predicados so os denominados reconhecedores universais. Estes no reconhecem elementos particulares de um tipo
de dados mas sim todos os elementos de um particular tipo de dados. Um
reconhecedor universal aceita qualquer tipo de valor como argumento e
devolve verdade se o valor do tipo pretendido.
Por exemplo, para sabermos se uma determinada entidade um nmero, podemos empregar o predicado numberp:
_$ (numberp 1)
T
_$ (numberp nil)
nil
_$ (numberp "Dois")
nil
Para a maioria dos tipos, o Auto Lisp no providencia nenhum reconhecedor universal, antes preferindo usar a funo genrica type que devolve
o nome do tipo como smbolo. Como vimos na secco 2.19, temos:
42
_$ (type
REAL
_$ (type
INT
_$ (type
STR
_$ (type
USUBR
_$ (type
SUBR
pi)
1)
"Ola")
quadrado)
+)
igualmente trivial definir um reconhecedor universal de strings e outro para funes (pr-definidas ou no):
(defun stringp (obj)
(= (type obj) str))
(defun functionp (obj)
(or (= (type obj) subr)
(= (type obj) usubr)))
2.30
Exerccios
Exercicio 2.37 O que uma expresso condicional? O que uma expresso lgica?
Exercicio 2.38 O que um valor lgico? Quais so os valores lgicos empregues em Auto
Lisp?
Exercicio 2.39 O que um predicado? D exemplos de predicados em Auto Lisp.
Exercicio 2.40 O que um operador relacional? D exemplos de operadores relacionais em
Auto Lisp.
Exercicio 2.41 O que um operador lgico? Quais so os operadores lgicos que conhece
em Auto Lisp?
Exercicio 2.42 O que um reconhecedor? O que um reconhecedor universal? D exemplos em Auto Lisp.
Exercicio 2.43 Traduza para Lisp as seguintes expresses matemticas:
1. x < y
43
2. x y
3. x < y y < z
4. x < y x < z
5. x y z
6. x y < z
7. x < y z
2.31
Seleco
_$ (if (> 3 2)
1
2)
1
_$ (if (> 3 4)
1
2)
2
1 se x < 0
sgn x = 0
se x = 0
1
caso contrrio
Em linguagem natural, dizemos que se x for negativo, o valor de sgn x
1, caso contrrio, se x for 0, o valor 0, caso contrrio, o valor 1.
Isto mostra que, na verdade, a definio anterior emprega duas expresses
condicionais encadeadas, da forma:
1
se x < 0
(
sgn x =
0 se x = 0
caso contrrio
1 caso contrrio
Assim sendo, para definirmos esta funo em Lisp, temos de empregar
dois ifs:
45
2.32
O cond aceita qualquer nmero de argumentos. Cada argumento denominado clusula e constitudo por uma lista de expresses. A semntica
do cond consiste em avaliar sequencialmente a primeira expresso expri,0
de cada clusula at encontrar uma cujo valor seja verdade. Nesse momento, o cond avalia todas as restantes expresses dessa clusula e devolve
o valor da ltima. Se nenhuma das clusulas tiver uma primeira expresso
que avalie para verdade, o cond devolve nil. Se a clusula cuja primeira
expresso verdade no contiver mais expresses, o cond devolve o valor
dessa primeira expresso.
importante perceber que os parntesis que envolvem as clusulas no
correspondem a nenhuma combinao: eles simplesmente fazem parte da
sintaxe do cond e so necessrios para separar as clusulas umas das outras.
A pragmtica usual para a escrita de um cond (em especial quando
cada clusula contm apenas duas expresses) consiste em alinhar as expresses umas debaixo das outras.
Usando o cond, a funo sinal pode ser escrita de forma mais simples:
(defun signum (x)
(cond ((< x 0)
-1)
((= x 0)
0)
(t
1)))
verdade, pelo que a sua presena garante que ela ser avaliada no caso de
nenhuma das clusulas anteriores o ter sido. Neste sentido, clusula da
forma (t ...) representa um em ltimo caso . . . .
Exercicio 2.44 Qual o significado de (cond (expr1 expr2))?
Exercicio 2.45 Qual o significado de (cond (expr1) (expr2))?
Exercicio 2.46 Defina uma funo soma-maiores que recebe trs nmeros como argumento e determina a soma dos dois maiores.
Exercicio 2.47 Defina a funo max3 que recebe trs nmeros como argumento e calcula o
maior entre eles.
Exercicio 2.48 Defina a funo segundo-maior que recebe trs nmeros como argumento
e devolve o segundo maior nmero, i.e., que est entre o maior e o menor.
Modelao Geomtrica
3.1
Coordenadas
A Arquitectura pressupe a localizao de elementos no espao. Essa localizao expressa-se em termos do que se designa por coordenadas: cada
coordenada um nmero e uma sequncia de coordenadas identifica univocamente um ponto no espao. A Figura 2 esquematiza uma possvel
sequncia de coordenadas (x, y, z) que identificam o ponto P num espao
tridimensional. Diferentes sistemas de coordenadas so possveis e, no caso
da Figura 2, estamos a empregar aquele que se designa por sistema de coordenadas rectangulares, tambm conhecido por sistema de coordenadas Cartesianas, em honra do seu inventor: Ren Descartes.12
Se queremos trabalhar com coordenadas em Auto Lisp, temos de saber
como formar sequncias de nmeros. Vimos, nas seces anteriores, que o
Auto Lisp sabe trabalhar com nmeros. Vamos agora mostrar que tambm
sabe trabalhar com sequncias. Para isso, vamos introduzir o conceito de
lista.
12
47
Y
P
y
X
3.2
Listas
Note-se que a funo list, semelhana de outras funes como a adio e multiplicao, recebe qualquer nmero de argumentos, agrupandoos todos numa lista. Note-se ainda que quando o Lisp escreve a lista resultante, emprega a mesma sintaxe que usada para a escrita de combinaes,
i.e., separando os elementos da lista com um espao e envolvendo-os num
par de parntesis. Existe, contudo, uma excepo a esta regra: uma lista
vazia, i.e., uma lista sem elementos, escrita usando o smbolo nil, exactamente o mesmo que usado para representar a falsidade. O nome nil
uma contraco da palavra nihil que, em latim, significa o vazio. isso que
acontece na seguinte interaco:
_$ (list)
nil
A funo null devolve verdade quando aplicada a uma lista vazia e falso
em qualquer outro caso:
_$ (null (list 1 2 3))
nil
_$ (null (list))
T
Uma vez que a construo de uma lista feita usando uma funo, a
sua invocao segue as mesmas regras de avaliao de todas as outras invocaes de funes, ou seja, as expresses que constituem os argumentos
so avaliadas e so os resultados dessas avaliaes que so usados como
elementos da lista. Assim, temos:
_$ (list (+ 1 2) (* 3 4))
(3 12)
_$ (list 1 "dois" (+ 1 2))
(1 "dois" 3)
_$ (list (area-circulo 10) (area-triangulo 20 30))
(314.159 300)
3.3
A partir do momento em que sabemos construir listas, podemos criar coordenadas e podemos definir operaes sobre essas coordenadas. Para criarmos coordenadas tridimensionais podemos simplesmente juntar numa
lista os trs nmeros das coordenadas (x, y, z). Por exemplo, o ponto do
espao cartesiano (1, 2, 3) pode ser construdo atravs de:
13
Mais frente iremos ver que existem formas mais eficientes de aceder aos elementos de
uma lista. Por agora, e apenas por motivos pedaggicos, vamos limitar-nos funo nth.
49
_$ (list 1 2 3)
(1 2 3)
Uma vez que estamos a fazer uma lista que contm, primeiro, a coordenada x, a seguir, a coordenada y e, por ltimo, a coordenada z, podemos
obter estes valores usando a funo nth com os ndices 0, 1, e 2, respectivamente.
Para melhor percebermos a utilizao destas funes, imaginemos que
pretendemos definir uma operao que mede a distncia d entre os pontos P0 = (x0 , y0 , z0 ) e P1 = (x1 , y1 , z1 ). Essa distncia determinada pela
frmula
p
d = (x1 x0 )2 + (y1 y0 )2 + (z1 z0 )2
e a sua traduo para Auto Lisp ser:
(defun distancia (p0
(sqrt (+ (quadrado
(quadrado
(quadrado
p1)
(- (nth 0 p1) (nth 0 p0)))
(- (nth 1 p1) (nth 1 p0)))
(- (nth 2 p1) (nth 2 p0))))))
3.4
Abstraco de Dados
As funes xyz, cx, cy, e cz constituem uma abstraco das coordenadas que nos permitem manipular coordenadas sem termos de pensar
na sua implementao em termos de listas. Esse facto torna-se evidente
quando reescrevemos a funo distancia usando estas novas funes:
(defun distancia (p0
(sqrt (+ (quadrado
(quadrado
(quadrado
p1)
(- (cx p1) (cx p0)))
(- (cy p1) (cy p0)))
(- (cz p1) (cz p0))))))
51
P0
z
P
y
y
X
Figura 3: O ponto P 0 como resultado da translao do ponto P = (x, y, z)
de x no eixo do X, y no eixo do Y , e z no eixo do Z.
_$ (distancia (xyz 1 2 3) (xyz 8 6 4))
8.12404
Uma vez que esta funo recebe coordenadas como argumento e produz coordenadas como resultado, ela constitui outra importante adio ao
52
conjunto de operaes disponveis para lidar com coordenadas. Naturalmente, podemos usar a funo +xyz para definir novas funes como, por
exemplo, os casos particulares de deslocamento horizontal e vertical que se
seguem:
(defun +x (p dx)
(+xyz p dx 0 0))
(defun +y (p dy)
(+xyz p 0 dy 0))
(defun +z (p dz)
(+xyz p 0 0 dz))
3.5
Tipos Abstractos
+yz
Y
z
+z
+xyz
+y
z
y
+xz
+xy
x
X
z
y
+x
Figura 4: As translaces realizadas pelas funes +x, +y, +z, +xy, +xz,
+yz, e +xyz a partir de um ponto arbitrrio P e dos deslocamentos x ,
y , e z .
tracto, e os selectores que, a partir de um elemento do tipo abstracto, produzem os seus constituintes. Existem ainda outras categorias de operaes
mas, por agora, iremos concentrarmo-nos apenas nestas duas.
No caso das coordenadas cartesianas tridimensionais, o conjunto dos
construtores apenas contm a funo xyz, enquanto que o conjunto dos selectores contm as funes cx, cy e cz. Para um tipo abstracto, a relao
entre os construtores e os selectores crucial pois eles tm de ser consistentes entre si. Matematicamente, essa consistncia assegurada por equaes
que, no caso presente, se podem escrever da seguinte forma:
(cx (xyz x y z)) = x
(cy (xyz x y z)) = y
(cz (xyz x y z)) = z
Estas equaes asseguram que, se modificarmos a representao de coordenadas, mas mantivermos a consistncia entre os construtores e os selectores, manter-se- tambm o correcto funcionamento do tipo abstracto.
Exercicio 3.6 O que um construtor de um tipo abstracto?
Exercicio 3.7 O que um selector de um tipo abstracto?
Exercicio 3.8 O que a representao de um tipo abstracto?
54
3.6
Coordenadas Bidimensionais
55
P1
...
P0
3.7
Coordenadas em AutoCad
x
Figura 5: Coordenadas rectangulares e polares.
conseguir perceber se uma dada lista presente num programa significa coordenadas ou se significa outro tipo abstracto qualquer.
3.8
Coordenadas Polares
Apesar do AutoCad exigir que as coordenadas estejam descritas no sistema Cartesiano, nada nos impede de usar outros sistemas de coordenadas, desde que tenhamos o cuidado de, antes da passagem de coordenadas
para o AutoCad, proceder sua converso para o sistema Cartesiano.
No caso bidimensional, um dos sistemas mais teis o de coordenadas
polares.
Tal como representado da Figura 5, uma posio no plano bidimensional descrita, em coordenadas rectangulares, pelos nmeros x e y
significando, respectivamente, a abcissa e a ordenadaenquanto que a mesma
posio em coordenadas polares descrita pelos nmeros e significando,
respectivamente, o raio vector (tambm chamado mdulo) e o ngulo polar
(tambm chamado argumento). Com a ajuda da trigonometria e do teorema de Pitgoras conseguimos facilmente converter de coordenadas polares para coordenadas rectangulares:
(
x = cos
y = sin
ou de coordenadas rectangulares para coordenadas polares:
p
= x2 + y 2
= arctan y
x
Com base nas equaes anteriores, podemos definir o construtor de coordenadas polares pol (abreviatura de polar) que contri coordenadas
a partir da sua representao polar simplesmente convertendo-a para a representao rectangular equivalente.
57
15
Note-se, nestes exemplos, que alguns valores das coordenadas no so zero, como seria expectvel, mas sim valores muito prximos de zero, que resultam de erros de arredondamento. Note-se tambm que, como estamos a usar coordenadas bidimensionais, a
coordenada z sempre igual a zero.
58
P0
Como se pode ver, embora as coordenadas no sejam iguais, elas so bastante prximas, ou seja, a distncia entre elas muito prxima de zero. Proponha uma nova definio
para a funo =c baseada no conceito de distncia entre as coordenadas.
3.9
A funo command
59
AutoCAD
Figura 7: Um crculo com o texto "AutoCad".
_$ (command "osnap" "off")
nil
importante memorizar esta ltima expresso pois, sem a sua invocao, todos os usos da funo command estaro sob o efeito de Object
Snaps, fazendo com que as coordenadas que indicamos para as nossas figuras geomtricas no sejam estritamente respeitadas pelo AutoCad, que
as arredondar de acordo com a malha do Object Snaps.
Como exemplo da utilizao de comandos em Auto Lisp, a Figura 8
mostra o resultado da avaliao das seguintes expresses onde usamos coordenadas polares para desenhar crculos e texto:
(command "erase" "all" "")
(command "circle" (pol 0 0) 4)
(command "text" (+pol (pol 0 0) 5 0)
1 0 "Raio: 4")
(command "circle" (pol 4 (/ pi 4)) 2)
(command "text" (+pol (pol 4 (/ pi 4)) 2.5 0)
0.5 0 "Raio: 2")
(command "circle" (pol 6 (/ pi 4)) 1)
(command "text" (+pol (pol 6 (/ pi 4)) 1.25 0)
0.25 0 "Raio: 1")
(command "zoom" "e")
Exercicio 3.12 Refaa o desenho apresentado na Figura 8 mas utilizando apenas coordenadas rectangulares.
Existem algumas particularidades da funo command que importante discutir. Para as compreendermos preciso recordar que a funo
command simula a interaco do utilizador com o AutoCad. Consideremos ento um exemplo de uma interaco: imaginemos que estamos em
frente interface do AutoCad e pretendemos apagar todo o contedo da
nossa rea de desenho no AutoCad. Para isso, podemos invocar o comando
erase do AutoCad, o que podemos fazer escrevendo as letras e-r-a-s-e e
61
Raio: 1
Raio: 2
Raio: 4
Finalmente, sabemos que depois desta interaco, o AutoCad vai continuar espera que indiquemos que terminmos a seleco de objectos atravs do premir da tecla enter, o que implica que temos de indicar funo
command para simplesmente passar o tal premir virtual da tecla enter.
Ora j sabemos que a funo faz isso automaticamente aps passar os caracteres de uma string. Assim, se no queremos passar caracteres alguns,
mas apenas a tecla enter, ento, logicamente, temos de usar uma string
vazia, ou seja:
(command "erase" "all" "")
Como se pode constatar pelo exemplo anterior, a funo command termina assim que conseguir passar todos os argumentos que tem para o AutoCad, independentemente de eles serem suficientes ou no para o AutoCad conseguir completar o pretendido. Se no forem, o AutoCad limita-se
a continuar espera que lhe forneamos, via command ou directamente na
interface, os dados que lhe faltam, o que nos permite implementar um processo de colaborao com o AutoCad: parte do que se pretende feito no
lado do Auto Lisp e a parte restante no lado do AutoCad.
Por exemplo, imaginemos que pretendemos criar um crculo num dado
ponto mas queremos deixar ao utilizador a escolha do raio. Uma soluo
ser iniciar a construo do crculo centrado num dado ponto atravs da
funo command, mas aguardar que o utilizador termine essa construo,
indicando explicitamente no AutoCad (por exemplo, usando o rato) qual
o raio do crculo pretendido. Assim, iniciariamos o comando com:
(command "circle" (xy 0 0))
Um outro aspecto importante da funo command prende-se com a passagem de nmeros e coordenadas (representadas por listas de nmeros).
Embora nos exemplos anteriores estes tipos de dados tenham sido directamente passadas funo command, na realidade tambm podem ser passados simulando o premir das teclas correspondentes. Isto quer dizer que
possvel criar um crculo com centro no ponto (2, 3) e raio 1 atravs da
expresso:
(command "circle" "2,3" "1")
64
Escreva uma sequncia de expresses que, quando avaliadas, produzem a figura anterior.
Exercicio 3.14 Pretendemos colocar quatro circunferncias de raio unitrio em torno da
origem de modo a que fiquem encostadas umas s outras, tal como se ilustra no seguinte
desenho:
Escreva uma sequncia de expresses que, quando avaliadas, produzem a figura anterior.
Exercicio 3.15 Pretendemos colocar trs circunferncias de raio unitrio em torno da origem de modo a que fiquem encostadas umas s outras, tal como se ilustra no seguinte
desenho:
Escreva uma sequncia de expresses que, quando avaliadas, produzem a figura anterior.
3.10
Variantes de Comandos
3.11
ngulos em Comandos
66
67
3.12
Efeitos Secundrios
Vimos anteriormente que qualquer expresso Lisp tem um valor. No entanto, aquilo que se pretende de uma expresso que use a funo command
no saber qual o seu valor mas sim qual o efeito que produzido num
determinado desenho. De facto, a execuo de um comando AutoCad produz, em geral, uma alterao do desenho actual, sendo irrelevante o seu
valor.
Este comportamento da funo command fundamentalmente diferente
do comportamento das funes que vimos at agora pois, anteriormente,
as funes eram usadas para computar algo, i.e., para produzir um valor
a partir da sua invocao com determinados argumentos e, agora, no o
valor que resulta da invocao do comando que interessa mas sim o efeito
secundrio (tambm chamado efeito colateral) que interessa.
Contudo, mesmo no caso em que apenas nos interessa o efeito secundrio, necessrio continuar a respeitar a regra de que, em Lisp, qualquer expresso tem um valor e, por isso, tambm uma invocao de funo tem de
produzir um valor como resultado. por este motivo que a invocao da
funo command devolve sempre nil como resultado. Obviamente, qualquer outro valor serviria (pois no suposto ser usado) mas convenciona-se
que, nos casos em que no h um valor mais relevante a devolver, deve-se
devolver nil (que, em Latim, significa nada).
Um dos aspectos importantes da utilizao de efeitos secundrios est
na possibilidade da sua composio. A composio de efeitos secundrios
faz-se atravs da sua sequenciao, i.e., da realizao sequencial dos vrios
efeitos. Na seco seguinte iremos discutir a sequenciao de efeitos secundrios.
3.13
Sequenciao
68
O desenho produzido pela funo depende, naturalmente, do valor lgico do parmetro inscrito?, ou seja, a definio da funo dever ser
algo da forma:
(defun circulo-quadrado (inscrito?)
(if inscrito?
desenha um crculo e um rectngulo inscrito no crculo
desenha um crculo e um rectngulo circunscrito ao crculo))
69
Basta-nos agora traduzir cada um dos desenhos elementares em invocaes da funo command. No caso do rectngulo inscrito, vamos utilizar
coordenadas polares pois sabemos que os vrtices tero de ficar sobre o
crculo, um a /4 e ou outro a + /4 = 5/4. Assim, temos:
(defun circulo-quadrado (inscrito?)
(if inscrito?
(progn
(command "_.circle" (xy 0 0) 1)
(command "_.rectangle" (pol 1 (/ (* 5 pi) 4)) (pol 1 (/ pi 4))))
(progn
(command "_.circle" (xy 0 0) 1)
(command "_.rectangle" (xy -1 -1) (xy 1 1)))))
claro que, agora, os dois progns dentro do if apenas tm uma expresso, pelo que o seu uso perfeitamente dispensvel. Assim, podemos
simplificar a definio para:
70
3.14
A Ordem Drica
71
(1, 11)
(1, 10.5)
(1, 11)
(1, 10.5)
(0.8, 10)
(0.8, 10)
x
(1, 0) (0, 0) (1, 0)
Outras diferenas incluem o facto de as plines poderem ter espessura e estarem limitadas a um plano.
73
No caso do baco, podemos empregar uma abordagem idntica ou podemos explorar outro comando do AutoCad ainda mais simples destinado
construo de rectngulos. Este comando apenas necessita de dois pontos
para definir completamente o rectngulo:
(defun abaco ()
(command "_.rectangle"
(xy -1 10.5)
(xy 1 11)))
Repare-se, na funo coluna, que ela invoca sequencialmente as funes fuste, coxim e, finalmente, abaco.
A Figura 13 mostra o resultado da invocao da funo coluna.
74
rt
P1 = (x rt , y + a)
P2 = (x + rt , y + a)
P = (x, y)
P4 = (x rb , y)
rb
P3 = (x + rb , y)
3.15
rt
P2 = (x rt , y + a)
P3 = (x + rt , y + a)
a
P = (x, y)
P1 = (x rb , y)
rb
P4 = (x + rb , y)
la
rbc
aa
ac
af
rbf
Com base nestas funes, podemos agora facilmente experimentar variaes de colunas. As seguintes invocaes produzem o desenho apresentado na Figura 18.
(coluna
(coluna
(coluna
(coluna
(coluna
(coluna
(xy 0 0)
(xy 3 0)
(xy 6 0)
(xy 9 0)
(xy 12 0)
(xy 15 0)
9
7
9
8
5
6
0.5
0.5
0.7
0.4
0.5
0.8
0.4
0.4
0.5
0.3
0.4
0.3
0.3
0.6
0.3
0.2
0.3
0.2
0.3
0.6
0.2
0.3
0.1
0.4
1.0)
1.6)
1.2)
1.0)
1.0)
1.4)
Como bvio pela anlise desta figura, nem todas as colunas desenhadas obedecem aos cnones da ordem Drica. Mais frente iremos ver que
modificaes sero necessrias para evitar este problema.
3.16
Documentao
79
N
O desenho deve ainda obedecer s seguintes propores:
O ngulo de abertura da seta de 45 .
O comprimento da farpa de 2 .
O centro da letra N dever ser posicionado a uma distncia de
da seta segundo a direco da seta.
10
da extremidade
81
diviso e um texto a descrever a funo dessa diviso na habitao. Com esses valores a
funo dever construir o rectngulo correspondente e deve colocar no interior desse rectngulo duas linhas de texto, a primeira com a funo da diviso e a segunda com a rea da
diviso. Por exemplo, a sequncia de invocaes
(divisao-rectangular
(divisao-rectangular
(divisao-rectangular
(divisao-rectangular
(divisao-rectangular
(divisao-rectangular
(xy
(xy
(xy
(xy
(xy
(xy
0
4
6
0
5
8
0)
0)
0)
5)
5)
3)
4
2
5
5
3
3
3
3
3
4
4
6
"cozinha")
"despensa")
"quarto")
"sala")
"i.s.")
"quarto")
sala i.s.
Area:20.00
quarto
Area:12.00
Area:18.00
3.17
cozinha
despensa
Area:12.00
Area:6.00
quarto
Area:15.00
Depurao
Como sabemos, errare humanum est. O erro faz parte do nosso dia-a-dia e,
por isso, em geral, sabemos lidar com ele. J o mesmo no se passa com
as linguagens de programao. Qualquer erro num programa tem como
consequncia que o programa tem um comportamento diferente daquele
que era esperado.
Uma vez que fcil cometer erros, deve tambm ser fcil detect-los
e corrigi-los. actividade de deteco e correco de erros denomina-se
depurao. Diferentes linguagens de programao providenciam diferentes mecanismos para essa actividade. Neste domnio, como iremos ver, o
AutoCad est particularmente bem apetrechado.
Em termos gerais, os erros num programa podem classificar-se em erros
sintticos e erros semnticos.
3.17.1
Erros Sintticos
O erro de que o Auto Lisp nos est a avisar de que a forma defun
que lhe demos para avaliar no obedece sintaxe exigida para essa forma
e, de facto, uma observao atenta da forma anterior mostra que no seguimos a sintaxe exigida para uma definio e que, tal como discutimos na
seco 2.11, era a seguinte:
(defun nome (parmetro1 ... parmetron )
corpo)
83
3.17.2
Erros Semnticos
Os erros semnticos so muito diferentes dos sintticos. Um erro semntico no um erro na escrita de uma frase da linguagem, mas sim um
erro no significado dessa frase. Dito de outra forma, um erro semntico
ocorre quando escrevemos uma frase que julgamos ter um significado e, na
verdade, ela tem outro.
Em geral, os erros semnticos apenas so detectveis durante a invocao das funes que os contm. Parte dos erros semnticos detectvel
pelo avaliador de Lisp, mas h inmeros erros cuja deteco s pode ser
feita pelo prprio programador.
Como exemplo de erro semntico consideremos uma operao sem significado, como seja a soma de um nmero com uma string:
_$ (+ 1 "dois")
; error: bad argument type: numberp: "dois"
Consegue detect-lo?
84
:ERROR-BREAK
(+ nil -0.3)
(+XY (nil 0 0) -0.3 9)
(FUSTE (nil 0 0) 9 0.5 0.3)
(COLUNA (nil 0 0) 9 0.5 0.4 0.3 0.3 0.5)
(COLUNA-STANDARD)
Acontece que, em Auto Lisp, qualquer nome que no tenha sido previamente definido tem o valor nil e, como o nome constitudo pela letra O
no est definido, a avaliao do primeiro argumento da funo xy , na
verdade, nil. Esta funo, como se limita a fazer uma lista com os seus
22
85
argumentos, cria uma lista cujo primeiro elemento nil e cujos restantes
elementos so zero. A lista resultante assim passada de funo em funo
at chegarmos funo +xy que, ao tentar fazer a soma, acaba por provocar
o erro.
Esta sesso de depurao mostra o procedimento habitual para deteco de erros. A partir do momento em que o erro identificado, geralmente fcil corrigi-lo mas convm ter presente que o processo de identificao de erros pode ser moroso e frustrante. tambm um facto que
quanto mais experincia tivermos na deteco de erros, mais rapidamente
se detectam novos erros.
3.18
Modelao Tridimensional
As verses mais recentes do AutoCad disponibilizam um conjunto de operaes pr-definidas que constroem um slido a partir das suas coordenadas tridimensionais. Embora as operaes pr-definidas apenas permitam
construir um conjunto muito limitado de slidos, esse conjunto suficiente
para a elaborao de modelos sofisticados.
As operaes pr-definidas para criao de slidos permitem construir
paralelippedos (comando box), cunhas (comando wedge), cilindros (comando cylinder), cones (comando cone), esferas (comando sphere),
toros (comando torus) e pirmides (comando pyramid). Os comandos
cone e pyramid permitem ainda a construo de troncos de cone e troncos
de pirmide atravs da utilizao do parmetro "Top". Cada um destes comandos aceita vrias opes que permitem construir slidos de diferentes
maneiras.24 A Figura 20 mostra um conjunto de slidos construdos pela
avaliao das seguintes expresses:25
24
Para se conhecer as especificidades de cada comando recomenda-se a consulta da documentao que acompanha o AutoCad.
25
A construo de uma pirmide exige a especificao simultnea do raio e ngulo da
86
Note-se que alguns dos slidos, nomeadamente o paralelippedo e a cunha s podem ser construdos com a base paralela ao plano XY . Esta no
uma verdadeira limitao do AutoCad, pois possvel alterar a orientao
do plano XY atravs da manipulao do sistema de coordenadas UCSuser
coordinate system.
A partir dos comandos disponibilizados pelo AutoCad possvel definir funes Auto Lisp que simplifiquem a sua utilizao. Embora o AutoCad permita vrios modos diferentes de se criar um slido, esses modos
esto mais orientados para facilitar a vida ao utilizador do AutoCad do que
propriamente para o programador de Auto Lisp. Para este ltimo, prefervel dispor de uma funo que, a partir de um conjunto de parmetros
simples, invoca o comando correspondente em AutoCad, especificando automaticamente as opes adequadas para a utilizao desses parmetros.
Para vermos um exemplo, consideremos a criao de um cilindro. Embora o AutoCad permita construir o cilindro de vrias maneiras diferentes,
cada uma empregando diferentes parmetros, podemos considerar que os
base. Tal como explicado na seco 3.11, a funo raio&angulo constri essa especificao
a partir dos valores do raio e do ngulo.
87
Usando esta funo agora mais simples definir outras estruturas mais
complexas. Por exemplo, uma cruz papal define-se pela unio de trs cilindros horizontais de comprimento progressivamente decrescente dispostos
ao longo de um cilindro vertical, tal como se pode ver na Figura 21. de
salientar que os cilindros tm todos o mesmo raio e que o seu comprimento
e posicionamento funo desse raio. Em termos de proporo, o cilindro
vertical da cruz papal tem um comprimento igual a 20 raios, enquanto que
os cilindros horizontais possuem comprimentos iguais a 14, 10 e 6 raios
e o seu eixo est posicionado a uma altura igual a 9, 13 e 17 raios. Estas
propores so implementadas pela seguinte funo:
88
(defun cruz-papal
(cilindro p
raio
(+xyz
(cilindro (+xyz
raio
(+xyz
(cilindro (+xyz
raio
(+xyz
(cilindro (+xyz
raio
(+xyz
(p raio)
p 0 0 (* 20 raio)))
p (* -7 raio) 0 (* 9 raio))
p (* +7 raio) 0 (* 9 raio)))
p (* -5 raio) 0 (* 13 raio))
p (* +5 raio) 0 (* 13 raio)))
p (* -3 raio) 0 (* 17 raio))
p (* +3 raio) 0 (* 17 raio))))
(p rb rt
p rb (+x
p rb (+y
p rb (+z
p rb (+x
p rb (+y
p rb (+z
c)
p c)
p c)
p c)
p (p (p (-
rt)
rt)
rt)
c)) rt)
c)) rt)
c)) rt))
89
90
Exercicio 3.24 Defina uma funo denominada prisma que cria um slido prismtico regular. A funo dever receber o nmero de lados do prisma, as coordenadas tridimensionais do centro da base do prisma, a distncia do centro da base a cada vrtice, o ngulo de
rotao da base do prisma e as coordenadas tridimensionais do centro do topo do prisma.
A ttulo de exemplo, considere as expresses
(prisma
(prisma
(prisma
(prisma
(prisma
3
5
4
6
7
(xyz 0 0
(xyz -2 0
(xyz 0 2
(xyz 2 0
(xyz 0 -2
0)
0)
0)
0)
0)
0.4
0.4
0.4
0.4
0.4
0
0
0
0
0
(xyz 0 0 5))
(xyz -1 1 5))
(xyz 1 1 5))
(xyz 1 -1 5))
(xyz -1 -1 5))
3.18.2
Coordenadas Cilndricas
z
y
x
Figura 23: Coordenadas cilndricas.
e o ngulo correspondem s coordenadas polares da projeco do ponto no
plano z = 0.
A partir da Figura 23 fcil vermos que, dado um ponto (, , z) em
coordenadas cilndricas, o mesmo ponto em coordenadas rectangulares
( cos , sin , z)
De igual modo, dado um ponto (x, y, z) em coordenadas rectangulares,
o mesmo ponto em coordenadas cilndricas
p
y
( x2 + y 2 , atan , z)
x
Estas equivalncias permitem-nos definir uma funo que constri pontos em coordenadas cilndricas empregando as coordenadas rectangulares
como representao cannica:
(defun cil (ro fi z)
(xyz (* ro (cos fi))
(* ro (sin fi))
z))
No caso de pretendermos simplesmente somar a um ponto um deslocamento em coordenadas cilndricas, podemos tirar partido da funo +xyz
e definir:
(defun +cil (p ro fi z)
(+xyz p
(* ro (cos fi))
(* ro (sin fi))
z))
92
Exercicio 3.25 Defina os selectores cil-ro, cil-fi e cil-z que devolvem, respectivamente, os componentes , e z de um ponto construdo pelo construtor cil.
Exercicio 3.26 Defina uma funo escadas capaz de construir uma escada em hlice. A
imagem seguinte mostra trs exemplos destas escadas.
Como se pode ver pela imagem anterior, a escada constituda por um cilindro central
no qual se apoiam 10 degraus cilndricos. Para facilitar a experimentao considere que o
cilindro central de raio r. Os degraus so iguais ao cilindro central, possuem 10 raios de
comprimento e esto dispostos a alturas progressivamente crescentes. Cada degrau est
a uma altura h em relao ao degrau anterior e, visto em planta, faz um ngulo com o
degrau anterior.
A funo escada dever receber as coordenadas do centro da base do cilindro central,
o raio r, a altura h e o ngulo . A ttulo de exemplo, considere que as trs escadas anteriores
foram construdas pelas seguintes invocaes:
(escada (xyz 0 0 0) 1.0 3 (/ pi 6))
(escada (xyz 0 40 0) 1.5 5 (/ pi 9))
(escada (xyz 0 80 0) 0.5 6 (/ pi 8))
3.18.3
Coordenadas Esfricas
93
P
y
psi)
psi) (cos fi))
psi) (sin fi))
psi))))
94
Exercicio 3.28 O corte de cabelo de estilo Moicano foi muito utilizado no perodo punk. Ele
consiste em fixar os cabelos em bicos que se dispoem em forma de leque ou crista, tal como
se esquematiza na seguinte imagem.
3.18.4
95
desenvolver-se ao longo do eixo dos Z. Embora fosse trivial empregar outro arranjo dos eixos do sistema de coordenadas, este aquele que mais
prximo da realidade.
semelhana de inmeras outras operaes do AutoCad, cada uma
das operaes de modelao de slidos do AutoCad permite vrios modos
diferentes de invocao. No caso da operao de modelao de troncos
de coneconeo modo que nos mais conveniente aquele em que a
operao recebe as coordenadas do centro da base do cone e o raio dessa
base, de seguida, o raio do topo do cone (com a opo Top radius) e,
finalmente, a altura do tronco.
Tendo isto em conta, podemos redefinir a operao que constri o fuste
tal como se segue:
(defun fuste (p a-fuste r-base r-topo)
(command "_.cone" p r-base
"_t" r-topo a-fuste))
Finalmente, no que diz respeito ao bacoo paralelippedo que colocado no topo da colunatemos vrias maneiras de o especificarmos. A
mais directa consiste em indicar os dois cantos do paralelippedo. Uma outra, menos directa, consiste em indicar o centro do paralelippedo, seguido
do tamanho dos seus lados. Por agora, vamos seguir a mais directa:
(defun abaco (p a-abaco l-abaco)
(command "_.box"
(+xyz p (/ l-abaco -2.0) (/ l-abaco -2.0) 0)
(+xyz p (/ l-abaco +2.0) (/ l-abaco +2.0) a-abaco)))
Exercicio 3.29 Implemente a funo abaco mas empregando a criao de um paralelippedo centrado num ponto seguido da especificao do seu comprimento, largura e altura.
Com estas redefinies, podemos agora repetir as colunas que desenhmos na seco 3.15 e que apresentmos na Figura 18, mas, agora, gerando
96
(xyz 0 0
(xyz 3 0
(xyz 6 0
(xyz 9 0
(xyz 12 0
(xyz 15 0
0)
0)
0)
0)
0)
0)
9
7
9
8
5
6
0.5
0.5
0.7
0.4
0.5
0.8
0.4
0.4
0.5
0.3
0.4
0.3
0.3
0.6
0.3
0.2
0.3
0.2
0.3
0.6
0.2
0.3
0.1
0.4
1.0)
1.6)
1.2)
1.0)
1.0)
1.4)
Funes
4.1
Variveis Locais
97
a
e tentemos definir uma funo Auto Lisp que calcula a rea do tringulo a
partir dos parmetros a, b e c.
Uma das formas de calcular a rea do tringulo baseia-se na famosa
frmula de Heron:27
A=
s (s a) (s b) (s c)
a+b+c
2
c)
2) a)
2) b)
2) c))))
98
Na definio anterior h dois aspectos novos que vamos agora discutir: a declarao da varivel local s e a atribuio dessa varivel atravs do
operador setq.
4.1.1
Declarao
Para se indicar que uma funo vai usar variveis locais, estas tm de ser
declaradas conjuntamente com a lista de parmetros da funo. Para isso,
vamos agora ampliar a sintaxe da definio de funes que apresentmos
anteriormente (na seco 2.11) de modo a incorporar a declarao de variveis locais:
(defun nome (parmetro1 ... parmetron
/ varivel1 ... varivelm )
corpo)
4.1.2
Atribuio
Para alm da declarao de uma varivel local ainda necessrio atribuirlhe um valor, i.e., realizar uma operao de atribuio. Para isso, o Auto
Lisp disponibiliza o operador setq, cuja sintaxe :
99
A semntica deste operador consiste simplesmente em avaliar a expresso expresso1 e associar o seu valor ao nome varivel1 , repetindo este
processo para todas as restantes variveis e valores.
A utilizao que fazemos deste operador na funo area-triangulo
fcil de compreender:
(defun area-triangulo (a b c / s)
(setq s (/ (+ a b c) 2))
(sqrt (* s (- s a) (- s b) (- s c))))
Ao invocarmos a funo area-triangulo, passando-lhe os argumentos correspondentes aos parmetros a, b e c, ela comea por introduzir um
novo nomesque vai existir apenas durante a invocao da funo. De
seguida, atribui a esse nome o valor que resultar da avaliao da expresso (/ (+ a b c) 2). Finalmente, avalia as restantes expresses do corpo
da funo. Na prtica, como se a funo dissesse: Sendo s = a+b+c
2 ,
p
calculemos s (s a) (s b) (s c).
H dois detalhes que importante conhecer relativamente s variveis
locais. O primeiro detalhe, que iremos discutir mais em profundidade na
prxima seco, que se nos esquecermos de declarar a varivel, ela ser
tratada como varivel global. O segundo detalhe que se nos esquecermos
de atribuir a varivel ela fica automaticamente com o valor nil. Logicamente, para que uma varivel nos seja til, devemos mudar o seu valor
para algo que nos interesse.
4.2
Variveis Globais
1+ 5
=
1.6180339887
2
28
Na realidade, o Auto Lisp permite ainda uma terceira categoria de nomes que no so
nem locais, nem globais. Mais frente discutiremos esse caso.
29
Tambm conhecida por proporo divina e nmero de ouro, entre outras designaes, e
abreviada por em homenagem a Fineas, escultor Grego responsvel pela construo do
Partnon onde, supostamente, usou esta proporo. A razo de ouro foi inicialmente in-
100
basta-nos escrever:
(setq razao-de-ouro (/ (+ 1 (sqrt 5)) 2))
A partir desse momento, o nome razao-de-ouro pode ser referenciado em qualquer ponto dos programas.
importante referir que o uso de variveis globais deve ser restrito,
na medida do possvel, definio de constantes, i.e., variveis cujo valor
nunca muda como, por exemplo, pi. Outros exemplos que podem vir a ser
teis incluem 2*pi, pi/2, 4*pi e pi/4, bem como os seus simtricos, que
se definem custa de:
(setq 2*pi (* 2 pi))
(setq pi/2 (/ pi 2))
(setq 4*pi (* 4 pi))
(setq pi/4 (/ pi 4))
(setq -pi (- pi))
(setq -2*pi (- 2*pi))
(setq -pi/2 (- pi/2))
(setq -4*pi (- 4*pi))
(setq -pi/4 (- pi/4))
O facto de uma varivel global ser uma constante implica que a varivel atribuda uma nica vez, no momento da sua definio. Esse facto
permite-nos usar a varivel sabendo sempre qual o valor a que ela est associada. Infelizmente, por vezes necessrio usarmos variveis globais que
no so constantes, i.e., o seu valor muda durante a execuo do programa,
por aco de diferentes atribuies feitas em locais diferentes e em momentos diferentes. Quando temos variveis globais que so atribuidas em diversos pontos do nosso programa, o comportamento deste pode tornar-se
muito mais difcil de entender pois, na prtica, pode ser necessrio compreender o funcionamento de todo o programa em simultneo e no apenas
funo a funo, como temos feito. Por este motivo, devemos evitar o uso
de variveis globais que sejam atribuidas em vrios pontos do programa.
troduzida por Euclides quando resolveu o problema de dividir um segmento de recta em
duas partes de tal forma que a razo entre o segmento de recta e a parte maior fosse igual
razo entre a parte maior e a menor. Se for a o comprimento do parte maior e b o da menor,
o problema de Euclides idntico a dizer que a+b
= ab . Daqui resulta que a2 ab b2 = 0
a
b b2 +4b2
ou que a =
= b 12 5 . A raiz que faz sentido , obviamente, a = b 1+2 5 e,
2
101
4.3
Variveis Indefinidas
4.4
Propores de Vitrvio
A modelao de colunas dricas que desenvolvemos na seco 3.18.4 permitenos facilmente construir colunas, bastando para isso indicarmos os valores
dos parmetros relevantes, como a altura e o raio da base do fuste, a altura e raio da base do coxim e a altura e largura do baco. Cada um destes
parmetros constitui um grau de liberdade que podemos fazer variar livremente.
Embora seja lgico pensar que quantos mais graus de liberdade tivermos mais flexvel a modelao, a verdade que um nmero excessivo
de parmetros pode conduzir a modelos pouco realistas. Esse fenmeno
evidente na Figura 26 onde mostramos uma perspectiva de um conjunto
de colunas cujos parmetros foram escolhidos aleatoriamente.
Na verdade, de acordo com os cnones da Ordem Drica, os diversos
parmetros que regulam a forma de uma coluna devem relacionar-se entre
30
102
Figura 26: Perspectiva da modelao tri-dimensional de colunas cujos parmetros foram escolhidos aleatoriamente. Apenas uma das colunas obedece
aos cnones da Ordem Drica.
si segundo um conjunto de propores bem definidas. Vitrvio,31 no seu
famoso tratado de arquitectura, considera que essas propores derivam
das propores do prprio ser humano:
Uma vez que pretendiam erguer um templo com colunas
mas no tinham conhecimento das propores adequadas, [. . . ]
mediram o comprimento dum p de um homem e viram que
era um sexto da sua altura e deram coluna uma proporo
semelhante, i.e., fizeram a sua altura, incluindo o capitel, seis
vezes a largura da coluna medida na base. Assim, a ordem Drica obteve a sua proporo e a sua beleza, da figura masculina.
Mais concretamente, Vitrvio caracteriza as colunas da Ordem Drica
em termos do conceito de mdulo:
A largura das colunas, na base, ser de dois modulos e a sua altura, incluindo
os capitis, ser de catorze.
Daqui se deduz que um mdulo iguala o raio da base da coluna e que
a altura da coluna dever ser 14 vezes esse raio. Dito de outra forma,
1
o raio da base da coluna dever ser 14
da altura da coluna.
A altura do capitel ser de um mdulo e a sua largura de dois mdulos e um
sexto.
31
Vitrvio foi um escritor, arquitecto e engenheiro romano que viveu no sculo um antes
de Cristo e autor do nico tratado de arquitectura que sobreviveu a antiguidade.
103
Isto implica que a altura do coxim somado do baco ser um mdulo, ou seja, igual ao raio da base da coluna e a largura do baco ser
de 2 61 mdulos ou 13
6 do raio. Juntamente com o facto de a altura da
coluna ser de 14 mdulos, implica ainda que a altura do fuste ser de
13 vezes o raio.
Seja a altura do capitel dividida em trs partes, das quais uma formar o
baco com o seu cimteo, o segundo o quino (coxim) com os seus aneis e o
terceiro o pescoo.
Isto quer dizer que o baco tem uma altura de um tero de um modulo, ou seja 13 do raio da base, e o coxim ter os restantes dois teros,
ou seja, 23 do raio da base.
Estas consideraes levam-nos a poder determinar o valor de alguns
dos parmetros de desenho das colunas dricas em termos do raio da base
do fuste. Em termos de implementao, isso quer dizer que os parmetros
da funo passam a ser variveis locais cuja atribuio feita aplicando
as propores estabelecidas por Vitrvio ao parmetro r-base-fuste. A
definio da funo fica ento:
(defun coluna (p
r-base-fuste r-base-coxim
/ a-fuste a-coxim a-abaco l-abaco)
(setq a-fuste (* 13 r-base-fuste)
a-coxim (* (/ 2.0 3) r-base-fuste)
a-abaco (* (/ 1.0 3) r-base-fuste)
l-abaco (* (/ 13.0 6) r-base-fuste))
(fuste p a-fuste r-base-fuste r-base-coxim)
(coxim (+z p a-fuste) a-coxim r-base-coxim (/ l-abaco 2.0))
(abaco (+z p (+ a-fuste a-coxim)) a-abaco l-abaco))
(xyz 0 0
(xyz 3 0
(xyz 6 0
(xyz 9 0
(xyz 12 0
(xyz 15 0
0)
0)
0)
0)
0)
0)
0.3
0.5
0.4
0.5
0.5
0.4
0.2)
0.3)
0.2)
0.4)
0.5)
0.7)
As propores de Vitrvio permitiram-nos reduzir o nmero de parmetros independentes de uma coluna Drica a apenas dois: o raio da base
do fuste e o raio da base do coxim. Contudo, no parece correcto que estes parmetros sejam totalmente independentes pois isso permite construir
colunas aberrantes, em que o topo do fuste mais largo do que a base, tal
como acontece com a coluna mais direita na Figura 27.
104
105
O fragmento anterior corresponde, obviamente, afirmao: se uma coluna tem menos de quinze ps, divida-se a largura na base em seis partes e usem-se
cinco dessas partes para formar a largura no topo. No caso de a coluna no ter
menos de quinze ps, ento passamos ao caso seguinte: se a coluna tem entre
quinze e vinte ps, divida-se a largura na base em seis partes e meio e usem-se cinco
e meio dessas partes para a largura no topo da coluna. A traduo deste segundo
caso permite-nos escrever:
(defun raio-topo-fuste (raio-base altura)
(cond ((< altura 15)
(* (/ 5.0 6.0) raio-base))
((and (>= altura 15) (< altura 20))
(* (/ 5.5 6.5) raio-base))
...))
(raio-base altura)
(* (/ 5.0 6.0) raio-base))
(* (/ 5.5 6.5) raio-base))
(* (/ 6.0 7.0) raio-base))
(* (/ 6.5 7.5) raio-base))
(* (/ 7.0 8.0) raio-base))
6
7
20
15
5 12
6 12
5
6
Para percebermos claramente de que princpios estamos a falar, consideremos a evoluo da relao entre o topo e a base das colunas que visvel
na imagem lateral.
A razo entre o raio do topo da coluna e o raio da base da coluna
, tal como se pode ver na margem (e j era possvel deduzir da funo
raio-topo-fuste), uma sucesso da forma
5 5 12 6 6 12 7
, ,
, ,
,
6 6 12 7 7 12 8
Torna-se agora bvio que, para colunas mais altas, os mesmos princpios de que Vitrvio fala se resumem a, para cada 10 ps adicionais, somar
1
2 quer ao numerador, quer ao denominador. No entanto, importante reparar que este princpio s pode ser aplicado a partir dos 15 ps de altura,
pois o primeiro intervalo maior que os restantes. Assim, temos de tratar de forma diferente as colunas at aos 15 ps e, da para a frente, basta
subtrair 20 ps altura e determinar a diviso inteira por 10 para saber o
nmero de vezes que precisamos de somar 12 quer ao numerador quer ao
denominador de 67 .
este tratar de forma diferente um caso e outro que, mais uma vez,
sugere a necessidade de um mecanismo de seleco: necessrio distinguir
dois casos e reagir em conformidade para cada um. No caso da coluna de
Vitrvio, se a coluna tem uma altura a at 15 ps, a razo entre o topo e a
base r = 56 ; se a altura a no inferior a 15 ps, a razo r entre o topo e a
base ser:
1
6 + b a20
10 c 2
r=
1
7 + b a20
10 c 2
A ttulo de exemplo, consideremos uma coluna com 43 ps de altura. A
diviso inteira de 43 20 por 10 2 portanto temos de somar 2 12 = 1 ao
numerador e denominador de 76 , obtendo 78 = 0.875.
Para um segundo exemplo, nos limites do absurdo, consideremos uma
coluna da altura do Empire State Building, i.e., com 449 metros de altura.
Um p, na ordem Drica, media 324 milmetros pelo que em 449 metros
existem 449/0.324 1386 ps. A diviso inteira de 1386 20 por 10
136. A razo entre o topo e a base desta hipottica coluna ser ento de
6+136/2
74
7+136/2 = 75 = 0.987. Este valor, por ser muito prximo da unidade, mostra
que a coluna seria praticamente cilndrica.
Com base nestas consideraes, podemos agora definir uma funo
que, dado um nmero inteiro representando a altura da coluna em ps,
calcula a razo entre o topo e a base da coluna. Antes, contudo, convm
simplificar a frmula para as colunas com altura no inferior a 15 ps. Assim,
r=
6 + b a20
10 c
a20
7 + b 10 c
1
2
1
2
a
a
12 + b a20
12 + b 10
c2
10 + b 10
c
10 c
=
=
a
a
a20
14 + b 10 c 2
12 + b 10 c
14 + b 10 c
107
O seguinte exemplo de utilizao da funo produz a sequncia de colunas apresentadas na Figura 28:33
(coluna-dorica (xy 0 0) 10)
(coluna-dorica (xy 10 0) 15)
(coluna-dorica (xy 20 0) 20)
(coluna-dorica (xy 30 0) 25)
(coluna-dorica (xy 40 0) 30)
(coluna-dorica (xy 50 0) 35)
108
4.5
Recurso
Vimos que as nossas funes, para fazerem algo til, precisam de invocar
outras funes. Por exemplo, se j tivermos a funo que calcula o quadrado de um nmero e pretendermos definir a funo que calcula o cubo
de um nmero, podemos facilmente faz-lo custa do quadrado e de uma
multiplicao adicional, i.e.:
(defun cubo (x)
(* (quadrado x) x))
Como bvio, podemos continuar a definir sucessivamente novas funes para calcular potncias crescentes, mas isso no s moroso como ser
sempre limitado. Seria muito mais til podermos generalizar o processo e
definir simplesmente a funo potncia que, a partir de dois nmeros (a
base e o expoente), calcula o primeiro elevado ao segundo.
No entanto, aquilo que fizemos para a quarta-potencia, o cubo e
o quadrado do-nos uma pista muito importante: se tivermos uma funo
que calcula a potncia de expoente imediatamente inferior, ento basta-nos uma
multiplicao adicional para calcular a potncia seguinte.
Dito de outra forma, temos:
109
(defun potencia (x n)
(* (potencia-inferior x n) x))
Embora tenhamos conseguido simplificar o problema do clculo de potncia, sobrou uma questo por responder: como podemos calcular a potncia imediatamente inferior? A resposta poder no ser bvia mas, uma
vez percebida, trivial: a potncia imediatamente inferior potncia de expoente
n a potncia de expoente (n1). Isto implica que (potencia-inferior x n)
exactamente o mesmo que (potencia x (- n 1)). Com base nesta
ideia, podemos reescrever a definio anterior:
(defun potencia (x n)
(* (potencia x (- n 1)) x))
A funo anterior um exemplo de uma funo recursiva, i.e., uma funo que est definida em termos de si prpria. Dito de outra forma, uma
funo recursiva uma funo que se usa a si prpria na sua definio. Esse
uso bvio quando desenrolamos a avaliao de (potencia 4 3):
(potencia 4 3)
(* (potencia 4 2) 4)
(* (* (potencia 4 1) 4) 4)
(* (* (* (potencia 4 0) 4) 4) 4)
(* (* (* 1 4) 4) 4)
(* (* 4 4) 4)
(* 16 4)
64
A recurso o mecanismo que permite que uma funo se possa invocar
a si prpria durante a sua prpria avaliao. A recurso uma das mais
importantes ferramentas de programao, pelo que fundamental que a
percebamos bem. Muitos problemas aparentemente complexos possuem
solues recursivas surpreendentemente simples.
Existem inmeros exemplos de funes recursivas. Uma das mais simples a funo factorial que se define matematicamente como:
(
1,
se n = 0
n! =
n (n 1)!, caso contrrio.
A traduo desta frmula para Lisp directa:
111
(factorial -1)
(* -1 (factorial -2))
(* -1 (* -2 (factorial -3)))
(* -1 (* -2 (* -3 (factorial -4))))
(* -1 (* -2 (* -3 (* -4 (factorial -5))))))
(* -1 (* -2 (* -3 (* -4 (* -5 (factorial -6))))))
...
O caso mais frequente de erro numa funo recursiva a recurso nunca
parar, ou porque no se detecta correctamente o caso bsico, ou por a recurso no diminuir a complexidade do problema. Neste caso, o nmero
de invocaes recursivas cresce indefinidamente at esgotar a memria do
computador, altura em que o programa gera um erro. No caso do Auto
Lisp, esse erro no inteiramente bvio pois o avaliador apenas interrompe
a avaliao sem apresentar qualquer resultado. Eis um exemplo:
_$ (factorial 3)
6
_$ (factorial -1)
_$
muito importante compreendermos bem o conceito de recurso. Embora a princpio possa ser difcil abarcar por completo as implicaes deste
conceito, a recurso permite resolver, com enorme simplicidade, problemas
aparentemente muito complexos.
Exercicio 4.2 A funo de Ackermann definida para nmeros no negativos da seguinte
forma:
se m = 0
n + 1
A(m, n) = A(m 1, 1)
se m > 0 e n = 0
113
e
c
P
Figura 29: Perfil de uma escada comn n degraus cujo primeiro degrau comea no ponto P e cujos degraus possuem um cobertor c e um espelho
e.
4.6
Recurso em Arquitectura
Como iremos ver, tambm em arquitectura a recurso um conceito fundamental. A ttulo de exemplo, consideremos o perfil de uma escada, tal como
esquematizado na Figura 29 e supunhamos que pretendemos definir uma
funo denominada escada que, dado o ponto P , dados o comprimento
do cobertor c e o comprimento do espelho e de cada degrau e, finalmente,
dado o nmero n de degraus, desenha a escada em AutoCad com o primeiro espelho a comear a partir do ponto P . Dados estes parmetros, a
definio da funo dever comear por:
(defun escada (p c e n)
...)
O problema que se coloca agora que a funo escada precisa de parar de desenhar degraus num determinado momento. fcil vermos que
114
n 1 degraus
P0
n degraus
Figura 30: Decomposio do desenho de uma escada de n degraus no desenho de um degrau seguido do desenho de uma escada de n 1 degraus.
esse momento chega quando, ao reduzirmos sucessivamente o nmeros de
degraus, atingimos um ponto em que esse nmero zero. Assim, quando
pedimos para desenhar uma escada com zero degraus, a funo escada
j no precisa de fazer nada. Isso quer dizer que a funo tem de ter a
seguinte forma:
(defun escada (p c e n)
(if (= n 0)
...
...
(degrau p c e)
(escada (+xy p c e) c e (- n 1)))
(defun escada (p0 degraus espelho cobertor / p1 p2)
(if (= degraus 0)
nil
(progn
(setq p1 (+y p0 espelho)
p2 (+x p1 cobertor))
(command "_.pline" p0 p1 p2 "")
(escada p2 (1- degraus) espelho cobertor))))
Exercicio 4.4 Defina uma funo equilibrio-circulos capaz de criar qualquer uma
das figuras apresentadas em seguida:
115
Note que os crculos possuem raios que esto em progresso geomtrica de razo f ,
com 0 < f < 1. Assim, cada crculo (excepto o primeiro) tem um raio que o produto de f
pelo raio do crculo maior em que est apoiado. O crculo mais pequeno de todos tem raio
maior ou igual a 1. A sua funo dever ter como parmetros o centro e o raio do crculo
maior e, ainda, o factor de reduo f .
Exercicio 4.5 Considere o desenho de crculos tal como apresentado na seguinte imagem:
y
r1
r0
116
Exercicio 4.6 Considere o desenho de flores simblicas compostas por um crculo interior
em torno da qual esto dispostos crculos radiais correspondentes a ptalas. Estes crculos
devero ser tangentes uns aos outros e ao crculo interior, tal como se apresenta na seguinte
imagem:
Defina a funo flor que recebe apenas o ponto correspondente ao centro da flor, o
raio do crculo interior e o nmero de ptalas.
Teste a sua funo com as expresses
(flor (xy 0 0) 5 10)
(flor (xy 18 0) 2 10)
(flor (xy 40 0) 10 20)
117
4.7
Este ltimo erro, como bvio, no tem a ver com a regras da gramtica
do Lisp: a frase da invocao da funo factorial est correcta. O
problema est no facto de no fazer sentido calcular o factorial de uma
string, pois o clculo do factorial envolve operaes aritmticas e estas no
so aplicveis a strings. Assim sendo, o erro tem a ver com o significado
da frase escrita, i.e., com a semntica. Trata-se, portanto, de um erro
semntico.
A recurso infinita outro exemplo de um erro semntico. Vimos que a
funo factorial s pode ser invocada com um argumento no negativo ou
provoca recurso infinita. Consequentemente, se usarmos um argumento
negativo, estaremos a cometer um erro semntico.
34
H casos de erros semnticos que podem ser detectados antes da execuo do programa,
mas essa deteco depende muito da qualidade da implementao da linguagem e da sua
capacidade em antecipar as consequncias dos programas.
118
4.7.1 Trace
Vimos, na seco3.17, que o Visual Lisp disponibiliza vrios mecanismos
para fazer a deteco de erros. Um dos mais simples a forma trace
que permite visualizar as invocaes das funes. A forma trace recebe o
nome das funes cuja invocao se pretende analisar e altera essas funes
de forma a que elas escrevam as sucessivas invocaes com os respectivos
argumentos, bem como o resultado da invocao. Se o ambiente do Visual
Lisp estiver activo, a escrita feita numa janela especial do ambiente do
Visual Lisp, denominada Trace,35 caso contrrio, feita na janela de comandos do AutoCad. A informao apresentada em resultado do trace ,
em geral, extremamente til para a depurao das funes.
Por exemplo, para visualizarmos uma invocao da funo factorial,
consideremos a seguinte interaco:
_$ (trace factorial)
FACTORIAL
_$ (factorial 5)
120
Note-se, no texto anterior escrito em consequncia do trace, que a invocao que fizemos da funo factorial aparece encostada esquerda.
Cada invocao recursiva aparece ligeiramente para a direita, permitindo
assim visualizar a profundidade da recurso, i.e., o nmero de invocaes recursivas. O resultado devolvido por cada invocao aparece alinhado na mesma coluna dessa invocao.
de salientar que a janela de Trace no tem dimenso infinita, pelo
que as recurses excessivamente profundas acabaro por no caber na janela. Neste caso, o Visual Lisp reposiciona a escrita na coluna esquerda
mas indica numericamente o nvel de profundidade em que se encontra.
Por exemplo, para o (factorial 15), aparece:
35
119
No caso de recurses infinitas, apenas so mostradas as ltimas invocaes realizadas antes de ser gerado o erro. Por exemplo, para (factorial -1),
teremos:
120
...
[19215]
Entering (FACTORIAL -19216)
[19216]
Entering (FACTORIAL -19217)
[19217]
Entering (FACTORIAL -19218)
[19218]
Entering (FACTORIAL -19219)
[19219]
Entering (FACTORIAL -19220)
[19220] Entering (FACTORIAL -19221)
[19221]
Entering (FACTORIAL -19222)
[19222]
Entering (FACTORIAL -19223)
[19223]
Entering (FACTORIAL -19224)
[19224]
Entering (FACTORIAL -19225)
...
[19963]
Entering (FACTORIAL -19964)
[19964]
Entering (FACTORIAL -19965)
[19965]
Entering (FACTORIAL -19966)
[19966]
Entering (FACTORIAL -19967)
[19967]
Entering (FACTORIAL -19968)
[19968]
Entering (FACTORIAL -19969)
[19969]
Entering (FACTORIAL -19970)
[19970] Entering (FACTORIAL -19971)
[19971]
Entering (FACTORIAL -19972)
[19972]
Entering (FACTORIAL -19973)
[19973]
Entering (FACTORIAL -19974)
[19974]
Entering (FACTORIAL -19975)
[19975]
Entering (FACTORIAL -19976)
Note que os crculos possuem raios que esto em progresso geomtrica de razo 12 .
Dito de outra forma, os crculos mais pequenos tm metade do raio do crculo maior que
121
lhes adjacente. Os crculos mais pequenos de todos tm raio maior ou igual a 1. A sua
funo dever ter como parmetros apenas o centro e o raio do crculo maior.
Exercicio 4.9 Defina uma funo denominada serra que, dado um ponto P , um nmero
de dentes, o comprimento c de cada dente e a altura a de cada dente, desenha uma serra em
AutoCad com o primeiro dente a comear a partir do ponto P , tal como se v na imagem
seguinte:
a
P
c
Exercicio 4.10 Defina uma funo losangulos capaz de criar a figura apresentada em
seguida:
Note que os losangos possuem dimenses que esto em progresso geomtrica de razo 12 . Dito de outra forma, os losangos mais pequenos tm metade do tamanho do losango
maior em cujas extremidades esto centrados. Os losangos mais pequenos de todos tm
largura maior ou igual a 1. A sua funo dever ter como parmetros apenas o centro e a
largura do losango maior.
Exercicio 4.11 Considere a escada esquematizada na seguinte figura e destinada a vencer
uma rampa de inclinao .
P
Defina a funo escada-rampa que recebe o ponto P , o ngulo , o cobertor c e o
nmero de degraus n e constri a escada descrita no esquema anterior.
Exercicio 4.12 Considere a escada esquematizada na seguinte figura e destinada a vencer
uma rampa de inclinao .
122
P
Note que os degraus da escada possuem dimenses que esto em progresso geomtrica de razo f , i.e., dado um degrau cujo cobertor de dimenso c, o degrau imediatamente acima tem um cobertor de dimenso f c. Defina a funo escada-progresso-geometrica
que recebe o ponto P , o ngulo , o cobertor c, o nmero de degraus n e o factor f e constri
a escada descrita no esquema anterior.
4.8
Templos Dricos
~v
Q
X
S =R
R = P + Q = S/
Q=RP
P =RQ
p1)
p0) (cx p1))
p0) (cy p1))
p0) (cz p1))))
(defun -c (p0
(xyz (- (cx
(- (cy
(- (cz
p1)
p0) (cx p1))
p0) (cy p1))
p0) (cz p1))))
(defun *c
(xyz (*
(*
(*
(p a)
(cx p) a)
(cy p) a)
(cz p) a)))
(defun /c (p a)
(*c p (/ 1.0 a)))
Exercicio 4.13 Um vector unitrio um vector de magnitude unitria. Defina a operao
vector-unitario que, dado um vector qualquer, calcula o vector unitrio que tem a
mesma direco que o vector dado.
Exercicio 4.14 O vector simtrico de um vector ~v o vector ~v 0 tal que ~v + ~v 0 = 0. Dito
de outro modo, o vector de igual magnitude mas direco oposta. Defina a operao
vector-simetrico que, dado um vector qualquer, calcula o vector simtrico do vector
dado.
(pol
(pol
(pol
(pol
(pol
10
10
10
10
10
0.0)
0.4)
0.8)
1.2)
1.6)
(pol
(pol
(pol
(pol
(pol
50
50
50
50
50
126
0.0)
0.4)
0.8)
1.2)
1.6)
8
8
8
8
8
6)
6)
6)
6)
6)
127
129
rp
ab
rb
x
rb
Figura 36: Corte da base de um Tholos. A base composta por uma sequncia de cilindros sobrepostos cujo raio de base rb encolhe de rb a cada degrau e cuja altura incrementa ab a cada degrau.
Caso contrrio, colocamos um degrau (modelado por um cilindro)
com o raio e a altura do degrau e, recursivamente, colocamos os restantes degraus em cima deste, i.e., numa cota igual altura do degrau
agora colocado e com um raio reduzido do comprimento do cobertor
do degrau agora colocado.
Este processo implementado pela seguinte funo:
(defun base-tholos (p n-degraus raio d-altura d-raio)
(if (= n-degraus 0)
nil
(progn
(command "_.cylinder" p raio d-altura)
(base-tholos (+xyz p 0 0 d-altura)
(- n-degraus 1)
(- raio d-raio)
d-altura
d-raio))))
Para o posicionamento das colunas, vamos tambm considerar um processo em que em cada passo apenas posicionamos uma coluna numa dada
posio e, recursivamente, colocamos as restantes colunas a partir da posio circular seguinte.
130
ap
ab
rb
rp
y
rp
x
Figura 37: Esquema da construo de um Tholos: rb o raio da base, rp a
distncia do centro das colunas ao centro da base, ap a altura das coluna,
ab a altura da base, o ngulo inicial de posicionamento das colunas e
o ngulo entre colunas.
Dada a sua estrutura circular, a construo deste gnero de edifcios
simplificada pelo uso de coordenadas circulares. De facto, podemos conceber um processo recursivo que, a partir do raio rp do peristilo e do ngulo
inicial , coloca uma coluna nessa posio e que, de seguida, coloca as restantes colunas usando o mesmo raio mas incrementando o ngulo de
, tal como se apresenta na Figura 37. O incremento angular obtmse pela diviso da circunferncia pelo nmero n de colunas a colocar, i.e.,
= 2
n . Uma vez que as colunas se dispem em torno de um crculo,
o clculo das coordenadas de cada coluna fica facilitado pelo uso de coordenadas polares. Tendo este algoritmo em mente, a definio da funo
fica:
131
Finalmente, definimos a funo tholos que, dados os parmetros necessrios s duas anteriores, as invoca em sequncia:
(defun tholos (p n-degraus rb dab drb n-colunas rp ap)
(base-tholos p n-degraus rb dab drb)
(colunas-tholos (+xyz p 0 0 (* n-degraus dab))
n-colunas
rp
0
(/ 2*pi n-colunas)
ap))
Exercicio 4.16 Uma observao atenta do Tholos apresentado na Figura 38 mostra que existe
um erro: os bacos das vrias colunas so paralelos uns aos outros (e aos eixos das abcissas e ordenadas) quando, na realidade, deveriam ter uma orientao radial. Essa diferena
132
evidente quando se compara uma vista de topo do desenho actual ( esquerda) com a
mesma vista daquele que seria o desenho correcto ( direita):
Defina uma nova funo coluna-dorica-rodada que, para alm da altura da coluna, recebe ainda o ngulo de rotao que a coluna deve ter. Uma vez que o fuste e o
coxim da coluna tm simetria axial, esse ngulo de rotao s influencia o baco, pelo que
dever tambm definir uma funo para desenhar um baco rodado.
De seguida, redefina a funo colunas-tholos de modo a que cada coluna esteja
orientada correctamente relativamente ao centro do Tholos.
Exercicio 4.17 Considere a construo de uma torre composta por vrios mdulos em que
cada mdulo tem exactamente as mesmas caractersticas de um Tholos, tal como se apresenta na figura abaixo, esquerda:
O topo da torre tem uma forma semelhante da base de um Tholos, embora com mais
degraus.
Defina a funo torre-tholos que, a partir do centro da base da torre, do nmero
de mdulos, do nmero de degraus a considerar para o topo e dos restantes parmetros
necessrios para definir um mdulo idntico a um Tholos, constri a torre apresentada anteriormente.
Experimente a sua funo criando uma torre composta por 6 mdulos, com 10 degraus
no topo, 3 degraus por mdulo, qualquer deles com comprimento de espelho e de cobertor
de 0.2, raio da base de 7.9 e 20 colunas por mdulo, com raio de peristilo de 7 e altura de
coluna de 4.
Exercicio 4.18 Com base na resposta ao exerccio anterior, redefina a construo da torre de
forma a que a dimenso radial dos mdulos se v reduzindo medida que se ganha altura,
tal como acontece na torre apresentada no centro da imagem anterior.
133
Exercicio 4.19 Com base na resposta ao exerccio anterior, redefina a construo da torre de
forma a que o nmero de colunas se v tambm reduzindo medida que se ganha altura,
tal como acontece na torre da direita da imagem anterior.
Exercicio 4.20 Considere a criao de uma cidade no espao, composta apenas por cilindros com dimenses progressivamente mais pequenas, unidos uns aos outros por intermdio de esferas, tal como se apresenta (em perspectiva) na seguinte imagem estereoscpica:36
Defina uma funo que, a partir do centro da cidade e do raio dos cilindros centrais
constri uma cidade semelhante representada.
4.9
A Ordem Jnica
134
P1 ~v0
rf
P
~v1 ~v
rf f f
2
P2
P3
rf f
136
Como se v pela figura, para se desenhar a espiral temos de ir desenhando sucessivos quartos de circunferncia. O primeiro quarto de circunferncia ser centrado no ponto P e ter raio r. Este primeiro arco vai desde
o ngulo /2 at ao ngulo . O segundo quarto de circunferncia ser centrado no ponto P1 e ter raio r f , sendo f um coeficiente de reduo da
espiral. Este segundo arco vai desde o ngulo at ao ngulo 32 . Um detalhe importante a relao entre as coordenadas P1 e P : para que o segundo
arco tenha uma extremidade coincidente com o primeiro arco, o seu centro
tem de estar na extremidade do vector ~v0 de origem em P , comprimento
r(1 f ) e ngulo igual ao ngulo final do primeiro arco.
Este processo dever ser seguido para todos os restantes arcos de circunferncia, i.e., teremos de calcular as coordenadas P2 , P3 , etc., bem como
os raios r f f , r f f f , etc, necessrios para traar os sucessivos arcos
de circunferncia.
Dito desta forma, o processo de desenho parece ser complicado. No
entanto, possivel reformul-lo de modo a ficar muito mais simples. De
facto, podemos pensar no desenho da espiral completa como sendo o desenho de um quarto de circunferncia seguido do desenho de uma espiral
mais pequena. Mais concretamente, podemos especificar o desenho da espiral de centro no ponto P , raio r e ngulo inicial como sendo o desenho
de um arco de circunferncia de raio r centrado em P com ngulo inicial
e final + 2 seguido de uma espiral de centro em P + ~v , raio r f e ngulo
inicial + 2 . O vector ~v ter origem em P , mdulo r(1 f ) e ngulo + 2 .
Obviamente, sendo este um processo recursivo, necessrio definir o
caso de paragem, havendo (pelo menos) duas possibilidades:
Terminar quando o raio r inferior a um determinado limite.
Terminar quando o ngulo superior a um determinado limite.
Por agora, vamos considerar a segunda possibilidade. De acordo com o
nosso raciocnio, vamos definir a funo que desenha a espiral de modo a
receber, como parmetros, o ponto inicial p, o raio inicial r, o ngulo inicial
a-ini, o ngulo final a-fin e o factor de reduo f:
(defun espiral (p r a-ini a-fin f)
(if (> a-ini a-fin)
nil
(progn
(quarto-circunferencia p r a-ini)
(espiral (+pol p (* r (- 1 f)) (+ a-ini (/ pi 2)))
(* r f)
(+ a-ini (/ pi 2))
a-fin
f))))
r a-ini)
p r a-ini) "_a" 90)
a-ini) "")
(+ a-ini (/ pi 2))) ""))
2.
claro que agora podemos facilmente construir outras espirais. As seguintes expresses produzem as espirais representadas na Figura 42:
(espiral (xy 0 0) 10 (/ pi 2) (/ pi 2) (* pi 6) 0.9)
(espiral (xy 20 0) 10 (/ pi 2) (/ pi 2) (* pi 6) 0.7)
(espiral (xy 40 0) 10 (/ pi 2) (/ pi 2) (* pi 6) 0.5)
Outra possibilidade de variao est no ngulo de incremento. As seguintes expresses experimentam aproximaes aos processos de Sebasti139
Figura 42: Vrias espirais com razes de reduo de 0.9, 0.7 e 0.5, respectivamente.
Note-se que se trata, to somente, de aproximaes. Os processos originais eram bastante mais complexos.
140
r1
r2
r2
r0
4.10
Recurso na Natureza
142
f c
f c
c
(x0 , y0 )
Figura 45: Parmetros de desenho de uma rvore.
Para darmos dimenses rvore, vamos considerar que a funo arvore
recebe, como argumento, as coordenadas da base da rvore, o comprimento
do tronco e o ngulo actual do tronco. Para a fase recursiva, teremos como
parmetros o ngulo de abertura alpha que o novo tronco dever fazer
com o actual e o factor de reduo f do comprimento do tronco. O primeiro passo a computao do topo do tronco usando a funo +pol. Em
seguida, desenhamos o tronco desde a base at ao topo. Finalmente, testamos se o tronco desenhado suficientemente pequeno. Se for, terminamos
com o desenho de um crculo centrado no topo. Caso contrrio fazemos
uma dupla recurso para desenhar uma sub-rvore para a direita e outra
para a esquerda. A definio da funo fica:
(defun arvore (base comprimento angulo alfa f / topo)
(setq topo (+pol base comprimento angulo))
(ramo base topo)
(if (< comprimento 2)
(folha topo)
(progn
(arvore topo
(* comprimento f)
(+ angulo alfa)
alfa f)
(arvore topo
(* comprimento f)
(- angulo alfa)
alfa f))))
(defun ramo (base topo)
(command "_.line" base topo ""))
(defun folha (topo)
(command "_.circle" topo 0.2))
143
fe c
fd c
c
(x0 , y0 )
Figura 48: Parmetros de desenho de uma rvore com crescimento assimtrico.
direita e esquerda. Para isso, em vez de termos um s ngulo de abertura e um s factor de reduo de comprimento, vamos empregar dois, tal
como se apresenta na Figura 48.
A adaptao da funo arvore para lidar com os parmetros adicionais trivial:
(defun arvore (base comprimento angulo
alfa-e f-e alfa-d f-d
/ topo)
(setq topo (+pol base comprimento angulo))
(ramo base topo)
(if (< comprimento 2)
(folha topo)
(progn
(arvore topo
(* comprimento f-e)
(+ angulo alfa-e)
alfa-e f-e alfa-d f-d)
(arvore topo
(* comprimento f-d)
(- angulo alfa-d)
alfa-e f-e alfa-d f-d))))
A Figura 49 apresenta novos exemplos de rvores com diferentes ngulos de abertura e factores de reduo dos ramos esquerdo e direito, geradas
pelas seguintes expresses:
(arvore (xy 0 0) 20 (/ pi 2) (/ pi 8) 0.6 (/ pi 8) 0.7)
(arvore (xy 100 0) 20 (/ pi 2) (/ pi 4) 0.7 (/ pi 16) 0.7)
(arvore (xy 200 0) 20 (/ pi 2) (/ pi 6) 0.6 (/ pi 16) 0.8)
Atribuio
5.1
Aleatoriedade
Desenhar implica tomar decises conscientes que conduzam a um objectivo pretendido. Neste sentido, desenhar aparenta ser um processo racional
onde no h lugar para a aleatoriedade, a sorte ou a incerteza. De facto, nos
desenhos que temos feito at agora a racionalidade tem sido crucial, pois o
computador exige uma especificao rigorosa do que se pretende, no permitindo quaisquer ambiguidades. No entanto, sabido que um problema
de desenho frequentemente exige que o arquitecto experimente diferentes
solues antes de encontrar aquela que o satisfaz. Essa experimentao
passa por empregar alguma aleatoriedade no processo de escolha dos parmetros do desenho. Assim, embora um desenho final possa apresentar
uma estrutura que espelha uma inteno racional do arquitecto, o processo
que conduziu a esse desenho final no necessariamente racional e pode
ter passado por fases de ambiguidade e incerteza.
146
5.2
Nmeros Aleatrios
Em qualquer dos casos anteriores, podemos reduzir a aleatoriedade escolha de nmeros dentro de certos limites. Para uma cor aleatria, podemos
gerar aleatoriamente trs nmeros que representem os valores RGB38 da
cor. Para um comprimento aleatrio, podemos gerar aleatoriamente um
nmero dentro dos limites desse comprimento. Para uma deciso lgica,
podemos gerar aleatoriamente um nmero inteiro entre zero e um, decidindo de um modo se o nmero for zero, e de outro modo se o nmero for
um. Para uma escolha aleatria de entre um conjunto de alternativas podemos simplesmente gerar um nmero aleatrio entre um e o nmero de
elementos do conjunto e escolher a alternativa correspondente ao nmero
aleatrio gerado.
38
147
149
_$ (aleatorio)
2822
_$ (aleatorio)
11031
_$ (aleatorio)
21180
5.3
Estado
A funo aleatorio apresenta um comportamento diferente do das funes que vimos at agora. At este momento, todas as funes que tnhamos definido comportavam-se como as funes matemticas tradicionais:
dados argumentos, a funo produz resultados e, mais importante, dados
os mesmos argumentos, a funo produz sempre os mesmos resultados. Por
exemplo, independentemente do nmero de vezes que invocarmos a funo quadrado, para um dado argumento ela ir sempre produzir o quadrado desse argumento.
A funo aleatorio diferente de todas as outras, pois, para alm de
no precisar de argumentos, ela produz um resultado diferente de cada vez
que invocada.
Do ponto de vista matemtico, uma funo sem parmetros no tem
nada de anormal: precisamente aquilo que se designa por uma constante.
De facto, tal como escrevemos sin cos x para designar sin(cos(x)), tambm
escrevemos sin para designar sin(()), onde se v que pode ser interpretado como uma funo sem argumentos.
Do ponto de vista matemtico, uma funo que produz resultados diferentes a cada invocao no tem nada de normal: uma aberrao, pois,
de acordo com a definio matemtica de funo, esse comportamento no
possvel. E, no entanto, precisamente este o comportamento que gostaramos de ter na funo aleatorio.
Para se obter o pretendido comportamento necessrio introduzir o
conceito de estado. Dizemos que uma funo tem estado quando o seu comportamento depende da sua histria, i.e., das suas invocaes anteriores. A
funo aleatrio um exemplo de uma funo com estado, mas h inmeros outros exemplos no mundo real. Uma conta bancria tambm tem
um estado que depende de todas as transaces anteriores que lhe tiverem
sido feitas. O depsito de combustvel de um carro tambm tem um estado
que depende dos enchimentos e dos trajectos realizados.
Para que uma funo possa ter histria necessrio que tenha memria,
i.e., que se possa recordar de acontecimentos passados para assim poder
influenciar os resultados futuros. At agora vimos que o operador setq
nos permitia definir associaes entre nomes e valores, mas o que ainda no
tnhamos discutido a possibilidade desse operador modificar associaes,
i.e., alterar o valor que estava associado a um determinado nome. esta
possibilidade que nos permite incluir memria nas nossas funes.
150
5.4
Vimos anteriormente que uma funo pode ter variveis locais bastando,
para isso, a sua indicao a seguir aos parmetros da funo. Cada varivel local possui um nome que apenas visvel para a funo que a contm.42 Acontece que no caso da funo aleatorio, ela usa uma vari41
Note-se que o operador setq, para alm de estabelecer uma associao entre um nome
e um valor devolve o valor que ficou associado.
42
Esta afirmao no inteiramente verdade para o Auto Lisp. Mais frente explicaremos
aquilo que verdadeiramente acontece no caso do Auto Lisp.
151
5.5
Escolhas Aleatrias
152
precisarmos de nmeros aleatrios contidos em intervalos muito mais pequenos. Por exemplo, se pretendermos simular o lanar de uma moeda
ao ar, estaremos interessados em ter apenas os nmeros aleatrios 0 ou 1,
representando caras ou coroas.
Tal como os nmeros aleatrios que produzimos so limitados ao intervalo [0, 65536[ pela obteno do resto da diviso por 65536, tambm agora
podemos voltar aplicar a mesma operao para produzir um intervalo mais
pequeno. Assim, no caso do lanamento de uma moeda ao ar, podemos
simplesmente usar a funo aleatorio para gerar um nmero aleatrio
e, de seguida, aplicamos-lhe o resto da diviso por dois. No caso geral, em
que pretendemos nmeros aleatrios no intervalo [0, x[, aplicamos o resto
da diviso por x. Assim, podemos definir uma nova funo que gera um
nmero aleatrio entre zero e o seu parmetro e que, por tradio, iremos
baptizar de random:
(defun random (x)
(rem (aleatorio) x))
Na verdade, o limite superior deve ser bastante inferior ao limite da funo aleatorio
para manter a equiprobabilidade dos resultados.
153
Infelizmente, quando testamos a funo aleatorio, obtemos resultados bizarros: 64454845, 960821323, 553057299, 924795749, 444490781,
. . . . Sendo o parmetro ultimo-aleatorio inicialmente positivo e sendo
o produto e o resto da diviso obtidos usando operandos positivos, o resultado teria necessariamente de ser no-negativo. Uma vez que existem
valores negativos na sequncia, isso sugere que est a ocorrer o mesmo
fenmeno que discutimos na seco 2.16: overflow, i.e., o resultado da multiplicao , por vezes, um nmero demasiado grande para a capacidade
de representao do Auto Lisp. Para resolver este problema, inventou-se
154
um algoritmo (ver [?]) capaz de computar os nmeros sem exceder a capacidade da mquina, desde que esta seja capaz de representar todos os inteiros no intervalo [231 , 231 1], ou seja, [2147483648, 2147483647] que
precisamente a gama de valores representveis em Auto Lisp. O algoritmo
baseia-se simplesmente em garantir que todos os valores intermdios do
clculo so sempre representveis pelo Auto Lisp.
(defun proximo-aleatorio (ultimo-aleatorio / teste)
(setq teste (- (* 16807 (rem ultimo-aleatorio 127773))
(* 2836 (/ ultimo-aleatorio 127773))))
(setq ultimo-aleatorio
(if (> teste 0)
teste
(+ teste 2147483647))))
Esta funo usa o reconhecedor universal realp que foi definido na seco 2.29.
155
5.5.2
Se, ao invs de gerarmos nmeros aleatrios no intervalo [0, x[, preferirmos gerar nmeros aleatrios no intervalo [x0 , x1 [, ento basta-nos gerar
um nmero aleatrio no intervalo [0, x1 x0 [ e somar-lhe x0 . A funo
random-[] implementa esse comportamento:
(defun random-[] (x0 x1)
(+ x0 (random (- x1 x0))))
Para incorporarmos alguma aleatoriedade neste modelo de rvore podemos considerar que os ngulos de abertura dos ramos e os factores de
reduo de comprimento desses ramos no possuem valores constantes ao
longo da recurso, antes variando dentro de certos limites. Assim, em vez
de nos preocuparmos em ter diferentes aberturas e factores para o ramo
esquerdo e direito, teremos simplesmente variaes aleatrias em ambos:
156
Usando esta nova verso, podemos gerar inmeras rvores semelhantes e, contudo, suficientemente diferentes para parecerem bastante mais
naturais. As rvores apresentadas na Figura 50 foram geradas usando exactamente os mesmos parmetros de crescimento:
(arvore
(arvore
(arvore
(arvore
(arvore
(arvore
(xy
(xy
(xy
(xy
(xy
(xy
0
0) 20 (/
150
0) 20 (/
300
0) 20 (/
0 150) 20 (/
150 150) 20 (/
300 150) 20 (/
pi
pi
pi
pi
pi
pi
2)
2)
2)
2)
2)
2)
(/
(/
(/
(/
(/
(/
157
pi
pi
pi
pi
pi
pi
16)
16)
16)
16)
16)
16)
(/
(/
(/
(/
(/
(/
pi
pi
pi
pi
pi
pi
4)
4)
4)
4)
4)
4)
0.6
0.6
0.6
0.6
0.6
0.6
0.9)
0.9)
0.9)
0.9)
0.9)
0.9)
Exercicio 5.1 As rvores produzidas pelas funo arvore so pouco realista pois so totalmente bidimensionais, com troncos que so simples linhas e folhas que so pequenas
circunferncias. O clculo das coordenadas dos ramos e folhas tambm bidimensional,
assentando sobre coordenadas polares que so dadas pelos parmetros comprimento e
angulo.
Pretende-se que redefina as funes ramo, folha e arvore de modo a aumentar o
realismo das rvores geradas.
Para simplificar, considere que as folhas podem ser simuladas por pequenas esferas
e que os ramos podem ser simulados por troncos de cone, cujo raio da base 10% do
comprimento do tronco e cujo raio do topo 90% do raio da base.
Para que a gerao de rvores passe a ser verdadeiramente tridimensional, redefina
tambm a funo arvore de modo a que o topo de cada ramo seja um ponto em coordenadas esfricas escolhidas aleatoriamente a partir da base do ramo. Isto implica que a funo
rvore, ao invs de ter dois parmetros para o comprimento e o ngulo das coordenadas
polares, precisar de ter trs, para o comprimento, a longitude e a co-latitude. Do mesmo
modo, ao invs de receber os quatro limites para a gerao de comprimentos e ngulos
aleatrios, precisar de seis limites para os trs parmetros.
Experimente diferentes argumentos para a sua redefinio da funo arvore de modo
a gerar imagens como a seguinte:
Exercicio 5.2 Defina uma funo denominada cilindros-aleatorios que recebe como
argumento um nmero de cilindros n e que gera n cilindros colocados em posies aleatrias, com raios aleatrios e comprimentos aleatrios, tal como se apresenta na seguinte
imagem:
158
Exercicio 5.3 Uma caminhada aleatria uma formalizao do movimento de uma particula
que est sujeita a impulsos de intensidade aleatria vindos de direces aleatrias. este
fenmeno que acontece, por exemplo, a um gro de plen cado na gua: medida que as
molculas da gua vo chocando com ele, o gro vai se movendo aleatoriamente.
A seguinte imagem mostra trs caminhadas aleatrias:
159
5.6
Planeamento Urbano
Figura 51: Vista area da cidade de New York nos Estados Unidos. Fotografia de Art Siegel.
edifcio ter uma largura determinada pela largura do quarteiro e uma altura mxima imposta. Os edifcios sero separados uns dos outros por ruas
com uma largura fixa.
Para estruturarmos a funo que constri a cidade em malha ortogonal,
vamos decompor o processo na construo de sucessivas ruas. A construo de cada rua ser ento decomposta na construo dos sucessivos
prdios. Assim, teremos de parametrizar a funo com o nmero de ruas
a construir na cidade e com o nmero de prdios por rua. Para alm disso
iremos necessitar de saber as coordenadas do ponto p onde se comea a
construir a cidade, a largura e a altura de cada prdio, respectivamente,
l-predio e a-predio e, finalmente, a largura da rua l-rua. A funo
ir construir uma faixa de prdios seguido de uma rua e, recursivamente,
construir as restantes faixas de prdios e ruas no ponto correspondente
faixa seguinte. Para simplificar, vamos assumir que as ruas estaro alinhadas com os eixos x e y, pelo que cada nova rua corresponde a um deslocamento ao longo do eixo y e cada novo prdio corresponde a um deslocamento ao longo do eixo x. Assim, temos:
161
Para a construo das ruas com prdios, o racioccio idntico: colocamos um prdio nas coordenadas correctas e, recursivamente, colocamos os
restantes prdios aps o deslocamento correspondente. A seguinte funo
implementa este processo:
(defun rua-predios (p predios l-predio a-predio l-rua)
(if (= predios 0)
nil
(progn
(predio p l-predio a-predio)
(rua-predios (+x p (+ l-predio l-rua))
(1- predios)
l-predio
a-predio
l-rua))))
162
Figura 52: Uma urbanizao em malha ortogonal com cem edifcios todos
da mesma altura.
(defun predio (p l-predio a-predio)
(command "_.box"
p
(+xyz p
l-predio
l-predio
(* (random-[] 0.1 1.0) a-predio))))
Usando exactamente os mesmos parmetros anteriores em duas avaliaes sucessivas da mesma expresso, conseguimos agora construir as urbanizaes esteticamente mais apelativas representadas nas Figuras 53 e
54.
Exercicio 5.6 As urbanizaes produzidas pelas funes anteriores no apresentam variabilidade suficiente, pois os edifcios tm todos a mesma forma. Para melhorar a qualidade
esttica da urbanizao pretende-se empregar diferentes funes para a construo de diferentes tipos de edifcios: a funo predio0 dever construir um paralelippedo de altura
aleatria tal como anteriormente e a funo predio1 dever construir uma torre cilndrica
de altura aleatria e contida no espao de um quarteiro. Defina estas duas funes.
Exercicio 5.7 Pretende-se que use as duas funes predio0 e predio1 definidas no exerccio anterior para a redefinio da funo predio de modo a que esta, aleatoriamente,
construa prdios diferentes. A urbanizao resultante dever ser constituda aproximadamente por 20% de torres circulares e 80% de prdios rectangulares, tal como exemplificado
na imagem seguinte:
163
Figura 53: Uma urbanizao em malha ortogonal com cem edifcios com
alturas aleatrias.
Figura 54: Uma urbanizao em malha ortogonal com cem edifcios com
alturas aleatrias.
164
Exercicio 5.8 As cidades criadas nos exerccios anteriores apenas permitem dois tipos de
edifcios: torres paralelipipdicas ou torres cilndricas. Contudo, quando observamos uma
cidade real como a apresentada na Figura 55, verificamos que existem prdios com muitas outras formas pelo que, para aumentarmos o realismo das nossas simulaes, teremos
de implementar um vasto nmero de funes, cada uma capaz de construir um edifcio
diferente.
Felizmente, uma observao atenta da Figura 55 mostra que, na verdade, muitos dos
prdios seguem um padro e podem ser modelado por paralelippedos sobrepostos com
dimenses aleatrias mas sempre sucessivamente mais pequenos em funo da altura, algo
que podemos facilmente implementar com uma nica funo.
Considere que este modelo de edifcio parametrizado pelo nmero de blocos sobrepostos pretendidos, pelas coordenadas do primeiro bloco e pelo comprimento, largura
165
e altura do edifcio. O bloco de base tem exactamente o comprimento e largura especificados mas a sua altura dever estar entre 20% e 80% da altura total do edifcio. Os blocos
seguintes esto centrados sobre o bloco imediatamente abaixo e possuem um comprimento
e largura que esto entre 70% e 100% dos parmetros correspondentes no bloco imediatamente abaixo. A altura destes blocos dever ser entre 20% e 80% da altura restante do
edifcio. A imagem seguinte mostra alguns exemplos deste modelo de edifcios:
Com base nesta especificao, defina a funo predio-blocos e use-a para redefinir
a funo predio0 de modo a que sejam gerados prdios com um nmero aleatrio de
blocos sobrepostos. Com esta redefinio, a funo malha-predios dever ser capaz de
gerar urbanizaes semelhantes imagem seguinte, em que se empregou para cada prdio
um nmero de blocos entre 1 e 6:
166
dada por
o )2 +( yyo )2
( xx
x
y
f (x, y) = e
167
Exercicio 5.11 Pretende-se criar um conjunto de n esferas tangentes a uma esfera virtual
de centro em p e raio limite rl . As esferas possuem centros a uma distncia de p que um
valor aleatrio compreendido entre um raio interior ri e um raio exterior re , tal como se
pode visualizar no seguinte esquema:
re
p
ri
rl
Listas
Vimos anteriormente que uma lista uma sequncia de elementos que podemos construir usando a funo list. Vimos tambm que podemos aceder a cada um destes elementos utilizando a funo nth que, dada a posio de um elemento e a lista que o contm, devolve esse elemento. Eis um
exemplo do uso destas operaes:
_$ (setq
("Filipa"
_$ (nth 0
"Filipa"
_$ (nth 3
"Maria"
No passado, usmos as listas para implementar coordenadas tridimensionais, i.e., agrupamentos de trs nmeros representando posies no espao. Agora, vamos us-las para agrupar um nmero arbitrrio de elementos. Para isso, temos de adoptar uma viso diferente das listas e temos de
168
introduzir novas funes que nos permitem trabalhar mais facilmente com
listas. Comecemos por introduzir uma funocons, abreviatura da palavra constructque nos permite criar uma lista maior a partir de um novo
elemento e de uma lista j existente.
_$ (setq novos-amigos (cons "Bernardo" amigos))
("Bernardo" "Filipa" "Pedro" "Carlos" "Maria")
_$ amigos
("Filipa" "Pedro" "Carlos" "Maria")
Dito de outra forma, podemos afirmar que a funo car devolve o primeiro elemento da lista e a funo cdr devolve o resto da lista, i.e., a lista
aps o primeiro elemento. Os nomes car e cdr tm raizes histricas e,
embora possa no parecer, so relativamente fceis de decorar. Uma mnemnica que pode ajudar pensar que o cAr obtm o que vem Antes e
o cDr obtm o que vem Depois.
Naturalmente, as funes car e cdr podem ser encadeadas:
_$ (car (cdr novos-amigos))
"Filipa"
_$ (cdr (cdr (cdr novos-amigos)))
("Carlos" "Maria")
_$ (car (cdr (cdr (cdr novos-amigos))))
"Carlos"
_$
(1
_$
(1
_$
(1
_$
(1
(cons 1
2 3 4)
(cons 1
2 3 4)
(cons 1
2 3 4)
(cons 1
2 3 4)
(list 2 3 4))
(cons 2 (list 3 4)))
(cons 2 (cons 3 (list 4))))
(cons 2 (cons 3 (cons 4 (list)))))
Embora o Auto Lisp use o smbolo nil para representar uma lista vazia,
sabemos que este smbolo tambm usado para representar a falsidade,
tal como a ltima expresso demonstra. Embora internamente seja exactamente a mesma coisa, para distinguir os dois usos o Auto Lisp permite
uma notao diferente para o smbolo nil: (). Isso visvel na seguinte
interaco:
_$ ()
nil
_$ (null ())
T
6.1
Pares
Vimos que a funo cons permite juntar um elemento a uma lista mas,
na verdade, ela faz algo bastante mais fundamental. Esta funo aceita
quaisquer duas entidades como argumentos e produz um par com essas
duas entidades, i.e., um valor que representa um aglomerado dessas duas
entidades. Tradicionalmente, usual dizer que o par um cons. As funes car e cdr so meramente os selectores que devolvem o primeiro e o
segundo elemento do par.
Eis um exemplo da criao de um par de nmeros:
170
_$
(1
_$
1
_$
2
(cons 1 2)
. 2)
(car (cons 1 2))
(cdr (cons 1 2))
6.2
"dois"
171
Repare-se, nas expresses anteriores, que o segundo argumento da funo cons , ou uma lista vazia, ou uma lista contendo alguns elementos.
Nestes casos, o resultado da invocao da funo cons ser sempre uma
lista.
6.3
Tipos Recursivos
6.4
Recurso em Listas
173
Experimentando, temos:
_$ (numero-elementos (list 1 2 3 4))
4
_$ (numero-elementos (list))
0
importante percebermos que a presena de sublistas no altera o nmero de elementos de uma lista. De facto, os elementos das sublistas no
so considerados elementos da lista. Por exemplo:
_$ (list (list 1 2) (list 3 4 5 6))
((1 2) (3 4 5 6))
_$ (numero-elementos (list (list 1 2) (list 3 4 5 6)))
2
frequentemente necessrio termos de concatenar listas. Para isso, podemos imaginar uma funo concatena que, dadas duas listas, devolve
uma lista contento, pela mesma ordem, os elementos das duas listas. Por
exemplo:
174
Falta agora tratar o caso bsico. Para isso, basta pensar que se estamos
a reduzir a primeira lista a cada invocao recursiva ento chegar um momento em que a primeira lista fica vazia. O que ento a concatenao de
uma lista vazia a uma outra lista qualquer? Obviamente, a outra lista.
Assim, podemos finalmente definir completamente a funo:
(defun concatena (l1 l2)
(if (null l1)
l2
(cons (car l1)
(concatena (cdr l1) l2))))
Para definirmos esta funo, podemos recursivamente simplificar o problema da obteno da sublista de (e0 e1 ... en ) entre os ndices i e j para
passar a ser a obteno da sublista de (e1 ... en ) entre os ndices i 1
e j 1. Quando i for zero, ento passamos a transformar o problema da
obteno da sublista de (e0 e1 ... en ) entre os ndices 0 e j para passar
a ser o cons de e0 com a sublista de (e1 ... en ) entre os ndices 0 e j 1.
Traduzindo este algoritmo para Lisp, temos:
(defun sublista (lista inicio fim)
(cond ((> inicio 0)
(sublista (cdr lista) (1- inicio) (1- fim)))
((> fim 0)
(cons (car lista)
(sublista (cdr lista) inicio (1- fim))))
(t
())))
Exercicio 6.1 Defina a funo elimina-n-esimo que recebe um nmero n e uma lista, e
elimina o n-simo elemento da lista. Note que o primeiro elemento da lista corresponde a
n igual a zero.
Por exemplo:
_$ (elimina-n-esimo 2 (list 0 1 2 3 4 5))
(0 1 3 4 5)
Exercicio 6.2 Escreva uma funo muda-n-esimo que recebe um nmero n, uma lista e
um elemento, e substitui o n-simo elemento da lista por aquele elemento. Note que o
primeiro elemento da lista corresponde a n igual a zero.
Por exemplo:
_$ (muda-n-esimo 2 (list 0 1 2 3 4 5) 9)
(0 1 9 3 4 5)
_$ (muda-n-esimo 2 (list "Vou" "para" "Coimbra") "Lisboa")
("Vou" "para" "Lisboa")
Exercicio 6.3 Escreva uma funo que dada uma lista de elementos devolve um elemento
dessa lista, escolhido aleatoriamente.
Exercicio 6.4 Defina a funo um-de-cada que, dada uma lista de listas, constri uma lista
contendo, por ordem, um elemento aleatrio de cada uma das listas. Por exemplo:
176
_$
(2
_$
(1
_$
(1
Exercicio 6.6 Redefina a funo elementos-aleatorios de modo a que o resultado respeite a ordem dos elementos na lista de onde foram escolhidos.
Exercicio 6.7 Como vimos, a funo cons acrescenta um novo primeiro elemento a uma
lista, a funo car devolve o primeiro elemento de uma lista e a funo cdr devolve a lista
sem o primeiro elemento.
Escreva as funes inversas do cons, car e cdr, designadas snoc, rac e rdc que,
ao invs de operarem com o primeiro elemento, operam com o ltimo. O snoc recebe um
elemento e uma lista e junta o elemento ao fim da lista. O rac devolve o ltimo elemento
da lista. O rdc devolve uma lista com todos os elementos menos o ltimo.
Exercicio 6.8 Defina uma funo inverte que recebe uma lista e devolve outra lista que
possui os mesmos elementos da primeira s que por ordem inversa.
6.5
Para testarmos se uma determinada entidade uma lista, podemos empregar o predicado listp. Este predicado verdade para qualquer lista
(incluindo a lista vazia) e falso para tudo o resto:
_$ (listp
T
_$ (listp
nil
_$ (listp
T
_$ (listp
T
(list 1 2))
1)
(list))
(cons 1 2))
Note-se, no ltimo exemplo, que o reconhecedor universal listp tambm considera como lista um mero par de elementos. Na realidade, este
reconhecedor devolve verdade sempre que o seu argumento um dotted
pair ou o nil.
Uma vez que as funes car e cdr nos permitem inspecionar dotted
pairs, a sua aplicao consecutiva permite-nos chegar at aos constituintes
ltimos dos pares, que sero nmeros, strings, etc. Estes constituintes ltimos, por j no serem mais decomponveis por intermdio das funes
car e cdr, denominam-se atmicos: em Lisp, tudo o que no for um dotted
pair considerado um tomo.
177
Uma vez que as listas so constituidas por pares, lgico que no sejam
consideradas tomos. H, no entanto, uma excepo: a lista vazia considerada simultneamente uma lista e um tomo. Isso visivel na seguinte
interaco:
_$ (atom (list 1 "dois" 3.0))
nil
_$ (atom (list))
T
Exercicio 6.9 Sendo as listas uma estrutura de dados to flexvel, muito frequente usarmos listas contendo outras listas que, por sua vez, podem conter outras listas, at ao nvel
de profundidade que se queira. Por exemplo, consideremos a seguinte lista de posies:
_$ (list (list 1 2) (list 3 4) (list 5 6))
((1 2) (3 4) (5 6))
Escreva uma funo denominada alisa que recebe uma lista (possivelmente com sublistas) como argumento e devolve outra lista com todos os tomos da primeira e pela
mesma ordem, i.e.
_$ (alisa (1 2 (3 4 (5 6)) 7))
(1 2 3 4 5 6 7)
Exercicio 6.10 Escreva uma funo que calcula o nmero de tomos que uma lista (possivelmente com sublistas) tem.
Exercicio 6.11 A concatenao de strings pode ser realizada pela funo strcat. Defina a
funo concatena-strings que, dada uma lista de strings, devolve uma s string com a
concatenao de todas elas. Por exemplo:
_$ (concatena-strings (list "A" "vista" "da" "Baixa" "da" "Banheira"))
"AvistadaBaixadaBanheira"
Exercicio 6.12 A funo concatena-strings cola as palavras umas s outras sem deixar espaos entre elas. Defina uma nova funo denominada forma-frase que recebe
uma lista de strings e concatena-as mas deixando um espao entre cada duas palavras. Por
exemplo:
178
Exercicio 6.13 Defina a funo frase-aleatoria que recebe uma lista de listas de palavras alternativas e devolve uma frase feita pela escolha aleatria de palavras de cada uma
das listas. Por exemplo, sucessivas avaliaes da seguinte expresso
(frase-aleatoria
(list (list "AutoLisp" "Scheme" "Common Lisp")
(list "" "sempre foi" "continua a ser")
(list "uma linguagem")
(list "fantstica." "fabulosa." "moderna.")))
6.6
Enumeraes
Vamos agora considerar uma funo que ser til no futuro para criar enumeraes. Dados os limites a e b de um intervalo [a, b] e um incremento i,
a funo dever devolver uma lista com todos os nmeros a, a + i, a + 2i,
a + 3i, a + 4i,. . . , at que a + ni > b.
Mais uma vez, a recurso ajuda: a enumerao dos nmeros no intervalo [a, b] com um incremento i exactamente o mesmo que o nmero a
179
(enumera 1 5 1)
2 3 4 5)
(enumera 1 5 2)
3 5)
(enumera 1 5 1)
2 3 4 5)
(enumera 5 1 -1)
4 3 2 1)
(enumera 6 0 -2)
4 2 0)
Exercicio 6.15 Infelizmente, a funo enumera desnecessariamente ineficiente pois, apesar do incremento nunca mudar ao longo das invocaes recursivas, estamos sistematicamente a testar se ele positivo. Obviamente, basta testar uma nica vez para se decidir, de
uma vez por todas, qual o teste que se deve fazer. Redefina a funo enumera de modo a
que no sejam feitos quaisquer testes desnecessrios.
180
(iota
1 2 3
(iota
2 4 6
10 1)
4 5 6 7 8 9)
10 2)
8)
(enumera 0 1 (/ 1.0
0.1 0.2 0.3 0.4 0.5
(enumera 0 1 (/ 1.0
0.01 0.02 0.03 0.04
10))
0.6 0.7 0.8 0.9 1.0)
100))
... 0.94 0.95 0.96 0.97 0.98 0.99)
6.7
Comparao de Listas
Vimos que o Lisp disponibiliza vrias funes de comparao e, em particular, a funo = aplicvel a nmeros, strings e smbolos.
No entanto, quando aplicamos esta funo a pares os resultados no
so os esperados:
181
_$ (= 1 1)
T
_$ (= "dois" "dois")
T
_$ (= (cons 1 "dois") (cons 1 "dois"))
nil
Note-se que embora a funo no tenha dado qualquer erro (implicando que aplicvel a pares), devolveu falso a indicar que os pares so
diferentes. Experimentemos agora uma variante:
_$ (setq par-1-dois (cons 1 "dois"))
(1 . "dois")
_$ (= par-1-dois par-1-dois)
T
Como se pode ver, a comparao foi feita entre duas referncia para um
par criado anteriormente. Supreendentemente, o resultado agora afirmativo. Qual ento a semntica da funo = aplicado a pares? A resposta
subtil: quando aplicada a dois argumentos do tipo par, a funo = devolve
verdade apenas quando os dois argumentos so o mesmo par.
Consideremos, por exemplo, a seguinte interao:
_$
(1
_$
(1
_$
(1
nil
l2
l3
O aspecto crucial destas estruturas que l2 e l3 se referem mesma
lista. Por este motivo, o operador = considera o valor de l2 igual ao valor
de l3. J o mesmo no acontece quando se compara l2 com l1 pois estes
nomes designam diferentes estruturas. Este comportamento visvel na
seguinte interaco:
182
_$ (= l1 l2)
nil
_$ (= l2 l3)
T
6.8
Comparao de Smbolos
At agora, apenas temos usado smbolos para a construo dos nossos programas, como nomes de funes e variveis. No entanto, os smbolos so
tambm teis noutros contextos em que so usados como valores.
Por exemplo, como vimos na seco 2.29, a funo type devolve um
smbolo que identifica o tipo de objecto. Vimos tambm que, para a definio de um reconhecedor para um determinado tipo, era til poder fazer
comparaes entre smbolos, de modo a identificarmos o smbolo pretendido:
(defun realp (obj)
(= (type obj) real))
183
6.9
1 3 (list 3 4))
1.01 2.99 (list 3 4.01)))
1 3 (list 3 4))
1.01 2.99 (list 3 4.01))
184
Carregamento de Ficheiros
185
(load "utilitarios")
Quando omitimos o caminho para o ficheiro, ento o Auto Lisp ir procurar o ficheiro segundo a seguinte estratgia:
1. O ficheiro procurado na directoria actual.51
2. Se no for encontrado, o ficheiro procurado na directoria do desenho actual.
3. Se no for encontrado, o ficheiro pesquisado em cada um dos directrios especificados no caminho de pesquisa do AutoCad.
4. Se no for encontrado, o ficheiro pesquisado na directoria que contm o AutoCad.
Uma vez que no conveniente alterar a directoria actual ou a directoria do desenho actual ou colocar os nossos ficheiros misturados com os do
AutoCad, a melhor soluo para facilmente podermos carregar os nossos
utilitrios consiste em criar uma directoria onde colocamos os vrios ficheiros e acrescentamos o caminho para essa directoria no caminho de pesquisa
do AutoCad. Esse caminho especificado por uma sequncia de directrios indicados no tabulador Files, opo Support File Search Path do
dilogo que resulta do comando OPTIONS.
Note-se que a sequncia de directrios indicados nesse tabulador define
a ordem de pesquisa feita pelo AutoCad. Se pretendemos que os nossos
ficheiros sejam encontrados primeiro que outros com o mesmo nome, ento
deveremos acrescentar o caminho para a nossa directoria antes dos outros
caminhos na sequncia.
7.1
Carregamento de Dependncias
Esta a directoria em que o AutoCad comea a funcionar. No caso do Windows, corresponde ao valor da opo Start In das propriedades do cone do AutoCad.
186
Deste modo, quando avaliamos (load "grafico") o Auto Lisp localiza o ficheiro em questo e, uma vez que a primeira expresso desse
ficheiro (load "listas"), o Auto Lisp suspende momentaneamente o
carregamento do ficheiro grafico e procura pelo ficheiro listas. Quando
o encontra, comea a avaliar as suas expresses mas, mais uma vez, como a
primeira dessas expresses (load "utils") o Auto Lisp suspende momentaneamente o carregamento do ficheiro e procura pelo ficheiro utils.
Quando o encontra, avalia todo o seu contedo, regressando ento ao carregamento do ficheiro listas. Aps ter avaliado todas as expresses
deste ficheiro regressa finalmente ao primeiro ficheiro grafico para passar avaliao da expresso seguinte: (load "grafico-utils"). Novamente, o Auto Lisp suspende momentaneamente o carregamento do ficheiro grafico, para agora procurar pelo ficheiro grafico-utils, avaliar todas as suas expresses e, por fim, regressar ao ficheiro grafico para
avaliar as restantes formas.
Esta relao de dependncia entre os vrios ficheiros pode ser representada graficamente num grafo, tal como se apresenta na Figura 56.
7.2
Mdulos
utils
listas
grafico-utils
grafico
Figura 56: Dependncias entre os ficheiros grafico, listas, utils e
grafico-utils.
utilitrios e que composto pelo ficheiro listas e, finalmente, existe um
mdulo de grficos que depende do mdulo de listas e que constitudo
pelos ficheiros grafico e grafico-utils.
O conceito de mdulo muito importante pois permite abstrair um conjunto de ficheiros numa s entidade. Do ponto de vista de quem usa o mdulo, irrelevante saber se ele constitudo por um, dois ou mil ficheiros,
qual a ordem de carregamento desses ficheiros ou quais as dependncias
que esse mdulo tem de outros mdulos. Desde que no se reduza a funcionalidade de um mdulo, esta abstraco permite que quem criou um
mdulo possa alter-lo, acrescentando, retirando ou modificando ficheiros,
sem afectar quem depende do mdulo.
Consideremos agora uma situao mais complexa (mas mais frequente).
Para alm dos ficheiros grafico-utils.lsp, grafico.lsp, listas.lsp
e utils.lsp que tnhamos no exemplo anterior, temos ainda, num outro
ficheiro chamado testes.lsp, operaes teis para a realizao de testes,
operaes essas cuja definio depende, por um lado, de algumas das operaes de utils e, por outro, de algumas das operaes de listas, tal
como se apresenta em seguida:
testes.lsp
(load "utils")
(load "listas")
(defun ...)
...
188
utils
listas
grafico-utils
grafico
testes
colunas
Figura 57: Dependncias entre os ficheiros grafico, listas, utils e
grafico-utils.
colunas.lsp
(load "testes")
(load "utils")
(load "graficos")
(defun ...)
...
um ficheiro pode acabar por ser carregado mltiplas vezes. Para percebermos isto, pensemos na sequncia de carregamentos que ocorre quando
avaliamos (load "colunas"):
1. (load "testes")
(a) (load "utils")
(b) (load "listas")
i. (load "utils")
2. (load "utils")
3. (load "grafico")
(a) (load "listas")
i. (load "utils")
4. (load "grafico-utils")
fcil ver que, ao preservarmos a abstraco de cada mdulo, i.e., ao
no conhecermos as dependncias de cada mdulo, acabamos inadvertidamente por carregar mltiplas vezes vrios ficheiros: listas carregado
duas vezes e utils carregado quatro vezes.
Obviamente, este mltiplo carregamento de ficheiros indesejvel. Para
resolver este problema, devemos complementar o processo de carregamento
com um registo de tudo o que j tiver sido carregado para evitar carregar
algum ficheiro mais do que uma vez.
Para isso, vamos comear por usar uma varivel global para conter os
nomes dos ficheiros j carregados e, em seguida, definimos uma funo
usa que, dado o nome de um ficheiro que se pretende usar, verifica se ele
j foi carregado e, se no tiver sido, carrega-o. Estas duas formas sero
colocadas no ficheiro usa.lisp:
usa.lsp
(setq ficheiros-carregados ())
(defun usa (nome)
(if (member nome ficheiros-carregados)
nil
(progn
(load nome)
(setq ficheiros-carregados
(cons nome ficheiros-carregados))
t)))
190
grafico.lsp
(usa "listas")
(usa "grafico-utils")
(defun ...)
...
listas.lsp
(usa "utils")
(defun ...)
...
testes.lsp
(usa "utils")
(usa "listas")
(defun ...)
...
colunas.lsp
(usa "testes")
(usa "utils")
(usa "graficos")
(defun ...)
...
7.3
Carregamento Automtico
7.4
Interpretao e Compilao
Vimos que, quando o Auto Lisp avalia uma expresso, ele primeiro analisaa, decompondo-a nas suas subexpresses e, recursivamente, avalia estas de
acordo com as regras da linguagem, seguindo este processo at chegar s
expresses mais simples de todas, para as quais o Auto Lisp sabe imediatamente qual o valor, passando ento a combinar os valores das subavaliaes at produzir o valor da expresso original.
Este processo, que o Auto Lisp segue para a avaliao de qualquer expresso, denomina-se interpretao e o programa que o realiza diz-se um
192
interpretador. Quando estamos a usar o REPL do AutoCad estamos, na realidade, a usar um interpretador para a linguagem Auto Lisp.
Embora a interpretao seja um processo muito til para a depurao
dos programas, sofre de um problema: computacionalmente pouco eficiente. Se pensarmos, por exemplo, na funo factorial, fcil vermos
que a avaliao de uma invocao da funo factorial implica uma sequncia de anlises e combinao de resultados que tem de ser repetida para
cada uma das sucessivas invocaes recursivas da funo.
Existe um outro processo de avaliao que, embora menos flexvel que
a interpretao, tem o potencial para ser muito mais eficiente: a compilao.
A compilao uma operao que realizada por um compilador e que
se baseia em analisar expresses sem as avaliar e em transform-las noutras expresses equivalentes que, quando avaliadas, produzam os mesmos
resultados mas de forma mais eficiente. A ideia fundamental da compilao que possvel converter um programa escrito numa linguagem num
programa escrito noutra linguagem que seja mais eficiente de interpretar
ou, no limite, que seja directamente executvel pelo computador.
Em geral, a compilao em Lisp transforma um ficheiro contendo expresses Lisp num outro ficheiro com as mesmas expresses traduzidas
para outra linguagem muito mais eficiente de avaliar. Em geral, h duas
vantagens em usar ficheiros compilados:
muito mais rpido carregar um ficheiro compilado do que um no
compilado.
A invocao das funes que foram definidas a partir de um ficheiro
compilado mais rpida, por vezes, muito mais rpida.
Para se compilar um ficheiro necessrio invocar a funo vlisp-compile.
Esta funo recebe trs argumentos:
1. Um smbolo indicando qual o grau de optimizao desejado.
2. Uma string indicando o ficheiro a compilar. Se a extenso do ficheiro
for omissa, considera-se .lsp como extenso. Se apenas se indicar o nome do ficheiro, sem o caminho at ele, o Visual Lisp usa o
processo normal de procura de ficheiros para o encontrar.
3. Uma string opcional indicando o caminho para o ficheiro a criar para
conter o resultado da compilao. Quando omisso, idntico ao argumento anterior, mas usando .fas como extenso. Quando no
omisso, ento poder ser apenas o nome do ficheiro (caso em que o
o Visual Lisp ir colocar o ficheiro na sua directoria de instalao) ou
o caminho completo para o ficheiro.
193
Listas de Coordenadas
8.1
Polgonos
Imaginemos, a ttulo de exemplo, que pretendemos representar um polgono. Por definio, um polgono uma figura plana limitada por um caminho fechado composto por uma sequncia de segmentos de recta. Cada
segmento de recta uma aresta (ou lado) do polgono. Cada ponto onde se
encontram dois segmentos de recta um vrtice do polgono.
A partir da definio de poligono fcil vermos que uma das formas
mais simples de representar um polgono ser atravs de uma sequncia
de coordenadas que indica qual a ordem pela qual devemos unir os vrtices com uma aresta e onde se admite que o ltimo elemento ser unido
ao primeiro. Para representar esta sequncia podemos simplesmente usar
52
Essa dificuldade de compreenso pode ser til quando se pretende ceder a terceiros um
programa mas em que no se pretende que se saiba como est feito.
53
Note-se a utilizao da plica para evitar a avaliao do smbolo st.
194
uma lista. Por exemplo, uma lista com as coordenadas de quatro vrtices pode representar um quadriltero, um octgono ser representado por
uma lista de oito vrtices, um hentriacontgono ser representado por uma
lista de trinta e um vrtices, etc.
A representao de polgonos usando listas apenas o primeiro passo
para os podermos visualizar graficamente. O segundo passo a invocao
dos comandos do AutoCad que constroem o polgono em questo. Para
isso, temos de invocar o comando line (ou, alternativamente, o comando
pline) e, de seguida, passar os sucessivos pontos para o AutoCad. No
final da sequencia de pontos temos ainda de passar a opo close para
que o AutoCad feche o polgono, unindo o ltimo ao primeiro ponto.
Decompondo o problema em duas partes, podemos escrever:
(defun poligono (vertices)
(command "_.line")
(passa-pontos vertices)
(command "_close"))
Uma vez que a passagem dos pontos tem de ser feita percorrendo a lista
com os vrtices, vamos definir uma funo recursiva para o fazer:
(defun passa-pontos (pontos)
(if (null pontos)
nil
(progn
(command (car pontos))
(passa-pontos (cdr pontos)))))
Usando a funo poligono podemos agora facilmente desenhar inmeros polgonos. Por exemplo, as seguintes avaliaes produzem o resultado apresentado na Figura 58.
(poligono (list (xy -2 -1) (xy 0 2) (xy 2 -1)))
(poligono (list (xy -2 1) (xy 0 -2) (xy 2 1)))
importante notarmos que a funo poligono independente de quaisquer polgonos em particular. Ela tanto se aplica ao desenho de tringulos como quadrados como qualquer outro polgono. Esta independncia
tornou-se possvel pela utilizao de listas para representar as coordenadas
dos vrtices dos polgonos. Agora, apenas necessrio concentrarmo-nos
na criao destas listas de coordenadas.
8.1.1
Estrelas Regulares
O polgono representado na Figura 58 foi gerado manualmente pela sobreposio de dois tringulos. Um polgono mais interessante o famoso
195
196
2
5
197
raio)
2) (*
2) (*
2) (*
2) (*
2) (*
0
1
2
3
4
0.8
0.8
0.8
0.8
0.8
pi)))
pi)))
pi)))
pi)))
pi)))))
Como bvio, a funo vertices-pentagrama possui excessiva repetio de cdigo, pelo que seria prefervel encontrarmos uma forma mais
estruturada de gerarmos aqueles vrtices. Para isso, vamos comear por
pensar na generalizao da funo.
O caso geral de um pentagrama a estrela regular, em que se faz variar o
nmero de vrtices e o nmero de arcos que separam um vrtice do vrtice
a que ele se une. O pentagrama um caso particular da estrela regular em
que o nmero de vrtices cinco e o nmero de arcos de separao dois.
Matematicamente falando, uma estrela regular representa-se pelo smbolo
de Schlfli55 { av } em que v o nmero de vrtices e a o nmero de arcos
de separao. Nesta notao, um pentagrama escreve-se como { 52 }.
Para desenharmos estrelas regulares vamos idealizar uma funo que,
dado o centro da estrela, o raio do crculo circunscrito, o nmero de vrtices
v (a que chamaremos n-vertices) e o nmero de arcos de separao a (a
que chamaremos n-arcos), calcula o tamanho do arco que preciso
avanar a partir de cada vrtice. Esse arco , obviamente, = a 2
v . Tal
como no pentagrama, para primeiro vrtice vamos considerar um ngulo
inicial de = 2 . A partir desse primeiro vrtice no preciso mais do
que ir aumentando o ngulo de de cada vez. As seguintes funes
implementam este raciocnio:
(defun vertices-estrela (p raio n-vertices n-arcos)
(pontos-circulo p
raio
pi/2
(* n-arcos (/ 2*pi n-vertices))
n-vertices))
(defun pontos-circulo (p raio fi dfi n)
(if (= n 0)
(list)
(cons (+pol p raio fi)
(pontos-circulo p
raio
(+ fi dfi)
dfi
(- n 1)))))
Ludwig Schlfli foi um matemtico e gemetra Susso que fez importantes contribuies, em particular, na geometria multidimensional.
198
Figura 61: Estrelas regulares em AutoCad. Da esquerda para a direita, temos um pentagrama ({ 52 }), dois heptagramas ({ 27 } e { 73 }) e um octograma
({ 83 }).
qualquer estrela regular. A Figura 61 apresenta as estrelas regulares desenhadas a partir das seguintes expresses:
(poligono (vertices-estrela (xy 0 0) 1 5 2))
(poligono (vertices-estrela (xy 2 0) 1 7 2))
(poligono (vertices-estrela (xy 4 0) 1 7 3))
(poligono (vertices-estrela (xy 6 0) 1 8 3))
muito importante salientarmos a forma como a representao grfica de estrelas est separada em duas partes distintas. De um lado, o da
funo vertices-estrela, produzimos as coordenadas dos vrtices das
estrelas pela ordem em que estes devem ser unidos. No outro lado, o da
funo poligono, usamos essas coordenadas para criar uma representao grfica dessa estrela baseada em linhas que ligam os seus vrtices. A
passagem das coordenadas de um lado para o outro realizada atravs de
uma lista que produzida num lado e consumida no outro.
Esta utilizao de listas para separar diferentes processos fundamental
e ser por ns repetidamente explorada para simplificar os nossos programas.
8.1.2
Polgonos Regulares
Um polgono regular um polgono que tem todos os lados de igual comprimento e todos os ngulos de igual amplitude. A Figura 62 ilustra exemplos
de polgonos regulares. Como bvio, um polgono regular um caso particular de uma estrela regular em que o nmero de arcos de separao
um.
Para criarmos polgonos regulares, vamos definir uma funo denominada vertices-poligono-regular que gera uma lista de coordenadas
correspondente s posies dos vrtices de um polgono regular de n lados, inscrito numa circunferncia de raio r centrada em p, cujo primeiro
vrtice faz um ngulo com o eixo dos X. Sendo um polgono regular um
199
Figura 62: Polgonos regulares. Da esquerda para a direita temos um tringulo equiltero, um quadrado, um pentgono regular, um hexgono regular, um heptgono regular, um octgono regular, um enegono regular e
um decgono regular.
caso particular de uma estrela regular, basta-nos invocar a funo que computa os vrtices de uma estrela regular mas usando, para o parmetro ,
apenas a diviso da circunferncia 2 pelo nmero de lados n, i.e.:
(defun vertices-poligono-regular (p r fi n)
(pontos-circulo p r fi (/ 2*pi n) n))
8.2
Iterao em Listas
A iterao em listas tambm muito til para experimentarmos variaes de figuras geomtricas. Uma vez que a funo enumera (definida na
seco 6.6) gera uma sequncia de nmeros, podemos usar esses nmeros
em combinao com a forma foreach para desenhar uma sequncia de
figuras. Por exemplo, a seguinte expresso gera a Figura 63:
(foreach a (enumera 1 9 1)
(poligono
(vertices-estrela (xy (* 2 a) 0) 1 20 a)))
201
Exercicio 8.2 Considere um polgono representado pela lista dos seus vrtices (p0 p1 ... pn ),
tal como apresentamos no seguinte esquema, esquerda:
P2
P2
P1
P3
P1
P3
P0
P4
P0
P4
Pretende-se dividir o polgono em dois sub-polgonos, tal como apresentado no esquema anterior, direita. Defina a funo divide-poligono que, dada a lista de vrtices
do polgono e dados dois ndices i e j onde se deve fazer a diviso (com i < j), calcula as listas de vrtices de cada um dos sub-polgonos resultantes e devolve-as numa lista. Por exemplo, no caso da imagem, temos que (divide-poligono (list p0 p1 p2 p3 p4 ) 1 4)
produz a lista de listas ((p0 p1 p4 ) (p1 p2 p3 p4 ))
Exercicio 8.3 Podemos considerar uma generalizao do exerccio anterior baseada na bisseco do polgono usando uma linha arbitrria, tal como podemos ver no esquema seguinte:
P2
P3
P2
P1
P3
P0
P4
P1
P0
P4
Para simplificar o processo, considere que cada extremidade da linha de bisseco est
localizada a uma determinada fraco fi [0, 1] da distncia que vai do vrtice Pi ao vrtice
sequinte Pi+1 (com Pn+1 = P0 ). Por exemplo, no esquema anterior, os vrtices em questo
so P1 e P4 e a fraces so, respectivamente, de f1 = 0.3 e f4 = 0.5.
Defina a funo bisseccao-poligono que, dada a lista de vrtices do polgono e
dados os dois ndices i e j imediatamente anteriores aos extremos da linha de bisseco e
dadas as fraces fi e fj da distncia, respectivamente, entre os vrtices (Pi , Pi+1 ) e entre
(Pj , Pj+1 ), calcula as listas de vrtices de cada um dos sub-polgonos resultantes e devolveas numa lista (i.e., devolve uma lista de listas de vrtices).
Exercicio 8.4 Defina a funo bisseccao-aleatoria-poligono que, dados os vrtices
de um polgono, devolve uma lista de listas de vrtices dos sub-polgonos correspondentes
a uma diviso aleatria do polgono. A seguinte imagem mostra exemplos de divises
aleatrias de um octgono.
202
8.3
203
Figura 64: Comparao entre uma linha poligonal e uma spline que unem o
mesmo conjunto de pontos.
(defun 3dpoly-pontos (pontos)
(command "_.3dpoly")
(foreach p pontos (command p))
(command ""))
Para termos uma maior liberdade de posicionamento da curva sinusise no espao, podemos modificar a funo anterior para incorporar um
ponto P em relao ao qual se calcula a curva:
(defun pontos-seno (p x0 x1 dx)
(if (> x0 x1)
(list)
(cons (+xy p x0 (sin x0))
(pontos-seno p (+ x0 dx) x1 dx))))
206
8.4
Trelias
Uma trelia uma estrutura composta por barras rgidas que se unem em
ns, formando unidades triangulares. Sendo o tringulo o nico polgono
intrinsecamente estvel, a utilizao de tringulos convenientemente interligados permite que as trelias sejam estruturas indeformveis. Apesar
da simplicidade dos elementos triangulares, diferentes arranjos destes elementos permitem diferentes tipos de trelias.
conhecido o uso de trelias desde a Grcia antiga, em que eram utilizadas para o suporte dos telhados. No sculo dezasseis, nos seus Quatro
Livros de Arquitectura, Andrea Palladio ilustra pontes de trelias. No sculo
dezanove, com o uso extensivo de metal e a necessidade de ultrapassar
vos cada vez maiores, inventaram-se vrios tipos de trelias que se distinguem pelos diferentes arranjos de barras verticais, horizontais e diagonais
e que, frequentemente, se denominam de acordo com os seus inventores.
Temos assim trelias Pratt, trelias Howe, trelias Town, trelias Warren,
207
Desenho de Trelias
O passo fundamental para o desenho de trelias a construo dos elementos triangulares fundamentais. Embora frequentemente se conside208
209
a0
c0
b0
a1
c1
b1
a2
c2
A funo no-trelica (notemos o singular, por oposio ao plural empregue na funo nos-trelica) recebe as coordenadas de um ponto e
responsvel por criar o modelo tridimensional que representa o n da trelia centrado nesse ponto. Uma hiptese simples ser esta funo criar uma
esfera onde se encaixaro as barras mas, por agora, vamos deixar a deciso
sobre qual o modelo em concreto para mais tarde e vamos simplesmente
admitir que a funo no-trelica far algo apropriado para criar o n.
Assim, podemos comear a idealizar a funo que constri a trelia completa a partir das listas de pontos as, bs e cs:
(defun trelica
(nos-trelica
(nos-trelica
(nos-trelica
...)
(as bs cs)
as)
bs)
cs)
lise da Figura 72 ficamos a saber que temos uma ligao entre cada ai e cada
ci , outra entre ai e bi , outra entre ci e bi , outra entre bi e ai+1 , outra entre bi
e ci+1 , outra entre ai e ai+1 , outra entre bi e bi+1 e, finalmente, outra entre ci
e ci+1 . Admitindo que a funo barra-trelica cria o modelo tridimensional dessa barra (por exemplo, um cilindro, ou uma barra prismtica),
podemos comear por definir uma funo denominada barras-trelica
(notemos o plural) que, dadas duas listas de pontos ps e qs, cria barras
de ligao ao longo dos sucessivos pares de pontos. Para criar uma barra,
a funo necessita de um elemento dos ps e outro dos qs, o que implica
que a funo deve terminar assim que uma destas listas estiver vazia. A
definio fica ento:
(defun barras-trelica (ps qs)
(if (or (null ps) (null qs))
nil
(progn
(barra-trelica (car ps) (car qs))
(barras-trelica (cdr ps) (cdr qs)))))
Para ligar os ns bi aos ns ai+1 podemos simplesmente subtrair o primeiro n da lista as e estabelecer a ligao como anteriormente. O mesmo
podemos fazer para ligar cada bi a cada ci+1 . Finalmente, para ligar cada
ai a cada ai+1 podemos usar a mesma ideia mas aplicando-a apenas lista
as. O mesmo podemos fazer para a lista cs. A funo completa fica, ento:
211
as))
cs))
as))
cs))
bs)))
As funes anteriores constroem trelias com base nas funes elementares no-trelica e barra-trelica. Embora o seu significado seja
bvio, ainda no definimos estas funes e existem vrias possibilidades.
Numa primeira abordagem, vamos considerar que cada n da trelia ser
constitudo por uma esfera onde se iro unir as barras, barras essas que
sero definidas por cilindros. O raio das esferas e da base dos cilindros
ser determinado por uma varivel global, para que possamos facilmente
alterar o seu valor. Assim, temos:
(setq raio-no-trelica 0.1)
(defun no-trelica (p)
(esfera p raio-no-trelica))
(setq raio-barra-trelica 0.03)
(defun barra-trelica (p0 p1)
(cilindro p0 raio-barra-trelica p1))
(trelica
(list (xyz
(xyz
(list (xyz
(xyz
(list (xyz
(xyz
0)
0))
0 2)
0)
0)))
Exercicio 8.9 Defina uma funo denominada trelica-recta capaz de construir qualquer uma das trelias que se apresentam na imagem seguinte.
213
bi
l
h
ai
ai+1
ci
ci+1
l
Defina ainda a funo trelica-modulo que constri uma trelia com barras todas do
mesmo comprimento, orientada segundo o eixo X. A funo dever receber o ponto inicial
da trelia, a largura da trelia e o nmero de ns das fileiras laterais.
Exercicio 8.11 Dadas as coordenadas dos quatro vrtices da base de uma pirmide quadrangular e a altura dessa pirmide, possvel calcular as coordenadas do vrtice do topo
dessa pirmide determinando o centro da base e o vector normal base.
Exercicio 8.12 Considere o desenho de uma trelia plana, tal como se apresenta na seguinte
figura:
b0
a0
b1
a1
bn1
...
...
an1
an
Defina uma funo trelica-plana que recebe, como parmetros, duas listas de pontos
correspondentes aos pontos desde a0 at an e desde b0 at bn1 e que cria os ns nesses
pontos e as barras que os unem. Considere, como pr-definidas, as funes nos-trelica,
que recebe uma lista de pontos como argumento e barras-trelica que recebe duas listas
de pontos como argumentos.
Teste a funo de definir com a seguinte expresso:
(trelica-plana
(coordenadas-linha (xyz 0 0 0) 2.0 20)
(coordenadas-linha (xyz 1 0 1) 2.0 19))
214
c0
a0
c1
a1
cn
an
b0
bn1
Defina uma funo trelica-especial que recebe, como parmetros, trs listas de
pontos correspondentes aos pontos desde a0 at an , desde b0 at bn1 e desde c0 at cn e que
cria os ns nesses pontos e as barras que os unem. Considere, como pr-definidas, as funes nos-trelica que recebe uma lista de ponto como argumento e barras-trelica
que recebe duas listas de pontos como argumentos.
8.4.2
Gerao de Coordenadas
r1
r0
216
Exercicio 8.14 Considere a construo de abbabas apoiadas em trelias distribuidas radialmente, tal como a que se apresenta na imagem seguinte:
217
0
r0
x
y
r
x
218
8.4.3
Trelias Espaciais
Vimos como possvel definir trelias a partir de trs listas cada uma contendo as coordenadas dos ns a que as barras das trelias se ligam. Ligando
entre si vrias destas trelias possvel produzir uma estrutura ainda maior
a que se d o nome de trelia espacial. A Figura 75 mostra um exemplo onde
so visveis trs trelias espaciais.
Para podermos definir um algoritmo que gere trelias espaciais importante termos em conta que embora este tipo de trelias aglomere vrias
trelias simples, estas esto interligadas de tal modo que cada trelia partilha um conjunto de ns e barras com a trelia que lhe adjacente, tal como
visvel na Figura 76 que apresenta um esquema de uma trelia espacial.
Assim, se uma trelia espacial for constituda por duas trelias simples interligadas, a trelia espacial ser gerada, no por seis listas de coordenadas,
mas apenas por cinco listas de coordenadas. No caso geral, uma trelia espacial constituda por n trelias simples, ser definida por um 2n + 1 listas
de pontos, i.e., por um nmero mpar de listas de pontos (no mnimo, trs
listas).
A definio da funo que contri uma trelia espacial segue a mesma
lgica da funo que constri uma trelia simples s que agora, em vez de
operar com apenas trs listas, opera com um nmero impar delas. Assim,
a partir de uma lista contendo um nmero mpar de listas de coordenadas,
iremos processar essas listas de coordenadas duas a duas, sabendo que a
terceira lista de coordenadas ci,j da trelia i tambm a primeira lista
de coordenadas ai+1,j da trelia seguinte i + 1.
219
Figura 75: Trelias espaciais no estdio Al Ain nos Emiratos rabes Unidos.
Fotografia de Klaus Knebel.
b0,0
c0,0 = a1,0
c1,0 = a2,0
b0,1
a0,0
a0,1
b1,0
b1,1
c0,2 = a1,2
c0,1 = a1,1
c1,1 = a2,1
a0,2
c1,2 = a2,2
220
Figura 77: Uma trelia espacial horizontal, composta por oito trelias simples com dez pirmides cada uma.
de outra linha bi deslocada para o centro da pirmide e altura desta, seguida das restantes linhas, at o final, em que teremos de produzir mais
uma linha ai . ainda necessrio termos em conta que as linhas bi tm menos um n do que as linhas ai . Com base nestas consideraes, podemos
escrever:
(defun coordenadas-piramides-horizontais (p h l m n)
(if (= m 0)
(list (coordenadas-linha p l n))
(cons
(coordenadas-linha p l n)
(cons
(coordenadas-linha
(+xyz p (/ l 2.0) (/ l 2.0) h) l (- n 1))
(coordenadas-piramides-horizontais
(+y p l) h l (- m 1) n)))))
222
Exercicio 8.17 Considere a construo de uma trelia espacial em arco, tal como a que se
apresenta na imagem seguinte (em perspectiva). Defina a funo trelica-espacial-arco
que, para alm dos parmetros da funo trelica-arco, possui ainda um parmetro adicional que indica o nmero de trelias simples que constituem a trelia espacial. A ttulo de
exemplo, considere que a trelia apresentada na imagem seguinte foi gerada pela expresso:
(trelica-espacial-arco (xyz 0 0 0) 10 9 1.0 20 0 -pi/3 pi/3 10)
223
Esta trelia semelhante trelia espacial em arco mas com uma nuance: os raios exterior rac e interior rb variam ao longo do eixo do arco. Esta variao corresponde a uma
sinusoide de amplitude r a variar desde um valor inicial 0 at um valor final 1 , em
incrementos de .
Defina a funo trelica-ondulada que constri este tipo de trelias, a partir dos
mesmos parmetros da funo trelica-espacial-arco e ainda dos parmetros 0 , 1 ,
e r . Como exemplo, considere que a figura anterior foi gerada pela invocao seguinte:
(trelica-ondulada (xyz 0 0 0) 10 9 1.0 20 0 -pi/3 pi/3 0 4*pi (/ pi 8) 1)
Manipulao de Entidades
O valor retornado pela avaliao de (entlast) tem, como representao externa, o texto <Entity name: ???>, em que ??? um identificador
da entidade, destinado apenas a permitir ao leitor distinguir diferentes entidades entre si pois cada entidade ter necessariamente um identificador
diferente.
Dada uma entidade, podemos estar interessados em conhecer as suas
propriedades. Para isso, o Auto Lisp disponibiliza a funo entget. Esta
funo recebe uma entidade como argumento e devolve uma lista com as
propriedades da entidade. Eis um exemplo:56
_$ (entget (entlast))
((-1 . <Entity name: 7ef91ed8>)
(0 . "CIRCLE")
(330 . <Entity name: 7ef91db8>)
(5 . "5B")
(100 . "AcDbEntity")
(67 . 0)
(410 . "Model")
(8 . "0")
(100 . "AcDbCircle")
(10 10.0 20.0 0.0)
(40 . 30.0)
(210 0.0 0.0 1.0))
225
Cdigo
-1
0
1
2
3-4
5
6
7
8
10
11-18
38
39
48
50-58
60
62
100
210
Significado
Nome (uma string que pode mudar de sesso para sesso)
Tipo
Texto primrio
Nome dado pelo utilizador (presente apenas nalgumas entidades)
Outros textos (presente apenas nalgumas entidades)
Referncia(uma string que nunca muda)
Tipo de linha (presente apenas nalgumas entidades)
Estilo de texto (presente apenas nalgumas entidades)
Nome do layer
Ponto primrio (o centro para um crculo, ponto inicial para
uma linha, etc)
Outros pontos (presente apenas nalgumas entidades)
Elevao (apenas para entidades com elevao diferente de
zero)
Espessura (apenas para entidades com espessura diferente de
zero)
Escala do tipo de linha (presente apenas nalgumas entidades)
ngulos
Visibilidade (opcional, 0 para visvel, 1 para invisvel)
ndice da cor
Marcador de subclasse
Direco de extruso
Tabela 5: Alguns dos cdigos DXF
9.1
Listas de Associaes
Este tipo de lista cujos elementos so pares denomina-se uma lista de associaes ou, abreviadamente, uma assoc-list ou, ainda mais abreviadamente,
uma alist.
No resultado devolvido pela ltima expresso h alguns elementos facilmente relacionveis com o crculo que tnhamos criado, nomeadamente,
a string "CIRCLE", as coordenadas (10.0 20.0 0.0) e o raio 30. Menos
claro o significado dos nmeros que aparecem como primeiro elemento
de cada par. Esses nmeros designam, na realidade, uma codificao numrica da propriedade correspondente e encontram-se definidos pela especificao DXF (Drawing eXchange Format) inventada pela AutoDesk para
permitir troca de informao entre aplicaes de CAD. Assim, o nmero 0
designa o tipo da entidade, o nmero 10 designa o ponto primrio da entidade (o centro do crculo, neste caso), etc. A Tabela 5 descreve o significado
de alguns dos cdigos definidos pela especificao DXF.
226
Quando se pretende saber apenas uma das propriedades de uma entidade, por exemplo, o seu tipo, pouco prtico ter de a procurar visualmente numa lista razoavelmente grande como a que resulta de entget.
Note-se que no basta aceder posio onde julgamos estar a propriedade
pois essa posio no a mesma para todos os objectos (pois nem todos
os objectos possuem as mesmas propriedades) nem necessariamente a
mesma para diferentes verses do AutoCad. Naturalmente, sendo o resultado da funo entget uma lista de pares, nada nos impede de definir
uma funo que processe essa lista procura da propriedade em questo.
Para concretizarmos, consideremos que pretendemos definir uma funo que, a partir do cdigo DXF de uma propriedade que procuramos e
da lista de propriedades de uma entidade, nos diz qual o seu valor para
aquela entidade. Para isso, o mais simples aplicarmos recurso:
Se o primeiro elemento do primeiro par da lista tem o cdigo DXF
que procuramos ento o valor correspondente o segundo elemento
desse par.
Se o primeiro elemento do primeiro par da lista no tem o cdigo
DXF pretendido, ento podemos recursivamente procurar no resto
da lista.
Traduzindo para Auto Lisp, temos:
(defun valor-propriedade (propriedade lista-assoc)
(cond ((= propriedade (car (car lista-assoc)))
(cdr (car lista-assoc)))
(t
(valor-propriedade propriedade (cdr lista-assoc)))))
detectarmos este caso e, caso ocorra, devolver um valor que signifique que
a propriedade no existe naquela lista. Em geral, a linguagem Lisp convenciona que, para essas situaes, o valor a devolver nil. Tendo em conta
este raciocnio, a funo fica ento com a seguinte forma:
(defun valor-propriedade (propriedade lista-assoc)
(cond ((null lista-assoc)
nil)
((= propriedade (car (car lista-assoc)))
(cdr (car lista-assoc)))
(t
(valor-propriedade propriedade (cdr lista-assoc)))))
_$ (valor-propriedade 0 (entget (entlast)))
"CIRCLE"
_$ (valor-propriedade 10 (entget (entlast)))
(10.0 20.0 0.0)
_$ (valor-propriedade 123456789 (entget (entlast)))
nil
9.2
A funo assoc
228
9.3
Modificao de Entidades
Vimos como aceder s propriedades de uma entidade. Vamos agora discutir a forma de modificarmos essas propriedades.
A funo entmod permite a modificao de entidades. Para isso, a
funo recebe como argumento uma lista de associaes contendo, para
alm dos pares propriedade/valor que pretendemos modificar, um par
nome/entidade contendo a entidade cujas propriedades pretendemos modificar. Por exemplo, se pretendermos mudar a origem do crculo criado
anteriormente para as coordenadas (0, 0, 0) basta-nos avaliar a expresso:
_$ (entmod (list (cons -1 (entlast))
(cons 10 (xyz 0 0 0))))
((-1 . <Entity name: 7ef91f30>) (10 0 0 0))
9.4
Criao de Entidades
229
Atravs da pseudo-funo command. Esta funo recebe como argumentos as expresses necessrias que sero avaliadas apenas se e
quando o AutoCad precisar dos valores correspondentes para criar a
entidade.
A criao da entidade ainda afectada por um conjunto de parmetros globais, como o layer em que se est a trabalhar, o UCS actual, o
modo OSNAP, a lngua, etc. Para se usarem valores diferentes destes
parmetros necessrio fazer as correspondentes alteraes previamente criao da entidade ou necessrio fazer posteriores alteraes entidade.
O uso desta funo ainda dependente das alteraes que a AutoDesk vai fazendo sintaxe e parmetros dos comandos em sucessivas
verses do AutoCad.
Atravs da funo entmake. Esta funo recebe uma lista de associaes idntica que devolvida pela funo entget e usa os valores
associados s propriedades correspondentes para criar e inicializar a
entidade. As propriedades no obrigatrias ficam com valores por
omisso.
A criao da entidade no afectada por quaisquer outros parmetros. Em particular, no existe dependncia do UCS actual, o que
implica que as coordenadas das entidades criadas so interpretadas
em termos do WCS.
O uso desta funo ainda dependente das alteraes que a AutoDesk vai fazendo ao formato DXF em sucessivas verses do AutoCad.
H ainda mais uma pequena diferena entre estas duas funes: em geral, usar entmake computacionalmente mais eficiente (por vezes, muito
mais eficiente) que usar command, embora esta ltima possa ser mais simples para o programador.
Uma vez que j vimos no passado a pseudo-funo command vamos
agora discutir a entmake. Para exemplificar, consideremos a criao de
um crculo de centro em (4, 4), raio 10 e cr 3 (verde). Como referimos
anteriormente, temos de usar como argumento uma lista de associaes
com os pares propriedade/valor pretendidos:
_$ (entmake (list (cons 0 "CIRCLE")
(cons 62 3)
(cons 10 (xy 4 4))
(cons 40 10)))
((0 . "CIRCLE") (62 . 3) (10 4 4 0) (40 . 10))
O par que contm o tipo da entidade tem de ser o primeiro ou o segundo elemento da lista. Se for o segundo, o primeiro ter de ser o
nome da entidade que ser simplesmente ignorado.
Embora no o tenhamos feito no exemplo anterior, a especificao
do marcador de subclasse tornou-se obrigatria em todas as verses
recentes do AutoCad. O marcador de subclasse corresponde a duas
ocorrncias do cdigo DXF 100, uma com a string AcDbEntity e outra com a classe de entidade (AcDbCircle, AcDbText, AcDbArc,
AcDbLine, AcDbPoint, etc). Isso quer dizer que a expresso anterior deveria ter a seguinte forma:
(entmake (list (cons
(cons
(cons
(cons
(cons
(cons
0 "CIRCLE")
100 "AcDbEntity")
100 "AcDbCircle")
62 3)
10 (xy 4 4))
40 10)))
231
9.5
Listas de Propriedades
H dois detalhes importantes a salientar do exemplo anterior. O primeiro detalhe que, ao invs de usarmos os cdigos numricos DXF, usmos nomes lgicos facilmente compreensveis, como centro:, raio: e
cor:. O segundo detalhe que, ao invs de usarmos uma lista de associaes em que cada associao um par propriedade/valor, da forma
((p0 . v0 ) (p1 . v1 ) ... (pn . vn )), usmos uma lista simples contendo uma sucesso de propriedades e valores, da forma (p0 v0 p1 v1 ... pn vn ).
A este tipo de lista d-se o nome de lista de propriedades ou, abreviadamente,
plist.
Uma lista de propriedades plist muito semelhante a uma lista de associaes alist. A diferena fundamental est no facto de as associaes
estarem espalmadas na prpria lista. Isso faz com que as listas de propriedades sejam mais legveis do que as listas de associaes.
No entanto, trivial converter listas de propriedades em listas de associaes. Mais uma vez, o pensamento recursivo ajuda: se a lista de propriedades uma lista vazia, ento a lista de associaes correspondente
tambm uma lista vazia. Caso contrrio, formamos um par com os dois
primeiros elementos da lista de propriedades (para formar uma associao) e juntamos esse par ao resultado de converter a lista sem esses dois
elementos.
(defun alist<-plist (plist)
(if (null plist)
(list)
(cons (cons (car plist) (cadr plist))
(alist<-plist (cddr plist)))))
232
Para algumas propriedades faz tambm sentido dar nomes lgicos aos
possveis valores. Por exemplo, no caso da visibilidade, cujo cdigo DXF
60, os possveis valores so 0 quando visivel e 1 quando invisivel:
(setq visibilidade: 60
visivel 0
invisivel 1)
(cria-circulo
(list centro: (xy 1 2)
raio: 5
visibilidade: invisivel))
(xy
(xy
(xy
(xy
(xy
(xy
0.0
2.5
5.0
0.0
2.5
5.0
0.0)
0.0)
0.0)
2.5)
2.5)
2.5)
1
1
1
1
1
1
0.5
0.5
0.5
0.2
0.5
0.8
10)
20)
30)
6)
6)
6)
Finalmente, para vermos um exemplo de uma entidade bastante parametrizvel, consideremos a criao de textos. Uma consulta documentao DXF do AutoCad revela vrias propriedades que podemos definir da
seguinte forma:
235
Uma outra imagem interessante a apresentada na Figura 80 que demonstra a capacidade do AutoCad para aplicar rotaes ao texto a inserir:
(foreach fraccao (enumera 0.0 1.0 0.1)
(cria-texto
(list ponto-inicial: (xy 0 0)
rotacao: (* fraccao 2 pi)
texto: "Rodado"
altura: 10)))
236
Abcde
Abcde
Abcde
Abcde
Abcde
Abcde
A
b
c
d
Abcde
Abcde
c
d
Abcde
Abcde
Abcde
A
b
Abcde
Ab
cd
e
Abcde
Ab
cd
e
Abcde
Abcde
Ab
cd
e
Abcde
Ab
cd
e
Abcde
Ab
cd
e
Abcde
Abcde
b
c
d
A
e
c
d
A
b
e
Abcde
c
d
Abcde
Abcde
A
b
Abcde
Abcde
Abcde
Inclinado
Inclinado
Inclinado
Inclinado
Inclinado
Inclinado
Inclinado
Inclinado
Inclinado
Inclinado
Inclinado
Figura 79: Um texto com diferentes inclinaes.
237
o
d
a
d
Ro
oda
do
o
d
a
d
Roo
Rodado
da
do
do
da
Roo
Rodado
d
a
d
o
do
oda
Ro
d
a
d
o
Exercicio 9.2 Embora os exemplos anteriores mostrem que a criao de entidades razoavelmente simples, nem todos os tipos de entidades possuem esta caracterstica. A criao
de um texto multilinha (tipo MTEXT) um exemplo de uma entidade cuja especificao DXF
complexa. Para alm de obrigar a lista de associaes a incluir a presena do marcador de
subclasse para textos multilinha (AcDbMText), existe ainda a necessidade de partir o texto
em subtextos com, no mximo 250 caracteres. Isso claro a partir da especificao desta
entidade que, para os cdigos DXF 1 e 3, afirma:
1 String de texto. Se a string tiver 250 (ou menos) caracteres, todos aparecem no cdigo
1. Caso contrrio, a string dividida em pores de 250 caracteres que aparecem
associadas a um ou mais cdigos 3. Se for usado algum cdigo 3, a ltima poro
fica associada ao cdigo 1 e possui menos de 250 caracteres.60
3 Texto adicional (em pores de 250 caracteres) (opcional)
60
238
do
do
a
d
Ro
oda
o
d
a
d
o
Rodado
R
a
d
o
Rodado
R
R
o
d
o
R
Roodad
Ro
da
do
o
ad
od
dad
o
9.6
Usando estas operaes, podemos tambm redefinir alguns dos selectores e modificadores que tnhamos introduzido anteriormente. Por exemplo,
para a cr, temos:
(defun cor (entidade)
(obtem-propriedade cor: entidade))
(defun muda-cor (entidade nova-cor)
(muda-propriedade cor: nova-cor entidade))
239
Exercicio 9.4 Defina a funo area-entidade-circulo que, dada uma entidade do tipo
circulo com um raio r, calcula a sua rea atravs da frmula A = r2 .
Exercicio 9.5 Defina a funo area-entidade-elipse que, dada uma entidade do tipo
elipse, calcula a sua rea. Dada uma elipse de semi-eixos a e b, a sua rea A dada por
A = ab.
9.7
Eliminao de Entidades
9.8
ltima Entidade
No passado dissemos que a funo entlast devolve a ltima entidade criada. Podemos agora, mais correctamente, dizer que esta funo devolve a
ltima entidade no eliminada, tal como se pode ver no seguinte exemplo:
240
_$ (cria-circulo
(list centro: (xy 1 2) raio: 10))
((0 . "CIRCLE") (10 1 2) (40 . 10))
_$ (tipo-entidade (entlast))
"CIRCLE"
_$ (cria-linha
(list ponto-inicial: (xy 3 4) ponto-final: (xy 5 6)))
((0 . "LINE") (10 3 4) (11 5 6))
_$ (tipo-entidade (entlast))
"LINE"
_$ (entdel (entlast))
<Entity name: 7efcaab8>
_$ (tipo-entidade (entlast))
"CIRCLE"
9.9
Iterao de Entidades
Como base nesta funo podemos construir outras bastante mais teis.
Por exemplo, dada uma entidade podemos coleccionar numa lista todas as
entidades que foram criadas depois dela:
241
9.10
Entidades Compostas
At agora vimos que cada figura geomtrica que criamos no AutoCad possui uma entidade associada. No entanto, algumas das figuras geomtricas
disponibilizadas pelo AutoCad so demasiadamente complexas para poderem ser representadas por uma nica entidade. Por exemplo, uma linha
poligonal a trs dimenses61 necessita no s de uma entidade para representar as caractersticas gerais da linha como tambm necessita de uma
sucesso de entidades para representar a sucesso dos vrtices da linha.
Por ser composta por vrias subentidades, uma linha poligonal diz-se uma
entidade composta.
Aps a criao de uma linha poligonal, embora a entidade que a representa seja acedvel usando a funo entlast, para se aceder s entidades
que representam os vrtices necessrio iterar a partir da primeira, usando
a funo entnext, tal como perceptvel na seguinte interaco:62
61
242
_$ (command "_.3DPOLY"
(xy -1 -1 0) (xy 1 0 1) (xy 0 1 -1)
"")
nil
_$ (entget (entlast))
((-1 . <Entity name: 7efcb1f0>)
(0 . "POLYLINE") ...
(10 0.0 0.0 0.0) ...)
_$ (entget (entnext (entlast)))
((-1 . <Entity name: 7efcb1f8>)
(0 . "VERTEX") ...
(10 -1.0 -1.0 0.0) ...)
_$ (entget (entnext (entnext (entlast))))
((-1 . <Entity name: 7efcb200>)
(0 . "VERTEX") ...
(10 1.0 0.0 1.0) ...)
_$ (entget (entnext (entnext (entnext (entlast)))))
((-1 . <Entity name: 7efcb208>)
(0 . "VERTEX") ...
(10 0.0 1.0 -1.0) ...)
_$ (entget (entnext (entnext (entnext (entnext (entlast))))))
((-1 . <Entity name: 7efcb210>)
(0 . "SEQEND") ...)
_$ (entnext (entnext (entnext (entnext (entnext (entlast))))))
nil
9.11
Redesenho de Entidades
9.12
As linhas poligonais descritas na seco 9.10 so entidades complexas compostas por vrias subentidades. Nesta seco vamos ver uma variante mais
244
ligeira dessas linhas poligonais que usada pelo AutoCad sempre que
lida com linhas poligonais bidimensionais.
Contrariamente a uma linha poligonal genrica, uma linha poligonal
leve uma nica entidade. Os vrtices da linha poligonal so representados como mltiplas ocorrncias de uma mesma propriedade cujo cdigo
DXF o nmero 10. Estes vrtices so relativos a um sistema de coordenadas prprio de cada entidade, denominado sistema de coordenadas do objecto
(do Ingls Object Coordinate System ou, abreviadamente, OCS). Sempre que
se pretender conhecer as coordenadas dos vrtices da linha poligonal relativamente ao sistema de coordenadas do mundo (do Ingls World Coordinate
System ou, abreviadamente, WCS) necessrio fazer uma transformao de
coordenadas, implementada pela funo trans.
Para construirmos uma destas linhas vamos definir a seguinte funo:
(defun cria-polilinha-leve (params)
(cria-entidade "LWPOLYLINE" params))
;;marcador de subclasse
;;idem
;;tipo de linha fechada
;;numero de vertices
;;vertice
;;idem
;;idem
;;idem
A ideia consiste em inventar uma nova opo vertices: (com um cdigo que no interfira com os cdigos DXF pr-definidos) e, sempre que
245
ele aparece, processamos a lista que lhe est associada de modo a gerar
o cdigo DXF correcto para cada vrtice. Note-se que os restantes parmetros no devem ser afectados, permitindo misturar as vrias formas de
especificar os vrtices. Por exemplo, se tivermos os vrtices p0 , . . . , p4 e a
lista de parmetros for (10 p0 70 1 -1000 (p1 p2 p3 ) 10 p4 ), a sua converso ir produzir a lista (10 p0 70 1 10 p1 10 p2 10 p3 10 p4 ). Este
comportamento est incorporado no seguinte programa onde comeamos
por definir as constantes relevantes:
(setq vertices: -1000
numero-vertices: 90
vertice: 10)
(defun converte-parametros (params)
(cond ((null params)
(list))
((= (car params) vertices:)
(append (converte-vertices (cadr params))
(converte-parametros (cddr params))))
(t
(cons (car params)
(cons (cadr params)
(converte-parametros (cddr params)))))))
(defun converte-vertices (vertices)
(if (null vertices)
(list)
(cons vertice:
(cons (car vertices)
(converte-vertices (cdr vertices))))))
Admitindo que todas as coordenadas so bi-dimensionais, podemos redefinir a funo de modo a usar a criao de polilinhas leves:
(defun poligono (vertices)
(cria-polilinha-leve
(list tipo-linha: linha-fechada
vertices: vertices)))
9.13
claro que se quisermos ter uma s funo que produz a lista de vrtices de uma linha poligonal qualquer, seja ela uma POLYLINE ou uma
LWPOLYLINE, basta-nos testar o tipo de entidade e usar a funo apropriada:
(defun vertices-polilinha (entidade / tipo)
(setq tipo (tipo-entidade entidade))
(cond ((= tipo "POLYLINE")
(vertices-polilinha-3d entidade))
((= tipo "LWPOLYLINE")
(vertices-polilinha-leve entidade))))
9.14
Podemos agora usar a funo entsel para obter a linha que pretendemos partir em duas e o ponto nessa linha onde a queremos partir, passando
248
9.15
At agora, todas as operaes que definimos apenas podiam ser invocadadas a partir do Auto Lisp. Para quem gosta de alisp, isso suficiente,
mas para o utilizador menos experiente de AutoCad isso pode rapidamente
tornar-se inconveniente: na maioria dos casos ser prefervel poder invocar
funes sem abandonar o ambiente do AutoCad e sem sequer ter se saber
a sintaxe do Lisp.
Para isso, o Auto Lisp permite a definio de comandos AutoCad. Essa
definio feita de forma idntica definio de funes, sendo a distino feita apenas por uma conveno de nomes: para se definir o comando
nome, basta definir uma funo cujo nome ser c:nome e cujo corpo ir
conter as aces que se pretende que o comando realize. Uma vez que a
funo se destina a ser invocada como se de um comando AutoCad se tratasse, ela no pode receber argumentos e, consequentemente, no pode ter
parmetros. No entanto, embora se destine fundamentalmente a ser usada
no AutoCad, o comando definido no deixa de estar implementado por
uma funo Lisp e, por isso, pode tambm ser invocado a partir do Lisp.
semelhana de qualquer outra invocao de funo, o comando nome assim definido pode ser invocado como (c:nome). Note-se que o nome da
funo, em Auto Lisp, aquele que foi empregue na definio. apenas
para o AutoCad que o nome perde o prefixo c:.
Na definio de comandos, importante termos em conta que se o comando a definir tiver o mesmo nome que um comando pr-definido, ele s
ficar activo quando indefinirmos o comando pr-definido.
Usando a definio de comandos AutoCad podemos tornar mais prtica a operao de partir uma linha:
(defun c:parte-linha (/ seleccao)
(setq seleccao (entsel))
(parte-linha (car seleccao) (cadr seleccao)))
249
Funo
getint
getreal
getstring
getpoint
getcorner
getdist
getangle
getorient
Tipo de Resultado
Um inteiro.
Um real.
Uma string.
Um ponto obtido na rea de desenho ou na linha de comandos.
Um ponto relativo a um outro ponto dado, obtido na rea
de desenho ou na linha de comandos.
Uma distncia obtida na rea de desenho ou na linha de
comandos.
Um ngulo (em radianos) obtido na rea de desenho ou
na linha de comandos. O ngulo zero dado pela varivel
ANGBASE e cresce segundo ANGDIR.
Um ngulo (em radianos) obtido na rea de desenho ou
na linha de comandos. O ngulo zero sempre para a
direita e cresce segundo ANGDIR.
9.16
Obteno de Informao
9.17
reas de Polgonos
Vimos que a definio de funes Auto Lisp pode ser usada tambm para
definir comandos AutoCad. Nesta seco vamos combinar a definio de
comandos com a utilizao de funes que pedem informaes ao utilizador.
A ttulo de exemplo, consideremos um comando para criar uma diviso
250
Uma vez que tem parmetros, esta funo apenas pode ser invocada
a partir do Auto Lisp. Isso suficiente para testarmos o seu funcionamento mas no suficiente para o seu uso a partir do AutoCad. O objectivo, agora, criar um comando que recolhe do utilizador os dados
suficientes para conseguir invocar a funo anterior. Para evitar estarmos sempre a definir novos nomes, vamos reutilizar o nome da funo
divisao-rectangular para baptizar o comando:
(defun c:divisao-rectangular (/ p0 p1)
(setq p0 (getpoint "\nEspecifique o primeiro canto")
p1 (getcorner "\nEspecifique o segundo canto" p0))
(divisao-rectangular p0 p1))
Area:40.000
Area:-40.000
Area:40.000
Area:-40.000
Figura 82: Divises rectangulares com a rea ou a orientao do texto incorrectamente calculadas.
Area:19.349
Area:5.162
Area:7.737
Area:6.360
Area:15.854
Area:28.597
253
254
(x1 , y1 )
(x0 , y0 )
x
Figura 84: Decomposio de um polgono arbitrrio em trapzios rectangulares.
_$ (command "_.rectangle" (xy 1 2) (xy 3 4))
nil
_$ (tipo-entidade (entlast))
"LWPOLYLINE"
_$ (command "_.polygon" 5 (xy 1 2) "_inscribed" 3)
nil
_$ (tipo-entidade (entlast))
"LWPOLYLINE"
Assim, podemos preocupar-nos apenas em lidar com este tipo de entidades e, automaticamente, ficaremos habilitados a lidar com uma enorme
variedade de figuras geomtricas. Temos, portanto, de encontrar uma forma
de calcular a rea e o centro de um qualquer polgono delimitado por linhas
poligonais leves.
Para calcular a rea de um polgono podemos empregar uma abordagem simples que foi inventada independentemente pelos matemticos
Meister e Gauss em finais do sculo dezoito. A ideia consiste em decompor
o polgono num conjunto de trapzios rectangulares, tal como se apresenta
na Figura 84. Se for [(x0 , y0 ), (x1 , y1 ), (x2 , y2 ), . . . , (xn1 , yn1 ), (xn , yn )] a
sequncia de coordenadas dos vrtices do polgono, o primeiro trapzio
ter os vrtices em (x0 , 0), (x0 , y0 ), (x1 , y1 ) e (x1 , 0), o segundo em (x1 , 0),
(x1 , y1 ), (x2 , y2 ) e (x2 , 0), o penltimo em (xn1 , 0), (xn1 , y0 ), (xn , yn ) e
(xn , 0) e o ltimo trapzio ter os vrtices em (xn , 0), (xn , yn ), (x0 , y0 ) e
(x0 , 0).
A rea de cada um destes trapzios pode ser calculada pela frmula
1
A = (xi+1 xi )(yi+1 + yi)
2
sendo que a diferena xi+1 xi ser positiva ou negativa consoante xi menor ou maior que xi+1 , implicando que a rea do trapzio respectivo ser
255
tambm positiva ou negativa. Ora sendo o polgono fechado, se percorrermos os vrtices por ordem, por exemplo, segundo os ponteiros do relgio,
necessriamente que alguns dos vrtices tero coordenadas xi sucessivamente crescente enquanto outros a tero sucessivamente decrescente. No
difcil vermos que ao somarmos os trapzios com rea positiva aos trapzios com rea negativa, iremos obter a rea total do polgono. Essa rea
poder ser positiva ou negativa consoante a ordem escolhida para percorrer os vrtices do polgono mas, em qualquer caso, ser a rea total do
polgono.
Traduzindo este raciocnio para Lisp, podemos definir as seguintes funes que, a partir de uma lista com as coordenadas dos vrtices do poligono, calculam a sua rea:
(defun area-vertices (vertices)
(if (null (cdr vertices))
0
(+ (area-trapezio (car vertices) (cadr vertices))
(area-vertices (cdr vertices)))))
(defun area-trapezio (p0 p1)
(* 0.5
(- (cx p1) (cx p0))
(+ (cy p0) (cy p1))))
Exercicio 9.6 Embora correcto, o algoritmo anterior realiza trabalho desnecessrio. Isso
torna-se bvio quando desenvolvemos o clculo para um polgono qualquer. Por exemplo, num polgono de trs vrtices, temos:
A=
1
1
1
(x1 x0 )(y1 + y0 ) + (x2 x1 )(y2 + y1 ) + (x0 x2 )(y0 + y2 )
2
2
2
ou seja
1
A = (x1 y1 + x1 y0 x0 y1 x0 y0 )+
2
1
(x2 y2 + x2 y1 x1 y2 x1 y1 )+
2
1
(x0 y0 + x0 y2 x2 y0 x2 y2 )
2
evidente, na frmula anterior, que h clculos que so feitos repetidamente mas com
sinais opostos. Eliminando os termos que se anulam, obtemos:
1
A = (x1 y0 x0 y1 )+
2
1
(x2 y1 x1 y2 )+
2
1
(x0 y2 x2 y0 )
2
No difcil generalizar a frmula anterior para uma sequncia arbitrria de vrtices,
permitindo-nos obter uma simplificao do processo de clculo:
A=
n1
1X
xi+1 yi xi yi+1
2 i=0
256
H um detalhe do algoritmo anterior que ainda no est tratado: o ltimo trapzio tem vrtices em (xn , 0), (xn , yn ), (x0 , y0 ) e (x0 , 0), mas a lista
de vrtices termina em (xn , yn ). Uma forma trivial de implementarmos
este detalhe consiste em acrescentarmos o vrtice (x0 , y0 ) ao fim da lista de
vrtices. precismente isso que a seguinte funo faz onde aproveitamos
tambm para obter o valor absoluto para termos sempre uma rea positiva:
(defun area-poligono (vertices)
(abs (area-vertices (append vertices (list (car vertices))))))
y =
d(2a + b)
3(a + b)
a2 + ab + b2
3(a + b)
Quando falamos de polgonos arbitrrios usual designar-se o seu centro pelo termo
centride.
257
Area:5.890
Area:9.511
Area:12.100
Area:7.069
Area:15.901
agora possvel seleccionar entidades de tipos variados e inserir automaticamente a sua rea, tal como se apresenta na Figura 85
Exercicio 9.7 Um semi-octaedro uma pirmide de base quadrangular que se define por
cinco pontos: quatro para a base e um para o topo ou znite.
Considere a criao de um comando AutoCad denominado semi-octaedro que pede
ao utilizador as cinco coordenadas necessrias para definir um semi-octaedro e cria as linhas correspondentes s arestas do slido.
259
9.18
A partir deste momento, podemos usar o nome "USO" para associar informaes a qualquer entidade. Para isso, o AutoCad reserva um conjunto
66
Cada programa Auto Lisp considerado pelo AutoCad como uma aplicao. Esta terminologia reflecte-se no nome da funo regapp pois ele constitui uma contraco de register
application.
260
Cdigo
1000
1001
1002
1010
1040
1070
1071
Significado
Uma string at 255 caracteres.
O nome de uma aplicao.
O nome de um layer.
Uma coordenada tridimensional.
Um valor real.
Um valor inteiro de 16 bits.
Um valor inteiro de 32 bits.
Tabela 7: Cdigos DXF para informaes adicionais. Cada cdigo representa um tipo particular de dados.
de cdigos DXF que podem ser usados repetidamente para categorizar a
informao associada. A Tabela 7 explica alguns desses cdigos. Da observao da tabela conclumos, por exemplo, que para associarmos uma string
a uma entidade temos de empregar o cdigo DXF 1000. Vrios outros cdigos existem, incluindo cdigos que permitem estruturar a informao em
vrios nveis de detalhe.
Uma vez que estes cdigos e os valores associados tm de ser particionados por aplicao, a lista de associaes tem de ser agrupada numa outra
lista que contm o cdigo DXF 3, indicador de que h informaes adicionais associadas entidade. Por exemplo, para atribuirmos o uso sala
ltima entidade criada temos de avaliar a seguinte expresso:
(entmod
(list (cons -1 (entlast))
(cons -3 (list
(cons "USO"
(list (cons 1000 "sala")))))))
Para recuperar aquela informao, temos de ter em conta que, por omisso, a funo entget no devolve a informao adicional e, para a obtermos, temos de especificar num parmetro adicional uma lista contendo as
aplicaes cuja informao tambm pretendemos.
_$ (assoc -3 (entget (entlast) (list "USO")))
(-3 ("USO" (1000 . "sala")))
funo, lista essa que depois convertemos para uma lista de associaes tal
como a funo entmod pretende:
(defun adiciona-informacao (entidade aplicacao plist)
(entmod
(list (cons -1 entidade)
(cons -3 (list
(cons aplicacao (alist<-plist plist)))))))
Para recuperarmos a informao que adicionmos a uma entidade vamos definir a funo obtem-informacao. Esta funo precisa de saber
qual a aplicao e qual a propriedade especifica dessa aplicao que foram
usadas para guardar a informao. Tendo em conta a estrutura de listas de
associao encadeadas que usada para guardar informao adicional em
entidades, a definio da funo fica:
(defun obtem-informacao (entidade aplicacao propriedade)
(cdr (assoc propriedade
(cdadr (assoc -3
(entget entidade (list aplicacao)))))))
262
9.19
Escadas
Uma escada uma sucesso de degraus que estabelece uma ligao entre
dois nveis. Os degraus so agrupados em lanos e os lanos so interligados por patamares. Cada degrau caracterizado pelo comprimento c do seu
cobertor e pela altura e do seu espelho, tal como se representa na Figura 88.
Notemos, nessa figura, que uma escada com n cobertores tem n + 1 espelhos. Assim, dado um nmero de cobertores n, o comprimento l dada
por l = nc mas a altura h vencida pelos correspondentes n + 1 espelhos
h = (n + 1)e.
Imaginemos agora que pretendemos definir um comando que nos permita criar escadas facilmente. Para isso, recomendvel dividirmos o problema em dois subproblemas:
1. Primeiro, definimos o programa Auto Lisp que, a partir dos parmetros geomtricos do problema, produz a sua soluo. Este programa
263
Area:5.890
Area:9.511
Quarto:9.511
Sala:15.901
Cozinha:12.100
Tanque:7.069
Piscina:5.890
Area:12.100
Area:7.069
Area:15.901
Figura 87: Uma escada na ilha de Santorini, na Grcia. Fotografia de Christopher Riess.
264
P1
h
e
P0
265
Estas duas funes sero agora usadas para definir o caso recursivo e o
caso final da funo lanco-escada: um lano de escada com n degraus
obtido atravs da criao de um degrau seguido da criao de um lano
de escada com n 1 degraus a comear do ponto onde terminou o degrau
anterior; um lano de escada com 0 degraus meramente um espelho.
(defun lanco-escada (p c e n)
(if (= n 0)
(espelho p c e)
(lanco-escada (degrau p c e) c e (- n 1))))
Para este problema, seria til que se conseguisse garantir, no s que a resposta do uti-
266
Em segundo lugar, vamos definir a funo lancos-escada que, a partir de um ponto de partida p, de um comprimento de cobertor c, de uma
altura de espelho e, de um nmero de cobertores n por lano, de um nmero total de lanos e do comprimento de cada patamar, desenha a escada
separando-a em vrios lanos. A funo ter de distinguir o caso em que
s tem de desenhar um lano de escadas daquele em que tem de desenhar
mais do que um. Neste ltimo caso, a funo ter que desenhar tambm
um patamar:
(defun lancos-escada (p c e n lancos lpatamar)
(if (= lancos 1)
(lanco-escada p c e n)
(lancos-escada
(patamar (lanco-escada p c e n) lpatamar)
c e n (- lancos 1) lpatamar)))
267
Figura 90: Uma escada composta por dois lanos com um patamar intermdio. Fotografia de Mateusz Szczerbinski.
(lancos-escada (xy 0.0 0.0) 0.26 0.16 10 4 1.0)
(lancos-escada (xy 10.0 0.0) 0.26 0.36 10 2 2.0)
(lancos-escada (xy 13.0 0.0) 0.16 0.12 8 7 0.5)
268
P0
Modifique a funo c:lancos-escada de modo a que o patamar fique orientado na
mesma direco da escada, a menos que o utilizador fornea um comprimento de patamar
negativo, caso em que o patamar dever ficar com a direco oposta.
9.19.1
Dimensionamento de Escadas
269
c = n
h
e = n+1
emin e emax
Para alm disto ainda necessrio ter em conta que o nmero de cobertores n tem de ser um nmero inteiro.
Estas restries tornam mais difcil o dimensionamento de uma escada
pois impedem-nos de usar um nmero arbitrrio de cobertores. Felizmente, podemos usar o Auto Lisp e desenvolver um algoritmo que calcula
quais so os nmeros aceitveis apenas a partir do comprimento l e altura
h da escada. Para isso, substitumos a segunda equao na terceira, ficando
emin
h
emax
n+1
ou seja
h
h
1n
1
emax
emin
Para incluirmos a restrio de que n tem de ser um nmero inteiro,
basta-nos acrescentar os arredondamentos adequados:
l h
m
j h
k
1 n
1
emax
emin
Assim, dada uma altura h e as alturas mnimas emin e mximas emax do
espelho, podemos obter o nmero mnimo e mximo de cobertores. Por
exemplo, consideremos uma escada que necessita de vencer uma altura
h = 3.55m usando degraus com um espelho e entre emin = 0.14m e emax =
0.18m. Substituindo os valores na inequao anterior, temos d18.7e n
b24.4c, i.e., poderemos usar 19, 20, 21, 22, 23 ou 24 cobertores. Estamos
ento em condies de implementar uma funo que nos devolve um par
com este nmero mnimo e mximo de cobertores:
(defun cobertores (h emin emax / nmin nmax)
(setq nmin (ceiling (- (/ h emax) 1))
nmax (fix (- (/ h emin) 1)))
(cons nmin nmax))
Infelizmente, a funo cobertores no tem em conta todas as restries ergonmicas: para alm das limitaes na altura do espelho e de um
270
Podemos agora confirmar os resultados que obtivemos para os exemplos anteriores, o primeiro para um comprimento de 5.1m, o segundo para
um comprimento de 4.1m:
_$ (cobertores 3.55 0.14 0.18 5.1 0.23)
(19 . 22)
_$ (cobertores 3.55 0.14 0.18 4.1 0.23)
No possvel dimensionar o cobertor.
Aumente o comprimento para 4.3700
nil
l
h
+2
bmax
n
n+1
272
f (n)
Para calcular os extremos do intervalo anterior, vamos comear por definir a funo que calcula o nmero de cobertores n a partir da frmula de
Blondel para o mdulo b:
(defun cobertores-blondel (h l b / l+2h-b)
(setq l+2h-b (+ l (* 2 h) (- b )))
(/ (+ l+2h-b (sqrt (+ (quadrado l+2h-b) (* 4 b l))))
(* 2 b)))
274
18.4 n 23.5
n 22.2
18.37 n 18.95
Uma vez que n tem de ser um nmero inteiro, a terceira desigualdade
no satisfazvel. Isto implica que, tal como anteriormente, o nosso algoritmo poder no conseguir dimensionar a escada e, nesse caso, dever
avisar o utilizador de qual dever ser o comprimento adequado. Para isso,
recuperamos a frmula de Blondel
bmin
l
h
+2
bmax
n
n+1
e resolvmo-la em relao a l:
n(bmin 2
h
h
) l n(bmax 2
)
n+1
n+1
275
276
277
Usando esta funo agora possvel calcular automaticamente a melhor escada (em termos dos critrios ergonmicos que adoptmos). Por
exemplo, a escada anterior pode ser dimensionada partindo de um comprimento 0.0:
_$ (comprimento-cobertores 2.8 0.14 0.18 0.0 0.23 0.62 0.64)
(4.051 . 15)
Exercicio 9.9 A funo cobertores comea por calcular o nmero mnimo e mximo de
cobertores a partir da altura h a vencer e das dimenses mxima e mnima do espelho (emax
e emin ):
l h
m
j h
k
1 n
1
emax
emin
As dimenses mxima e mnima do espelho dependem, naturalmente, da legislao
aplicvel. No caso portugus, por exemplo, o Regulamento Geral de Edificaes Urbanas
refere:
Os degraus da escada no podero ter largura inferior a 23 centmetros, no
contando o focinho; a sua altura deve ficar compreendida entre 14 e 18 centmetros;
Infelizmente, ao tentarmos dimensionar uma escada com uma altura de 55 centmetros
de altura, encontramos a seguinte impossibilidade:
l 0.55
m
j 0.55
k
1 n
1
0.18
0.14
278
ou seja
3n2
Redefina a funo cobertores de modo a detectar estas impossibilidades e a sugerir
alturas que as evitem.
9.19.2
Dimensionamento de Lanos
279
A Figura 93 mostra uma sucesso de escadas que vencem a mesma altura mas com alturas mximas de lance sucessivamente crescentes.
Exercicio 9.10 A funo c:dimensiona-escada tem um inconveniente grave: sempre
que invocada, pede todos os parmetros necessrios ao utilizador, embora muitos desses parmetros (como, por exemplo, emin , emax , cmin , bmin e bmax ) sejam tendencialmente
constantes.
Redefina a funo c:dimensiona-escada de modo a que os parmetros possam ter
valores de omisso que o utilizador s especifica se assim o pretender.
9.19.3
El Castillo
Embora actualmente as escadas sejam objecto de um conjunto relativamente grande de regras, nem sempre isso aconteceu e existem inmeros
exemplos no passado de escadas desenhadas para fins muito mais importantes do que meramente o de permitir deslocar pessoas entre diferentes
nveis.
Um bom exemplo ocorre no templo de Cuculcn, em Chichn Itz no
Mxico, apresentado na Figura 94. Cuculcn uma divindade da mitologia
Maia, representada por uma serpente emplumada. O templo a ela dedicado ter sido construdo h mais de mil e cem anos e foi denominado El
Castillo pelos conquistadores espanhis quando encontraram as runas de
Chichn Itz. As escadas que ladeiam cada um dos quatro lados do templo
tm, cada uma, 91 degraus e vrios historiadores atribuem a este nmero
um significado cronolgico: as quatro escadas totalizam 364 degraus ao
280
Figura 95: Esquema de El Castillo. Da esquerda para a direita, encontrase (1) a escada original do templo, (2) a escada que possui um cobertor
mnimo de 0.23m e espelho entre 0.14m e 0.18m, (3) a escada que, para
alm disso, obedece regra de Blondel (com limites entre 0.62m e 0.64m)
e, finalmente, (4) a escada que, para alm das restries anteriores, possui
lanos que no excedem os 3.5m de altura.
Para compararmos a evoluo destas escadas, a Figura 95 mostra um
esquema do templo de Cuculcn onde, da esquerda para a direita, mostramos as escadas originais do templo, as escadas que respeitam o comprimento mnimo do cobertor, as escadas que respeitam tambm a regra de
Blondel e, finalmente, as escadas finais que respeitam ainda a altura mxima dos lanos.
9.20
Caixas de Escada
Como vimos nas seces anteriores, a funo c:dimensiona-escada aumenta o comprimento da escada tanto quanto for necessrio para respeitar
as restries ergonmicas. Isto implica que se a altura a vencer for muito
elevada, como acontece com El Castillo, a escada resultante pode ficar
com um comprimento enorme.
Infelizmente, nem sempre possvel aumentar o comprimento de uma
escada. Na maioria das situaes, na realidade, quer o espao horizontal
quer o espao vertical disponveis para o desenvolvimento de uma escada
esto limitados (ou desejvel que estejam) e a soluo para vencer alturas elevadas assenta no uso de patamares intermdios e lanos de escadas
alternados, tal como se apresenta na Figura 96.
Para implementar este tipo de escadas, vamos comear por model-las
de acordo com a Figura 97. Nessa figura podemos ver vrios lanos de
escadas, interligados entre si por patamares representados por rectngulos
282
283
P
Figura 97: Um modelo de escadas com lanos alternados. Da esquerda
para a direita, as escadas possuem trs, quatro e cinco lanos. O ponto P
representa o nicio da primeira escada.
a tracejado.
Do ponto de vista da modelao destas escadas, os patamares so totalmente desnecessrios pois, admitindo que os patamares tm todos a
mesma dimenso, para uma dada dimenso horizontal de escada que inclua patamares trivial derivar a dimenso que no inclui os patamares.
Por este motivo, vamos considerar que o ponto de partida de cada escada
no inclui o patamar e coincide com o arranque da escada, tal como se v
representado pelo ponto P na escada mais esquerda.
Para desenharmos este tipo de escadas no temos mais do que definir
uma funo idntica funo lancos-escada mas que, de cada vez que
inicia um novo lano de escada, usa o simtrico do cobertor para efectuar a
mudana de direco:
(defun lancos-alternados-escada (p c e n lancos)
(if (= lancos 1)
(lanco-escada p c e n)
(lancos-alternados-escada
(lanco-escada p c e n)
(- c) e n (- lancos 1))))
Para dimensionarmos estas escadas temos, antes de mais, de saber quantos lanos sero necessrios para vencer uma dada altura. Para isso, importante percebermos que o nmero de lanos depende (entre outros factores) de o incio da escada ficar, ou no, do mesmo lado que o seu fim. Como
fcil percebermos pela anlise da Figura 97, se o incio da escada est do
mesmo lado que o fim, a escada ter necessariamente de ter um nmero
par de lanos. Se o incio da escada est no lado oposto ao do fim, ento
284
a escada ter necessariamente um nmero mpar de lanos. Este facto implica que, para um dado incio e fim de escada, medida que a altura da
escada aumenta, o nmero de lanos apropriado para a vencer ter sempre
de aumentar dois lanos de cada vez.
Deste modo, podemos idealizar um algoritmo para o dimensionamento
destas escadas que, para alm das medidas do espao onde temos de inserir a escada, ir tambm receber um nmero inicial de lanos pretendidos.
Se esse nmero for par, o incio e o fim da escada esto no mesmo lado,
caso contrrio, esto em lados opostos. Este algoritmo ir determinar as
dimenses do cobertor e espelho de cada lano individual e, caso eles violem as restries ergonmicas que j discutimos anteriormente, aumenta o
nmero de lanos em duas unidades e tenta de novo. Quando o nmero
de lanos se tornar to grande que o tamanho do espelho e correspondente
fica inferior altura mnima admissvel emin , o algoritmo desiste, devolvendo nil para assinalar que no possvel satisfazer os constrangimentos. Nessa altura, o utilizador dever relaxar algumas das restries como,
por exemplo, os limites da regra de Blondel.
Atendendo a este algoritmo, a seguinte funo uma adaptao da funo comprimento-cobertores mas que, no caso de violao de restries, se limita a aumentar o nmero de lanos:
(defun altura-cobertores-lancos
(lancos ht emin emax l cmin bmin bmax /
h nmin nmax ncmax nbmin nbmax nfinalmax nfinalmin)
(setq h (/ ht lancos)
nmin (ceiling (- (/ h emax) 1))
nmax (fix (- (/ h emin) 1))
ncmax (fix (/ l cmin)))
(if (< h emin)
nil
(if (< ncmax nmin)
(altura-cobertores (+ lancos 2)
ht emin emax l cmin bmin bmax)
(progn
(setq nmax (min nmax ncmax)
nbmin (cobertores-blondel h l bmax)
nbmax (cobertores-blondel h l bmin))
(if (> (ceiling nbmin) (fix nbmax))
(altura-cobertores (+ lancos 2)
ht emin emax l cmin bmin bmax)
(progn
(setq nfinalmin (max nmin (ceiling nbmin))
nfinalmax (min nmax (fix nbmax)))
(if (> nfinalmin nfinalmax)
(altura-cobertores (+ lancos 2)
ht emin emax l cmin bmin bmax)
(list h (round (/ (+ nfinalmin nfinalmax) 2)) lancos))))))))
Para facilitar a utilizao desta funo podemos definir outra que, dados dois pontos que delimitam um rectngulo, dado o nmero inicial de
285
286
Figura 98: Lanos de escada criados de modo a ocuparem as reas delimitadas pelos rectngulos. Da esquerda para a direita, as escadas so dimensionadas para um nmero mnimo de dois, trs, trs e dois lanos, respectivamente, mas as suas dimenses finais implicam quatro, cinco, trs e
doze lanos, respectivamente. As escadas possuem um cobertor mnimo
de 0.23m, espelho entre 0.14m e 0.18m e limites de Blondel entre 0.62m e
0.64m.
287