Bom, pela enquete, parece que lisp ainda é um assunto interessante!! Que bom, afinal isso livra a gente de muito pepino, hehehe.
O intuito desta página será dar uma introdução ao AutoLisp, para que você, que ainda não sabe nada, ou muito pouco do assunto, saiba ao menos de onde começar.
Já aviso, isso não é um curso de AutoLisp, não é completo e nem tem a pretensão de ser.
Acredito muito que a melhor maneira de aprender é o método Sr.
Miagui de aprender, hehehe.
Primeiro o jeito difícil, depois o jeito fácil....
A primeira coisa que você deverá saber, é que AutoLisp não é uma linguagem de programação propriamente dita, na verdade é um pequeno pedaço do LISP, muito usado ainda no linux...
A sintaxe é dela é o que se chama PRÉ FIXADA.
Existem três tipo de notação pré fixada, infixada e pós fixada.
Mas onde se usa isso?
Exemplos:
Notação pós fixada HP48, sem dúvida a melhor calculadora científica, financeira, programável, [adjetivos mil], que já conheci.
Quem teve ou tem uma sabe do que eu estou falando....
Mesmo a HP50, a meu ver não chegou ao seus pés...
Nela somamos dois números assim:
Escrevemos os argumentos, depois o operador.
Aí clicamos Enter e obtemos o resultado.
Notação infixada É como escrevemos no excel, por exemplo:
Escrevemos o primeiro operando(1), em seguida o operador (+), por fim o segundo operando (2)
Notação pré-fixada É o que o AutoLisp usa!!! adivinha como que faz:
Colocamos em primeiro o OPERADOR (+), depois os operandos (1 e 2)
Mas...
E porque os parenteses????
Bom, isso é pra delimitar o escopo do operador.
Imagine a conta:
(*3(+1 2) )
Se não colocamos os parenteses, como vamos saber o que soma e o que multiplica?
Claro existe uma definição melhor pra isso.
Procura na wikipédia...
Note que se escrevêssemos no excel, faríamos:
fx = 3 * (1 + 2)
E ainda, a sintaxe do AutoLisp permite fazer isso:
(+1 2 3 4)
Economizando parenteses....
Bom, agora que já sabemos a estrutura básica da sintaxe, o que mais precisamos saber???
Primeiro, que é aconselhável usar uma IDE.
O AutoCAD possui sua própria IDE para escrever programas em AutoLisp, é o VLIDE.
Então digite VLIDE na linha de comando, pressione ENTER e veja a tela que se abre:
Note é que apenas um editor de texto metido, hehehe
Você notou que o texto é colorido? Esse é uma feature de todos os IDEs.
Eles colorem o texto pelo tipo de objeto.
No caso do lisp, temos:
As cores ajudam na visualização do código.
E agora? Agora, você deveria saber formular algorítimos para resolver seus problemas...
Mas como assim?
É o seguinte, escrever programas em AutoLisp, C, C++, VB, java é simples, é so uma questão de sintaxe...
O difícil é formular a ideia do algorítimo.
Por exemplo.
Precisamos de um programa que numere os pontos de uma poligonal.
Simples, não? existem milhares de soluções pra isso já, na internet....
Mas, pense, o que será preciso para escrever este programa?
Veja:
Um nome, para chamarmos ele
Depois de chamarmos, ele deverá pedir a seleção de uma polilinha.
Se temos a polilinha, vamos numerar!!
Começa com que número?
Temos que obter os vértices da polilinha.
Iterar sobre cada um deles, escrevendo o texto.
Parece simples não? E é!!! Este é o nosso algorítimo para este caso.
E se quisermos somar o comprimento de linhas selecionadas?, novamente, precisamos definir o algorítimo:
Nome para chamarmos o comando
Pedir a seleção de linhas
Iterar em cada linha, calculando seu comprimento e somando com o total anterior
Devolver o resultado
Agora, como fazemos cada passo desses? Já dizia, jack, vamos por parte, hehehe
Já definimos o algorítimo, então já temos o problema.
Dividimos cada parte dele num problema menor.
Agora, vamos resolver um por um.
No primeiro programa, precisamos saber como criar um comando que podemos chamar na linha de comando.
Em visual lisp (é o AutoLisp colorido do VLIDE), fazemos assim:
(defun c:nome_do_comando ( / variaveis locais
)
;faz alguma coisa legal)
Note os parentese em vermelho, a função defun em azul, o nome do comando em preto agora, escreva isso no VLIDE e salve com o nome que você quiser:
Já resolvemos o primeiro problema.
Agora, como pedimos a seleção de uma polilinha?
Aqui vamos fazer uma pausa, porque eu não vou explicar todas as funções do visual lisp.
Então sugiro você dar uma olhada no help .
No geral, as funções que pedem alguma coisa na linha de comando do AutoCAD, começam com GET.
Então vamos olhar as funções que começam com G!! Se não achar nada, podemos procurar por entity.
no visual lisp, as coisas que estão desenhadas na tela do cad são entities (entidades, ou objetos).
E como usamos isso? Confesso que quando comecei a aprender a programar, eu olhava para as funções e nem desconfiava o que era aquilo entre colchetes, hehehehe
Quando algo está entre colchetes no help do visual lisp, é porque é um argumento (ou operando) que é opcional.
Neste caso colocar uma [msg] é opcional.
Se fizermos isto na linha de comando do dad:
Percebeu? Ele colocou o texto "Select Object".
Mas e se colocarmos outro text, por exemplo:
Ficou bacana, né? E se clicamos a polilinha, será escrito na linha de comando:
Command: (entsel "\nSelecione a polilinha:")
Selecione a polilinha:(<Entityname 7fffb5b65a0> (1818.91 577.047 0.0))
Mas o que é isso? Olhando no help (!!!!), são dois valores.
O primeiro < entity 7fffb5b65a0="" name:="" > é um ponteiro para a polilinha (em C, ponteiro um objeto que nos dá acesso a algo maior, sem blá, blá, blá).
É como o seu CPF, ou RG, ou C.
U. (este é um blog de respeito!!).
O segundo valor nada mais é que as coordenadas do cursos na hora do clique (Hum, isso poderá ser útil!!).
Já sabemos como selecionar a polilinha.
Precisamos salvar isso numa varivel para usar depois.
Mas como salvamos alguma coisa numa variavel em AutoLisp??
Antes, queriamos pegar (get) alguma coisa.
Agora queremos salvar, setar, definir como (set), uma variável.
Então no help, encontramos SETQ .
Sua sintaxe é:
( setq variavel ( entsel "\nSelecione a polilinha" ) )
Onde 'variável' será quem armazena alguma coisa e 'valor' é ess alguma coisa.
Juntando as duas funções, teremos:
(setq variavel (entsel "\nSelecione a polilinha"))
Já pedimos a seleção, já definimos o comando.
Vamos juntar tudo!!
Percebe?.
Agora salve.
Na linha de comando do cad, digite APPLOAD.
Se você ainda não sabe, este é o comando que carrega a nossa lisp para podermos usar como se fosse um comando
Só que aí em umas pegadinhas.
O comando só pode ser usado se definimos ele com a função defun e se colocamos o prefixo C: no seu nome.
Olhe novamente para o código.
Viu? (defun c:...
sem o defun, o AutoLisp pensará que (nome_do_comando) é uma função definida pelo usuário.
Em AutoLisp chamamos isso de subrotina (eu pelo menos...
) e esta está sendo CHAMADA e não DEFINIDA.
E se esquecemos do C:, a subrotina não é acessível na linha de comando como se fosse um comando.
A única forma de chamar seria assim:
(nome_da_subrotina)
Bom, se você já carregou, digite nome_do_comando, na linha de comando!!
Chique, não??
Resolvemos dois problemas!! Agora, precisamos iterar sobre os vértices dessa polilinha.
Iterações em algorítimos se fazem com FOR, DO, WHILE...
REPEAT...
Todas as linguagens de programação tem uma estrutura de looping.
O Lisp não é diferente.
Nele, temos o FOREACH, o WHILE e o REPEAT.
Para iterar, normalmente também precisamos de um contador, que é incrementado a cada looping da iteração.
Já temos o ponteiro para a polilinha (Entity Name....
) Mas precisamos do objeto em si, com suas propriedades.
No AutoCAD cada objeto é armazenado como uma lista de propriedades, e estas propriedades são classificadas segundo seu significado.
Esta é a lista de uma LINE.
Para obter a lista de um objeto qualquer, digite, na linha de comando:
(entget (car (entsel)))
Não se preocupe em não entender a inha acima agora.
é so pra testar.
Olhando para a lista, vemos que temos uma lista organizada, onde cada item é uma outra lista, que contem 3 ou mais coisas.
Basicamente cada item é um objeto que possui um identificador e um valor.
O Ponto serve para delimitar onde termina o identificador e onde começa o valor.
Assim:
0 (zero) serve para dizer qual o tipo do objeto, que pode ser "LINE", "LWPOLYLINE", etc
8, é o layer do objeto
10, é a coordenada inicial (no caso de lines)
11, é a coordenada final (no caso de lines)
410, diz se está no model ou paper (na verdade em qual espaço se encontra o objeto)
Para polilinhas, temos,
Identificador
Valor
Descrição
0
"LWPOLYLINE"
Tipo de objeto
8
"0"
layer da polilinha
90
5
Número de vértices
10
1 2
Coordenadas X e Y em OCS do vértice.
Tem um desses para cada vértice
Claro que tem mais um monte de outros.
Veja quais são em DXF ENTITIES
Então é só escolher os identificadores que começam com 10 para obter as coordenadas, correto? Sim Daniel Sam!!!
Lembra que eu disse que tem o FOREACH? Então.
Sua sintaxe é:
(FOREACH var lista ;faz algo legal)
Ele faz um looping, atribuindo o valor do item Nésimo à variavel 'var' e executa alguma coisa com esta variável.
Volte no seu programa.
Pegamos a polilinha e armazenamos seu ponteiro na variável chamada 'variável'
Mas esta variável também armazena o ponto clicado.
No momento ele não nos interessa.
Vamos pegar somente o primeiro elemento que é o ponteiro.
Pra pegar o primeiro elemento de uma lista, podemos usar a função:
(Ah, resolvemos mais um pequeno problema.como pegar o Nésimo item de uma lista!!!)
E como fazemos para obter a LISTA????
Uma pausa!!
o Ponteiro (Entity Name....
) chamamos de ENAME.
a lista que o ENAME aponta é o ELIST
Para obter o ELIST, usamos a função
(ENTGET ename)
Juntando então estes pedaços, temos:
(defun c:nome_do_comando ( / variavel ename elist
)
;pede a selecao da polilinha (setq variavel (entsel "\nSelecione a polilinha"
))
;pega o ename da polilinha (setq ename ( nth 0 variavel
) )
;pega o elist da polilinha (setq elist (entget ename
) )
;itera sobre os item da elist (foreach
obj elist
;faz algo legal
)
)
Agora, falta sabermos como desenhar um texto, como verificar se o item OBJ é uma coordemada ou outra coisa e outros probleminhas menores!!
Lembra que eu falei sobre subrotinas?
Bom, podemos usar uma que eu já fiz, é a draw-text.
Sua sintaxe é assim:
(draw-textstr pt lay rot alt st ali)
Onde:
str, STRING é o texto que queremos escrever
pt, (X Y), coordenadas
lay, STRING, nome do layer que o texto ficará
rot, REAL, rotação em radianos em relação ao WCS
alt, REAL, altura do texto
st, STRING, é o textstyle
ali, STRING, mc, bc, l, ml....
Alinhamento do texto
Eu particularmente não gosto do command...
Você até pode achar mais simples, mas quando for usar DCL, talvez vocÊ entenda porque não usar ele.....
De qualquer forma, resolvemos mais um pedaço do problema.
Vou supor que você escreveu a segunda opção, usando o command.
Mas para que você entenda a ideia de subrotina, vamos escrever ele como uma subrotina, assim:
;subrotina que desenha textos
(
defun draw-text (str pt lay rot alt st ali
)
(
command
"._text" "J" ali
;alinhamento do text pt ;ponto de iserção do texto alt ;altura do texto rot ;rotação
str
;o texto a ser escrito
)
)
Esta subrotina, irá funcionar?
Talvez.
Se o OSNAP estiver ligado, pode ser que ele atrapalhe!!
Se o estilo de texto não existir, dá erro!!
Se o estilo de texto existir e tiver altura de texto diferente de zero, dá erro!!!
Então esses são os motivos pelos quais eu não gosto do COMMAND.
..
A principio, deixe assim mesmo.
Depois melhoramos o nosso programa.
Lembra do FOREACH ? e o ELIST?
no ELIST, precisamos somente daqueles items que se identificam com o ID=10
então, precisamos testar, se o identificador é realmente o 10.
Pra isso, podemos adicionar um IF!!!
(if teste (then_alguma_coisa) ; se teste é diferente de NIL ; [ (else_outra_coisa) ] ; se teste é nil )
Em lisp, tudo menos o NIL é verdadeiro.
Vamos, lá, fica assim:
Note que adicionei algumas funções que não comentei.
São elas: CAR, CDR.
Nada de mais.
Agora vamos testar!! Salve a lisp, Carregue com APPLOAD
O que faltou???
Incrementar o contador, claro!!!!
Vamos fazer uma pequena alteração no programa.
Localize a linha depois do If:
Escreva :
(setq cont (1+ cont)) Nesta linha
Peraí, eu posso escrever função dentro de outra função?
Pode, mas tome cuidado.
O lisp sempre devolve o último argumento avaliado (putz, nem eu entendi isso...
)
É assim, se um bloco e parenteses faz uma porção de coisas, por exemplo:
(setq a 1 b (+ a 1))
Isso retorna 2.
Pois 1 é armazenado em 'a', depois a é somado a 1, o resultado é armazenado em 'b'
O armazenamento em 'b' 'r a última coisa avaliada, efetuada, calculada, no bloco do setq.
Então isso é retornado....
Então voltemos ao código....
Salve.
Carregue com APPLOAD.
Teste!!!
Deu certo??
Então use o UNDO para desfazer....
O que acontece? Precisa fazer UNDO tantas vezes quanto o número de vértices, certo?
Isso não é o comportamento mais desejado.
Seria interessante que com apenas UM UNDO, desfizesse tudo.
Este é outro problema, correto?
Outra coisa, clique F2.
Olhe a linha de comando....
Tosco né? Precisamos que não escreva nada alem do necessário!!! Isso é ainda mais interessante qnado compilamos a nossa lisp para VLX...
Para proteger o código.
Pior ainda, ligue o OSNAP e deixe o INSERT ligado...
Pode ser que os textos se sobreponham todos na mesma coordenada!!!! pois o comando texto pode achar o INSERT do primeiro ou de um texto qualquer!!!
Não vou colar o código todo aqui.
Quero que você o digite!!! Miaghi, lembra???
Gostou? Compartilha!!!
Na próxima, eu digo como resolver esses probleminhas acima!!!
Um abraço ao Luis Silva, que havia salvo as imagens em um documento do WORD para consulta e me possibilitou arrumar o tutorial!!