Está en la página 1de 123

Introduccin aI estudio de AutoLISP

ndice de temas
Tema 1 : Introduccin.
Tema 2 : Las variabIes en AutoLISP.
Tema 3 : Operaciones matemticas bsicas.
Tema 4 : SoIicitar nmeros aI usuario.
Tema 5 : Funciones de usuario y nuevos comandos.
Tema 6 : Introduccin aI entorno de VisuaI LISP.
Tema 7 : Cargar Ios archivos de AutoLISP.
Tema 8 : Operaciones matemticas.
Tema 9 : Obtener textos y puntos deI usuario.
Tema 10 : Funciones para manejar Iistas.
Tema 11 : Ejecutar comandos de AutoCAD.
Tema 12 : Operaciones de comparacin.
Tema 13 : Operaciones Igicas.
Tema 14 : Estructuras condicionaIes.
Tema 15 : Mostrar textos en pantaIIa.
Tema 16 : VariabIes de sistema.
Tema 17 : Funciones de conversin.
Tema 18 : Obtener distancias y nguIos deI usuario.
Tema 19 : EI comando deshacer en Ias rutinas de AutoLISP.
Tema 20 : Funciones de tratamiento de errores.
Tema 21 : Limitar Ias respuestas de Ios usuarios a Ias funciones de soIicitud
de datos (I).
Tema 22 : Limitar Ias respuestas de Ios usuarios a Ias funciones de soIicitud
de datos (y II).
Tema 23 : Estructuras repetitivas.
Tema 24 : Funciones para manipuIar cadenas de texto.
Tema 25 : Trabajar con nguIos y distancias.
Tema 26 : Funciones avanzadas para trabajar con Iistas.
Tema 27 : ApIicar funciones a Ios eIementos de Ias Iistas.
Tema 28 : LiteraIes y otras funciones de utiIidad.
Tema 29 : Carga automtica de archivos de AutoLISP.
Tema 30 : Operaciones con archivos.
Tema 31 : Leer y escribir archivos de texto.

Interfaces de programacin
AutoCAD dispone varios entornos de programacin, Ia seIeccin deI tipo de interfaz
a empIear para crear una apIicacin depender de Ias necesidades de Ia apIicacin y
de Ia experiencia o conocimientos deI programador/es:
AutoLISP es una adaptacin deI Ienguaje de programacin CommonLISP
para AutoCAD. Es senciIIo de aprender y aI mismo tiempo potente. AutoCAD
cuenta con un intrprete interno de LISP que permite introducir cdigo desde
Ia Inea de comando o cargar programas desde archivos externos. Puedes
utiIizar AutoLISP para automatizar tareas repetitivas y crear nuevos
comandos de AutoCAD.
ActiveX Automation constituye una aIternativa moderna aI AutoLISP. Puedes
acceder y controIar objetos de AutoCAD desde cuaIquier apIicacin que
utiIice un controIador Automation como VisuaI Basic y DeIphi, o cuaIquiera
de Ias apIicaciones que dispongan de VisuaI Basic for appIications (VBA).
VBA es un entorno de programacin basado en objetos que utiIiza
ntegramente Ia sintaxis deI Ienguaje VisuaI Basic y permite usar controIes
ActiveX. Permite tambin Ia integracin con otras apIicaciones que utiIizan
VBA como MS Office o MS Project. Las ediciones de desarroIIo de MS VisuaI
Basic, que se adquieren por separado, compIementan AutoCAD VBA con
componentes adicionaIes como un dispositivo externo de base de datos y
funcionaIidades de escritura de informes.
ObjectARX es un entorno de programacin de Ienguaje compiIado para eI
desarroIIo de apIicaciones de AutoCAD. EI entorno de programacin
ObjectARX incIuye varias bibIiotecas de vncuIos dinmicos (DLL) que
ofrecen acceso directo a Ias estructuras de Ia base de datos, eI sistema de
grficos y Ios dispositivos de geometra de AutoCAD.
Caractersticas de AutoLISP
AutoLISP es un Ienguaje evaIuado. EI cdigo se convierte a Ienguaje mquina (ceros
y unos) y se aImacena en Ia memoria temporaI. No es tan Iento como Ios Ienguajes
interpretados, ni tan rpido como Ios compiIados. En Ios Ienguajes interpretados, se
va traduciendo eI programa a cdigo mquina (eI idioma de Ios ordenadores) a
medida que se ejecuta. En Ios Ienguajes compiIados, eI cdigo fuente (texto) deI
programa se traduce a cdigo mquina generando un archivo ejecutabIe (.EXE) que
es eI que ejecutar eI programa.
Una de Ias caractersticas ms importantes deI AutoLISP es Ia posibiIidad de
acceder a Ia base de datos de Ios dibujos de AutoCAD. Donde podemos acceder a
Ias capas, estiIos de texto, SCP... as como a todas Ias entidades deI dibujo. Esta
informacin se puede modificar, extraer e incIuso aadir ms entidades aI dibujo.
AutoLISP permite crear nuevos comandos para AutoCAD, que se ejecuten como
cuaIquier otra orden. Es posibIe incIuso redefinir Ios comandos de AutoCAD para
que funcionen de forma distinta, por ejempIo se puede redefinir eI comando
"POLIGONO" para que dibuje poIgonos estreIIados en Iugar de Ios reguIares.
AutoLISP se ha mejorado con Ia creacin de VisuaI LISP que ofrece un entorno de
desarroIIo integrado dentro de AutoCAD. VisuaI LISP incIuye un compiIador, un
depurador y diversas utiIidades para faciIitar Ia programacin. Adems aade
nuevos comandos para permitir Ia interaccin con objetos que utiIizan ActiveX. Otra
de Ias novedades que aporta VisuaI LISP son Ios reactores de objetos que permiten
que AutoLISP responda a eventos.
Expresiones y procedimientos de evaIuacin
Un programa en AutoLISP consiste en una serie de expresiones deI tipo "(funcin
argumentos)". Cada expresin comienza con un parntesis de apertura aI que sigue
eI nombre de una funcin de AutoLISP (o una funcin creada por eI usuario) y una
serie de argumentos (a veces opcionaIes) que dependen de Ia funcin indicada y
van separados por aI menos un espacio en bIanco. Cada expresin termina con un
parntesis de cierre, esto es muy importante pues eI nmero de parntesis de
apertura debe ser iguaI aI de cierre.
Cada expresin de AutoLISP devueIve un vaIor. Un argumento tambin puede ser
una expresin, crendose as una estructura formada por expresiones (Iistas)
anidadas unas dentro de otras; de modo que Ia ms interior devoIver su resuItado
como un argumento a Ia Iista exterior. Cuando existen Iistas anidadas (unas dentro
de otras), primero se evaIan Ias ms interiores.
Los primeros ejempIos que vamos a ver son senciIIos y cortitos, as que puedes
tecIearIos directamente en Ia ventana de comandos de AutoCAD.
EjempIo:
(+ 1 2) Ejecuta Ia funcin + que reaIiza Ia suma de Ios argumentos 1 y 2 devueIve eI
resuItado 3.
(+ 31 22 -3) Ejecuta Ia funcin + que reaIiza Ia suma de Ios argumentos 31, 22 y -3
devueIve eI resuItado 50.
Prueba tambin:
(- 17 2)
(+ 2.5 22.8)
(- 0.25 22.5)
(+ 12 -2 31 -7.5)
EjempIo:
(+ (* 2 3) 2) devueIve 8. Primero evaIa Ia Iista interior y devueIve su resuItado a Ia
exterior.
(+ 7 (/ 5.0 2) -3) devueIve 6.5.
Qu sucedera si aI escribir Ia expresin (+ 1 (/ 5.0 2)) nos oIvidsemos de escribir
eI Itimo parntesis? Haz Ia prueba, veras que AutoCAD te indica que faIta 1
parntesis de cierre.
Si eI interprete de comandos de AutoCAD encuentra un parntesis de apertura,
supone que todo Io que vaya a continuacin hasta eI parntesis de cierre es una
expresin de AutoLISP. De modo que enva esa expresin aI interprete de AutoLISP
para que Ia evaIe.
En eI tema 2 veremos aIgunas de Ias operaciones matemticas que se pueden
reaIizar con AutoLISP.
Tipos de objetos y datos
Los eIementos de Ias expresiones de AutoLISP pueden ser smboIos, vaIores
concretos y tambin otras expresiones. Se pueden distinguir Ios siguientes tipos de
eIementos:
SmboIos: CuaIquier eIemento que no sea un vaIor concreto. Por ejempIo una
variabIe, una funcin.
Enteros: Nmeros enteros comprendidos entre -32000 y 32000.
ReaIes: Nmeros reaIes (180 es un nmero entero, pero 180.0 es un nmero
reaI).
Cadenas de texto: Texto con una Iongitud mxima de 132 caracteres.
Descriptores de archivo: Representan un archivo de texto ASCII abierto.
Nombres de entidades de AutoCAD: Nombre en hexadecimaI de una entidad
deI dibujo.
Conjuntos designados por eI usuario: Conjuntos de entidades de AutoCAD.
Funciones de usuario: Funciones definidas por eI usuario.
Funciones de AutoLISP: Funciones o comandos predefinidos de AutoLISP.
EjempIo:
(+ 5 2) devueIve 7.
(+ 5 2.0) devueIve 7.0.
En eI primer caso todos Ios argumentos son nmeros enteros, y eI resuItado de su
suma es un nmero entero. En eI segundo caso, tenemos un nmero reaI, as que eI
resuItado es un nmero reaI. Para que comprendas Ia importancia de esta distincin,
reaIiza eI siguiente ejempIo:
(/ 5 2)
(/ 5 2.0)
Una de Ias mayores virtudes de AutoLISP es que pueden ejecutarse expresiones en
medio de un comando de AutoCAD.
EjempIo:
Ejecuta eI comando "LINEA" e indica eI primer punto, activa eI forzado ortogonaI
(F8) y tecIea... (+ 11 25) Esto devueIve eI resuItado de Ia suma aI comando que se
estaba ejecutando. Por eso dibuja una Inea de 36 mm de Iongitud en Ia direccin
que indicaba eI cursor.
Prueba ahora indicando eI radio de Ia circunferencia (- 70 25) aI utiIizar eI comando
IIamado "CIRCULO" (maI IIamado, debera ser "circunferencia").
Podemos empIear tambin Ia constante PI = 3.14159... para reaIizar cIcuIos. Por
ejempIo, ejecuta de nuevo eI comando "CIRCULO" y cuando pregunte eI radio de Ia
circunferencia, tecIea (/ 6 (* 2 PI)). Obtendremos una circunferencia de permetro 6.
Notacin empIeada
Para describir Ias funciones de AutoLISP que se expIiquen a Io Iargo deI curso se
seguir Ia siguiente notacin:
(FUNCIN Argumentos_necesarios [Argumentos_opcionaIes] )
Los nombres de Ias funciones de AutoLISP aparecen en coIor azuI y eI cdigo a
tecIear en cursiva.
Convenciones recomendadas
En este apartado se indicarn una serie de convenciones recomendabIes a Ia hora
de programar. AIguna de eIIas puede que an no Ias entiendas, pero no te
preocupes porque Ias iremos recordando a medida que avancemos en eI curso.
Para Ios comentarios incIuidos en eI cdigo, se recomienda utiIizar eI
siguiente mtodo:
o ;;; Antes deI cdigo de Ias funciones, expIicando su funcionamiento.
o ;; En medio deI cdigo deI programa.
o ; Para expIicar una Inea de cdigo. A diferencia de Ias anteriores, esta
no se inserta en Ia coIumna 1, se insertar aI terminar eI cdigo de Ia
Inea que comenta.
Es muy recomendabIe utiIizar un formato tabuIado para eI cdigo.
Evitar eI uso de variabIes gIobaIes innecesarias.
UtiIizar Ios comandos de AutoCAD y sus opciones en IngIs y precedidos por
"._"
No abusar de Ia funcin "SETQ".
No utiIizar T, MIN, MAX, LAST como smboIos (nombres de variabIes y
funciones).
Recuperar eI vaIor iniciaI de Ias variabIes de AutoCAD que han sido
modificadas.
Aadir unas Ineas aI finaI deI programa para indicar eI nombre deI nuevo
comando, autor...
No introducir demasiado cdigo en Ia funcin principaI.
IncIuir una funcin de tratamiento de errores.
Evitar que eI usuario pueda introducir datos errneos.
En generaI es recomendabIe que, tras ejecutar eI nuevo comando, si se
ejecuta eI comando "DESHACER" ("H") se deshagan todos Ios cambios
reaIizados por eI comando.
Qu es una variabIe?
Que no sabes que es una variabIe? Recuerdas cuando en Ia escueIa te decan
"Tengo 3 meIones, Ie doy uno a Juan y despus de comprar otros 2, me com uno
porque tena hambre". Pues Ios meIones son una variabIe. Nosotros hacamos: 1
tengo 3 meIones x=3 (x es nuestra variabIe). Luego Ie doy uno a Juan x = 3-1=2.
Compro otros dos x = 2+2=4 y me com uno x=4-1. As que x=3. "x" no es ms que
un vaIor que vara (o puede hacerIo) a Io Iargo deI tiempo. Pero podamos haber
IIamado a Ia variabIe "y"o "z", y por qu no "meIones"?
(SETQ VariabIe1 VaIor1 [VariabIe2 VaIor2 ... ] )
En eI ejempIo anterior Iogramos dibujar una circunferencia de 6 unidades de
permetro, pero que sucede si queremos utiIizar eI vaIor obtenido por (/ 6 (* 2 PI))
para reaIizar otra operacin, tendremos que voIver a tecIear Ia expresin anterior.
Existe aIguna opcin para aImacenar en memoria Ios resuItados de una operacin,
taI como hace una caIcuIadora? Desde Iuego que si, AutoLISP permite aImacenar
miIes de datos en variabIes, que se aImacenan en Ia memoria deI ordenador.
La funcin de AutoLISP empIeada para definir variabIes y asignarIes un vaIor es
SETQ y permite definir varias variabIes en una misma expresin. La funcin SETQ
devueIve eI vaIor de Ia Itima variabIe definida.
Con respecto a Ios nombres utiIizados para designar a Ios smboIos creados por eI
usuario (variabIes y funciones):
No son sensibIes a Ias mayscuIas. Es Io mismo bIoque, BLOQUE y BIoque.
No pueden contener espacios en bIanco, ni Ios caracteres " ( ) . ; '
Pueden contener nmeros, pero no estar formados nicamente por eIIos.
No utiIizaremos nombres de variabIes que coincidan con Ios nombres de Ias
funciones de AutoLISP ni de Ias variabIes de sistema de AutoCAD.
No existe Imite en cuanto aI nmero de caracteres, pero es recomendabIe
empIear nombre cortos y descriptivos.
No es necesario decIarar previamente Ias variabIes, como sucede en otros
Ienguajes de programacin. En AutoLISP una misma variabIe puede contener
primero un nmero entero, Iuego uno reaI, despus una cadena de texto, etc.
EjempIo:
(SETQ a 3) Esta expresin crea Ia variabIe a y Ie asigna eI vaIor 3. DevueIve eI vaIor
de Ia variabIe a.
Que vaIor crees que devoIver (SETQ b (+ 1 3) melones 23.0)? Fjate que se han
definido dos variabIes b y meIones de vaIor 4 y 23.0 respectivamente. Como
meIones ha sido Ia Itima variabIe evaIuada, Ia expresin anterior devueIve su vaIor.
Si eI interprete de comandos de AutoCAD recibe una paIabra precedida por eI signo
de excIamacin "!", comprobar si ese termino ha sido empIeado como un smboIo
(nombre de variabIe o una funcin de usuario) de AutoLISP. En cuyo caso devoIvera
su vaIor y en caso contrario devoIvera niI, que es Io mismo que nada o vaco. Por
ejempIo: !a devueIve 3.
Prueba tambin Ias siguientes expresiones y comprueba Ios vaIores asignados a Ias
variabIes:
(SETQ c (+ b 3)) Los vaIores de Ias variabIes tambin pueden utiIizarse para reaIizar
operaciones y asignar eI resuItado de dichas operaciones a una variabIe.
(SETQ d b) Se puede definir una variabIe iguaI aI vaIor de otra variabIe.
(SETQ a 3.5) Se puede modificar eI vaIor asociado a una variabIe, por eso se IIama
variabIe.
(SETQ b 2.0) Qu sucede con eI vaIor de Ia variabIe d? Tomar eI nuevo vaIor de b
o seguir con eI anterior? AI definir Ia variabIe d se Ie asigno eI vaIor que tena Ia
variabIe b en ese momento, no se estabIeci ninguna reIacin entre ambas
variabIes.
Tambin se puede asignar vaIores no numricos a Ias variabIes. Por ejempIo, una
cadena de texto. Las cadenas de texto son secuencias de uno o ms caracteres
encerrados entre comiIIas. Dentro de una cadena de texto pueden insertarse una
serie de carcteres de controI:
\\ representa aI smboIo \
\" representa aI smboIo "
\n representa un cambio de Inea (retorno deI carro)
\t representa una tabuIacin
(SETQ a "\tBienvenido aI tema de AutoLISP" )
En este caso adems, hay que notar que en Ia variabIe a primero se aImacenaba un
vaIor entero, Iuego uno reaI y ahora una cadena de texto. La posibiIidad de reutiIizar
variabIes con distintos tipos de datos puede ser muy tiI, pues dota aI programador
de una gran fIexibiIidad aI escribir eI cdigo. Pero tambin supone que se requiera
ms cuidado para no pasar a una funcin una variabIe con un tipo de dato
incorrecto. Por ejempIo: (+ a b)
Existen una serie de smboIos predefinidos:
T Representa aI vaIor Igico Cierto o Verdadero.
niI Representa aI vaIor Igico FaIso.
(SETQ b T)
(SETQ c niI)
En este caso, a Ia variabIe a se Ie ha asignado una cadena de texto, a b eI vaIor
Cierto o Verdadero y a c FaIso.
Para aImacenar eI radio de Ia circunferencia de permetro 6 unidades en una variabIe
podemos tecIear:
(SETQ rad (/ 6 (* 2 PI)))
EjempIo: Por qu Ias siguientes expresiones estn maI?
(SETQ 157 25)
(SETQ rad 5 Rad 4)
(SETQ b Curso de AutoLISP)
Por Itimo veamos porque no debemos empIear para Ios nombres de Ias variabIes
Ios nombres de Ias funciones de AutoLISP.
(SETQ + 23) En este caso asignamos a Ia variabIe + eI vaIor 23.
Prueba (+ 5 2.5) Ahora + no representa a Ia funcin suma, sino a una variabIe de
vaIor 23. De modo que eI primer termino de Ia expresin anterior no es una funcin,
por Io que da un error. Para recuperar eI modo habituaI de trabajo de Ia funcin + es
necesario cerrar Ia sesin actuaI de AutoCAD e iniciar una nueva sesin.
Operaciones matemticas bsicas
En eI tema anterior ya vimos aIgn ejempIo de como funcionan Ias funciones
matemticas bsicas (suma, resta, divisin y muItipIicacin). Ahora expIicaremos su
funcionamiento con mayor profundidad.
(+ [nmero1 nmero2 ... ] )
Suma Ios nmeros indicados como argumentos y devueIve eI resuItado de dicha
suma. Si todos Ios nmeros de Ia Iista son enteros, eI resuItado tambin ser entero.
(+ 3 9) devueIve 12
(+ 3.0 9) devueIve 12.0
(SETQ a (+ 3 9 4)) devueIve 16 y Io aImacena en Ia variabIe a
(+ 3.5 -1) devueIve 2.5
Prueba ahora Ia siguiente expresin:
(SETQ a (+ a 2.5)) devueIve 18.5
Hemos asignado a Ia variabIe a eI resuItado de una operacin en Ia que usamos eI
anterior vaIor asignado a Ia variabIe a como uno de Ios argumentos de Ia operacin.
Si Ie pasamos a Ia funcin + un nico nmero como argumento, nos devueIve ese
nmero.
(+ 12.5) devueIve 12.5
(+ -7.0) devueIve -7.0
Si ejecutamos Ia funcin suma sin argumentos, devueIve 0.
(+ ) devueIve 0
La expresin (+ .5 2) nos dar un error. Los nmeros reaIes siempre deben
comenzar por un nmero entero, incIuso si es cero, seguido de Ia parte decimaI.
(+ 0.5 2) devueIve 2.5
(+ 3 -0.6) devueIve 2.4
(- [nmero1 nmero2 ... ] )
Resta aI primer nmero todos Ios siguientes nmeros pasados como argumentos. Si
todos Ios nmeros de Ia Iista son enteros, eI resuItado tambin ser entero.
(- 11.0 5) devueIve 6.0
(- 11 5) devueIve 6
(SETQ a (- 12 5 4)) devueIve 3 y Io aImacena en Ia variabIe a
(- 3.5 -1) devueIve -4.5
(SETQ a (- a 2.5)) devueIve 0.5 y Io aImacena en Ia variabIe a.
Si Ie pasamos a Ia funcin - un nico nmero como argumento, nos devueIve ese
nmero cambiado de signo.
(- 12.5) devueIve -12.5
(- -7.0) devueIve 7.0
En Ia expresin anterior, eI primer signo "-" representa a Ia funcin resta, mientras
que eI segundo representa eI signo de un nmero negativo.
Si ejecutamos Ia funcin resta sin argumentos, devueIve 0.
(- ) devueIve 0
(* [nmero1 nmero2 ... ] )
MuItipIica Ios nmeros indicados como argumentos y devueIve eI resuItado de dicho
producto. Si todos Ios nmeros de Ia Iista son enteros, eI resuItado tambin ser
entero.
(* 3 9) devueIve 27
(* 3.0 9) devueIve 27.0
(SETQ a (* 3 9 4)) devueIve 108 y Io aImacena en Ia variabIe a
(* 3.5 -1) devueIve -3.5
Prueba ahora Ia siguiente expresin:
(SETQ a (* a 2.5)) devueIve 270.0
Si Ie pasamos a Ia funcin * un nico nmero como argumento, nos devueIve ese
nmero.
(* 12.5) devueIve 12.5
(* -7.0) devueIve -7.0
Si ejecutamos Ia funcin * sin argumentos, devueIve 0.
(* ) devueIve 0
(/ [nmero1 nmero2 ... ] )
Divide eI primer nmero entre eI siguiente y devueIve eI resuItado. Si se pasan ms
de dos nmeros como argumentos, eI primer nmero se dividir entre eI producto
de Ios restantes nmeros.
(/ 45 5 3) devueIve 3
(/ 11 5.5) devueIve 2.0
En esta funcin es muy importante recordar que si todos Ios nmeros de Ia Iista son
enteros, eI resuItado tambin ser entero.
(/ 7 2) devueIve 3
(/ 7 2.0) devueIve 3.5
(SETQ a (/ 12.5 4 2)) devueIve 1.5625 y Io aImacena en Ia variabIe a
(/ 3.5 -1) devueIve -3.5
(SETQ a (/ a 0.5)) devueIve 3.125 y Io aImacena en Ia variabIe a.
Si Ie pasamos a Ia funcin / un nico nmero como argumento, nos devueIve ese
nmero.
(/ 12.5) devueIve 12.5
(/ -7.0) devueIve -7.0
Si ejecutamos Ia funcin / sin argumentos, devueIve 0.
(/ ) devueIve 0
(1+ <nmero> )
Esta funcin incrementa en una unidad eI nmero indicado como argumento.
(1+ 5) devueIve 6. Ojo entre "1" y "+" no debe haber ningn espacio, ya que eI
nombre de Ia funcin es "1+".
(1+ 2.5) devueIve 3.5
(1+ 0) devueIve 1
(1+ -7) devueIve -6
Una apIicacin bastante habituaI de esta funcin es Ia de incrementar ndices o
contadores:
(SETQ i 1)
(SETQ i (1+ i)) devueIve 2
(1- <nmero> )
Esta funcin reduce en una unidad eI nmero indicado.
(1- 5) devueIve 4. Ojo entre "1" y "-" no debe haber ningn espacio, ya que eI nombre
de Ia funcin es "1-".
(1- 2.5) devueIve 1.5
(1- 0) devueIve -1
(1- -1) devueIve -2
SoIicitar nmeros aI usuario
En este apartado veremos dos funciones de AutoLISP que no permitirn soIicitar aI
usuario un nmero entero o reaI. Esto nos permitir interactuar con eI usuario y
pedirIe informacin.
(GETINT [mensaje] )
SoIicita deI usuario un nmero entero. En caso de que eI usuario introduzca un
nmero reaI o cuaIquier otro dato que no sea un nmero entero, AutoCAD recordar
mediante un mensaje que est soIicitando un nmero entero y no finaIizar Ia
ejecucin de Ia funcin hasta que se introduzca un vaIor entero, o se puIse ESC para
canceIar su ejecucin.
(GETINT)
Puede indicarse un mensaje de soIicitud opcionaI, que faciIite aI usuario informacin
acerca de Io que se est pidiendo. EI mensaje debe ser una cadena de texto y por
tanto debe estar entre comiIIas.
(GETINT "Cuantos aos tienes:")
Podemos asignar eI vaIor introducido por eI usuario a una variabIe y as utiIizarIo
despus.
(SETQ edad (GETINT "Cuantos aos tienes:"))
(SETQ edad (+ edad 1)) nos dar Ia edad que tendrs eI prximo ao.
Tambin puedes crear una variabIe que contenga eI mensaje de soIicitud de Ia
funcin GETINT
(SETQ mens "Cuantos aos tienes:")
(SETQ edad (GETINT mens))
En este caso mens es una variabIe que aImacena una cadena de texto, pero no es
una cadena de texto. Por Io tanto, no debe ir entre comiIIas.
Prueba ahora eI siguiente ejempIo:
(SETQ a 27 mens "Cuantos aos tienes:")
(SETQ edad (GETINT mens))
Que pasar si como respuesta a Ia soIicitud de Ia edad deI usuario se introduce !a.
Parece Igico que Ie estamos indicando eI vaIor de Ia variabIe a, que contiene eI
vaIor numrico 27, de modo que Ia variabIe edad debera tomar eI vaIor 27, pero
observaras que no es as. Haz Ia prueba: nos indicar que es "Imposible volver a
entrar en LISP.". Esto es debido a que aI ejecutar Ia funcin GETINT se est
ejecutando eI interprete de LISP, y aI indicar !a como respuesta estamos diciendo
que ejecute eI interprete de LISP para obtener eI vaIor asociado a Ia variabIe a. Como
eI interprete de LISP ya est en ejecucin, no puede voIver a ejecutarse y nos
muestra eI mensaje anterior.
(GETREAL [mensaje] )
SoIicita deI usuario un nmero reaI. En caso de que eI usuario introduzca un nmero
entero, eI interprete de AutoLISP Io considerar como un reaI. Si se introduce
cuaIquier otro tipo de dato que no sea numrico, recordar mediante un mensaje
que est soIicitando un nmero reaI y no finaIizar Ia ejecucin de Ia funcin hasta
que se introduzca un vaIor numrico, o se puIse ESC para canceIar su ejecucin.
(GETREAL)
Puede indicarse un mensaje de soIicitud opcionaI, que faciIite aI usuario informacin
acerca de Io que se est pidiendo. EI mensaje debe ser una cadena de texto y por
tanto debe estar entre comiIIas.
(SETQ peso (GETREAL "Cuantos kiIos pesas:"))
(SETQ peso (- peso 1)) nos dar eI peso que tendrs si adeIgazas un kiIo.
Tambin puedes crear una variabIe que contenga eI mensaje de soIicitud de Ia
funcin GETREAL
(SETQ mens "Cuantos kiIos pesas:")
(SETQ peso (GETREAL mens))
Definir funciones de usuario
Hemos visto tan soIo aIgunas de Ias funciones de AutoLISP, pero tambin es posibIe
crear nuestras propias funciones. Es ms, podemos redefinir Ias funciones de
AutoLISP e incIuso Ios comandos de AutoCAD. La instruccin de AutoLISP que nos
permitir crear nuestras propias funciones, denominadas funciones de usuario, se
IIama DEFUN.
(DEFUN <funcin> ( [argumentos] / [variabIes_IocaIes] ) [expr1] [expr2] ...)
EI primer argumento representa eI nombre de Ia funcon de usuario que queremos
definir. Hay que tener cuidado de no empIear Ios nombres de Ias funciones de
AutoLISP, ya que en dicho caso se redefiniran.
Despus de indicar eI nombre de Ia funcin, se deben indicar entre parntesis Ios
argumentos y Ias variabIes IocaIes, separados por una barra incIinada.
Los argumentos son vaIores que recibir Ia funcin cuando sea ejecutada
por eI usuario, o IIamada desde otras funciones.
Las variabIes IocaIes son aqueIIas variabIes que se empIearn tan soIo
dentro de Ia funcin que queremos definir, de modo que restringimos su uso
aI entorno de Ia funcin.
Por Itimo, se aaden Ias expresiones que ejecutar Ia funcin. Veamos aIgunos
ejempIos:
(DEFUN 2+ ( vaIor ) (+ vaIor 2))
En este caso hemos definido una nueva funcin IIamada "2+", que recibe como
argumento un nmero y reaIiza Ia suma de ese nmero y 2. Las funciones de
AutoLISP Ias ejecutabamos escribiendo (1+ 5) directamente desde Ia Inea de
comandos, bien pues Ias funciones de usuario se ejecutan exactamente iguaI.
Prueba:
(2+ 5) devueIve 7
(2+ 0) devueIve 2
(2+ -2) devueIve 0
Defun devueIve eI resuItado de Ia Itima expresin ejecutada, que en eI caso anterior
es (+ vaIor 2).
Que sucede si tratamos de ejecutar Ia funcin sin pasarIe ningn argumento, o
pasandoIe un argumento que no sea de tipo numrico?. VeamosIo:
(2+ ) indica "; error: argumentos insui!ientes"
(2+ "texto") indica "; error: tipo "e argumento err#neo: numberp: "te$to""
(2+ 1 2) indica "; error: "emasia"os argumentos"
Podras pensar que eI nmero indicado se aImacena en una variabIe IIamada "vaIor",
pero no es as. CompruebaIo escribiendo !vaIor en Ia Inea de comandos, Io que nos
devoIver niI.
En Ia funcin anterior tenemos un argumento y no hay variabIes IocaIes. Vamos a
modificarIa un poco:
(DEFUN 2+ ( vaIor ) (SETQ vaIor (+ vaIor 2)))
Ahora seguro que estas totaImente convencido de que eI resuItado obtenido se
aImacena en Ia variabIe "vaIor". Pues comprobemos si tienes razn:
(2+ 5) devueIve 7
!vaIor devueIve niI
Parece que estabas equivocado. La funcin "2+" recibe como argumento un
nmero, que aImacena en Ia variabIe "vaIor". Pero eI mbito de apIicacin es IocaI,
es decir una vez que saIgamos de Ia funcin "2+" Ia variabIe "vaIor" recupera su
vaIor iniciaI, que en este caso es niI. Vamos con otra prueba...
(SETQ vaIor 5) devueIve 5
(2+ 4) devueIve 6
Que vaIor crees que tendr Ia variabIe vaIor? Pensemos un poco.
1. IniciaImente vaIor = niI
2. AI ejecutar (SETQ vaIor 5) vaIor = 5
3. Cuando IIamamos a Ia funcin "2+" tenemos que "vaIor" = 4
4. Dentro de Ia funcin "2+" asignamos (SETQ vaIor (+ vaIor 2)) de modo que
"vaIor" = 4 + 2 = 6
5. Pero aI saIir de Ia funcin "2+" recuperamos eI vaIor que tena Ia variabIe
"vaIor" antes de IIamar a Ia funcin, vaIor = 5
Por tanto, si tecIeamos !vaIor devoIvera 5.
Pero, que pasa si ejecutamos (SETQ vaIor (2+ 4)). Se repiten Ios puntos 1-4
anteriores, pero aI saIir de Ia funcin "2+" Ie asignamos a "vaIor" eI vaIor devueIto
por Ia funcin, que es 6. De modo que "vaIor" = 6.
Retoquemos un poco ms Ia funcin "2+" y borremos eI contenido de "vaIor"
(DEFUN 2+ ( vaIor ) (SETQ iniciaI vaIor vaIor (+ vaIor 2)))
(SETQ vaIor niI)
En este caso, dentro de Ia funcin "2+" decIaramos una variabIe a Ia que se Ie
asigna eI vaIor que recibe como argumento Ia funcin.
(2+ 4)
Que vaIor tendrn ahora Ias variabIes "vaIor" e "iniciaI"? CompruebaIo:
!vaIor devueIve niI
!iniciaI devueIve 4
Observa que "vaIor" se comporta como una variabIe IocaI, soIo se empIea dentro de
Ia funcin. Sin embargo "iniciaI" es de mbito gIobaI, es decir sigue empIeandose aI
saIir de Ia funcin. Vamos a modificar un poquito ms nuestra funcin:
(DEFUN 2+ ( vaIor / iniciaI ) (SETQ iniciaI vaIor vaIor (+ vaIor 2)))
Ahora hemos aadido Ia variabIe "iniciaI" a Ia Iista de variabIes IocaIes, con Io que
su mbito ser IocaI. Para comprobarIo...
!iniciaI devueIve 4
(SETQ iniciaI niI)
!iniciaI devueIve niI
(2+ 3)
!iniciaI devueIve niI
Bueno, vamos con Ia Itima modificacin de Ia funcin "2+"
(DEFUN 2+ ( / vaIor ) (SETQ vaIor (GETINT "Nmero: ")) (SETQ vaIor (+ vaIor 2)))
Ahora Ia funcin "2+" no tiene argumentos, as que para ejecutarIa tan soIo
debemos poner su nombre entre parntesis:
(2+)
La variabIe "vaIor" es de mbito IocaI y se empIea GETINT para soIicitar un nmero
aI usuario.
Lo habituaI es que se trate de evitar eI uso de variabIes gIobaIes innecesarias. De
modo que Ias variabIes que no sean gIobaIes, se deberan aadir a Ia Iista de
variabIes IocaIes dentro de Ias definiciones de Ias funciones de usuario.
Crear nuevos comandos de AutoCAD
La funcin de AutoLISP DEFUN no soIo nos permite crear funciones de usuario,
tambin nos permite crear nuevos comandos de AutoCAD.
Siguiendo con eI ejempIo anterior...
(DEFUN C:2+ ( / vaIor ) (SETQ vaIor (GETINT "Nmero: ")) (SETQ vaIor (+ vaIor 2)))
Si anteponemos aI nombre de Ia funcin a definir "C:" en Iugar de crear una funcin
de usuario, se crea un nuevo comando de AutoCAD. La funcin seguir funcionando
exactamente iguaI, Ia nica diferencia est en eI modo de ejecutarse. Ahora no es
necesario poner eI nombre de Ia funcin entre parntesis, sino que se escribe
directamente.
2+
Tambin puede ejecutarse poniendo eI nombre de Ia funcin precedido de "C:" entre
parntesis.
(C:2+)
En caso de que eI nuevo comando creado necesite aIgn argumento, tan soIo podr
ejecutarse deI Itimo modo.
(DEFUN C:2+ ( vaIor / iniciaI ) (SETQ iniciaI vaIor vaIor (+ vaIor 2)))
(C:2+ 2) devueIve 4
La funcin que hemos creado soIo nos servir para Ia sesin actuaI de AutoCAD. Es
ms, tan soIo est definida Ia funcin 2+ en eI dibujo actuaI, de modo que si hay ms
dibujos abiertos, en eIIos no est definida. En eI siguiente tema veremos como
guardar nuestras funciones en archivos de texto, a Ia vez que comenzamos a
trabajar con eI entorno de VisuaI LISP.
Archivos de cdigo fuente en AutoLISP
Ya hemos visto que Ias funciones de AutoLISP se pueden ejecutar directamente
desde Ia ventana de comandos de AutoCAD. Pero eI escribir eI cdigo directamente
en AutoCAD tiene varios inconvenientes, como ya dijimos en eI primer tema deI
curso:
1. EI reducido tamao de Ia ventana de comandos de AutoCAD.
2. La dificuItad de escribir todo eI cdigo seguido, sin tabuIar. Esto es debido a
que cada vez que se puIsa Intro, AutoCAD evaIa Io que se ha escrito.
3. EI cdigo no se aImacena en ningn sitio, as que se perder aI cerrar eI
dibujo actuaI o AutoCAD.
De modo que en Ia ventana de comandos de AutoCAD tan soIo se escribiran
pequeas Ineas de cdigo que no interese guardar. SueIe empIearse por tanto para
hacer pruebas y depurar cdigo, aunque tambin se puede utiIizar como una ayuda
ms para eI diseo con AutoCAD.
EI cdigo de Ias funciones de AutoLISP se escribe en un editor de textos ASCII, para
que as se puedan aImacenar. Se puede empIear cuaIquier editor de texto que
permita tan soIo cdigos ASCII, por ejempIo eI bIoc de notas de Windows. Otros
editores, como MS Word, insertan cdigos para diferenciar Ios estiIos de texto, Ias
tabuIaciones, etc. y no se pueden empIear para escribir Ias rutinas de AutoLISP, ya
que eI interprete de AutoLISP no sabe interpretar esos cdigos.
Adems deI bIoc de notas, existen muchos otros editores de texto que se pueden
empIear para escribir cdigo fuente en AutoLISP. AIgunos de estos editores,
disponen de utiIidades para Ia programacin (permitiendo incIuso empIearIos para
distintos Ienguajes de programacin). Otros editores estn ya enfocados a Ia
programacin en LISP o AutoLISP.
Desde Ia versin 14, AutoCAD incorpora un editor para AutoLISP, en eI que tenemos
entre otras Ias siguientes utiIidades:
EvaIuacin de parntesis durante Ia programacin.
PosibiIidad de compiIar eI cdigo, consiguiendo as aumentar su veIocidad
de ejecucin.
Depurador de cdigo especfico para AutoLISP con opciones para: Ejecutar
eI cdigo paso a paso, indicar puntos de parada, evaIuar expresiones y
vaIores de variabIes, etc.
Diferenciar eI cdigo fuente con distintos coIores.
TabuIado automtico deI cdigo.
UtiIidades para gestionar proyectos con varios archivos de cdigo.
Carga de Ios archivos en AutoCAD.
Nosotros seguiremos utiIizando Ia ventana de comandos de AutoCAD para ver como
trabajan Ias funciones de AutoLISP, y nos iremos aI editor de VisuaI Lisp para crear
nuevas funciones y comandos.
Los archivos de AutoLISP son archivos de texto con extensin LSP.
Nuestra primera funcin de usuario
Antes de comenzar con eI editor de VisuaI LISP, vamos a crear nuestra primera
funcin de usuario: Se trata de una funcin para convertir un nguIo de radianes a
grados decimaIes. EI cdigo de Ia funcin sera eI siguiente:
(defun RAG ( ang )
(/ (* ang 180.0) pi)
)
EI cdigo de Ias rutinas pubIicadas en eI curso se escribir con eI siguiente formato:
Comentarios en eI cdigo
Funciones de AutoLISP
Nmeros
Textos
FUNCIONES DE USUARIO Y NUEVOS COMANDOS
Nombres de variabIes, parntesis, etc...
Hay tres regIas bsicas que sigue AutoLISP:
1. EI nmero de parntesis de apertura debe ser iguaI aI nmero de parntesis
de cierre.
2. Primero se evaIuan Ias Iistas ms interiores.
3. Toda funcin de AutoLISP devueIve un resuItado.
EI interprete de AutoLISP no evaIa Ios retornos de carro (Intros), de modo que eI
cdigo se poda haber escrito todo seguido, en una misma Inea: (defun RAG ( ang )
(/ (* ang 180.0) pi) ) pero as es ms difciI de Ieer. Esta funcin tiene muy poco
cdigo, pero imaginate una funcin mucho mayor escrita toda en Ia misma Inea...
Fjate en que Ia segunda Inea se presenta tabuIada, de modo que no comienza a Ia
misma aItura que eI resto, sino que est despIazada hacia Ia derecha. Esto nos
indica que est incIuida dentro de una Iista de niveI superior, Ia de Ia funcin defun.
No es necesario tabuIar eI cdigo, pero faciIita su Iectura y adems nos permite
detectar posibIes errores con Ios parntesis (RegIa nmero 1). Pi es una constante
que ya est definida en AutoLISP, pi = 3.141592...
En Ia primera Inea "(defun RAG ( ang )" definimos Ia funcin RAG (Radianes A
Grados) que recibe un argumento "ang" (eI nguIo en radianes).
Veamos como funciona Ia segunda Inea: Por Ia RegIa nmero 2, primero se evaIuar
Ia Iista interior (* ang 180.0) que muItipIica eI nguIo en radianes "ang" por 180.0 y
devueIve eI resuItado a Ia Iista de niveI superior (recuerda Ia RegIa nmero 3) que Io
divide entre pi = 3.141592... devoIviendo a su vez eI resuItado de Ia divisin (eI
nguIo en grados decimaIes) a Ia Iista de niveI superior, defun.
La Itima Inea cierra Ia Iista de Ia funcin defun, verificandose as Ia RegIa nmero
1.
Recordemos Ia estructura de Ia funcin de AutoLISP defun: (DEFUN <funcin>
( [argumentos] / [variabIes_IocaIes] ) [expresin1] [expresin2] ...) . En Ia funcin
RAG tenemos un argumento y no se han decIarado variabIes IocaIes (por Io que no
es necesario poner eI caracter "/"), adems soIo tenemos una expresin (/ (* ang
180.0) pi) . Como se dijo en eI tema anterior, defun devueIve eI resuItado de Ia Itima
expresin, que en nuestro caso resuIta ser eI nguIo ya convertido a grados
decimaIes.
Nuestra funcin RAG se ejecutara as: (RAG 1.57) siendo 1.57 eI nguIo en radianes,
y devoIvera ese nguIo en grados decimaIes (aproximadamente 90). No es
necesario poner eI nombre de Ia funcin RAG en mayscuIas, ya que AutoLISP no
diferencia Ias mayscuIas de Ias minscuIas (saIvo en contadas excepciones que ya
expIicaremos). Aunque aI poner Ios nombres de Ias funciones en mayscuIas se
diferencian perfectamente deI resto deI cdigo.
Los comentarios en eI cdigo
Es imprescindibIe aadir comentarios aI cdigo para expIicar que es Io que hace y
como se hace. En AutoLISP todo Io que en una Inea va despus de un punto y coma
(como este ;) se considera un comentario, de modo que no se evaIa. Da iguaI poner
uno, dos o 45 punto y comas seguidos, aI poner eI primero AutoLISP ya sabe que
todo Io que est a continuacin, en esa Inea, es un comentario.
TaI vez penseis que no es tan importante aadir expIicaciones en eI cdigo. Pero si
teneis que Ieer una rutina que creasteis hace meses os sern muy tiIes, por que
seguramente no recordareis muy bien como funciona. Adems, si aIguien va a Ieer
aIguna de vuestras rutinas Ie faciIitariais mucho Ia Iabor. AI iguaI que a vosotros os
ser ms senciIIo Ieer y entender una rutina con abundantes comentarios.
Para Ios comentarios incIuidos en eI cdigo, se recomienda utiIizar eI siguiente
mtodo:
;;; Antes deI cdigo de Ias funciones, expIicando su funcionamiento.
;; En medio deI cdigo deI programa.
; Para expIicar una Inea de cdigo. A diferencia de Ias anteriores, esta no se
inserta en Ia coIumna 1, sino aI terminar eI cdigo de Ia Inea que comenta.
Por ejempIo, Ia funcin RAG con comentarios podra quedar as:
;;; Esta funcin recibe eI vaIor de un nguIo en radianes y Io devueIve en grados
decimaIes.
(defun RAG ( ang ) ; Recibe un nguIo en radianes
(/ (* ang 180.0) pi)
;; MuItipIica eI nguIo en radianes por 180.0 y Io divide por pi.
)
EI editor de VisuaI LISP
EI editor de VisuaI Lisp se inicia desde AutoCAD de varias formas:
Ejecutando eI comando de AutoCAD "VLIDE".
Desde eI men despIegabIe "Herr-->AutoLISP-->Editor de VisuaI Lisp"
Mostrar aIgo simiIar a Ia siguiente imagen:
AI abrir eI editor veremos dos ventanas, "consoIa de VisuaI LISP" y "Rastreo". De
momento no vamos a expIicar para que se usan ni como funcionan estas ventanas.
Estamos ante un editor de textos, como otro cuaIquiera, pero con utiIidades
especficas para Ia programacin en AutoLISP. De modo que para crear un nuevo
archivo hacemos Io mismo que en cuaIquier editor de textos: "Archivo-->Nuevo
archivo" (o puIsa ControI + N). Aparece una nueva ventana, taI como puede verse en
Ia siguiente imagen:
Es en esta pantaIIa donde vamos a escribir eI cdigo de nuestra rutina RAG, pero
antes un pequeo comentario...
Es bastante habituaI aadir aI principio de Ios archivos de AutoLISP unas Ineas de
comentarios indicando eI nombre deI autor, fecha, nombre de Ios comandos y/o
funciones definidas en eI archivo, y una breve descripcin de estos. De modo que aI
cdigo anterior Ie aadiremos unas Ineas en Ia cabecera deI archivo:
;;;________________________MecaniCAD__________________________;;;
;;;_____________http://www.peIetash.com/mecanicad_____________;;;
;;;_________________________RAG.LSP___________________________;;;
;;;_______________________Versin 1.0_________________________;;;
;;;________________________21/02/2002_________________________;;;
;;; Esta funcin recibe eI vaIor de un nguIo en radianes y Io devueIve en grados
decimaIes.
(defun RAG ( ang ) ; Recibe un nguIo en radianes
(/ (* ang 180.0) pi)
;; MuItipIica eI nguIo en radianes por 180.0 y Io divide por pi.
)
EI editor de VisuaI LISP reaIiza Ias tabuIaciones automticamente. Y aunque se
pueden eIiminar o modificar a vuestro gusto (aadiendo o quitando espacios y
tabuIaciones), Io recomendabIe es mantener eI formato por defecto para eI cdigo.
Veamos como queda Ia funcin GAR en eI editor:
En primer Iugar observamos que eI cdigo tiene distintos coIores. Esto es
simpIemente una ayuda visuaI para diferenciar Ios diferentes eIementos de nuestras
rutinas:
Las funciones de AutoLISP se muestran de coIor azuI.
Los comentariosen morado, con gris de fondo.
Los nmeros en verde.
Etc.
EI formato coIoreado deI cdigo se puede desactivar, o se pueden modificar Ios
coIores predefinidos para Ios diferentes eIementos. Pero eI mantener eI formato de
coIores para eI cdigo, nos puede ayudar a detectar errores. Por ejempIo, si
ponemos "(SETW radianes ...", SETW aparecer en negro y no en azuI, por que Ia
funcin de AutoLISP es SETQ, de modo que nos indica que hemos escrito maI eI
nombre de Ia funcin.
En cuanto a Ia tabuIacin, taI vez IIame Ia atencin eI Itimo parntesis (eI de cierre
de Ia funcin defun), ya que no est a Ia misma aItura que su parntesis de apertura.
Hay editores para AutoLISP que insertan Ios parntesis de cierre a Ia misma aItura
que sus correspondientes parntesis de apertura y hay otros editores que insertan
Ios parntesis de cierre tabuIados, taI como hace (por defecto) eI editor de VisuaI
LISP.
Una vez escrito eI cdigo de Ia funcin RAG, tan soIo nos queda guardarIo en un
archivo. Es recomendabIe crear un directorio (carpeta) en eI que guardar todas
nuestras rutinas. Se Ie sueIe dar a Ios archivos de AutoLISP eI mismo nombre deI
comando o funcin que est definida en I, aunque podemos guardar esta rutina en
eI archivo "kIhsduif.Isp" Iuego no Ia reconoceriamos. As que Io mejor ser guardar
eI cdigo de Ia funcin GAR en eI archivo "RAG.Isp", dentro deI directorio que
hemos creado para aImacenar nuestras rutinas. As que seIecciona "Archivo -->
Guardar como" e indica Ia ruta y eI nombre deI archivo.
Ahora puedes intentar crear una funcin IIamada GAR que reciba como argumento
un nguIo en grados decimaIes y que devueIva ese nguIo en radianes. Es
practicamente iguaI a Ia funcin que acabamos de ver. Pero recuerda... Antes de
empezar a programar que hay q hacer? Pues pensar en Io que hay que hacer y en
como Io vamos a hacer. Como esta rutina es muy senciIIa no es necesario escribir eI
pseudocdigo (ni hacer un diagrama de fIujo), tan soIo hay que pensar un poco en Io
que se va a hacer. Guarda eI cdigo de Ia funcin GAR en un archivo IIamado
"GAR.Isp" en eI directorio donde tengas tus rutinas.
Cargar Ios archivos de AutoLISP
Para que Ia funcin RAG que creamos en eI tema anterior se pueda ejecutar en
AutoCAD, hay que cargar eI archivo de AutoLISP en eI que est definida. Existen
varias formas de cargar Ios archivos de AutoLISP, pero de momento tan soIo vamos
a ver tres:
1. Cargar un archivo desde eI editor de VisuaI LISP.
2. En eI men despIegabIe de AutoCAD "Herr-->AutoLISP-->Cargar".
3. UtiIizando Ia funcin de AutoLISP LOAD.
Si estamos en eI editor de VisuaI LISP y tenemos abierto un archivo con una rutina,
para cargarIa en AutoCAD podemos:
SeIeccionar en Ios mens despIegabIes deI VisuaI LISP "Herramientas -->
Cargar texto en editor".
PuIsando sobre eI icono .
TecIeando Ia combinacin de tecIas CTRL+ALT+E.
AI cargar eI archivo, aparece Ia ConsoIa de VisuaI LISP mostrando un mensaje
parecido aI siguiente: "; N formuIarios cargado de #<editor "RUTA/rag.Isp">. En
caso de que se produzca aIgn error en eI proceso de carga deI archivo, en Ia
consoIa de VisuaI LISP se nos indicara eI tipo de error que se ha producido. De
modo que habria que modificar eI cdigo para corregir ese error antes de cargar Ia
rutina.
Una vez cargada Ia rutina en AutoCAD, podemos probar si funciona. TecIea
directamente en Ia ventana de comandos de AutoCAD:
(rag 0)
(rag pi)
(rag (/ pi 4))
EI segundo mtodo para cargar un archivo de AutoLISP en AutoCAD (seIeccionando
en eI men de AutoCAD "Herr-->AutoLISP-->Cargar") muestra un Ietrero de diIogo
en eI que se seIecciona eI archivo a cargar (tambin se pueden seIeccionar ms de
un archivo) y se puIsa eI botn "Cargar".
(LOAD archivo [resuItado_si_faIIa])
La funcin LOAD permite cargar en AutoCAD eI archivo de AutoLISP que se indique.
Por ejempIo para cargar eI archivo RAG sera:
(Ioad "rag")
No hace faIta indicar Ia extensin deI archivo. Escribiendo as eI nombre deI archivo
soIo cargar eI archivo RAG.LSP si est en uno de Ios directorios de soporte de
AutoCAD o en eI directorio actuaI. En caso contrario hay q indicar Ia ruta compIeta:
(Ioad "c:\rutinas\rag.Isp")
Pero esto nos dara un error, ya que AutoCAD no reconoce eI caracter "\", de modo
que hay que escribirIo de forma aIgo especiaI. Para AutoLISP eI caracter "\" hay que
indicarIo de cuaIquiera de esas 2 formas: "\\" o "/". Por Io tanto:
(Ioad "c:\\rutinas\\rag.Isp")
o
(Ioad "c:/rutinas/rag.Isp")
En caso de que no se encuentre eI archivo, Ia expresin Ioad puede ejecutar Io que
se indique en [resuItado_si_faIIa]. Por ejempIo:
(LOAD "rag" (setq test 0))
En este caso, si no se encuentra eI archivo RAG.Isp a Ia variabIe test se Ie asigna eI
vaIor cero. SueIe empIearse para que, cuando se ejecute LOAD desde un archivo de
AutoLISP, podamos indicarIe aI usuario que no se ha encontrado eI archivo. Como
indica eI siguiente pseudocdigo:
Si test = 0 ==> Mensaje aI usuario "Archivo no encontrado"
Esto es todo, de momento, sobre Ia carga de archivos de AutoLISP en AutoCAD.
Ms adeIante veremos mtodos mucho mejores para cargar nuestras rutinas.
Veamos como sera Ia funcin GAR propuesta en eI tema anterior:
;;;________________________MecaniCAD__________________________;;;
;;;_____________http://www.peIetash.com/mecanicad_____________;;;
;;;_________________________GAR.LSP___________________________;;;
;;;_______________________Versin 1.0_________________________;;;
;;;________________________21/02/2002_________________________;;;
;;; Esta funcin recibe eI vaIor de un nguIo en grados decimaIes y Io devueIve en
radianes.
(defun GAR ( ang )
(/ (* ang pi) 180.0)
)
Es muy muy parecida a Ia funcin RAG, no?
Crear un directorio para Ios archivos de AutoLISP
Supongamos que eI directorio que hemos creado para aImacenar nuestras rutinas
es "C:\Rutinas". Veamos como aadirIo a Ios directorios de soporte de AutoLISP:
Inicia AutoCAD. En eI men despIegabIe "Herr" seIecciona "Opciones". As aparece
un Ietrero de diIogo que nos permitir configurar AutoCAD. En Ia primera pestaa
"Archivos" tenemos una opcin denominada "Ruta de bsqueda de archivos de
soporte". Si no est expandida, para ver su contenido puIsamos con eI ratn sobre
eI + que aparece a Ia izquierda. Para aadir un nuevo directorio de soporte puIsamos
eI botn "Aadir" que se encuentra a Ia derecha deI cuadro de diIogo. Esto crear
una nueva etiqueta, en Ia que podemos escribir Ia ruta deI directorio o puIsar eI
botn "Examinar" para seIeccionarIo. Ya hemos aadido "C:\Rutinas" a Ios
directorios de soporte de AutoCAD.
Tambin podemos subir o bajar eI nuevo directorio en Ia Iista de directorios de
soporte. Esto se hace para definir Ias prioridades, es decir donde buscar primero. De
modo que si subimos nuestro directorio hasta eI primer Iugar (como en Ia imagen),
este ser eI primer directorio en eI que busque aIgo AutoCAD.
Operaciones matemticas
Hemos visto Ias operaciones matemticas bsicas: suma, resta, muItipIicacin y
divisin y Ias funciones 1+ y 1-. Ahora vamos con otras funciones de AutoLISP que
nos permitiran reaIizar casi cuaIquier operacin matemtica en nuestras rutinas.
(ABS numero)
Esta funcin devueIve eI vaIor absoIuto deI nmero que se Ie pase como argumento.
Por ejempIo:
(abs 23.8) devueIve 23.8
(abs -23.8) tb devueIve 23.8
Si eI nmero que recibe como argumento es entero, devueIve un nmero entero y si
es un nmero reaI, devueIve un reaI.
(abs -7) devueIve 7
(abs -7.0) devueIve 7.0
(abs 0) devueIve 0
(FIX numero)
Esta funcin devueIve Ia parte entera de un nmero. De modo que devueIve un
nmero entero.
(fix 15.8) devueIve 15. Ojo! no redondea, sino que eIimina Io que est detras deI
punto decimaI.
(fix -15.8) devueIve -15
(fix 0.99) devueIve 0
(REM numero1 numero2 [numero3] ...)
Esta funcin devueIve eI resto de Ia divisin de numero1 entre numero 2.
(rem 2.5 2) devueIve 0.5
(rem 3 2) devueIve 1
Cuando se indica ms de 2 nmeros (rem 1 2 3) es equivaIente a (rem (rem 1 2) 3). Es
decir, primero caIcuIa eI resto de Ia divisin entre 1 y 2, que es 1, y despus Io divide
entre 3 y devueIve su resto, que es 1.
Si todos Ios nmeros que recibe como argumentos son enteros, devueIve un
nmero entero y si aIguno de eIIos es un nmero reaI, devueIve un reaI.
(rem 3 2) devueIve 1.0
(SIN anguIo)
DevueIve eI seno de un nguIo indicado en radianes.
(sin 0) devueIve 0.0
(sin (/ pi 2)) devueIve 1.0
(COS anguIo)
Funciona iguaI que Ia anterior, pero devueIve eI coseno deI nguIo, que hay que
pasarseIo en radianes.
(cos 0) devueIve 1.0
(cos pi) devueIve -1.0
(ATAN numero 1 [numero2])
DevueIve eI arco cuya tangente sea numero1. Por ejempIo
(atan 0) devueIve 0.0 ya que eI nguIo que tiene tangente 0 es eI 0.0
Si se indica un segundo nmero (ATAN num1 num2) Io que hace es dividir num1
entre num2 y devueIve eI arco cuya tangente sea eI resuItado de Ia divisin. Esto se
hace para faciIitar Io siguiente...
(atan (sin anguIo) (cos anguIo)) devueIve anguIo
(SQRT numero)
Esta funcin devueIve Ia raiz cuadrada deI numero que recibe como argumento.
Siempre devueIve un nmero reaI, no entero.
(sqrt 4) devueIve 2.0
(sqrt 2.0) devueIve 1.41..
(EXPT num exp)
DevueIve eI nmero num eIevado aI exponente exp.
(expt 2 2) devueIve 4
(expt 2 3) devueIve 8
Si todos Ios nmeros que recibe como argumentos son enteros, devueIve un
nmero entero y si aIguno de eIIos es un nmero reaI, devueIve un reaI.
(expt 3 2.0) devueIve 9.0
(EXP num)
DevueIve eI nmero e (e = 2.71828... ) eIevado aI nmero num. Siempre devueIve un
nmero reaI.
(exp 1) devueIve 2.71828
(exp 2) devueIve 7.38906
(LOG numero)
Esta funcin devueIve eI Iogaritmo neperiano deI nmero que recibe como
argumento.
(Iog 1) devueIve 0.0
(Iog 2) devueIve 0.693147
(GCD entero1 entero2)
Esta funcin recibe dos nmeros enteros y devueIve su mximo comn divisor (o
denominador). Siempre devueIve un nmero entero.
(gcd 15 5) devueIve 5
(gcd 9 27) devueIve 9
(MAX num1 num2 ...)
DevueIve eI mayor de Ios nmeros que recibe como argumentos.
(max 2 4 1 3 6) devueIve 6
(max 8 4 -9) devueIve 8
Si todos Ios nmeros que recibe como argumentos son enteros, devueIve un
nmero entero y si aIguno de eIIos es un nmero reaI, devueIve un reaI.
(max 8 4.0 -9) devueIve 8.0
(MIN num1 num2 ...)
DevueIve eI menor de Ios nmeros que recibe como argumentos.
(min 2 3 6) devueIve 2
(min 8 4 -9) devueIve -9
Si todos Ios nmeros que recibe como argumentos son enteros, devueIve un
nmero entero y si aIguno de eIIos es un nmero reaI, devueIve un reaI.
(min 8 4.0 -9) devueIve -9.0
Pues ya estn vistas todas Ias funciones matemticas... Enhorabuena
SoIicitar textos aI usuario
Recuerdas Ias funciones GETINT y GETREAL? Nos sirven para soIicitar aI usuario
un nmero entero y reaI, respectivamente. Pues Ia funcin que se utiIiza para
soIicitar textos aI usuario es muy parecida.
(GETSTRING [modo] [mensaje])
Se puede ejecutar sin parmetros (getstring) pero no es recomendabIe. Se sueIe
indicar un mensaje de texto que expIique aI usuario Io que se Ie est soIicitando. Por
ejempIo:
(getstring "CuaI es tu nombre?")
Supongamos q te IIamas Pepe, a (getstring "CuaI es tu nombre?") responderias
Pepe y ya est. IncIuso se podria asignar eI nombre que indique eI usuario a una
variabIe:
(setq nombre (getstring "CuaI es tu nombre?"))
Pero que sucede si te IIamas Jose Luis? Pues que en cuanto puIses eI espacio es
como si hubieras puIsado Intro. No nos permite insertar textos con espacios. Para
que admita textos con espacios, debemos hacer un pequeo cambio:
(setq nombre (getstring T "CuaI es tu nombre?"))
Le estamos indicando eI argumento [modo] = T. Este argumento puede ser cuaIquier
expresin de AutoLISP, en este caso Ie pasamos eI vaIor T = Cierto, verdadero. Si no
se indica eI modo, o si aI evaIuarIo devueIve niI (niI = FaIso, vaco) entonces no
admite espacios. Y si se pone cuaIquier expresin que aI evaIuarse no devueIva niI,
permite espacios.
(setq nombre (getstring (+ 1 2) "CuaI es tu nombre?")) permite responder con
espacios, ya que (+ 1 2) devueIve 3 que es distinto de niI.
(setq nombre (getstring (setq var1 niI) "CuaI es tu nombre?")) no permite responder
con espacios, ya que (setq var1 niI) devueIve niI.
SoIicitar puntos aI usuario
Para soIicitar puntos se utiIizan dos funciones que tambin son parecidas a GETINT
y a GETREAL.
(GETPOINT [pto_base] [mensaje])
Esta funcin Ie pide un punto aI usuario y devueIve una Iista con Ias coordenadas
deI punto indicado. EI usuario puede indicar eI punto en pantaIIa con eI digitaIizador
(ratn) o tecIeando sus coordenadas, taI y como se hara aI dibujar en AutoCAD.
Se puede ejecutar sin parmetros (getpoint) pero no es recomendabIe. Se sueIe
indicar un mensaje de texto que expIique aI usuario Io que se Ie est soIicitando. Por
ejempIo:
(getpoint "Punto iniciaI")
Lo habituaI es que adems ese punto se aImacene en una variabIe
(setq pto (getpoint "Punto iniciaI"))
As asignamos a Ia variabIe pto aIgo parecido a Io siguiente: (120.56 135.88 0.0)
Veamos ahora para que sirve eI argumento opcionaI [pto_base] aprovechando que
tenemos eI punto pto definido.
(getpoint pto "Siguiente punto:")
Aparece una Inea eIstica entre eI punto pto y Ia posicin deI cursor.
(GETCORNER pto_base [mensaje])
Esta funcin se utiIiza tambin para soIicitar puntos aI usuario. En este caso eI
punto base no es opcionaI, hay que indicarIo. Veamos Ia diferencia entre Ias dos
expresiones siguientes:
(getpoint pto "Siguiente punto:")
(getcorner pto "Siguiente punto:")
AI utiIizar getpoint, se muestra una Inea eIstica entre eI punto pto y Ia posicin deI
cursor. Si se utiIiza getcorner, en Iugar de una Inea eIstica, aparece un rectnguIo.
Fijemonos un momento en Io que devueIven tanto getpoint como getcorner: (125.68
117.68 0.0). Se trata de una Iista. En eI prximo tema veremos aIgunas funciones
para manejar Iistas.
Funciones para manejar Iistas
AutoLISP es un Ienguaje de programacin basado en Iistas, as que es Igico que eI
tratamiento que reciban Ias Iistas de eIementos sea muy bueno. Vamos a ver ahora
una serie de funciones para manipuIar Iistas de eIementos.
(CAR Iista)
Esta funcin devueIve eI primer eIemento de Ia Iista que recibe como argumento.
De modo que si (siguiendo con eI ejempIo deI tema anterior) en Ia variabIe pto
hemos asignado eI vaIor devueIto por getpoint, tenemos una Iista con Ias
coordenadas X, Y y Z deI punto designado. Supongamos que pto = (10.0 20.0 0.0).
(car pto) devueIve Ia coordenada X deI punto pto. Es decir 10.0
(CDR Iista)
Esta funcin devueIve Ia Iista que recibe como argumento pero sin eI primer
eIemento.
(cdr pto) devoIver una Iista formada por Ias coordenadas Y y Z deI punto pto. Es
decir, (20.0 0.0)
(CADR Iista) y otras
Cmo se obtendra Ia coordenada Y deI punto pto??? Veamos:
CDR devueIve Ia Iista sineI primer eIemento
CAR devueIve eI primer eIemento de una Iista
De modo que (cdr pto) devueIve (Y Z). As que para obtener Ia coordenada Y:
(car (cdr pto)) devueIve Ia coordenada Y deI punto pto.
y como obtenemos Ia coordenada Z??
(car (cdr (cdr pto))) devueIve Ia coordenada Z deI punto pto.
En resumen, Ias coordenadas deI punto pto se obtendrian mediante:
X ==> (car pto)
Y ==> (car (cdr pto))
Z ==> (car (cdr (cdr pto)))
Si en Ias coordenadas X, Y y Z ponemos Ias Ietras A y D de cAr y cDr en
mayscuIas, Io anterior quedara:
X ==> (cAr pto)
Y ==> (cAr (cDr pto))
Z ==> (cAr (cDr (cDr pto)))
Las funciones CAR y CDR se pueden agrupar. Para eIIo, existen una serie de
funciones que se denominan juntando Ias Aes y Ias Des de cAr y cDr
respectivamente. EI ejempIo anterior, queda:
X ==> (cAr pto)
Y ==> (cAr (cDr pto)) == (cADr pto)
Z ==> (cAr (cDr (cDr pto))) == (cADDr pto)
Esto nos servir como regIa mnemotcnica para recordar eI nombre de estas
funciones. Tan soIo se permiten 4 niveIes de anidacin, as que entre Ia c y Ia r soIo
puede haber 4 Ietras (Aes o Des).
Supongamos que tenemos Ia siguiente Iista asignada a Ia variabIe Ist = ((a b) (c d) (e
f)). OJO!! es una Iista en Ia q sus eIementos son a su vez Iistas.
Como obtendramos a ??
(car Ist) devueIve (a b) que es eI primer eIemento de Ist, y a es eI primer eIemento de
(a b) as que:
(car (car Ist)) devueIve a, o Io que es Io mismo:
(cAAr Ist) devueIve a
y eI eIemento c???
(cDr Ist) devueIve ((c d) (e f)). Ahora si hacemos (cAr (cDr Ist)) devueIve (c d). As
que:
(cAr (cAr (cDr Ist))) devueIve c, o Io que es Io mismo:
(cAADr Ist) devueIve c
Cmo obtener d ??
(cDr Ist) devueIve ((c d) (e f)) y (cAr (cDr Ist)) eI primer eIemento de ((c d) (e f)), es
decir devueIve (c d).
Si ahora hacemos (cDr (cAr (cDr Ist))) obtenemos (d), que no es Io mismo que d. Ya
que se trata de una Iista cuyo primer eIemento es d. As que:
(cAr (cDr (cAr (cDr Ist)))) devueIve d, o Io que es Io mismo:
(cADADr Ist) devueIve c
Y cmo obtener e ??
(cDr Ist) devueIve ((c d) (e f)) y (cDr (cDr Ist)) devueIve ((e f)). Ojo! se trata de una
Iista cuyo primer (y nico) eIemento es a su vez otra Iista con dos eIementos.
As que (cAr (cDr (cDr Ist))) devueIve (e f), y para obtener e:
(cAr (cAr (cDr (cDr Ist)))) devueIve e, o Io que es Io mismo:
(cAADDr Ist) devueIve e
Por Itimo, veamos cmo se obtiene f.
(cAr (cDr (cDr Ist))) devueIve (e f) taI como se vio en eI ejempIo anterior. As que (cDr
(cAr (cDr (cDr Ist)))) devueIve (f), que no es Io mismo que f. Por tanto:
(cAr (cDr (cAr (cDr (cDr Ist))))) devueIve f. Podriamos pensar que:
(cADADDr Ist) tambin devueIve f. Pero aI ejecutar esta Inea AutoCAD nos dice que
Ia funcin cADADDr no est definida. Ya dijimos antes que se pueden agrupar hasta
4 funciones cAr y cDr, pero aqui estamos intentando agrupar 5, y Iogicamente no
podemos. Para obtener f podriamos hacer, por ejempIo:
(cAr (cDADDr Ist)) o (cADADr (cDr Ist))
(LENGTH Iista)
En Ia variabIe pto teniamos una Iista con Ias coordenadas de un punto, pero si soIo
trabajamos en 2D, Ia Z no nos interesa. As que muchas veces Ios puntos tan soIo
tendran 2 coordenadas (X Y). Pero para un programa no es Io mismo que tenga 2
que 3 coordenadas, a Io mejor va a buscar Ia coordenada Z y no existe
produciendose un error en nuestra rutina.
As que necesitamos conocer eI nmero de eIementos que tienen Ias Iistas. Para eIIo
se utiIiza Ia funcin Iength, que devueIve eI nmero de eIementos de Ia Iista que
recibe como argumento. Por ejempIo:
(Iength pto) devueIve 3. y si eI pto estuvuiera en 2D (X Y) devoIvera 2.
Y qu devoIvera (Iength Ist) ??? siendo Ist = ((a b) (c d) (e f)). Pues devoIvera 3, ya
que Ist es una Iista con 3 eIementos que a su vez son Iistas.
Qu devoIvera (Iength (car Ist)) ??? EI nmero de eIementos deI primer eIemento de
Ist, es decir eI nmero de eIementos de (a b), que es 2.
(LIST eIemento1 eIemento2 ...)
Esta funcin devueIve una Iista formada por Ios eIementos indicados. De modo que
se utiIiza para crear Iistas. Por ejempIo:
(Iist 1 2 3) devueIve (1 2 3)
(Iist "pepe" 2 "Juan") devueIve ("pepe" 2 "Juan")
Veamos que hace Ia siguiente expresin:
(Iist (Iist "a" "b") "c" (Iist "d" "e") "f")
Veamos (Iist "a" "b") devueIve ("a" "b") y (Iist "d" "e") devueIve ("d" "e"). As que
(Iist (Iist "a" "b") "c" (Iist "d" "e") "f") devueIve (("a" "b") "c" ("d" "e") "f").
Ejecutar comandos de AutoCAD
Una de Ias mayoresventajas de Ia programacin en AutoLISP es Ia posibiIidad de
ejecutar comandos de AutoCAD en nuestras rutinas.
(COMMAND "comando" [datos])
Esta es Ia funcin que nos permite ejecutar comandos de AutoCAD. Hay que
destacar que siempre devueIve niI. Los nombres de Ios comandos de AutoCAD, y
sus opciones, se indican como textos por Io que van incIuidos entre comiIIas.
(command "Iinea" (Iist 0.0 0.0) (Iist 100.0 200.0)) Dibujar una Inea desde eI origen aI
punto 100,200. Pero, nos faIta aIgo: AI dibujar Ineas en AutoCAD se van indicando
puntos y siempre pide "Siguiente punto: " de modo que para terminar eI comando
"LINEA" hay que puIsar INTRO. Pues ese Intro tambin hay que pasarseIo a
command:
(command "Iinea" (Iist 0.0 0.0) (Iist 100.0 200.0) "") o as (command "Iinea" (Iist 0.0
0.0) (Iist 100.0 200.0) " ")
Lo reaImente potente de COMMAND es que podemos ejecutar casi todos Ios
comandos de AutoCAD. CuaIes no? Son muy pocos, por ejempIo "Nuevo" para
empezar un dibujo nuevo. Pero todos Ios comandos de dibujo, edicin, etc se
pueden ejecutar.
Los datos dependeran deI comando de AutoCAD indicado. Por ejempIo para eI
comando "circuIo", ser:
(command "circuIo" (Iist 0.0 0.0) 25.0) Esto dibujar una circunferencia de radio 25
con centro en eI origen.
Los idiomas de AutoCAD
Supongamos que no disponemos de una versin en casteIIano de AutoCAD, sino
que est en ingIs, o en Francs, o Chino Mandarn... Qu pasa si ejecutamos esto...
(command "Iinea" (Iist 0.0 0.0) (Iist 100.0 200.0) "")
AutoCAD no conocer eI comando "Iinea", as que nos dar un error.
Por suerte se puede soIucionar, ya que sino un programa reaIizado para AutoCAD
en IngIs sIo servira para Ias versiones en IngIs. AutoCAD en reaIidad no "habIa"
un nico idioma, sino que es biIingue, dispone de una Iengua que es Ia que muestra
(que corresponde con Ia versin idiomtica deI programa: CasteIIano, Francs, etc)
y una Iengua interna, eI IngIs.
De modo que Ios comandos de AutoCAD (y sus opciones) se pueden escribir en
CasteIIano o en ingIs. Pero para diferenciar unos de otros a Ios comandos en Ia
Iengua nativa de AutoCAD (IngIs) se Ies antepone un guin bajo:
(command "_circIe" (Iist 0.0 0.0) 25.0)
(command "_Iine" (Iist 0.0 0.0) (Iist 100.0 200.0) "")
Las opciones de Ios comandos tambin se deben indicar en ingIs anteponiendoIes
un guin bajo. Por ejempIo:
(command "_circIe" (Iist 0.0 0.0) "_d" 25.0) Esta Inea dibuja una circunferencia de
Dimetro 25 con centro en eI origen.
Comandos de AutoCAD redefinidos
Por otra parte, ya se ha dicho anteriormente que Ios comandos de AutoCAD se
podrn redefinir para que funcionen de forma distinta. As se puede cambiar eI
comando "circuIo" para que dibuje pentagonos y eI comando "Iinea" para que dibuje
circuIos.
Si redefinimos eI comando Inea para que dibuje circuIos, entonces debemos indicar
(command "Iinea" centro radio) y no (command "Iinea" pt0 pt1"") que no funcionara,
puesto que Ie estamos pasando unos parmetros que no espera. Pero cmo
hacemos ahora para dibujar una Inea?
Para ejecutar Ios comandos originaIes de AutoCAD, y no Ios redefinidos (si Io estn)
debemos anteponer aI nombre deI comando un punto, por ejempIo:
(command ".circuIo" (Iist 0.0 0.0) 25.0)
(command ".Iinea" (Iist 0.0 0.0) (Iist 100.0 200.0) "")
Podemos adems indicar Ios comandos en IngIs anteponiendoIes un guin bajo as
que tambin podriamos escribirIo as:
(command "._circIe" (Iist 0.0 0.0) 25.0)
(command "_.circIe" (Iist 0.0 0.0) 25.0)
Da iguaI si se pone antes eI punto o eI guin bajo.
Para redefinir un comando de AutoCAD:
1. Ejecutar eI comando "ANULADEF" (En IngIs "undefine") indicando eI
nombre deI comando a redefinir. De este modo se eIimina Ia definicin deI
comando de AutoCAD, y Ia nica forma de ejecutarIo ser anteponiendo aI
nombre deI comando un punto.
2. Crear y cargar una rutina en Ia que est definido un nuevo comando con eI
nombre deI comando que acabamos de anuIar.
VeamosIo con un ejempIo: Primero anuIamos Ia definicin deI comando Inea.
Podemos hacerIo desde AutoCAD con eI comando "ANULADEF" (En ingIs
"undefine") o desde AutoLISP: (command "_undefine" "Iinea")
Ahora podemos comprobar que eI comando Inea no funciona en AutoCAD, y Ia
nica forma de ejecutarIo es anteponiendo a su nombre un punto ".Iinea".
Cargamos Ia siguiente funcin:
(defun C:LINEA ( )
(setq pt (getpoint "Centro deI crcuIo: "))
(setq rad (getreaI "Radio deI crcuIo"))
(command "._circIe" pt rad)
)
Ahora eI comando "Iinea" dibujar crcuIos.
Para recuperar eI vaIor originaI deI comando podemos hacer dos cosas:
1. Cerrar AutoCAD y abrirIo de nuevo de modo que Ia rutina que hemos creado
se borre de Ia memoria deI ordenador.
2. Ejecutar eI comando de AutoCAD "redefine" (En IngIs es iguaI) e indicarIe eI
nombre deI comando deI que queremos recuperar su definicin originaI, es
decir "Iinea".
Bueno, por Itimo un ejercicio: Crear un nuevo comando IIamado CIRCPERI que
dibuje una circunferencia indicando su centro y Ia Iongitud de su permetro.
Operaciones de comparacin
Qu es una operacin de comparacin?? Pues comparar, por ejempIo, si aIgo es
mayor que aIgo, o menor, o si es iguaI.
(= expr1 expr2 ...)
Compara si expr1 devueIve eI mismo resuItado que expr2, en caso afirmativo
devueIve T y en caso ontrario devueIve niI.
(= 5 (+ 1 4)) devueIve T porque (+ 1 4) devueIve 5
(= 5 (+ 1 4.0)) devueIve T aunque (+ 1 4.0) devueIve 5.0 y no 5. Pero 5 y 5.0 vaIen Io
mismo, no?
(= 5 5.0) devueIve T
No soIo podemos evaIuar nmeros, tambin textos:
(setq txt1 "Curso de Lisp")
(= txt1 "Curso de Lisp") devueIve T
(= txt1 "Curso de LISP") devueIve niI. No es Io mismo un texto en mayscuIas que en
minscuIas.
(= "LISP" "Lisp") devueIve niI
Estamos comparando expresiones, as que:
(= (+ 1 5) (/ 12 2)) devueIve T porque ambas expresiones devueIven como resuItado
6.
La funcin = puede aceptar ms de dos expresiones:
(= 6 (+ 1 5) 6.0 (/ 12 2)) devueIve T, pues Ias cuatro expresiones devueIven 6 o 6.0
(que vaIe Io mismo).
(/= expr1 expr2 ...)
Es muy simiIar a Ia anterior. DevueIve T si Ias expresiones no devueIven eI mismo
vaIor y devueIve niI si todas Ias expresiones devueIven eI mismo vaIor.
(/= 6 6.0) devueIve niI, porque 6 y 6.0 no son distintos (vaIen Io mismo).
(/= (+ 5 5) (/ 12 2)) devueIve T, pues Ia primera expresin devueIve 10 y Ia segunda 6.
(/= "LISP" "Lisp") devueIve T
(< expr1 expr2 ...)
Compara si expr1 es menor q expr2
(< 4 5) devueIve T, ya que 4 es menor que 5
(< 4 -5) devueIve niI
(< 5 5.0) devueIve niI
Si se ponen ms de 2 expresiones, se comprueba que esten ordenadas de menor a
mayor y devueIve T si Io estn y niI si no Io estn.
(< 1 2 3) devueIve T
(< 1 2 0) devueIve niI
(< (+ 1 2) (* 2 2.0) (/ 12 2)) devueIve T
Tambin podemos comparar textos. EI interprete de AutoLISP evaIua Ios cdigos
ASCII de Ios textos. Es decir Ios ordena aIfabticamente de Ia "a" a Ia "z".
(< "AIbacete" "BarceIona") devueIve T
(< "a" "c") devueIve T
(< "d" "c") devueIve niI
(< "C" "c") devueIve T, puesto que Ios cdigos ASCII de Ia mayscuIas son
inferiores a Ios de Ias minscuIas.
Los cdigos ASCII, son una serie de nmeros que se asignaron a Ias Ietras deI
aIfabeto y a aIgunos de Ios caracteres ms usuaIes (aI menos en Occidente).
EI caracter "a" tiene asociado eI cdigo 97, Ia "b" eI 98, etc hasta Ia "z".
EI caracter "A" tiene asociado eI cdigo 65, Ia "B" eI 66, etc hasta Ia "Z".
(> expr1 expr2 ...)
Supongo que ya os imaginais como funciona, no? Comprueba si Ias expresiones
estn ordenadas de mayor a menor.
(> 5 3) devueIve T
(> -2 3) devueIve niI
(> 5 2 3) devueIve niI
(> 5 4 3) devueIve T
Y ahora con Ios textos:
(> "a" "c") devueIve niI, pues eI cdigo ASCII de "a" es menor que eI de "c".
(<= expr1 expr2 ...)
Comptrueban si Ias expresiones son menores o iguaIes que Ias anteriores.
(<= 1 2 2.0 3) devueIve T
(<= 1 3.0 2 3) devueIve niI
(>= expr1 expr2 ...)
Comptrueban si Ias expresiones son mayores o iguaIes que Ias anteriores
(>= 3 2 2.0 1) devueIve T
(>= 3 1.0 2 1) devueIve niI
(>= 3 3 3 3) devueIve T
Veamos como se hara eI ejercicio propuesto en eI tema anterior: Crear un nuevo
comando IIamado CIRCPERI que dibuje una circunferencia indicando su centro y Ia
Iongitud de su permetro.
Qu es Io primero que hay que hacer ??? Esta respuesta tiene que ser instintiva,
como un acto refIejo: EI pseudocdigo.
Siempre comenzaremos nuestras rutinas escribiendo eI pseudocdigo (o haciendo
un diagrama de fIujo) de Io que se pretende hacer. Bueno, cmo podria ser eI
pseudocdigo de esta rutina, vamos a ver:
1. Pedir aI usuario eI centro de Ia circunferencia.
2. Pedir aI usuario eI permetro de Ia circunferencia.
3. CaIcuIar eI radio de Ia circunferencia a partir de su permetro.
4. Dibujar Ia circunferencia.
Una vez que terminamos eI pseudocdigo, ya tenemos eI 80% de Ia rutina. Si eI
pseudocdigo es correcto, eI resto es de Io ms simpIe.
Primero hay que aadir Ia definicin deI nuevo comando CIRCPERI:
(defun C:CIRCPERI ( )
1) Pedir aI usuario eI centro de Ia circunferencia. Podriamos poner (getpoint "Centro
de Ia circunferencia") pero eso no servira de nada, por que no aImacenamos eI
punto que indica eI usuario en ningn sitio. Tendriamos que hacer, entonces...
(setq pto (getpoint "Centro de Ia circunferencia")) asi aImacenamos eI punto
indicado en Ia variabIe pto.
2) Pedir aI usuario eI permetro de Ia circunferencia. Por ejempIo (setq peri (getint
"Permetro:")) pero aI usar getint, soIo permite obtener nmero enteros. As que
podriamos cambiarIo por:
(setq peri (getreaI "Permetro:"))
3) CaIcuIar eI radio de Ia circunferencia a partir de su permetro. Peri = 2* pi * rad as
que rad = Peri / ( 2 * pi). TraduciendoIo a cdigo:
(setq rad (/ peri (* pi 2)))
4) Dibujar Ia circunferencia
(command "_.circIe" pto rad)
SIo nos faIta una cosa. Pista: EI nmero de parntesis de apertura tiene que ser
iguaI aI nmero de parntesis de cierre. As que:
)
EI cdigo compIeto de Ia rutina sera:
(defun C:CIRCPERI ( )
(setq pto (getpoint "Centro de Ia circunferencia"))
(setq peri (getreaI "Permetro:"))
(setq rad (/ peri (* pi 2)))
(command "_.circIe" pto rad)
)
Tambin deberias aadir comentarios aI cdigo y una cabecera con varias Ineas de
comentarios en eI archivo LSP indicando EI nombre de Ia rutina, fecha, autor, etc.
Te das cuenta de Ia importancia deI pseudocdigo? AI programar nos ha guiado
paso a paso.
Operaciones Igicas
Exste una serie de funciones de AutoLISP que nos permiten reaIizar operaciones
Igicas. SueIen empIearse en combinacin con Ias operaciones de comparacin.
(AND expr1 expr2 ...)
Esta funcin devueIve T si ninguna de Ias expresiones que recibe como argumento
es (devueIve) niI. Si una soIa de Ias expresiones devueIve niI, Ia funcin AND
devoIver niI. Es decir, comprueba que se cumpIan todas Ias expresiones que recibe
como argumento.
(and (< 3 4) (= 5 5.0)) devueIve T, porque Ias dos expresiones devueIven T
(and (> 3 4) (= 5 5.0)) devueIve niI, porque (> 3 4) devueIve niI
En eI ejempIo anterior, como Ia primera expresin (> 3 4) devueIve niI, ya no se
continuan evaIuando eI resto de expresiones. Cmo hay una expresin que devueIve
niI, AND devoIver niI. De modo que Ia expresin (= 5 5.0) ya no se evaIa.
Vamos a compIicarIo un poco... Qu devoIver Ia siguiente expresin?
(and (= 5 5.0) (< 3 4) "Soy un texto" 5.8)
PreguntndoIo de otra forma: AIguna de Ias expresiones que recibe AND como
argumentos es niI? No, as que AND devueIve T.
(setq a "Soy otro texto" b 15 c T d niI)
(and a b) devoIver T
(and a d)
(and a b c d) devoIver niI, porque d es niI
(OR expr1 expr2 ...)
DevueIve niI si todas Ias expresiones son niI. En caso de que aIguna de Ias
expresiones no devueIva niI, OR devueIve T. Es decir, comprueba si aIguna de Ias
expresiones se cumpIe.
(or (/= 5 5.0) (> 3 4)) devueIve niI, porque ambas expresiones son niI
(or (= 5 5.0) (> 3 4)) devueIve T, pues Ia primera expresin se cumpIe
En eI ejempIo anterior, como Ia primera expresin (= 5 5.0) devueIve T, ya no se
continuan evaIuando eI resto de expresiones. Cmo hay una expresin que devueIve
T, OR devoIver T. De modo que Ia expresin (> 3 4) ya no se evaIa.
(setq a "Soy otro texto" b 15 c T d niI)
(or a b) devueIve T
(or c d) devueIve niI
(or d d) devueIve niI
(EQUAL expr1 expr2 [precision])
En eI tema anterior vimos Ia funcin de comparacin = que nos sirve para
determinar si dos nmeros o textos son iguaIes. Pero que pasa si queremos
comparar otra cosa, por ejempIo dos Iistas (como dos puntos).
(setq pt1 (Iist 10.0 20.0 0.0) pt2 (Iist 10.0 (* 10.0 2) 0.0) pt3 (Iist 9.99 20.0 0.0) pt4 (Iist
9.99 20.02 0.0))
AI comparar estas Iistas (puntos) con Ia funcin = siempre nos devueIve niI. Aunque
pt1 y pt2 sean iguaIes, y muy parecidos a pt3 y pt4. Por tanto, Ia funcin = no nos
servir para comparar Iistas. Para comparar dos Iistas se utiIizar Ia funcin EQUAL.
(equaI 5 5.0) devueIve T, aI iguaI q Ia funcin =, porque 5 vaIe Io mismo que 5.0
(equaI pt1 pt2) devueIve T
EQUAL adems ofrece un argumento opcionaI... [precisin]. Veamos como
funciona :
(equaI 4.99 5.0 0.1) devueIve T, porque compara 4.99 y 5 pero con una precisin de
0.1. As que con esa precisin 4.99 == 5.0
Sin embargo, si subimos Ia precisin...
(equaI 4.99 5.0 0.001) devueIve niI
Y que pasa con Ias Iistas? Tambin podemos indicarIe una precisin? VeamosIo..
(equaI pt1 pt3 0.1) devueIve T, porque compara Ios eIementos de Ias Iistas
(coordenadas) con Ia precisin que hemos indicado, 0.1
Si subimos Ia precisin...
(equaI pt1 pt3 0.001) devueIve niI
(equaI pt1 pt4 0.01) devueIve niI
(equaI pt1 pt4 0.02) devueIve T, porque Ia precisin es 0.02 que es exactamente Ia
diferencia entre 20.02 y 20
EI utiIizar una precisin muy eIevada no impIica que todas Ias comparaciones
devueIvan T, todo depender de Ios vaIores a comparar:
(equaI 15 20 100) devueIve T
(equaI 5000 4200 100) devueIve niI
(NOT expr)
A esta funcin Ie gusta IIevarIe Ia contraria a Ia expresin que recibe como
argumento.
Si Ia expresin devueIve niI, entonces NOT devueIve T.
Si Ia expresin devueIve cuaIquier cosa que no sea niI, entonces NOT
devueIve niI.
(not 5) devueIve niI
(not "Texto") devueIve niI
(not (+ 5 1)) devueIve niI
Si hacemos...
(setq a 5 b niI c T d "Nuevo texto")
(not b) devoIver T, porque b es niI
(not c) devoIver niI.
Veamos que devueIve Ia siguiente expresin:
(and (not c) 5) Como c es T, (not c) devueIve niI. AI no cumpIirse Ia primera
expresin de AND, esta devueIve niI y no contina evaIuando.
Mostrar textos en pantaIIa
Hay varias funciones para mostrar textos en pantaIIa. De momento tan soIo vamos a
ver un par de eIIas, pero habr ms.
(PROMPT mensaje)
Muestra eI texto indicado como argumento en pantaIIa, y siempre devueIve niI.
(prompt "Bienvenidos aI Curso")
(ALERT mensaje)
Muestra eI texto que recibe como argumento en un Ietrero. Tambin devueIve niI. Se
utiIiza principaImente para avisar aI usuario en caso de error, o para mostrarIe
aIguna informacin importante.
(aIert "Error: Dato no vIido")
(TERPRI)
En eI tema 12, creamos un nuevo comando para AutoCAD denominado CIRCPERI. Si
habeis cargado y ejecutado eI comando, habreis observado que Ios mensajes para
soIicitar eI centro de Ia circunferencia y su permetro aparecen en Ia misma Inea y
pegados.
Para que Ios mensajes aparezcan en Ineas distintas, se puede empIear Ia funcin
TERPRI. Ya que esta funcin mueve eI cursor a una nueva Inea en Ia ventana de
comandos de AutoCAD, y devueIve niI. EI cdigo de Ia rutina quedara as:
(defun C:CIRCPERI ( )
(setq pto (getpoint "Centro de Ia circunferencia")) (terpri)
(setq peri (getreaI "Permetro:")) (terpri)
(setq rad (/ peri (* pi 2)))
(command "_.circIe" pto rad)
)
As Ios mensajes de soIicitud aparecern en Ineas separadas.
Los caracteres de controI
Creo que ya se dijo que AutoLISP no reconoce una serie de caracteres, por ejempIo
aI indicar Ia ruta de un archivo no reconoce eI caracter "\" y hay que indicarseIo as:
"\\". Pues existen ms caracteres de controI predefinidos:
\\ EquivaIe aI caracter \
\" EquivaIe aI caracter "
\e EquivaIe a ESCape
\n EquivaIe aI retorno de carro
\r EquivaIe a puIsar Intro
\t EquivaIe a puIsar Ia tecIa deI tabuIador
\" nos permite escribir Ias comiIIas dentro de un texto. Por ejempIo:
(aIert "Esto son un par de comiIIas \" o no?")
La nica comiIIa q se tiene q ver es Ia que est escrita as: \" . Las otras nos indican
donde comienza y termina eI texto, nada ms.
(aIert "Texto en Inea 1\nTexto en Inea 2")
Se pone 1\nTexto todo junto. Para qu poner espacios?
(aIert "Texto en Inea 1\n Texto en Inea 2")
Si Io ponemos as, aade un espacio en bIanco aI principio de Ia segunda Inea. Por
eso se pone todo seguido.
(aIert "Texto en Inea 1\n\tTexto en Inea 2")
En este ejempIo Ia segunda Inea est tabuIada.
Entonces, cmo quedara eI cdigo de Ia rutina CIRCPERI utiIizando caracteres de
controI, en Iugar de Ia funcin (TERPRI)???
(defun C:CIRCPERI ( )
(setq pto (getpoint "\nCentro de Ia circunferencia"))
(setq peri (getreaI "\nPermetro:"))
(setq rad (/ peri (* pi 2)))
(command "_.circIe" pto rad)
)
Un par de cosas ms con respecto a esta rutina... Cuando se crea un archivo LISP
en eI que est definido un nuevo comando es bastante tiI aadir aI finaI de todo eI
cdigo aIgo simiIar a...
(prompt "\nNuevo comando CIRCPERI cargado")
Esta Inea se pondra despus deI parntesis de cierre de defun. Es decir, que
cuando se ejecuta CIRCPERI desde AutoCAD esta Inea no se evaIa. Para qu
ponerIa entonces?? Pues muy senciIIo... para que cuando se cargue eI archivo en
AutoCAD muestre en pantaIIa: Nuevo comando CIRCPERI cargado. As eI usuario
sabe cuaI es eI nombre deI comando definido en eI archivo que se acaba de cargar.
De modo que eI mensaje sIo se mostrar aI cargar eI archivo.
Por otro Iado... si recordamos Ia estructura de Ia funcin DEFUN: (DEFUN
nombre_funcin ( argumentos / variabIes_IocaIes ) expr1 expr2 ...)
Veremos que en Ia rutina CIRCPERI no hemos indicado variabIes IocaIes, as que
todas Ias variabIes sern gIobaIes. Es decir que aI ejecutar CIRCPERI y dibujar un
crcuIo, Iuego nos quedan accesibIes Ios vaIores de Ias variabIes pto peri y rad
desde AutoCAD, ocupando y maIgastando memoria. As que vamos a ponerIas
como IocaIes. SIo habra que cambiar Ia siguiente Inea...
(defun C:CIRCPERI ( / pto peri rad )
OJO! Ia barra incIinada / hay que ponerIa, sino seran argumentos y no variabIes
IocaIes.
EI cdigo compIeto de Ia rutina es eI siguiente:
;;;________________________MecaniCAD__________________________;;;
;;;_____________http://www.peIetash.com/mecanicad_____________;;;
;;;_______________________CIRCPERI.LSP________________________;;;
;;;_______________________Versin 1.1_________________________;;;
;;;________________________26/02/2002_________________________;;;
;;; Comando para dibujar una circunferencia indicando su centro y Ia Iongitud
;;; de su permetro.
(defun C:CIRCPERI ( / pto peri rad )
(setq pto (getpoint "\nCentro de Ia circunferencia"))
(setq peri (getreaI "\nPermetro:"))
(setq rad (/ peri (* pi 2)))
(command "_.circIe" pto rad)
)
(prompt "\nNuevo comando CIRCPERI cargado")
Estructuras condicionaIes simpIes
Hasta ahora nuestro cdigo ha sido compIetamente IineaI, Ias Ineas de cdigo que
escribamos se ejcutaban despus una tras otra en eI mismo orden. En este tema
veremos un tipo de funciones que nos permitiran bifurcar eI cdigo, de modo que ya
no exista un nico camino sino dos o ms. Veamos un ejempIo en pseudocdigo:
1. Introducir eI Imite inferior
2. Introducir eI Imite superior
3. EI Imite superior es menor que eI inferior?
1. SI--> Mensaje "EI Imite superior debe ser mayor que eI inferior"
2. NO --> intervaIo = Imite superior - Imite inferior

(IF condicin expr_si_cumpIe [expr_no_cumpIe])
La funcin IF es una de Ias ms empIeadas aI programar. DevueIve eI vaIor de Ia
Itima expresin evaIuada. Si condicin es distinto de niI, entonces evaIa Ia
expr_si_cumpIe. Si condicin devueIve niI evaIa Ia expr_no_cumpIe, si existe y si
no existe no hace nada. Veamos aIgunos ejempIos:
(if (= 2 2.0) (aIert "Los nmeros son iguaIes"))
La condicin a evaIuar es: (= 2 2.0) en Ia que tenemos un nmero entero 2 y uno reaI
2.0, pero su vaIor es eI mismo. Aunque sean de distinto tipo 2 y 2.0 vaIen iguaI. As
que Ia condicin devueIve T, evaIuandose Ia condicin si cumpIe que muestra un
mensaje de aIerta. La funcin IF devueIve eI vaIor de Ia Itima expresin evaIuada,
es decir aIert, que es niI.
(if (= 2 3) (aIert "Los nmeros son iguaIes"))
En este caso Ia condicin devueIve niI y aI no existir expresin no cumpIe, no hara
nada ms. Qu vaIor devoIvera IF? EI de siempre, eI vaIor de Ia Itima expresin
evaIuada, que en este caso ha sido Ia propia condicin que devueIve niI. De modo
que IF devoIver niI.
(if (= 2 3)
(aIert "Los nmeros son iguaIes")
(aIert "Los nmeros son distintos")
)
En este caso eI cdigo se ha escrito en varias Ineas y tabuIado para faciIitar su
comprensin. Ahora si tenemos una expresin no cumpIe, que ser evaIuada ya que
Ia condicin devueIve niI.
Veamos eI siguiente ejempIo:
(setq Iiminf (getint "\nLmite inferior"))
(setq Iimsup (getint "\nLmite superior"))
(if (> Iiminf Iimsup)
(aIert "EI Imite superior debe ser mayor que eI inferior") (setq Iimsup (getint
"\nLmite superior")) (setq intervaIo (- Iimsup Iiminf))
(setq intervaIo (- Iimsup Iiminf))
)
Viendo eI cdigo anterior, taI vez pienses que si Ia condicin (> Iiminf Iimsup) se
cumpIe, entonces se evaIuar Ia Inea siguiente de cdigo. Pero no es as, se evaIa
Ia expresin si cumpIe, que es Ia primera expresin (aIert "EI Imite superior debe
ser mayor que eI inferior"). Si Ia condicin no se cumpIe, devueIve niI, se evaIuar Ia
expresin no cumpIe, que en este caso ser (setq Iimsup (getint "\nLmite
superior")).
Tanto Ia expresin si cumpIe, como Ia no cumpIe soIo pueden ser una nica
expresin. EI ejempIo de cdigo anterior nos dara un error ya que IF no puede tener
ms que 3 expresiones:
La condicin
La expresin si cumpIe
La expresin no cumpIe
(PROGN expr1 expr2 ...)
Para que se pueda indicar ms de una expresin si cumpIe, o no cumpIe, en Ia
funcin IF se sueIe empIear Ia funcin PROGN. EI vaIor devueIto por PROGN es eI de
Ia Itima expresin que recibe como argumento. Esta funcin en reaIidad no hace
nada, tan soIo nos permite agrupar una serie de expresiones.
Cmo quedara eI ejempIo anterior?
(setq Iiminf (getint "\nLmite inferior"))
(setq Iimsup (getint "\nLmite superior"))
(if (> Iiminf Iimsup)
(progn
(aIert "EI Imite superior debe ser mayor que eI inferior")
(setq Iimsup (getint "\nLmite superior"))
(setq intervaIo (- Iimsup Iiminf))
)
(setq intervaIo (- Iimsup Iiminf))
)
En este caso Ia condicin si cumpIe es todo Io siguiente:
(progn
(aIert "EI Imite superior debe ser mayor que eI inferior")
(setq Iimsup (getint "\nLmite superior"))
(setq intervaIo (- Iimsup Iiminf))
)
Si se cumpIe Ia condicin, se evaIa Ia condicin si cumpIe, es decir eI progn. De
modo que se van evaIuando Ias expresiones contenidas en Ia funcin PROGN, que
devueIve eI vaIor de Ia Itima expresin (setq intervaIo (- Iimsup Iiminf)), que ser eI
vaIor de Ia variabIe intervaIo.
En caso de que Ia condicin no se cumpIa, se evaIa Ia condicin no cumpIe, (setq
intervaIo (- Iimsup Iiminf)) que curiosamente tambin devueIve eI vaIor de Ia variabIe
intervaIo.
Pasemos ahora a unos ejempIos ms de estructuras condicionaIes:
(if (and (= 2 2.0) (< 2 3))
(aIert "Las dos condiciones se cumpIen")
(aIert "AI menos una condicin no se cumpIe")
)
En este caso Ia condicin es (and (= 2 2.0) (< 2 3)) que en este caso devoIvera T, ya
que se verifican Ias dos expresiones que recibe Ia funcin AND.
(if (not var1)
(aIert "VariabIe no definida")
(aIert "VariabIe definida")
)
En este caso si var1 es niI, (not var1) devoIver T, indicando que Ia variabIe no se ha
definido. En caso contrario, (not var1) devoIver niI evaIuandose Ia expresin no
cumpIe. Otro mtodo para hacer Io mismo, sera:
(if var1
(aIert "VariabIe definida")
(aIert "VariabIe no definida")
)
Si var1 es distinto de niI, se evaIa Ia expresin si cumpIe. En caso de que var1 sea
niI, se evaIuara Ia expresin no cumpIe.
Estructuras condicionaIes mItipIes
Con Ia funcin IF tan soIo podemos indicar una condicin y dos opciones, si cumpIe
y no cumpIe. Pero tambin tenemos Ia posibiIidad de indicar varias condiciones con
sus respectivas expresiones si cumpIe.
(COND (condicion1 [expr1_1] [expr1_2] ... ) [ (condicion2 [expr2_1]
[expr2_2] ... ) ] ... )
Esta funcin es simiIar a IF en cuanto a que se indican condiciones y una serie de
expresiones que se evaIuaran si se verifica cada condicin. n este caso no existe Ia
Iimitacin de indicar tan sIo una nica expresin si cumpIe, se pueden indicar
tantas como se desee. COND evaIuar Ia primera condicin encontrada, si se
verifica evaIuar Ias expresiones si cumpIe de dicha condicin. En caso de que no
se verifique, evaIuar Ia siguiente expresin.
Por Io tanto, COND evaIuar Ias expresiones si cumpIe de Ia primera condicin que
se verifique. Y devoIver eI resuItado de evaIuar Ia Itima expresin si cumpIe.
Pongamos un ejempIo:
(cond
((= a b)
(aIert "A y B son iguaIes")
(setq b (getreaI "Introduzca de nuevo B: "))
)
((< a c)
(aIert "A es menor que C")
)
((< a b))
(T
(aIert "A no es iguaI a B")
(aIert "A no es menor que C")
(aIert "A no es menor que B")
)
)
Supongamos ahora que antes de Ia expresin COND, hemos definido (setq a 2 b 2.0
c 3.5). En este caso, aI entrar en COND se evaIuar Ia primera condicin (= a b) que
se verifica, de modo que se evaIuaran Ias expresiones si cumpIe de esta condicin:
(aIert "A y B son iguaIes") y (setq b (getreaI "Introduzca de nuevo B: ")) finaIizando Ia
expresin COND que devueIve eI nuevo vaIor de b.
Aunque Ia siguiente condicin (< a c) se cumpIe, no se evaIa, ya que existe una
condicin anterior que tambin se cumpIa.
En caso de que se hubiera definido (setq a 2 b 2.5 c 3.5) Ia primera condicin (= a b)
no se verifica, de modo que se evaIa Ia segunda condicin (< a c) que si se cumpIe.
EvaIundose sus expresiones si cumpIe (aIert "A es menor que C") que devueIve niI.
Si fuera (setq a 2 b 2.5 c 1.5) Ia primera condicin en cumpIirse sera Ia tercera (< a
b) que no tiene expresiones si cumpIe. Qu devoIver entonces Ia funcin COND?
Pues eI vaIor de Ia Itima expresin evaIuada, es decir eI vaIor devueIto por Ia
condivin (< a b) que es T.
Por Itimo, si tenemos (setq a 2 b 1.0 c 1.5) ninguna de Ias tres condiciones
anteriores se verifica, de modo que pasamos a Ia siguiente condicin T, que
Igicamente siempre devueIve T, as que siempre se verifica. Esto se sueIe utiIizar
mucho en Ia funcin COND, aadir como Itima condicin una que se verifique
siempre. En Iugar de T se poda haber puesto (not niI) o (= 1 1.0) que tambin son
expresiones que siempre se cumpIen. Para qu aadir una expresin que siempre
se cumpIe? Muy senciIIo, para incIuir eI cdigo que se desea ejecutar en caso de
que no se verifique ninguna de Ias condiciones anteriores.
Y qu sucede si no se pone Ia condicin T como Itima condicin? Pues sucede
que Ias que estn a continuacin nunca se evaIuarn, ya que T siempre se cumpIir.
Si en eI ejempIo anterior hubieramos puesto:
(cond
(T
(aIert "A no es iguaI a B")
(aIert "A no es menor que C")
(aIert "A no es menor que B")
)
((= a b)
(aIert "A y B son iguaIes")
(setq b (getreaI "Introduzca de nuevo B: "))
)
((< a c)
(aIert "A es menor que C")
)
((< a b))
)
Independientemente de Ios vaIores de Ias variabIes a b y c siempre nos dira que A
no es iguaI a B, A no es menor que C y A no es menor que B.
Qu es una variabIe de sistema?
EI modo en que funciona eI entorno de AutoCAD, y Ia forma de trabajar de muchos
de sus comandos, se ven afectados por Ios vaIores asignados a Ias variabIes de
sistema. Podra decirse que controIan como trabaja AutoCAD. Por Io tanto, se
pueden modificar Ios vaIores asignados a Ias variabIes de sistema para personaIizar
AutoCAD para un usuario en concreto, para un tipo de trabajo determinado, e
incIuso para un archivo de dibujo. De modo que nos faciIite eI trabajar con AutoCAD.
Tipos de variabIes de sistema
Las variabIes de sistema pueden aImacenar distintos tipos de datos, en funcin de
Ia informacin que contengan. Podran cIasificarse deI siguiente modo:
Activada / Desactivada. Muchas variabIes de sistema sIo admiten dos
opciones: Activada y Desactivada. NormaImente tienen asignado eI vaIor "0"
cuando estn desactivadas, y "1" cuando estn activadas. Un ejempIo de
este tipo de variabIes es "bIipmode".
Nmeros enteros. Otras variabIes tienen ms de dos posibiIidades, para Io
que asignan un nmero entero para cada opcin. NormaImente empIean
nmeros correIativos, empezando desde eI cero. Una variabIe que utiIiza este
tipo de datos es "coords".
Cdigos binarios. AIgunas variabIes pueden empIear varias opciones a Ia
vez, para Io que sueIen empIear cdigos binarios. A cada opcin se Ie asigna
eI nmero resuItante de eIevar 2 a n. Asignando a n nmeros entero
correIativos a partir deI cero. Es decir, Ios vaIores para Ias distintas opciones
sern: 1,2,4,8,16,32,etc. De modo que para seIeccionar Ia primera y cuarta
opciones, hay que asignar a Ia variabIe Ia suma de sus vaIores: 1+8 = 9. Un
ejempIo muy interesante de este tipo de variabIes es "osmode".
Nmeros reaIes. Las variabIes que aImacenan vaIores de nguIos o
distancias, por ejempIo, utiIizan este tipo de vaIores. Un ejempIo de este tipo
es Ia variabIe "chamfera".
Puntos. Este tipo de entidades aImacenan Ias coordenadas de un punto, un
buen ejempIo es "ucsorg".
Cadenas de texto. Hay bastantes variabIes que aImacenan cadenas de texto,
como nombres de archivos o rutas de directorios. EjempIos de este tipo de
variabIes son "acadver" y "acadprefix".
Modificar Ios vaIores de Ias variabIes de sistema
Podramos cIasificar Ias variabIes de sistema en funcin deI Iugar en eI que se
guardan:
No guardadas. La informacin asignada a este tipo de entidades no se
guarda. Un ejempIo de este tipo de variabIes es "acadver".
En eI dibujo. La mayora de Ias variabIes de sistema son de este tipo, de
modo que cada dibujo trabajar con unos vaIores determinados para Ias
variabIes de sistema. Esto hace sumamente importante Ia definicin de Ios
vaIores de Ias variabIes de sistema en Ias pIantiIIas utiIizadas para crear
nuevos dibujos. Un ejempIo de variabIe guardada en eI dibujo es "Iuprec".
En eI registro. AIgunas variabIes de sistema se guardan en eI registro de
Windows. Por ejempIo "attdia".
La mayora de Ias variabIes de sistema de AutoCAD pueden editarse, modificando eI
vaIor que tengan asignado. Pero aIgunas variabIes son de soIo Iectura, de modo que
no se pueden modificar, tan soIo Ieer. Un ejempIo de variabIe de soIo Iectura es
"cdate".
Hay varios mtodos para modificar Ios vaIores asignados a Ias variabIes de sistema
de AutoCAD:
TecIeando eI nombre de Ia variabIe, como si fuese un comando ms de
AutoCAD.
Ejecutando eI comando "MODIVAR" e indicando Ia variabIe a modificar.
AIgunos comandos de AutoCAD permiten modificar Ios vaIores asignados a
aIgunas variabIes de sistema. Por ejempIo eI comando "MARCAAUX" permite
modificar eI vaIor asignado a Ia variabIe "bIipmode".
AIgunas variabIes se modifican aI ejecutar aIgn comando de AutoCAD. Por
ejempIo "circIerad" aImacena eI radio de Ia Itima circunferencia creada con
eI comando "crcuIo".
Las variabIes de sistema en Ios programas de AutoLISP
Los programadores sueIen Ieer y modificar eI contenido de aIgunas variabIes de
sistema de AutoCAD, ya que esto Ies permite definir eI modo en eI que desean que
se comporte AutoCAD o aIgunos comandos de AutoCAD.
Esto puede ocasionar cambios en Ios vaIores asignados a aIgunas de Ias variabIes
de sistema. AI programar deberas seguir Ios siguientes consejos para que esto no
suceda:
Deberas guardar Ios vaIores iniciaIes de Ias variabIes de sistema que se necesite
modificar, y asignarIes sus vaIores iniciaIes aI terminar eI programa.
Crear una funcin de tratamiento de errores, de modo que si se produce aIgn error
aI ejecutar eI programa se restabIezcan Ios vaIores iniciaIes de Ias variabIes de
sistema. La creacin de funciones de tratamiento de errores Ia trataremos ms
adeIante.
(GETVAR variabIe)
Esta funcin devueIve eI vaIor asociado a Ia variabIe que recibe como argumento.
Por ejempIo:
(getvar "osmode")
(getvar "bIipmode")
(getvar "acadver")
(SETVAR variabIe nuevo_vaIor)
Asigna a Ia vaiabIe indicada un nuevo vaIor, y devueIve dicho vaIor.
(setvar "bIipmode" 0)
(setvar "osmode" 32)
Veamos un ejempIo combinando Ias funciones GETVAR y SETVAR. Escribe Io
siguiente en Ia Inea de comandos de AutoCAD:
(getvar "Iuprec")
(setvar "Iuprec" 2)
(getvar "Iuprec")
Funciones de conversin de datos
Vamos a ver una serie de funciones que nos permitirn pasar un entero a reaI, a un
texto o aI revs...
(ITOA entero)
Convierte un entero en un texto. Integer TO Atom.
(itoa 24) devueIve "24"
(ATOI texto)
Hace justo Io contrario que Ia funcin anterior. Convierte un texto en un nmero.
Atom TO Integer
(atoi "24") devueIve 24
(atoi "-7") devueIve -7
Y que pasa si hacemos... (atoi "soy un texto") pues que devueIve cero. Siempre que
escribes aIgo que no sea un nmero devueIve 0.
(atoi "15.3") devueIve 15
(atoi "15.99999") devueIve 15
(FLOAT numero)
Convierte un nmero en reaI, as que Io Igico es pasarIe un entero.
(fIoat 5) devueIve 5.0
pero tb puedo hacer... (fIoat 5.36) devueIve 5.36 Io cuaI sera una tontera porque no
hace nada.
(ATOF texto)
Convierte un texto en reaI.
(atof "15.7") devueIve 15.7
(atof "15") devueIve 15.0
(atof "-15.7") devueIve -15.7
(atof "soy un texto") devueIve 0.0
(RTOS numero [modo [precision]])
La Itima funcin de este tipo que vamos a ver es aIgo ms compIicada, pero no
mucho. Convierte un reaI en texto. ReaI TO String.
(rtos 2.5) devueIve "2.5"
(rtos 2) devueIve "2" y no "2.0"
Veamos para qu sirven Ios argumentos opcionaIes [modo [precisin]]. Modo,
permite indicar un tipo de expresar Ios nmeros, es decir, permite seIeccionar eI
formato utiIizado para Ios nmeros. Hay 5 opciones:
1. Formato cientfico.
2. DecimaI. Es eI que se usa habituaImente.
3. Pies y puIgadas.
4. Pies y puIgadas en fracciones.
5. Fracciones.
Por ejempIo... (rtos 2.5 5) devueIve "2 1/2"
(rtos 2.5 1) devueIve "2.5000E+00"
Precisin nos permite definir eI nmero de decimaIes que deseamos.. por ejempIo:
(rtos 1.23456789 2 3) devueIve 1.235 as que redondea...
(rtos 9.99 2 0) devueIve 10
Obtener distancias y nguIos deI usuario
Hemos visto como se obtienen nmeros, puntos y textos deI usuario. Ahora Ie
vamos a soIicitar directamente una distancia o un nguIo.
(GETDIST [pto_base] [mensaje])
SoIicita una distancia y devueIve esa distancia como un nmero reaI. EI usuario
podr indicar Ia distancia por medio de un nmero o indicando 2 ptos en pantaIIa.
(getdist "Distancia de despIazamiento:")
EI mensaje es opcionaI, pero casi siempre se pone. Tambin podemos asignar eI
resuItado a una variabIe...
(setq dist1 (getdist "Distancia de despIazamiento:"))
En muchas ocasiones se puede reempIazar a Ia funcin GETREAL por GETDIST si Io
que se pide se puede reIacionar con aIguna distancia deI dibujo. Por ejempIo, en
nuestra rutina CIRCPERI podramos dibujar una circunferencia de permetro Ia
Iongitud de una recta.
EI argumento opcionaI [pto_base] funciona de modo simiIar a como Io hace en
GETPOINT permitiendo indicar Ia distancia a partir de un punto de origen ya
predefinido:
(setq pto (getpoint "Punto base"))
(setq dist1 (getdist pto "Distancia de despIazamiento:"))
(GETANGLE [pto_base] [mensaje])
SoIicita un nguIo aI usuario que puede escribirIo, o designarIo por medio de dos
puntos. DevueIve eI nguIo en radianes aunque eI usuario Io escribira en Ias
unidades actuaIes (generaImente grados decimaIes). Por ejempIo, a Ia expresin:
(getangIe "AnguIo: ") eI usuario responde... 180.0 y getangIe, devueIve pi.
Toma como origen de nguIos eI actuaI, que sueIe coincidir con eI sentido positivo
deI eje X deI SCU (Sistema de Coordenadas UniversaI). Pero siempre considerar
como sentido positivo de Ios nguIos eI antihorario.
EI parmetro opcionaI [pto_base] permite indicar un punto a partir deI cuaI indicar eI
nguIo.
(GETORIENT [pto_base] [mensaje])
Es casi iguaI a GETANGLE, y tambin se utiIiza para soIicitar un nguIo aI usuario.
La nica diferencia es que eI origen de nguIos siempre es eI deI sentido positivo
deI eje X deI SCU (Sistema de Coordenadas UniversaI).
Vamos ahora a modificar un poco Ia rutina CIRCPERI. Tenamos eI siguiente cdigo:
(defun C:CIRCPERI ( / pto peri rad )
(setq pto (getpoint "\nCentro de Ia circunferencia: "))
(setq peri (getreaI "\nPermetro: "))
(setq rad (/ peri (* pi 2)))
(command "_.circIe" pto rad)
)
(prompt "\nNuevo comando CIRCPERI cargado")
Si sustituimos Ia funcin getreaI por getdist adems de poder escribir un permetro
directamente, tambin podremos indicarIo mediante dos puntos .
Por otra parte, Si habeis ejecutado eI comando CIRCPERI vereis que Io de Ios
mensajes queda mejor que aI principio pero tampoco es perfecto ya que aparecen
unos textos en Ia ventana de comandos que no se sabe de dnde saIen:
Centro de Ia circunferencia:
Permetro: Designe segundo punto: _.circIe Precise punto centraI para crcuIo o
[3P/2P/Ttr (tangente tangente radio)]:
Precise radio de crcuIo o [Dimetro]: 23.00636765228087
Esto queda bastante feo y como hay que ser profesionaIes, vamos a ponerIo bien.
Hemos visto Ias funciones GETVAR y SETVAR que nos permiten acceder a Ias
variabIes de sistema de AutoCAD. Pues hay una variabIe que controIa eI "eco de
mensajes", es decir, eI que aparezcan esos mensajes en pantaIIa. La variabIe se
IIama CMDECHO y soIo admite dos vaIores posibIes:
0 Desactivada
1 Activada
Por defecto debera estar activada (1) as que se veran Ios mensajes raros de antes.
Cmo evitamos que aparezcan estos mensajes? Pues desactivando Ia variabIe.
Pero no conviene modificar Ios vaIores de Ias variabIes de sistema, porque taI vez eI
usuario Ios quiera mentener como estaban. De modo que se desactivar
momentaneamente y aI terminar Ia rutina se dejar con su vaIor iniciaI, es decir taI
como estaba.
Esto es ms bien una fiIosofa de vida: "Si aI entrar en un sitio, Ia puerta estaba
cerrada, vueIve a cerrarIa"
As que nuestro cdigo quedara...
(defun C:CIRCPERI ( / pto peri rad )
(setvar "cmdecho" 0) ; Desactiva eI eco de mensajes
(setq pto (getpoint "\nCentro de Ia circunferencia: "))
(setq peri (getdist "\nPermetro: "))
(setq rad (/ peri (* pi 2)))
(command "_.circIe" pto rad)
(setvar "cmdecho" 1) ; VueIve a activar eI eco de mensajes
)
(prompt "\nNuevo comando CIRCPERI cargado")
Efectivamente Ios mensajes raros desaparecen, pero... Qu pasa si aI entrar en una
habitacin, Ia puerta ya estaba abierta? Ia cerramos o Ia dejamos abierta de
nuevo?. Lo mejor es que todo quede "taI como Io encontramos". As nadie nos
dir... "Por qu cerraste Ia puerta? No ves que aqui no hay quien respire...". Y si Io
dice, Ie respondes: "Perdona, pero mi rutina, deja Ias cosas taI y como estaban, as
que o estaba cerrada antes o Ia cerraron despus".
Si cmdecho est iniciaImente desactivada nuestra rutina Ia descativa, o Io intenta, y
Iuego Ia activa. Quedando por Io tanto cmdecho activada. As que vamos a modificar
eI cdigo para que cmdecho quede con eI vaIor que tena antes de ejecutar Ia
rutina...
Lo primero que tenemos que saber es si Ia puerta est cerrada, si est cerrada Ia
abrimos y si ya est abierta no hacemos nada, simpIemente pasamos.
(getvar "cmdecho") me dir si cmdecho est activada o desactivada. Veamos que es
Io que hay que hacer:
1. Si Ia puerta est cerrada, Ia abro. Es decir, si cmdecho est activada, Ia
desactivo.
2. Aqui metemos eI cdigo de Ia rutina CIRCPERI
3. Si antes de entrar Ia puerta estaba cerrada , entonces Ia cierro. Es decir, si
cmdecho antes de entrar estaba activada, entonces Ia activo.
EI apartado 1 suena cIaramente a una estructura condicionaI, as que empIearemos
Ia funcin IF:
(if (= (getvar "cmdecho") 1)
(setvar "cmdecho" 0)
)
Y cmo haramos aI finaI de Ia rutina en eI apartado 3? Sera otro condicionaI, pero
necesitamos conocer eI vaIor que tena iniciaImente Ia variabIe cmdecho para saber
si estaba activada o desactivada. De modo que hay que modificar eI cdigo anterior
para que en eI apartado 1 se aImacene eI vaIor de cmdecho.
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
De este modo Ia variabIe cmd0 aImacena eI vaIor iniciaI de cmdecho. Es bastante
habituaI aImacenar Ios vaIores iniciaIes en variabIes cuyo nombre sea deI tipo cmd0,
osm0 o bIip0 pues eI 0 nos indica que aImacena eI vaIor iniciaI.
Ahora ya podemos poner eI cdigo deI apartado 3. Podramos hacerIo de dos
formas:
(setvar "cmdecho" cmd0)
Esta Inea de cdigo asignara a cmdecho eI vaIor que tena iniciaImente.
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
En este caso, si cmdecho estba iniciaImente activada entonces Ia activa. Si no
estaba iniciaImente activada, es decir estaba desactivada, entonces no hace nada
porque cmdecho ya est desactivada, aI iguaI que aI principio.
EI cdigo quedara as:
(defun C:CIRCPERI ( / pto peri rad cmd0 )
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(setq pto (getpoint "\nCentro de Ia circunferencia: "))
(setq peri (getdist "\nPermetro: "))
(setq rad (/ peri (* pi 2)))
(command "_.circIe" pto rad)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
)
(prompt "\nNuevo comando CIRCPERI cargado")
An nos queda una cosa... aI ejecutar ahora Ia rutina muestra eI siguiente texto:
Centro de Ia circunferencia
Permetro: Designe segundo punto: 1
Aparece un 1 aI finaI deI texto. Ese 1 es eI resuItado de Ia evaIuacin de Ia Itima
expresin de CIRCPERI (setvar "cmdecho" 1). Para que Ia saIida de nuestras rutinas
sea "Iimpia" aadiremos aI finaI deI cdigo de esta una funcin que devueIva niI, as
no escribir nada. Por ejempIo, se podra aadir (prompt "") aunque sueIe empIearse
Ia funcin (princ) que an no hemos visto, pero que tambin devueIve niI.
FinaImente eI cdigo resuItante ser:
(defun C:CIRCPERI ( / pto peri rad cmd0 )
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(setq pto (getpoint "\nCentro de Ia circunferencia: "))
(setq peri (getdist "\nPermetro: "))
(setq rad (/ peri (* pi 2)))
(command "_.circIe" pto rad)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(princ)
)
(prompt "\nNuevo comando CIRCPERI cargado")
En este tema no vamos a ver ninguna funcin de AutoLISP. Vamos a crear un nuevo
comando y a repasar un poco eI comando CIRCPERI.
Comenzaremos creando un nuevo comando... Crear un comando para dibujar
arandeIas en 2D. EI programa soIicitar aI usuario eI centro de Ia arandeIa, eI
dimetro interior y eI exterior. Se dibujarn dos circunferencias concncricas con
Ios dimetros indicados. Y antes de ponerse a escribir cdigo hay que ... escribir eI
pseudocdigo. Veamos, podamos hacer aIgo as:
1. Obtener eI centro deI ccuIo
2. Obtener eI radio deI crcuIo interior
3. Dibujar eI circuIo interior
4. Obtener eI radio deI crcuIo exterior
5. Dibujar eI circuIo exterior
AutoCAD ya tiene un comando que se IIama arandeIa (en ingIs donuts) as que
buscaremos otro nombre para nuestra rutina, por ejempIo ARAND. Es mejor utiIizar
nombres ms bien cortos y que evoquen a Ia funcin que tiene eI comando.
La primera Inea de cdigo es Ia definicin de Ia funcin:
(defun C:ARAND ( )
Ms adeIante Ie aadirmos Ias varibIes IocaIes si es que existen.
1) Obtener eI centro deI ccuIo. Podra ser aIgo as:
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
2) Obtener eI radio deI crcuIo interior:
(setq radi (getreaI "\nRadio interior: "))
3) Dibujar eI circuIo interior
(command "_.circIe" pto radi)
4) Obtener eI radio deI crcuIo exterior:
(setq rade (getreaI "\nRadio exterior: "))
5) Dibujar eI circuIo exterior
(command "_.circIe" pto rade)
Y por Itimo cerramos eI parntesis de Ia funcin defun
)
EI cdigo compIeto queda as:
(defun C:ARAND ( )
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
(setq radi (getreaI "\nRadio interior: "))
(command "_.circIe" pto radi)
(setq rade (getreaI "\nRadio exterior: "))
(command "_.circIe" pto rade)
)
Ahora vamos a retocar un poco eI comando, Ie aadiremos Ias siguientes mejoras:
Desactivar eI eco de mensajes, es decir desactivar Ia variabIe cmdecho aI
iniciar Ia rutina.
Recuperar eI vaIor iniciaI de cmdecho aI terminar Ia rutina.
Aadir una Inea aI finaI deI cdigo para que muestre un mensaje indicando eI
nombre deI nuevo comando aI cargar Ia funcin.
Poner Ias variabIes como IocaIes.
En Iugar de utiIizar GETREAL para obtener eI radio, usaremos GETDIST con
eI centro de Ias circunferencias como punto base.
Aadir una Inea aI finaI de Ia funcin para que Ia saIida deI programa sea
Iimpia.
EI cdigo despus de reaIizar Ias mejoras anteriores sera:
(defun C:ARAND ( / pto rad cmd0 )
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
(setq rad (getreaI "\nRadio interior: "))
(command "_.circIe" pto rad)
(setq rad (getreaI "\nRadio exterior: "))
(command "_.circIe" pto rad)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(princ)
)
(prompt "\nNuevo comando ARAND cargado")
Adems de Ias mejoras indicadas anteriormente, ahora Ia variabIe rad se utiIiza tanto
para aImacenar eI radio de Ia circunferencia interior como eI de Ia exterior. Puede
dar Iugar esto a aIgn probIema? VeamosIo:
En primer Iugar obtenemos eI centro de Ia circunferencia y Ia asignamos a Ia
variabIe pto.
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
SoIicitamos eI radio de Ia circunferencia interior y Io asignamos a Ia variabIe rad.
(setq rad (getreaI "\nRadio interior: "))
y dibujamos Ia circunferencia interior
(command "_.circIe" pto rad)
EI radio de Ia circunferencia interior no Io vamos a voIver a utiIizar en nuestra rutina,
de modo que podemos reutiIizar esa variabIe y asignarIe otro vaIor, eI radio de Ia
circunferemcia exterior.
(setq rad (getreaI "\nRadio exterior: "))
Ahora Ia variabIe rad aImacena eI radio de Ia circunferencia exterior y pto eI centro
de Ias dos circunferencias, de modo que dibujamos Ia circunferencia exterior.
(command "_.circIe" pto rad)
De este modo nos ahorramos una variabIe. Si es posibIe conviene reutiIizar Ias
variabIes.
Si cargamos Ia rutina y ejecutamos eI comando ARAND dibujaremos una arandeIa
formada por dos crcuIos. Pero qu pasa si despus de dibujarIa ejecutamos eI
comando "H" (deshacer)? Pues que "deshace eI Itimo comando ejecutado" que no
es ARAND sino (command "_.circIe" pto rad) de modo que deshace eI crcuIo
exterior. Pero eI interior no.
ControI de deshacer comandos
EI comando "DESHACER" es distinto aI comando "H". En reaIidad, "H" es una
opcin de "DESHACER". AI ejecutar este comando, AutoCAD muestra eI siguiente
mensaje: "Indique eI nmero de operaciones a deshacer o
[Auto/ControI/Inicio/Fin/Marca/Retorno] <1>:". Veamos como funcionan estas
opciones:
"Nmero de operaciones a deshacer"
La opcin por defecto es indicar eI nmero de operaciones a deshacer, que por
defecto tiene eI vaIor 1. Esta opcin funciona exactamente iguaI que eI comando
"H". Pero, podemos indicarIe un nmero de operaciones superior a 1 (cuaIquier
nmero entero entre 1 y 32767). Esta opcin es tiI para deshacer Ios cambios
reaIizados por Ios Itimos "n" comandos.
"ControI"
AI seIeccionar "ControI" nos ofrece Ias siguientes posibiIidades: "Indique una
opcin de controI DESHACER [Todas/Ninguna/Una] <Todas>:"
Con Ia opcin "Todas" seIeccionada (es Ia opcin por defecto), AutoCAD
aImacena en eI archivo temporaI "UNDO.ac$" Ia informacin sobre Ios
comandos ejecutados en eI dibujo actuaI y por tanto que se pueden
deshacer. Tambin aImacena en eI archivo temporaI "REDO.ac$" Ia
informacin sobre Ios comandos deI dibujo actuaI que se han deshecho.
Estos archivos se aImacenan en eI directorio temporaI deI sistema operativo.
Esta opcin permite deshacer todos Ios comandos reaIizados en eI dibujo
durante Ia sesin actuaI.
Si se seIecciona Ia opcin "Una", tan sIo se podr deshacer eI Itimo
comando ejecutado. Quedando desactivadas todas Ias opciones deI
comando "DESHACER" excepto "ControI" e "Indique eI nmero de
operaciones a deshacer <1>:"
SeIeccionando Ia opcin "Ninguna" se eIimina Ia capacidad de revocar de Ios
comandos "H" y "DESHACER", quedando estos desactivados. Y ya no se
utiIizan Ios archivos temporaIes anteriormente citados.
Lo recomendabIe es tener siempre activada Ia opcin "Todas".
"Marca y Retorno"
Estas dos opciones funcionan en pareja. Supongamos que vamos a ejecutar una
serie de comandos en eI dibujo actuaI, pero no sabemos si eI resuItado obtenido
ser eI deseado. En este caso, antes de comenzar puedes ejecutar eI comando
"DESHACER" y seIeccionar Ia opcin "Marca". De este modo activas una marca, a Ia
que podrs voIver en cuaIquier momento ejecutando "DESHACER" con Ia opcin
"Retorno". AI encontrar una marca AutoCAD mostrar eI mensaje "Marca
encontrada".
Si en Iugar de voIver a Ia marca Io que quieres es deshacer un nmero determinado
de comandos, puedes ejecutar eI comando "H" o "DESHACER" indicando eI nmero
de comandos a deshacer.
Adems, puedes definir tantas marcas como desees, y cada vez que ejecutes
"DESHACER" "Retorno" voIvers a Ia marca anterior. Si no existen ms marcas, o si
no se ha definido ninguna marca, AutoCAD preguntar si se desea deshacer todo.
"Auto"
AIgunos comandos de AutoCAD, estn formadas por un grupo de rdenes. De modo
que eI comando "H" no anuIara todo eI grupo de comandos ejecutados, sino sIo eI
Itimo. Activando esta opcin se agrupan estos comandos en uno sIo, a efectos de
Ia apIicacin de Ios comandos "H" y "DESHACER".
"Inicio y Fin"
Estas dos opciones tambin funcionan juntas. Con eIIas podemos agrupar una serie
de comandos, de modo que sean tratados como uno soIo aI ejecutar "H" o
"DESHACER".
Si "DESHACER" "Auto" est activada, AutoCAD coIoca automticamente un
"DESHACER" "Inicio" y un "DESHACER" "Fin" aI principio y finaI de Ias opciones de
Ios mens, y deja inutiIizadas estas opciones de forma manuaI.
Con Ia opcin "Auto" desactivada, Ias opciones "Inicio" y "Fin" se ejecutan de forma
anIoga a como se hace con "Marca" y "Retorno". Si se vueIve a ejecutar Ia opcin
"Inicio" sin haber ejecutado Ia opcin "Fin" para cerrar un grupo anterior, AutoCAD
entiende que se quiere cerrar eI grupo anterior y abrir uno nuevo.
EI comando deshacer en Ias rutinas de AutoLISP
UtiIizando Ias opciones anteriores deI comando deshacer, se puede Iograr que todo
eI cdigo de nuestras rutinas funcione como si se tratase de un nico comando,
aunque en reaIidad se utiIice ms de una IIamada a Ia funcin command de
AutoLISP.
Aadiremos aI inicio de nuestra rutina "deshacer" "inicio" y aI finaI de Ia rutina
"deshacer" "fin". VeamosIo:
(defun C:ARAND ( / pto rad cmd0 )
(command "_.undo" "_begin")
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
(setq rad (getreaI "\nRadio interior: "))
(command "_.circIe" pto rad)
(setq rad (getreaI "\nRadio exterior: "))
(command "_.circIe" pto rad)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(command "_undo" "_end")
(princ)
)
(prompt "\nNuevo comando ARAND cargado")
Deberamos aadir estas dos Ineas en Ia rutina CIRCPERI? Pues no es necesario,
puesto que en CIRCPERI tan soIo utiIizamos un comando. As que eI comando de
AutoCAD "H" deshara ese comando.
Funciones de tratamiento de errores
Las rutinas que hemos creado (CIRCPERI y ARAND) no est terminadas todava.
Para terminarIas debemos reaIizar dos modificaciones:
1. ControIar Io que hace Ia rutina en caso de que se produzca un error en su
ejecucin.
2. Impedir que eI usuario introduzca datos erroreos. Por ejempIo que indique 0
como radio de un crcuIo.
En este tema se estudiar eI primero de Ios dos apartados anteriores, y en eI
siguiente tema veremos eI segundo apartado. Fijmonos en eI cdigo de Ia rutina
ARAND:
(defun C:ARAND ( / pto rad cmd0 )
(command "_.undo" "_begin")
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
(setq rad (getreaI "\nRadio interior: "))
(command "_.circIe" pto rad)
(setq rad (getreaI "\nRadio exterior: "))
(command "_.circIe" pto rad)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(command "_.undo" "_end")
(princ)
)
(prompt "\nNuevo comando ARAND cargado")
Qu sucede si eI usuario como respuesta a Ia peticin deI radio interior puIsa
Intro? Pues que se asigna a Ia variabIe rad eI vaIor niI. Produciendose un error aI
evaIuar Ia siguiente Inea de cdigo: (command "_.circIe" pto rad)
En eI siguiente tema veremos cmo se puede evitar que eI usuario introduzca datos
erroneos. Por ejempIo, evitar que como respuesta a Ia peticin deI radio interior se
introduzca Intro. Pero una cosa est cIara, no siempre vamos a poder controIar
todos Ios posibIes errores en nuestras rutinas. De modo que necesitamos una
funcin de tratamiento de errores que informe aI usuario deI tipo de error que se
produce. Por ejempIo, indicarIe aI usuario que ha introducido un dato incorrecto.
AutoCAD en este caso nos dice: "; error: tipo de argumento errneo: numberp: niI"
AutoLISP dispone de una funcin de tratamiento de errores por defect. Dicha
funcin se IIama *error* y recibe como argumento una cadena de texto con Ia
descripcin deI error que se ha producido.
Podemos redefinir Ia funcin de tratamiento de errores que ofrece AutoLISP,
personaIizndoIa a nuestro gusto en funcin de nuestros intereses. Vamos a crear
una funcin de tratamiento de errores a Ia que IIamaremos ERRORES:
(defun ERRORES ( mens )
(if (= mens "quitar / saIir abandonar")
(princ)
(princ (strcat "\nError: " mens " "))
)
(princ)
)
No nos paremos demasiado aqui, ya Io veremos bien ms adeIante. Hemos creado
una funcin IIamada ERRORES para eI tratamiento de errores en nuestras rutinas.
Ahora habr que decirIe aI comando ARAND que utiIice esta funcin de tratamiento
de errores.
Antes, conviene expIicar cmo se pueden redefinir Ias funciones de AutoLISP. Hay
mtodos:
1. Crear una funcin con eI mismo nombre. Por ejempIo, (defun SIN ... Esto
redefinira Ia funcin SIN de AutoLISP.
2. AsignarIe un vaIor distinto mediante setq. Por ejempIo, si hacemos (setq sin
cos) Ia funcin SIN de AutoLISP pasar a funcionar como Ia funcin COS,
devoIviendo eI coseno de un nguIo en Iugar de eI seno. (sin 0.0) ahora
devoIvera 1.0 en Iugar de 0.
Veamos ahora eI cdigo de Ia funcin ARAND:
(defun C:ARAND ( / pto rad cmd0 error0 )
(command "_.undo" "_begin")
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(setq error0 *error* *error* errores)
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
(setq rad (getreaI "\nRadio interior: "))
(command "_.circIe" pto rad)
(setq rad (getreaI "\nRadio exterior: "))
(command "_.circIe" pto rad)
(setq *error* error0)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(command "_.undo" "_end")
(princ)
)
(prompt "\nNuevo comando ARAND cargado")
En Ia Inea (setq error0 *error* *error* errores) se asigna a Ia variabIe error0 Ia
antigua funcin de tratamiento de errores, *error*. Y se define Ia funcin de
tratamiento de errores como nuestra funcin ERRORES. Por supuesto, Ie decimos
que use nuestra funcin de tratamiento de errores aI principio deI cdigo. Pero
siempre despus de desactivar eI eco de mensajes.
Hemos redefinido Ia funcin de tratamiento de errores, pero aI terminar Ia rutina
debemos ponerIo todo como estaba antes. As que recuperamos Ia funcin de
tratamiento de errores iniciaI, Ia que ofrece AutoLISP por defecto. Lo haramos con
Ia siguiente Inea: (setq *error* erro0) que se debe poner antes de voIver a activar eI
eco de mensajes.
En Ia rutina CIRCPERI hariamos exactamente Io mismo:
(defun C:CIRCPERI ( / pto peri rad cmd0 error0 )
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(setq error0 *error* *error* errores)
(setq pto (getpoint "\nCentro de Ia circunferencia: "))
(setq peri (getdist "\nPermetro: "))
(setq rad (/ peri (* pi 2)))
(command "_.circIe" pto rad)
(setq *error* error0)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(princ)
)
(prompt "\nNuevo comando CIRCPERI cargado")
Repasemos un poco eI funcionamiento de Ia rutina CIRCPERI: Lo primero que
hacemos es desactivar eI eco de mensajes, a continuacin redefinimos Ia funcin de
tratamiento de errores, despus viene eI cdigo de Ia funcin, se restituye Ia funcin
de tratamiento de errores de AutoLISP y se recupera eI vaIor iniciaI de "cmdecho"
(que controIa eI eco de mensajes).
Qu diferencia existe entre nuestra funcin de tratamiento de errores y Ia ofrecida
por defecto por AutoLISP? Casi ninguna, de momento tan soIo se diferencia en que
si eI error que se ha producido tiene por descripcin "quitar / saIir abandonar", que
equivaIe a puIsar Ia tecIa de ESCape no hace nada. Si eI error no se ha producido
por puIsar ESC, sino por otra causa, entonces mostrar un mensaje indicando:
"Error: Descripcin deI error". Un "gran" cambio, no? Bueno Ios cambios vamos a
hacerIos ahora que ya sabemos como funciona Ia funcin ERRORES.
Qu sucede si eI usuario introduce un dato incorrecto aI soIicitarIe eI permetro?
En ese caso, en Ia siguiente Inea (setq rad (/ peri (* pi 2))) se producira un error,
iniciandose Ia funcin de tratamiento de errores. Cuando se produce eI error, ya se
ha evaIuado Ia Inea (setq error0 *error* *error* errores) en CIRCPERI, de modo que
hemos redefinido Ia funcin de tratamiento de errores. As que se ejecuta Ia funcin
ERRORES, que muestra Ia descripcin deI error que se produjo. Pero, saIimos de Ia
funcin ERRORES y no hemos recuperado eI vaIor de Ia funcin de tratamiento de
errores que nos ofrece por defecto AutoLISP. Y tambin se ha desactivado eI eco de
mensajes, pero no recuperamos su vaIor iniciaI.
De modo que vamos a modificar Ia funcin ERRORES:
(defun ERRORES ( mens )
(setq *error* error0)
(if (= mens "quitar / saIir abandonar")
(princ)
(princ (strcat "\nError: " mens " "))
)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(princ)
)
Ahora nuestra funcin ERRORES restituye eI vaIor iniciaI deI eco de mensajes y Ia
funcin de tratamiento de errores iniciaI. Puede extraar que se utiIicen Ias variabIes
cmd0 y error0 dentro de Ia funcin ERRORES, ya que estaban definidas como
variabIes IocaIes en CIRCPERI.
Cuando definimos una variabIe IocaI en una funcin, esta variabIe se puede utiIizar
sIo dentro de esa funcin. Pero, si desde CIRCPERI "IIamamos" a otra funcin, por
ejempIo ERRORES, en reaIidad estamos dentro de ERRORES, que est dentro de
CIRCPERI. As que seguimos dentro de CIRCPERI.
Otra de Ias principaIes apIicaciones de redefinir Ia funcin de tratamiento de errores
tiene que ver con eI tema anterior, Ios comandos deshacer en Ias rutinas de
AutoLISP.
Si nos fijamos en eI cdigo de Ia rutina ARAND, vemos que Ia primera Inea es
(command "_.undo" "_begin") Qu sucedera si se produce un error despus de
dibujar eI segundo crcuIo? Dara un error, y terminara eI comando sin ejecutar Ia
Inea (command "_.undo" "_end"). Con Io cuaI para deshacer Ia arandeIa deberiamos
ejecutar eI comando "H" (deshacer) dos veces, una por cada crcuIo. Es ms,
imagina que nuestra rutina no dibuja 2 crcuIos sino 120 y que eI error se produce aI
dibujar en crcuIo ensimo...
Podemos modificar Ia funcin de errores:
(defun ERRORES ( mens )
(setq *error* error0)
(if (= mens "quitar / saIir abandonar")
(princ)
(princ (strcat "\nError: " mens " "))
)
(command "_.undo" "_end")
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(princ)
)
Ahora, bastara con ejecutar eI comando deshacer una nica vez para que se
deshaga todo Io que hizo eI comando ARAND. Podemos incIuso decirIe a Ia funcin
ERRORES que si se produce un error, ejecute eI comando deshacer directamente:
(defun ERRORES ( mens )
(setq *error* error0)
(if (= mens "quitar / saIir abandonar")
(princ)
(princ (strcat "\nError: " mens " "))
)
(command "_.undo" "_end")
(command "_.undo" "")
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(princ)
)
En este caso si se produce un error ni siquiera hace faIta ejecutar eI comando
deshacer, Ia funcin ERRORES ya Io hace por nosotros.
Para terminar eI tema, vamos a aadirIe una nueva opcin a CIRCPERI. Se trata de
que ofrezca por defecto eI permetro deI Itimo circuIo dibujado. Podramos hacer Io
siguiente:
(defun C:CIRCPERI ( / pto peri cmd0 )
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(setq pto (getpoint "\nCentro de Ia circunferencia: "))
(if (not rad)
(prompt "\nPermetro: ")
(progn
(prompt "\nPermetro <")
(prompt (rtos (* rad 2 pi) 2 2))
(prompt ">: ")
)
)
(if (setq peri (getdist))
(setq rad (/ peri (* 2 pi)))
)
(command "_.circIe" pto rad)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(princ)
)
(prompt "\nNuevo comando CIRCPERI cargado")
Ponemos Ia variabIe rad como gIobaI, as se puede recuperar eI vaIor que tena en Ia
anterior ejecucin de CIRCPERI. Veamos ahora cmo funciona eI siguiente trozo de
cdigo:
(if (not rad)
(prompt "\nPermetro: ")
(progn
(prompt "\nPermetro <")
(prompt (rtos (* rad 2 pi) 2 2))
(prompt ">: ")
)
)
Si rad es iguaI a niI, no se ha definido, significa que es Ia primera vez que se ejecuta
eI comando CIRCPERI en eI dibujo actuaI. En este caso se muestra un mensaje
soIicitando eI permetro deI crcuIo.
Si no es Ia primera vez que se ejecuta CIRCPERI, Ia variabIe rad tendr asociado un
vaIor, correspondiente aI radio deI circuIo creado en Ia Itima ejecucin de
CIRCPERI. Tambin muestra un mensaje soIicitando eI permetro, pero entre Ios
caracteres "<" y ">" se indica adems eI vaIor de Ia variabIe gIobaI rad.
(if (setq peri (getdist))
(setq rad (/ peri (* 2 pi)))
)
A continuacin se soIicita una distancia. No se ha indicado ningn mensaje en Ia
funcin getdist, ya que eI mensaje de soIicitud se muestra en Ias Ineas anteriores.
Si se indica un permetro, ya sea por medio de dos puntos o escribiendoIo
directamente, entonces se caIcuIa su radio. Si como respuesta a getdist se puIsa
Intro, a Ia variabIe peri se asigna eI vaIor niI, que es devueIto por setq. De modo que
en este caso no hace nada, por Io tanto Ia variabIe rad sigue aImacenando eI radio
deI Itimo crcuIo creado con CIRCPERI.
(command "_.circIe" pto rad)
Por Itimo dibuja eI crcuIo.
AutoCAD dispone de una variabIe de sistema IIamada CIRCLERAD en Ia que
aImacena eI vaIor deI Itimo circuIo dibujado. As que podemos utiIizar esta variabIe
de sistema para obtener eI radio deI Itimo crcuIo, en Iugar de utiIizar Ia variabIe rad
como gIobaI. EI cdigo sera eI siguiente:
(defun C:CIRCPERI ( / pto rad peri cmd0 )
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(setq pto (getpoint "\nCentro de Ia circunferencia: "))
(if (= (getvar "circIerad") 0.0)
(prompt "\nPermetro: ")
(progn
(prompt "\nPermetro <")
(prompt (rtos (* (getvar "circIerad")2 pi) 2 2))
(prompt ">: ")
)
)
(if (setq peri (getdist))
(setq rad (/ peri (* 2 pi)))
(setq rad (getvar "circIerad"))
)
(command "_.circIe" pto rad)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(princ)
)
(prompt "\nNuevo comando CIRCPERI cargado")
Ahora ofrecer por defecto eI permetro deI Itimo crcuIo dibujado en AutoCAD,
independientemente de si dicho crcuIo se creo con Ia rutina CIRCPERI, con eI
comando CIRCULO o por cuaIquier otro medio. Veamos como funcionan Ios
cambios que hemos reaIizado:
(if (= (getvar "circIerad") 0.0)
(prompt "\nPermetro: ")
(progn
(prompt "\nPermetro <")
(prompt (rtos (* (getvar "circIerad")2 pi) 2 2))
(prompt ">: ")
)
)
Si an no se ha creado ningn crcuIo en eI dibujo, Ia variabIe circIerad tendr
asociado eI vaIor 0.0. En este caso soIicita eI permetro sin ofrecer ningn vaIor por
defecto, y en caso contrario ofrece por defecto eI permetro deI Itimo crcuIo
creado.
(if (setq peri (getdist))
(setq rad (/ peri (* 2 pi)))
(setq rad (getvar "circIerad"))
)
Si se introduce un permetro, por medio de dos puntos o escribiendoIo, se caIcuIa eI
radio correspondiente. En caso de que se puIse Intro, se asocia a Ia variabIe rad eI
radio deI Itimo crcuIo dibujado.
Limitar Ias respuestas de Ios usuarios a Ias funciones de
soIicitud de datos (I)
En tema anterior vimos Ias funciones de tratamiento de errores, que nos permiten
cotroIar Io que sucede cuando se produce un error en nuestras rutinas. Hoy
intentaremos que no se produzcan aIguno de Ios posibIes errores en nuestras
rutinas.
Los errores pueden deberse a que eI cdigo no funciona bien por que se ha
empIeado maI aIguna funcin de AutoLISP o se haIIa ejecutado incorrectamente un
comando de AutoCAD, por ejempIo, pero estos no son Ios tipos de errores que
corregiremos en este tema. M s adeIante veremos un tema en eI que se expIicarn
mtodos de depuracin de nuestras rutinas, en ese tema corregiremos Ios errores
debidos a un cdigo fuente incorrecto.
En este tema trataremos otro tipo de errores, Ios que se producen cuando eI usuario
introduce datos erroneos. Por ejempIo, cuando se soIicita un nmero positivo y eI
usuario indica cero o un nmero negativo.
(INITGET [modo] [paIabras_cIave])
Esta funcin se utiIiza para modificar eI funcionamiento de otras funciones de
AutoLISP, en concreto aqueIIas funciones en Ias que se soIicitan datos aI usuario.
Por ejempIo: GETpoint, GETreaI, GETint, ... casi todas comienzan por GET as que se
sueIen denominar funciones de tipo GET...
Initget siempre devueIve niI. Y si se indica soIo, sin argumentos, no hace nada. Tan
soIo devueIve niI. As que vamos a ver para que sirven Ios argumentos de Initget:
"modo"
Es un nmero entero que nos permitir Iimitar Ios datos que se puedan introducir en
Ia siguiente soIicitud de datos aI usuario. Initget NUNCA funciona por si soIa,
siempre se utiIiza para modificar eI funcionamiento de otra funcin.
EI argumento modo es en reaIidad un cdigo binario, que puede tener Ios siguientes
vaIores:
1 --> No admite vaIores nuIos, es decir que se indique Intro como respuesta
2 --> No admite eI 0 como respuesta
4 --> No admite vaIores negativos como respuesta
8 --> Permite indicar un punto fuera de Ios Imites deI dibujo. An cuando
estos estn activados.
16 --> Este vaIor no se utiIiza actuaImente
32 --> Dibuja Ia Inea o rectnguIo eIsticos con Ineas discontnuas en Iugar
de contnuas
64 --> Hace que GETdist devueIva Ia distancia en 2D. Es como si proyectase
Ia distancia reaI sobre eI pIano XY.
128 --> Permite introducir como respuesta una expresin de AutoLISP.
Bien, veamos como se utiIiza initget... por ejempIo, si queremos que eI usuario
introduzca un nmero entero y que no pueda puIsar Intro como respuesta, haramos
Io siguiente:
(initget 1)
(setq numero (getint "\nNmero entero: "))
Initget modifica a Ia siguiente funcin de soIicitud de datos, es decir, getint.
Si adems queremos que no pueda indicar 0 como respuesta, entonces sumamos
sus respectivos cdigos, eI 1 para que no se pueda indicar Intro como respuesta y eI
2 para que no se pueda indicar 0.
(initget (+ 1 2))
(setq numero (getint "\nNmero entero: "))
Tambin podemos indicar directamente (initget 3) en Iugar de (initget (+ 1 2)). Si eI
usuario indica como respuesta 0 o Intro, AutoCAD Ie dir que ese dato no es vIido y
que introduzca un dato correcto.
Si queremos que adems se indique un nmero positivo, entoces deberiamos poner:
(initget 7)
(setq numero (getint "\nNmero entero: "))
Ya que 7 = 1 + 2 + 4
Veamos ahora como funciona eI cdigo 8 como argumento modo de Initget. 8 -->
Permite indicar un punto fuera de Ios Imites deI dibujo. An cuando estos estn
activados.
Supongamos que tenemos Ios Imites deI dibujo de AutoCAD activados (comando
LIMITES) en ese caso no podemos indicar puntos fuera de esos Imites. De modo
que si se soIicita un punto aI usuario con GETPOINT debera indicarIo dentro de Ios
Imites deI dibujo. Pero si antes de soIicitar eI punto se ejecuta (initget 8) entonces si
nos dejara.
EI cdigo 16 no se utiIiza.
EI cdigo 32 se utiIiza en funciones de soIicitud en Ias que se indica un punto base,
por ejempIo:
(getpoint pto "\nIndicar punto:")
(getcorner pto "\nIndicar punto:")
En estos casos aparece una Inea, o un rectnguIo, eIstico con origen en eI punto
base pto. Estas Ineas y rectnguIos eIsticos se muestran con Inea continua. Pero
si antes de Ia funcin de soIicitud se aade (initget 32) se mostraran con Ineas
discontnuas. Por ejempIo:
(setq pt1 (getpoint "\nPunto base: "))
(initget 32)
(setq pt2 (getpoint pt1 "\nSegundo punto: "))
En este ejempIo aparece una Inea discontinua. Y en eI siguiente un rectnguIo con
Ineas discontinuas.
(setq pt1 (getpoint "\nPunto base: "))
(initget 32)
(setq pt2 (getcorner pt1 "\nSegundo punto: "))
Veamos ahora como funciona eI cdigo 64 --> Hace que GETdist devueIva Ia
distancia en 2D. Es como si proyectase Ia distancia reaI sobre eI pIano XY.
Getdist soIicita una distancia, que se puede escribir directamente, o se pueden
indicar dos puntos en pantaIIa. En este caso, getdist devoIver Ia distancia reaI entre
esos dos puntos. Si Io que nos interesa obtener es Ia distancia de sus proyecciones
sobre eI pIano XY actuaI se aadir (initget 64) antes de Ia ejecutar getdist. Por
ejempIo:
(setq pt1 (getpoint "\nPunto base: "))
(initget 64)
(setq dist12 (getdist pt1 "\nSegundo punto: "))
Por Itimo, eI cdigo 128 permite indicar una expresin de AutoLISP como
respuesta. Por ejempIo, podemos utiIizar nuestra rutina RAG (Radianes A Grados
decimaIes) para indicar un nguIo en grados decimaIes cuando nosotros Io tenemos
en radianes.
(initget 128)
(setq ang (getreaI "\nIntroducir nguIo: "))
En este caso eI usuario podra indicar como respuesta a Ia soIicitud deI nguIo:
(RAG (/ pi 4)) Es decir, un nguIo de 45.
Pues IIegados a este punto, antes de ver eI segundo argumento de (INITGET [modo]
[paIabras_cIave]), es decir, Ias paIabras cIave. Vamos a modificar nuestras rutinas
ARAND y CIRCPERI. Comenzamos con CIRCPERI:
(defun C:CIRCPERI ( / pto rad peri cmd0 )
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(setq pto (getpoint "\nCentro de Ia circunferencia: "))
(if (= (getvar "circIerad") 0.0)
(prompt "\nPermetro: ")
(progn
(prompt "\nPermetro <")
(prompt (rtos (* (getvar "circIerad")2 pi) 2 2))
(prompt ">: ")
)
)
(if (setq peri (getdist))
(setq rad (/ peri (* 2 pi)))
(setq rad (getvar "circIerad"))
)
(command "_.circIe" pto rad)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(princ)
)
(prompt "\nNuevo comando CIRCPERI cargado")
Tenemos Ia siguiente Inea: (setq pto (getpoint "\nCentro de Ia circunferencia: ")) Ie
aadiramos aIguna Iimitacin como respuesta deI usuario? VeamosIo:
Si eI usuario puIsa Intro como respuesta a Ia variabIe pto se Ie asocia eI vaIor niI,
que es Io que devoIvera Getpoint. Despus aI intentar dibujar eI crcuIo (command
"_.circIe" pto rad) se producira un error. As que debemos impedir que eI usuario
introduzca Intro como respuesta, de modo que aadiramos (initget 1) antes de Ia
funcin getpoint. Como estamos soIicitando un punto, eI cdigo 2 no tiene sentido y
Io mismo sucede con eI 4.
EI cdigo 8 permite indicar un punto fuera de Ios Imites deI dibujo, an cuando
estos estn activados. Este cdigo si podramos utiIizarIo, aunque si eI usuario
trabaja con Ios Imites activados, estn activados y ya est. Si quiere que Ios
desactive I, no? Porque supongo que Ios tendr activados por aIgn motivo. As
que no Ie aadimos a initget eI cdigo 8.
EI cdigo 32 no tiene sentido aqui, pues no aparece Ia Inea base. Y eI cdigo 64
tampoco ya que estamos soIicitando un punto, no una distancia.
EI cdigo 128 permite introducir como respuesta una expresin de AutoLISP. Este
cdigo tambin se podra indicar, pero Io habituaI es no hacerIo. Se podra indicar
en casos en Ios que eI usuario pudiera utiIizar una expresin de AutoLISP para
caIcuIar eI dato. Como en eI ejempIo que vimos antes, si tiene un nguIo en radianes
y Io tiene que indicar en grados decimaIes. Aqui nos pide un punto, as que no tiene
demasiado sentido.
Definitivamente eI cdigo quedara:
...
(initget 1)
(setq pto (getpoint "\nCentro de Ia circunferencia: "))
...
Sigamos modificando Ia rutina CIRCPERI... Unas Ineas despus de Ia soIIicitud deI
centro de Ia circunferencia, se soIicita su permetro:
(if (setq peri (getdist))
(setq rad (/ peri (* 2 pi)))
(setq rad (getvar "circIerad"))
)
Aadimos eI cdigo 1 antes de Ia funcin getdist? Veamos como funciona esta parte
deI cdigo: Si eI usuario introduce una distancia, se evaIa Ia condicin si cumpIe
deI IF es decir:
(setq rad (/ peri (* 2 pi)))
Y si eI usuario puIsa Intro, se asigna a peri eI vaIor niI y evaIa Ia condicin no
cumpIe deI IF, es decir:
(setq rad (getvar "circIerad"))
Si ponemos (initget 1), eI usuario no podr indicar Intro, as que nunca se ejecutara
Ia expresin no cumpIe. Por tanto no aadimos eI cdigo 1 a Initget.
EI permetro deI ccuIo no puede ser ni cero ni un nmero negativo, de modo que
podemos aadir a initget Ios cdigos 2 y 4. Tambin podramos aadirIe eI cdigo 64
para que GETdist devueIva Ia distancia en 2D. Pero normaImente no conviene aadir
este cdigo, excepto cuando Ia distancia "debe" siempre ser en 2D.
Una Itima nota sobre CIRCPERI... Cuando ejecutamos Ia rutina por primera vez en
un dibujo en eI que no se haIIa dibujado ningn crcuIo, Ia variabIe de sistema
"circIerad" tiene eI vaIor 0.0. En este caso, no ofrecemos Ia opcin de seIeccionar eI
radio deI Itimo crcuIo dibujado puIsando Intro, ya que no existe ningn crcuIo
dibujado previamente. En este caso, no deberamos indicar eI modo 6 a Initget, sino
eI 7 para que tampoco permita aI usuario indicar Intro como respuesta. Veamos
como se soIuciona en eI cdigo compIeto de Ia rutina:
(defun C:CIRCPERI ( / pto rad peri cmd0 )
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(initget 1)
(setq pto (getpoint "\nCentro de Ia circunferencia: "))
(if (= (getvar "circIerad") 0.0)
(progn
(prompt "\nPermetro: ")
(initget 7)
)
(progn
(prompt "\nPermetro <")
(prompt (rtos (* (getvar "circIerad")2 pi) 2 2))
(prompt ">: ")
(initget 6)
)
)
(if (setq peri (getdist))
(setq rad (/ peri (* 2 pi)))
(setq rad (getvar "circIerad"))
)
(command "_.circIe" pto rad)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(princ)
)
(prompt "\nNuevo comando CIRCPERI cargado")
Vamos ahora a modificar Ia rutina ARAND:
(defun C:ARAND ( / pto rad cmd0 )
(command "_.undo" "_begin")
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
(setq rad (getreaI "\nRadio interior: "))
(command "_.circIe" pto rad)
(setq rad (getreaI "\nRadio exterior: "))
(command "_.circIe" pto rad)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(command "_undo" "_end")
(princ)
)
(prompt "\nNuevo comando ARAND cargado")
La primera soIicitud que tenemos en ARAND es Ia deI centro de Ia arandeIa.
Practicamente es iguaI que Ia soIicitud deI centro deI ccuIo en CIRCPERI, as que Ie
aadimos tambin eI cdigo 1 a Initget:
(initget 1)
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
A continuacin soIicita Ios radios interior y exterior de Ia arandeIa. En Ios que
podemos evitar que eI usuario indique como respuesta Intro, 0 o un nmero
negativo. De modo que aadiriamos Initeget con eI modo 7. Veamos eI cdigo
compIeto:
(defun C:ARAND ( / pto rad cmd0 )
(command "_.undo" "_begin")
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(initget 1)
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
(initget 7)
(setq rad (getreaI "\nRadio interior: "))
(command "_.circIe" pto rad)
(initget 7)
(setq rad (getreaI "\nRadio exterior: "))
(command "_.circIe" pto rad)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(command "_undo" "_end")
(princ)
)
(prompt "\nNuevo comando ARAND cargado")
Limitar Ias respuestas de Ios usuarios a Ias funciones de
soIicitud de datos (y II)
En eI Itimo tema comenzamos a ver Ia funcin INITGET y vimos como funcionaba eI
argumento [modo] ahora vamos con [paIabras_cIave]...
(initget [modo] [paIabras_cIave])
[paIabras_cIave] nos permite indicar una serie de textos (paIabras) que tambin
seran aceptados como respuesta en Ia siguiente funcin de soIicitud de datos. Por
ejempIo:
(initget 7 "Diametro Perimetro")
(setq rad (getdist "\nRadio deI circuIo / Diametro / Perimetro :"))
como respuesta a getdist podemos indicar una distancia, ya sea escribiendoIa o
mediante dos puntos, pero ahora tambin aceptara como respuesta Diametro y
Perimetro. EI modo 7 impide que se indique como respuesta Intro, cero o un nmero
negativo.
Si indicamos como respuesta una distancia, asocia esa distancia a Ia varibIe
rad.
Si indicamos como respuesta Diametro, asocia a Ia varibIe rad Ia cadena de
texto "Diametro".
Si indicamos como respuesta Perimetro, asocia a Ia varibIe rad Ia cadena de
texto "Perimetro".
En [paIabras_cIave] indicamos una serie de paIabras, separadas por espacios, que
serviran como respuesta a Ia siguiente funcin de soIicitud de datos. No hace faIta
escribir eI nombre compIeto de Ia paIabra, como hicimos antes, basta con que eI
usuario introduzca como respuesta Ias Ietras que aparecen en mayscuIas. Es decir,
Ia D o Ia P. En eI siguiente ejempIo...
(initget 7 "Diametro DEShacer")
(setq rad (getdist "\nRadio deI circuIo / Diametro / DEShacer: "))
Para seIeccionar Ia opcin Diametro habr que escribir aI menos Ia D. Pero para
seIeccionar DEShacer aI menos habr que escribir DES. Tambin aceptara dia para
eI dimetro y desha para deshacer. Fjate que aI menos deben indicarse Ias Ietras en
mayscuIas.
Supongamos que tenemos eI siguiente cdigo:
(initget 7 "Diametro Perimetro")
(setq rad (getdist "\nRadio deI circuIo: "))
En este caso getdist aceptara como respuestas a Ia peticin deI radio deI crcuIo
"Diametro" y "Perimetro". Pero aI no indicar estas opciones en eI mensaje de
getdist, eI usuario no sabra que existen. De modo que Io deseabIe es indicar aI
usuario Ias opciones que puede seIeccionar:
(initget 7 "Diametro Perimetro")
(setq rad (getdist "\nRadio deI circuIo / Diametro / Perimetro :"))
Como mejor se ve es con un ejempIo as que... Vamos a modificar Ia rutina ARAND
aadiendo una opcin para indicar Ios dimetros en Iugar deI radio. Tenamos eI
siguiente cdigo:
(defun C:ARAND ( / pto rad cmd0 )
(command "_.undo" "_begin")
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(initget 1)
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
(initget 7)
(setq rad (getreaI "\nRadio interior: "))
(command "_.circIe" pto rad)
(initget 7)
(setq rad (getreaI "\nRadio exterior: "))
(command "_.circIe" pto rad)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(command "_undo" "_end")
(princ)
)
(prompt "\nNuevo comando ARAND cargado")
Tenemos que modificar Ias siguientes Ineas:
(initget 7)
(setq rad (getreaI "\nRadio interior: "))
Primero aadimos "Diametro" a Ia Iista de paIabras cIave de initget:
(initget 7 "Diametro")
Y a continuacin Ie decimos aI usuario que existe una opcin IIamada Diametro que
puede seIeccionar como respuesta:
(setq rad (getreaI "\nRadio interior / Diametro: "))
De esta forma ya hemos aadido Ia opcin Diametro, pero Qu sucede si eI usuario
indica como respuesta Ia opcin Diametro? Pues que asignariamos a Ia variabIe rad
Ia cadena de texto "Diametro" y en Ia siguiente Inea (command "_.circIe" pto rad) aI
intentar dibujar eI crcuIo, nos dara un error.
As que hay que modificar Ia rutina aadiendo a continuacin aIgo parecido a: Si eI
usuario seIecciona Ia opcin Diametro --> Preguntamos por eI dimetro. Pues esto
en AutoLISP, sera:
(if (= rad "Diametro")
(setq rad (getreaI "\nDimetro interior: "))
)
Hay que tener especiaI cuidado con Ia condicin deI IF (= rad "Diametro") ya que hay
que indicar Ia paIabra cIave taI y como aparece en Ia Iista de paIabras cIave de
initget. Es decir, no funcionara si ponemos (= rad "diametro") o (= rad "Dimetro")
ya que en eI primer caso no ponemos Ia "D" en mayscuIas y en eI segundo hemos
tiIdado Ia "a".
Fijemonos en Io que hace eI cdigo anterior:
Si eI usuario indica una distancia Ia asigna a Ia variabIe rad y Iuego (if (= rad
"Diametro")... devueIve niI, puesto que rad es distinto de "Diametro".
Si eI usuario indica D o Diam, o diametro, entonces asigna a Ia variabIe rad Ia cadena
de texto "Diametro". Luego aI entrar en eI IF, (= rad "Diametro") devueIve T as que
evaIa Ia expresin si cumpIe (setq rad (getreaI "\nDimetro interior: ")) que pide un
dimetro y Io asignamos a Ia variabIe rad.
Pero rad viene de radio, porque en esta variabIe aImacenamos eI radio deI crcuIo y
no eI dimetro. As que aI dibujar eI crcuIo (command "_.circIe" pto rad) dibujara un
circuIo deI dobIe deI dimetro de Io que ha dicho eI usuario. EI cdigo debera ser:
(initget 7 "Diametro")
(setq rad (getreaI "\nRadio interior / Diametro: "))
(if (= rad "Diametro")
(setq rad (/ (getreaI "\nDimetro interior: ") 2.0))
)
Pero, Qu pasa si eI usuario hace Io siguiente?
1. Indica D como respuesta aI radio interior.
2. Indica -50 o 0 como dimetro.
Pues que asignara a Ia variabIe rad eI resuItado de dividir -50 o 0 entre 2.0. Por tanto
tendriamos un crcuIo con radio negativo o cero. Recuerda que initget soIo tiene
efecto sobre Ia siguiente funcin de soIicitud de datos, de modo que tenemos que
aadir de nuevo Ia funcin Initget antes de preguntar por eI dimetro:
(initget 7 "Diametro")
(setq rad (getreaI "\nRadio interior / Diametro: "))
(if (= rad "Diametro")
(progn
(initget 7)
(setq rad (/ (getreaI "\nDimetro interior: ") 2.0))
)
)
Se ha aadido Ia funcin Progn ya que sino, soIo puedo ejecutar una expresin.
Para eI radio o dimetro exterior se hara exactamente Io mismo. Por tanto eI cdigo
compIeto sera:
(defun C:ARAND ( / pto rad cmd0 )
(command "_.undo" "_begin")
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(initget 1)
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
(initget 7 "Diametro")
(setq rad (getreaI "\nRadio interior / Diametro: "))
(if (= rad "Diametro")
(progn
(initget 7)
(setq rad (/ (getreaI "\nDimetro interior: ") 2.0))
)
)
(command "_.circIe" pto rad)
(initget 7 "Diametro")
(setq rad (getreaI "\nRadio exterior / Diametro: "))
(if (= rad "Diametro")
(progn
(initget 7)
(setq rad (/ (getreaI "\nDimetro exterior: ") 2.0))
)
)
(command "_.circIe" pto rad)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(command "_undo" "_end")
(princ)
)
(prompt "\nNuevo comando ARAND cargado")
(GETKWORD [mensaje])
Esta funcin de AutoLISP se utiIiza para obtener una opcin indicada por eI usuario.
Se utiIiza en combinacin con INITGET, por ejempIo:
(initget "DEShacer Nuevo Repetir")
(setq opc (getkword "\nDEShacer / Nuevo / Repetir: ")
En este caso eI usuario tan soIo podr indicar como respuesta una de Ias paIabras
cIave de Ia funcin Initget y se Ia asigna a Ia variabIe opc.
No hemos indicado eI modo en Initget, taI soIo Ias paIabras cIave. En Ia rutina
ARAND nos interesaba que apareciera eI modo 7 para que no se indique como
respuesta Intro, 0 o un nmero negativo. Pero no es obIigatorio indicar siempre un
modo.
Un ejempIo bastante habituaI en Ias rutinas es eI siguiente:
(initget "DEShacer Nuevo Repetir")
(setq opc (getkword "\nDEShacer / Nuevo / Repetir: "))
(cond
((= opc "DEShacer")
(aIert "Has seIeccionado Ia opcin DEShacer")
)
((= opc "Nuevo")
(aIert "Has seIeccionado Ia opcin Nuevo")
)
(T
(aIert "Has seIeccionado Ia opcin Repetir")
)
)
As en funcin de Io que indique eI usuario se hace una cosa u otra.
Estructuras repetitivas
Hasta hace poco tan soIo podiamos crear programas cuya ejecucin fuera IineaI:
1. Haz esto
2. Ahora esto otro
3. ...
Luego vimos Ias estructuras condicionaIes IF y COND que ya nos permiten jugar un
poco ms y hacer que nuestros programas no sean tan IineaIes. Ahora vamos a ver
funciones que nos permitiran crear repeticiones de cdigo y aIgo que taI vez te
suene, Ios bucIes, que se utiIizan mucho en programacin.
(WHILE condicin [expr1] [expr2] ...)
La funcin whiIe ejecuta Ias expresiones indicadas MIENTRAS se cumpIa Ia
condicin, y devueIve eI vaIor de Ia Itima expresin evaIuada. Por ejempIo:
(setq i 0)
(whiIe (< i 10)
(prompt "\n")
(prompt (itoa i))
(setq i (1+ i)
)
Mientras i sea menor que 10, ejecuta Ias expresiones. Es decir, escribira en Ia
ventana de comandos de AutoCAD Ios nmeros deI 0 aI 9. Cuando (setq i (1+ i)
asigna a Ia variabIe i eI vaIor 10, Ia condicin deI bucIe no se verifica, de modo que
termina eI bucIe. La funcin WhiIe devoIver eI vaIor de Ia Itima expresin
evaIuada, es decir 10.
Este es un tpico ejempIo de bucIe, una estructura repetitiva con un ndice o
contador, en este caso i, que puede ir aumentando o disminuyendo.
Fjate que una de Ias expresiones que se ejecutan dentro deI bucIe es (setq i (1+ i) es
decir, movemos eI contador. Si no Io hicieramos, i siempre sera menor que 10 y se
entrara en un bucIe sin fin, que da Iugar a un error.
Veamos eI siguiente ejempIo:
(setq i 10)
(whiIe (< i 10)
(prompt "\n")
(prompt (itoa i))
(setq i (1+ i)
)
En este caso i tiene asignado eI vaIor 10 antes de entrar en eI bucIe, de modo que Ia
condicin (< i 10) no se cumpIira y por tanto no se ejecutarian Ias expresiones
siguientes. WhiIe devueIve eI vaIor de Ia Itima expresin evaIuada, que en este caso
es Ia condicin as que devueIve niI.
Las expresiones en WhiIe son opcionaIes, de modo que podemos crear un bucIe en
eI que soIo se indique Ia condicin:
(whiIe (not (setq pt (getpoint "\nPunto iniciaI: "))))
En este caso Ia condicin es (not (setq pt (getpoint "\nPunto iniciaI: "))) es decir,
pide un punto aI usuario y Io aImacena en Ia variabIe pt.
Si eI usuario indica un punto, pt = (X Y Z) que es distinto de niI, de modo que
(not (setq pt (getpoint "\nPunto iniciaI: "))) devoIver niI y saIdr de Ia funcin
WhiIe.
Si eI usuario indica Intro, getpoint devoIver niI y Io aImacenar en Ia variabIe
pt, de modo que (not (setq pt (getpoint "\nPunto iniciaI: "))) devoIvera T, y
preguntara de nuevo por un punto.
Por Io tanto, mientras no se indica un punto, sigue preguntando.
Otro ejempIo tpico de bucIes es en eI que se utiIizan aIgunas variabIes como fIags
(banderas o banderiIIas) para indicar si aIgo est activado o desactivado o para
controIar distintos vaIores. Veamos un ejempIo, supongamos que a y b son dos
variabIes que aImacenan dos nmeros reaIes:
(if (< a b)
(setq fIag1 niI)
(setq fIag1 T)
)
(whiIe fIag1
(prompt "\na NO es menor que b")
(setq b (getreaI "\nIntroduzca un nmero: "))
(if (< a b)
(setq fIag1 niI)
)
)
En este caso:
Si a es menor que b --> fIag1 = niI
Si a NO es menor que b --> fIag1 = T
Luego Ia funcin WhiIe evaIa Ia condicin faIg1 que devoIvera su vaIor niI o T.
Si es fIag1 = niI (a es menor que b) no evaIa Ias expresiones pues no se
verifica Ia condicin.
Si es fIag1 = T (a NO es menor que b) se verifica Ia condicin as que se
ejecutan Ias expresiones. Primero nos dice que a no es menor que b, nos
vueIve a pedir eI vaIor de b y comprueba si a es menor que eI nuevo vaIor de
b en cuyo caso asigna a Ia banderiIIa fIag1 eI vaIor niI para saIir deI bucIe.
Es decir, mientas a NO sea menor que b, nos pedir un nuevo vaIor de b.
En Ia funcin WhiIe, aI iguaI que vimos con IF y COND, como condicin podemos
utiIizar expresiones Igicas. Por ejempIo:
(whiIe (or (< a b) (< b 0.0))
(prompt "\na NO es menor que b, o b es negativo")
(setq b (getreaI "\nIntroduzca un nmero positivo: "))
)
En este ejempIo, eI bucIe se ejecutar hasta que se indique un vaIor para b positivo
y mayor que a.
(REPEAT cantidad [expr1] [expr2])
La funcin repeat ejecuta Ias expresiones indicadas eI nmero de veces que se
indique en cantidad. DevueIve eI resuItado de Ia Itima expresin evaIuada.
(repeat 10 (propmt "Este curso es demasiado fciI para mi"))
Tambin podramos asignar Ia cantidad a repetir a una variabIe:
(setq Bart_Simpson (getint "\nNmero de repeticiones para Bart: "))
(repeat Bart_Simpson (prompt "\nNo voIver a hacer pompas con cido suIfrico en
cIase"))
En este caso escribira en Ia pizarra, es decir Ia ventana de comandos de AutoCAD,
esa frase tantas veces como Ie indiquemos.
Tambin podemos obtener Ia cantidad por medio de una funcin de AutoLISP, como
resuItado de una operacin:
(repeat (+ 4 5) (propmt "Este curso me parece poco serio"))
o suponiendo que Ias variabIes a y b tengan asignados dos nmeros enteros:
(propmt "Inspector Gadget, este mensaje se autodestruir en...")
(setq i 0)
(repeat (+ a b)
(propmt "\t")
(propmt (itoa i))
(setq i (1+ i))
)
Pero qu sucede si a o b son un nmero reaI y no un entero? repetir Ias
expresiones 2.5 veces? Pues no, nos dar un error. Por eso hay que estar bien
seguro de que se Ia cantidad indicada es un nmero entero y no un reaI. IncIuso si
como cantidad indicamos un nmero entero sin decimaIes, como 2.0, nos dara un
error.
Vamos a modifuicar Ia rutina ARAND para hacer que eI segundo radio sea mayor
que eI primero. EI cdigo correspondiente aI crcuIo exterior era eI siguiente:
(initget 7 "Diametro")
(setq rad (getreaI "\nRadio exterior / Diametro: "))
(if (= rad "Diametro")
(progn
(initget 7)
(setq rad (/ (getreaI "\nDimetro exterior: ") 2.0))
)
)
(command "_.circIe" pto rad)
Lo primero que vamos a cambiar es eI nombre de Ias variabIes. En Iugar de utiIizar Ia
variabIe rad tanto para eI radio interior como para eI exterio, vamos a utiIizar Ia
variabIe radi para eI radio interior y Ia variabIe rade para eI exterior. As podremos
comparar si rade es mayor que radi.
Podriamos sustituir eI cdigo anterior por eI siguiente:
(whiIe (or (not rade) (not (< radi rade)))
(initget 7 "Diametro")
(setq rad (getreaI "\nRadio exterior / Diametro: "))
(if (= rad "Diametro")
(progn
(initget 7)
(setq rad (/ (getreaI "\nDimetro exterior: ") 2.0))
)
)
)
(command "_.circIe" pto rade)
La primera vez que se evaIa Ia condicin deI bucIe, no se ha asignado an ningn
vaIor aI radio exterior. De modo que rade = niI y (not rade) devoIver T. (or (not rade)
(not (< radi rade))) comprueba que aI menos se verifique una de Ias dos condiciones.
AI verificarse Ia primera condicin (not rade) Ia segunda ni siquiera se evaIa (por
suerte puesto que aI no estar definida rade nos dara un error). La condicin se
verifica y ejecuta Ias expresiones que estn a continuacin, que nos piden un vaIor
para eI radio exterior.
Es decir, mientras no se indique eI radio exterior o este sea menor que eI radio
interior se ejecuta eI bucIe, que nos pide un nuevo vaIor para eI radio exterior. AI
saIir deI bucIe ya tenemos un radio exterior vIido as que dibujamos eI crcuIo
exterior. EI cdigo compIeto sera:
(defun C:ARAND ( / pto radi rade cmd0 )
(command "_.undo" "_begin")
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(initget 1)
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
(initget 7 "Diametro")
(setq radi (getreaI "\nRadio interior / Dimetro: "))
(if (= radi "Diametro")
(progn
(initget 7)
(setq radi (/ (getreaI "\nDimetro interior: ") 2.0))
)
)
(command "_.circIe" pto radi)
(whiIe (or (not rade) (not (< radi rade)))
(initget 7 "Diametro")
(setq rade (getreaI "\nRadio exterior / Dimetro: "))
(if (= rade "Diametro")
(progn
(initget 7)
(setq rade (/ (getreaI "\nDimetro exterior: ") 2.0))
)
)
)
(command "_.circIe" pto rade)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(command "_.undo" "_end")
(princ)
)
(prompt "\nNuevo comando ARAND cargado")
Estructuras repetitivas
Hasta hace poco tan soIo podiamos crear programas cuya ejecucin fuera IineaI:
1. Haz esto
2. Ahora esto otro
3. ...
Luego vimos Ias estructuras condicionaIes IF y COND que ya nos permiten jugar un
poco ms y hacer que nuestros programas no sean tan IineaIes. Ahora vamos a ver
funciones que nos permitiran crear repeticiones de cdigo y aIgo que taI vez te
suene, Ios bucIes, que se utiIizan mucho en programacin.
(WHILE condicin [expr1] [expr2] ...)
La funcin whiIe ejecuta Ias expresiones indicadas MIENTRAS se cumpIa Ia
condicin, y devueIve eI vaIor de Ia Itima expresin evaIuada. Por ejempIo:
(setq i 0)
(whiIe (< i 10)
(prompt "\n")
(prompt (itoa i))
(setq i (1+ i)
)
Mientras i sea menor que 10, ejecuta Ias expresiones. Es decir, escribira en Ia
ventana de comandos de AutoCAD Ios nmeros deI 0 aI 9. Cuando (setq i (1+ i)
asigna a Ia variabIe i eI vaIor 10, Ia condicin deI bucIe no se verifica, de modo que
termina eI bucIe. La funcin WhiIe devoIver eI vaIor de Ia Itima expresin
evaIuada, es decir 10.
Este es un tpico ejempIo de bucIe, una estructura repetitiva con un ndice o
contador, en este caso i, que puede ir aumentando o disminuyendo.
Fjate que una de Ias expresiones que se ejecutan dentro deI bucIe es (setq i (1+ i) es
decir, movemos eI contador. Si no Io hicieramos, i siempre sera menor que 10 y se
entrara en un bucIe sin fin, que da Iugar a un error.
Veamos eI siguiente ejempIo:
(setq i 10)
(whiIe (< i 10)
(prompt "\n")
(prompt (itoa i))
(setq i (1+ i)
)
En este caso i tiene asignado eI vaIor 10 antes de entrar en eI bucIe, de modo que Ia
condicin (< i 10) no se cumpIira y por tanto no se ejecutarian Ias expresiones
siguientes. WhiIe devueIve eI vaIor de Ia Itima expresin evaIuada, que en este caso
es Ia condicin as que devueIve niI.
Las expresiones en WhiIe son opcionaIes, de modo que podemos crear un bucIe en
eI que soIo se indique Ia condicin:
(whiIe (not (setq pt (getpoint "\nPunto iniciaI: "))))
En este caso Ia condicin es (not (setq pt (getpoint "\nPunto iniciaI: "))) es decir,
pide un punto aI usuario y Io aImacena en Ia variabIe pt.
Si eI usuario indica un punto, pt = (X Y Z) que es distinto de niI, de modo que
(not (setq pt (getpoint "\nPunto iniciaI: "))) devoIver niI y saIdr de Ia funcin
WhiIe.
Si eI usuario indica Intro, getpoint devoIver niI y Io aImacenar en Ia variabIe
pt, de modo que (not (setq pt (getpoint "\nPunto iniciaI: "))) devoIvera T, y
preguntara de nuevo por un punto.
Por Io tanto, mientras no se indica un punto, sigue preguntando.
Otro ejempIo tpico de bucIes es en eI que se utiIizan aIgunas variabIes como fIags
(banderas o banderiIIas) para indicar si aIgo est activado o desactivado o para
controIar distintos vaIores. Veamos un ejempIo, supongamos que a y b son dos
variabIes que aImacenan dos nmeros reaIes:
(if (< a b)
(setq fIag1 niI)
(setq fIag1 T)
)
(whiIe fIag1
(prompt "\na NO es menor que b")
(setq b (getreaI "\nIntroduzca un nmero: "))
(if (< a b)
(setq fIag1 niI)
)
)
En este caso:
Si a es menor que b --> fIag1 = niI
Si a NO es menor que b --> fIag1 = T
Luego Ia funcin WhiIe evaIa Ia condicin faIg1 que devoIvera su vaIor niI o T.
Si es fIag1 = niI (a es menor que b) no evaIa Ias expresiones pues no se
verifica Ia condicin.
Si es fIag1 = T (a NO es menor que b) se verifica Ia condicin as que se
ejecutan Ias expresiones. Primero nos dice que a no es menor que b, nos
vueIve a pedir eI vaIor de b y comprueba si a es menor que eI nuevo vaIor de
b en cuyo caso asigna a Ia banderiIIa fIag1 eI vaIor niI para saIir deI bucIe.
Es decir, mientas a NO sea menor que b, nos pedir un nuevo vaIor de b.
En Ia funcin WhiIe, aI iguaI que vimos con IF y COND, como condicin podemos
utiIizar expresiones Igicas. Por ejempIo:
(whiIe (or (< a b) (< b 0.0))
(prompt "\na NO es menor que b, o b es negativo")
(setq b (getreaI "\nIntroduzca un nmero positivo: "))
)
En este ejempIo, eI bucIe se ejecutar hasta que se indique un vaIor para b positivo
y mayor que a.
(REPEAT cantidad [expr1] [expr2])
La funcin repeat ejecuta Ias expresiones indicadas eI nmero de veces que se
indique en cantidad. DevueIve eI resuItado de Ia Itima expresin evaIuada.
(repeat 10 (propmt "Este curso es demasiado fciI para mi"))
Tambin podramos asignar Ia cantidad a repetir a una variabIe:
(setq Bart_Simpson (getint "\nNmero de repeticiones para Bart: "))
(repeat Bart_Simpson (prompt "\nNo voIver a hacer pompas con cido suIfrico en
cIase"))
En este caso escribira en Ia pizarra, es decir Ia ventana de comandos de AutoCAD,
esa frase tantas veces como Ie indiquemos.
Tambin podemos obtener Ia cantidad por medio de una funcin de AutoLISP, como
resuItado de una operacin:
(repeat (+ 4 5) (propmt "Este curso me parece poco serio"))
o suponiendo que Ias variabIes a y b tengan asignados dos nmeros enteros:
(propmt "Inspector Gadget, este mensaje se autodestruir en...")
(setq i 0)
(repeat (+ a b)
(propmt "\t")
(propmt (itoa i))
(setq i (1+ i))
)
Pero qu sucede si a o b son un nmero reaI y no un entero? repetir Ias
expresiones 2.5 veces? Pues no, nos dar un error. Por eso hay que estar bien
seguro de que se Ia cantidad indicada es un nmero entero y no un reaI. IncIuso si
como cantidad indicamos un nmero entero sin decimaIes, como 2.0, nos dara un
error.
Vamos a modifuicar Ia rutina ARAND para hacer que eI segundo radio sea mayor
que eI primero. EI cdigo correspondiente aI crcuIo exterior era eI siguiente:
(initget 7 "Diametro")
(setq rad (getreaI "\nRadio exterior / Diametro: "))
(if (= rad "Diametro")
(progn
(initget 7)
(setq rad (/ (getreaI "\nDimetro exterior: ") 2.0))
)
)
(command "_.circIe" pto rad)
Lo primero que vamos a cambiar es eI nombre de Ias variabIes. En Iugar de utiIizar Ia
variabIe rad tanto para eI radio interior como para eI exterio, vamos a utiIizar Ia
variabIe radi para eI radio interior y Ia variabIe rade para eI exterior. As podremos
comparar si rade es mayor que radi.
Podriamos sustituir eI cdigo anterior por eI siguiente:
(whiIe (or (not rade) (not (< radi rade)))
(initget 7 "Diametro")
(setq rad (getreaI "\nRadio exterior / Diametro: "))
(if (= rad "Diametro")
(progn
(initget 7)
(setq rad (/ (getreaI "\nDimetro exterior: ") 2.0))
)
)
)
(command "_.circIe" pto rade)
La primera vez que se evaIa Ia condicin deI bucIe, no se ha asignado an ningn
vaIor aI radio exterior. De modo que rade = niI y (not rade) devoIver T. (or (not rade)
(not (< radi rade))) comprueba que aI menos se verifique una de Ias dos condiciones.
AI verificarse Ia primera condicin (not rade) Ia segunda ni siquiera se evaIa (por
suerte puesto que aI no estar definida rade nos dara un error). La condicin se
verifica y ejecuta Ias expresiones que estn a continuacin, que nos piden un vaIor
para eI radio exterior.
Es decir, mientras no se indique eI radio exterior o este sea menor que eI radio
interior se ejecuta eI bucIe, que nos pide un nuevo vaIor para eI radio exterior. AI
saIir deI bucIe ya tenemos un radio exterior vIido as que dibujamos eI crcuIo
exterior. EI cdigo compIeto sera:
(defun C:ARAND ( / pto radi rade cmd0 )
(command "_.undo" "_begin")
(if (= (setq cmd0 (getvar "cmdecho")) 1)
(setvar "cmdecho" 0)
)
(initget 1)
(setq pto (getpoint "\nCentro de Ia arandeIa: "))
(initget 7 "Diametro")
(setq radi (getreaI "\nRadio interior / Dimetro: "))
(if (= radi "Diametro")
(progn
(initget 7)
(setq radi (/ (getreaI "\nDimetro interior: ") 2.0))
)
)
(command "_.circIe" pto radi)
(whiIe (or (not rade) (not (< radi rade)))
(initget 7 "Diametro")
(setq rade (getreaI "\nRadio exterior / Dimetro: "))
(if (= rade "Diametro")
(progn
(initget 7)
(setq rade (/ (getreaI "\nDimetro exterior: ") 2.0))
)
)
)
(command "_.circIe" pto rade)
(if (= cmd0 1)
(setvar "cmdecho" 1)
)
(command "_.undo" "_end")
(princ)
)
(prompt "\nNuevo comando ARAND cargado")
Trabajar con nguIos y distancias
AutoLISP nos proporciona una serie de funciones para trabajar con nguIos y
distancias, comenzaremos viendo Ios anguIos:
(ANGLE pt1 pt2)
Esta funcin devueIve eI nguIo formado por Ia Inea que va desde pt1 hasta pt2. EI
origen de anguIos ser eI eje X y eI sentido antihorario se considera positivo. Por
ejempIo:
(setq pt1 (getpoint "\nPunto1: "))
(setq pt2 (getpoint pt1 "\nPunto2: "))
(setq ang (angIe pt1 pt2))
Hay que fijarse en cuaI es eI punto que se indica primero en Ia funcin angIe, porque
si hacemos:
(setq ang2 (angIe pt2 pt1))
Obtendremos un nguIo distinto, eI anterior ms pi o menos pi. Por Io tanto: No es Io
mismo eI nguIo de pt1 a pt2 que eI nguIo de pt2 a pt1.
Si Ios puntos estn en 3D, Ios proyecta sobre eI pIano XY y devueIve eI nguIo
formado por sus proyecciones
(DISTANCE pt1 pt2)
DevueIve Ia distancia en 3D entre Ios puntos pt1 y pt2. Si uno de Ios puntos est en
2D, es decir no tiene coordenada Z, se ignora Ia coordenada Z deI otro punto
devoIviendo Ia distancia en 2D.
(setq pt1 (getpoint "\nPunto1: "))
(setq pt2 (getpoint pt1 "\nPunto2: "))
(setq dist12 (distance pt1 pt2))
En este caso, (setq dist21 (distance pt2 pt1)) sera iguaI a dist12. Ya que Ia distancia
deI punto pt1 aI pt2 es iguaI que Ia distancia deI punto pt2 aI pt1.
(POLAR ptobase ang dist)
Esta funcin se utiIiza para obtener un punto por medio de coordenadas poIares a
partir de un punto base. Por ejempIo:
(setq pt1 (getpoint "\nPunto1: "))
(setq pt2 (poIar pt1 0.0 50.0))
Esto asignara a Ia variabIe pt2 un punto que est a 50 unidades en Ia direccin deI
eje X a partir deI punto base pt1. Si hicieramos:
(command "_.Iine" pt1 pt2 "")
Dibujaramos una Inea horizontaI de 50 unidades, desde pt1 hasta pt2.
Hay que observar que en (poIar pt1 0.0 50.0) se indica primero eI punto base, Iuego
un nguIo en radianes y por Itimo una distancia. De modo que:
(setq pt2 (poIar pt1 (/ pi 2.0) 50.0))
DevoIver un punto que est a 50 unidades en Ia direccin deI eje Y a partir deI
punto base pt1. Ya que en este caso se ha indicado un nguIo de (/ pi 2.0) es deirc,
90.
Funciones avanzadas para trabajar con Iistas
Ya hemos visto aIgunas funciones para manejar Iistas: CAR, CDR, LIST... pero hay
muchas ms. En este tema veremos aIgunas de Ias que nos faItan.
(LAST Iista)
Esta funcin devueIve eI Itimo eIemento de Ia Iista que recibe como argumento. De
modo que si hacemos:
(setq pto (getpoint "\nPunto de insercin: "))
(setq z (Iast pto))
En Ia variabIe z aImacenamos Ia coordenada Z deI punto pto, siempre que eI punto
est en 3D porque si est en 2D aImacenara Ia coordenada Y. Los puntos son Iistas
deI tipo (10.0 20.0 0.0). EI ejempIo anterior no sera muy tiI para obtener Ia
coordenada Y, ya que si indicamos un punto en 3D devoIver Ia coordenada Z.
Entonces, cmo podemos obtener Ia coordenada Y? ya vimos un mtodo:
(CADR pto)
Pero supongamos que tenemos una Iista de 27 eIementos, y queremos obtener eI
eIemento 22. Cmo Io haramos? No podemos utiIizar (cADDD.....DDDr pto) ya que
soIo nos permite agrupar 4 funciones cAr y cDr. De modo que tendriamos que hacer
(cADDD (cDDDD (cDDDDr ..... pto). Pero hacerIo as bastante engorroso.
(NTH numero Iista)
DevueIve eI eIemento cuyo nmero de orden se indica de Ia Iista.
(nth 2 pto) devoIver Ia coordenada Y, no? Pues no!. Los eIementos de una Iista se
empiezan a numerar desde cero. Por ejempIo:
(nth 0 pto) devoIver Ia coordenada X deI punto pto.
(nth 1 pto) devoIver Ia coordenada Y deI punto pto.
(nth 2 pto) devoIver Ia coordenada Z deI punto pto, si existe y si no existe devoIver
niI.
Supongamos que tenemos una Iista como Ia siguiente:
(setq Ist (Iist "peras" "meIones" "sandias" "perros" "pIatanos"))
para comprobar si "perros" pertenece a Ia Iista Ist se utiIiza Ia funcin MEMBER.
(MEMBER eIemento Iista)
Con esta funcin, si eI eIemento indicado pertenece a Ia Iista devoIver Ia Iista a
partir de ese eIemento. Por ejempIo:
(member "perros" Ist) devoIver ("perros" "pIatanos")
Si eI eIemento no pertenece a Ia Iista, devoIver niI.
(member "gatos" Ist) devueIve niI
(SUBST eIem_nuevo eIem_antiguo Iista)
Esta funcin reempIaza un eIemento de una Iista por su nuevo vaIor. Por ejempIo,
para reempIazar "perros" por "naranjas":
(subst "naranjas" "perros" Ist) devueIve Ia Iista con eI eIemento que se ha
modificado ("peras" "meIones" "sandias" "naranjas" "pIatanos"). Pero Ia variabIe Ist
sigue aImacenando Ia Iista anterior ("peras" "meIones" "sandias" "perros"
"pIatanos"). Para modificar Ia Iista aImacenada en Ia variabIe Ist tenemos que
asignarIe eI vaIor devueIto por SUBST:
(setq Ist (subst "naranjas" "perros" Ist))
Supongamos que queremos aadir un nuevo eIemento "Iimones" a Ia siguiente Iista:
(setq Ist (Iist "peras" "naranjas" "manzanas"))
Podriamos hacerIo con Iist, pero sera un Iio:
(setq Ist (Iist (car Ist) (cadr Ist) (caddr Ist) "Iimones"))
Para una Iista de 3 eIementos se puede hacer, pero... Y si tenemos 30 eIementos?
(CONS eIemento Iista)
Esta funcin aade un eIemento a Ia Iista indicada. EI nuevo eIemento se sita en eI
primer Iugar. Es decir:
(cons "Iimones" Ist) devoIver ("Iimones" "peras" "naranjas" "manzanas")
Y aI iguaI que suceda con SUBST, si soIo hacemos (CONS "Iimones" Ist) no
estamos asignando Ia Iista resuItante a Ia variabIe Ist. Deberiamos hacerIo as:
(setq Ist (cons "Iimones" Ist))
Pero... y si Io que queremos es aadir un eIemento aI finaI de Ia Iista? Antes de ver
como sera, veamos otra funcin:
(REVERSE Iista)
DevueIve Ia Iista que recibe como argumento pero en orden inverso.
(reverse Ist) devoIver ("manzanas" "naranjas" "peras" "Iimones")
Bien, pues para aadir un eIemento aI finaI de una Iista...
(setq Ist (reverse (cons "pIatanos" (reverse Ist))))
Veamos como funciona Ia Inea de cdigo anterior: (reverse Ist) devueIve Ia Iista en
orden inverso, (cons "pIatanos" (reverse Ist)) aade "pIatanos" como primer
eIemento de Ia Iista invertida, y por Itimo voIvemos a invertir eI orden de Ia Iista:
(setq Ist (reverse (cons "pIatanos" (reverse Ist))))
(ACAD_STRLSORT Iista)
Esta funcin devueIve una Iista con sus eIementos, que deberan ser cadenas de
texto, ordenados aIfabticamente. Por ejempIo:
((acad_strIsort Ist) devoIver ("Iimones" "manzanas" "naranjas" "peras" "pIatanos")
Si tenemos dos Iistas:
(setq Ist1 (Iist "peras" "naranjas" "manzanas"))
(setq Ist2 (Iist "fresas" "Iimones"))
y que queremos unirIas...
(APPEND Iista1 [Iista2] ...)
Esta funcin une dos o ms Iistas y devueIve Ia Iista resuItante.
(append Ist1 Ist2) devoIver ("peras" "naranjas" "manzanas" "fresas" "Iimones")
Los pares punteados
Los pares punteados son simpIemente Iistas de dos eIementos separadas por un
punto. Por ejempIo: (0 . 27)
Qu diferencia a un par punteado de una Iista normaI? VeamosIo:
1. Aunque eI punto nos pueda engaar, tienen soIo dos eIementos. En este
caso 0 y 27.
2. Podemos obtener eI primer eIemento, como en cuaIquier Iista, mediante (car
par_punteado). Pero, si intentamos obtener eI segundo eIemento mediante
(cadr par_punteado) nos indicar "error: tipo de argumento errneo:" Para
obtener eI segundo eIemento utiIizaremos CDR en Iugar de CADR (cdr
par_punteado). Ojo! (cdr par_punteado) devoIver 27 y no (27).
Para qu se usan Ios pares punteados? Pues principaImente para crear Iistas de
asociaciones. Y qu es una Iista de asociaciones? Pues una Iista cuyos eIementos
son pares punteados. Por ejempIo: (("perro" . 0) ("gato" . 1) ("ratn" . 5))
AI primer eIemento de Ios pares punteados Ie denominaremos cdigo, y aI segundo
eIemento vaIor. En eI ejempIo anterior "perro", "gato" y "ratn" son Ios cdigos y 0,
1 y 5 sus respectivos vaIores.
En una Iista de asociaciones, generaImente no existen cdigos dupIicados. Un
ejempIo de Iista de asociacin con un cdigo dupIicado sera:
(("perro" . 0) ("gato" . 1) ("ratn" . 5) ("gato" . 7))
Siendo "gato" eI cdigo que est dupIicado.
Cmo se crear Ios pares punteados? Con Ia funcin que ya hemos visto, CONS.
Antes se expIico (CONS eIemento Iista) que nos permite aadir un eIemento nuevo
como primer eIemento de Ia Iista indicada. Si en Iugar de una Iista se indica otro
eIemento creamos un par punteado.
(CONS cdigo vaIor)
(setq par_punteado (cons 7 "sandias")) asignar a par_punteado (7 . "sandias")
Para crear una Iista de asociaciones, por ejempIo:
(setq Ist (Iist (cons "perro" 0) (cons "gato" 1) (cons "ratn" 5)))
Por Itimo veamos una funcin que utiIizaremos mucho, sobre todo aI trabajar con
Ias entidades de AutoCAD...
(ASSOC cdigo Iista_de asociaciones)
ASSOC nos servir para obtener eI par punteado, cuyo cdigo se indique, de Ia Iista
de asociaciones que recibe como argumento. Por ejempIo:
(assoc "gato" Ist) devoIver ("gato" . 1)
Si Io que queremos obtener es eI vaIor asociado a ese cdigo, es decir de ("gato" . 1)
queremos obtener eI 1. Entonces, podemos hacer Io siguiente:
(cdr (assoc "gato" Ist))
Pero, Por qu son tan importantes Ias Iistas de asociaciones y Ios pares
punteados? Por Io siguiente:
((-1 . <Nombre de entidad: 19e0958>) (0 . "LINE") (330 . <Nombre de entidad:
19e08f8>) (5 . "2B") (100 . "AcDbEntity") (67 . 0) (410 . "ModeI") (8 . "0") (100 .
"AcDbLine") (10 0.0 0.0 0.0) (11 100.0 100.0 0.0) (210 0.0 0.0 1.0))
Esta Iista de asociaciones, compuesta por pares punteados, es Ia Iista de
asociaciones de una entidad Iinea que se aImacena en Ia base de datos de AutoCAD.
En dicha Iista de asociaciones, eI cdigo 0 nos indica eI tipo de entidad. De modo
que:
(assoc 0 Iista_de_entidad) devoIver (0 . "LINE")
(cdr (assoc 0 Iista_de_entidad)) devoIver "LINE"
EI cdigo 8 nos indica Ia capa en Ia que est Ia entidad, en este caso en Ia capa 0. EI
cdigo 10 indica eI punto iniciaI de Ia Inea y eI 11 eI punto finaI. Por eso son tan
importantes Ias Iistas de asociaciones y Ios pares punteados.
ApIicar funciones a Ios eIementos de Ias Iistas
Supongamos que tenemos una Iista de puntos:
(setq Istptos (Iist (Iist 0.0 0.0) (Iist 10.0 0.0) (Iist 10.0 10.0) (Iist 0.0 10.0)))
Es decir, Istptos es una Iista con cuatro eIementos correspondientes a Ios vrtices
de un cuadrado de Iado 10. Supongamos que queremos dibujar un crcuIo en cada
uno de Ios puntos de Istptos. Hasta ahora podiamos hacerIo as:
(setq i 0 nent (Iength Istptos))
(whiIe (< i nent)
(setq pt (nth i Istptos))
(command "_.circIe" pt 1.0)
(setq i (1+ i))
)
La variabIe i nos servir como ndice o contador en eI bucIe WhiIe, por eso Ie
asignamos iniciaImente eI vaIor 0, porque Ios eIementos de una Iista se numeran
empezando desde cero. Es bastante habituaI que Ios nombres de Ias variabIes
utiIizadas como contadores sean i j k ... Tambin asignamos a nent eI nmero de
eIementos de Ia Iista Istptos, porque sino no sabremos como saIir deI bucIe ni hasta
que eIemento IIegar.
EI bucIe se ejecutar mientras eI contador sea menor que nent es decir, se ejecutar
para cada eIemento de Istptos. (setq pt (nth i Istptos)) se obtiene eI eIemento nmero
i de Istptos, que es un punto, y se dibuja un crcuIo de radio 1.0 en I. FinaImente
aumentamos eI contador para que pase aI siguiente punto (setq i (1+ i)). Esta Itima
Inea es muy importante, si estuviera i sera siempre iguaI a cero y eI bucIe no tendr
fin. Por Io que dibujara infinitos crcuIos en eI primer punto de Istptos y da un error.
Veamos otro mtodo para dibujar Ios crcuIos en Ios vrtices de Istptos:
(whiIe Istptos
(setq pt (car Istptos))
(command "_.circIe" pt 1.0)
(setq Istptos (cdr Istptos))
)
En este caso, eI bucIe se ejecutar mientras tengamos puntos en Ia Iista es decir,
mientras Istptos sea distinto de niI. Se define pt como eI primer punto de Ia Iista
Istptos, se dibuja un crcuIo de radio 1.0 con centro en pt y por Itimo se mueve eI
contador. Pero, qu contador? Si no existe! Pues, (setq Istptos (cdr Istptos))
eIiminamos eI primer eIemento de Ia Iista Istptos. De modo que Istptos va perdiendo
un eIemento (punto) cada vez que se ejecuta eI bucIe. LIega un momento en eI que
Istptos = ((0.0 10.0)) y aI evaIuarse (setq Istptos (cdr Istptos)) se asignar a Istptos eI
vaIor devueIto por CDR, es decir niI. Con Io cuaI deja de ejecutarse eI bucIe.
EI inconveniente de este segundo mtodo es que se vara Istptos, que finaImente
vaIdr niI. Por Io que Ia Iista de puntos iniciaI se perder. Por eso soIo se utiIizar
este segundo mtodo si no importa perder Ia Iista Istptos.
Bien, pero tenemos aIgunos mtodos que son mejores, y eso es Io que vamos a ver
en este tema.
(FOREACH variabIe Iista expresion)
Esta funcin te permite apIicar una expresin para cada eIemento de Ia Iista que
recibe como argumento. La variabIe simboIiza a un eIemento de dicha Iist, por Io que
se sueIe utiIizar en Ia expresin. Por ejempIo:
(foreach p Istptos (command "_.circIe" p 1.0))
La Inea de cdigo anterio representa eI tercer mtodo para dibujar Ios crcuIos en
Ios puntos de Istptos. A Ia variabIe Ia IIamamos p y Ia expresin a ejecutar para cada
eIemento de Ia Iista es: (command "_.circIe" p 1.0) dnde p es un eIemento de Ia
Iista.
En caso de tener una Iista de cadenas de texto, podria hacerse Io siguiente:
(setq Isttxt (Iist "Curso" "de" "AutoLISP"))
(foreach p Isttxt (prompt p))
Con Io cuaI, escribira todos Ios textos en Ia ventana de comandos de AutoCAD. Se
ha utiIizado eI mismo nombre de variabIe (p), pero podria haberse cambiado:
(foreach pepe Isttxt (princ pepe))
Supongamos ahora que tenemos una Iista de nmeros:
(setq Ist (Iist 5.0 -1.5 2.6 3.8 9.7))
Para sumar Ios nmeros podriamos hacer Io siguiente:
(setq i 0 nent (Iength Ist) totaI 0.0)
(whiIe (< i nent)
(setq num (nth i Ist))
(setq totaI (+ totaI num))
(setq i (1+ i))
)
IniciaImente definimos Ia variabIe totaI como 0.0, eI bucIe se ejecutar para cada
eIemento de Ist y se define num como eI nmero que est en Ia posicin i sumamos
a totaI ese nmero y movemos eI contador. Cuando se entra por primera vez en eI
bucIe, num = 5.0 de modo que totaI = 0.0 + 5.0. AI voIver a entrar en eI bucIe num =
-1.5 de modo que totaI = 5.0 + (-1.5) y as hasta que se IIega aI Itimo eIemento de Ist.
Tambin podria hacerse sin empIear contadores, como hicimos antes. Y tambin
podemos hacerIo con FOREACH, veamosIo:
(setq totaI 0.0)
(foreach p Ist (setq totaI (+ totaI p)))
Todo Io que antes poniamos en un bucIe se pone ahora en una soIa Inea de codigo.
(APPLY nombre_funcin Iista)
ApIica Ia funcin que recibe como argumento a todos Ios eIementos de Ia Iista. EI
nombre de Ia funcin a utiIizar en APPLY se indicar precedida por eI smboIo ' para
que AutoCAD interprete que Ie estamos pasando ese texto taI cuaI. EI ejempIo
anterior sera:
(setq totaI (appIy '+ Ist))
En (appIy '+ Ist) estamos apIicando Ia funcin + a todos Ios eIemento de Ist, equivaIe
a (+ 5.0 -1.5 2.6 3.8 9.7), y eI resuItado se Io asignamos a Ia variabIe totaI.
Digamos que '+ es eI nombre que utiIizamos en AutoLISP para hacer referencia a Ia
funcin +, ya que + es Ia funcin propiamente y no su nombre. Prueba Io siguiente
en Ia ventana de comando de AutoCAD:
(Iist "pepe" + 5.0) y fijate en Io que devueIve ("pepe" #<SUBR @0244f5a8 +> 5.0)
Y ahora prueba con eI IiteraI, es decir con eI caracter ' deIante deI +
(Iist "pepe" '+ 5.0) devueIve ("pepe" + 5.0)
Entiendes ahora porque ponemos '+? Para que no evaIue Ia funcin, ya que
devoIveria #<SUBR @0244f5a8 y nos dara un error.
Veamos un par de ejempIos ms:
(appIy 'max Ist) devoIver eI mayor nmero de Ist
(appIy 'min Ist) devoIver eI menor nmero de Ist
Si tuvieramos una Iista cuyos eIementos fueran textos:
(setq Isttxt (Iist "Curso" "de" "AutoLISP"))
para unir Ios textos:
(setq txt (appIy 'strcat Isttxt))
De modo que txt = "CursodeAutoLISP" todo junto.
(MAPCAR nombre_funcin Iista1 [Iista2]...)
Esta funcin apIica Ia funcin de AutoLISP que recibe como argumento a Ios
eIementos de Ias Iistas. Como as no se va a entender... ejempIos:
Supongamos que tenemos dos puntos:
(setq pt1 (getpoint "\nPunto 1: "))
(setq pt2 (getpoint pt1 "\nPunto 2: "))
Los puntos son Iistas con 2 o 3 eIementos, en funcin de si tienen 2 o 3
coordenadas.
Vamos a determinar eI vector con origen en pt1 y finaI en pt2. Tenemos que caIcuIar
Ias coordenadas X Y Z deI vector, que son eI resuItado de restar Ias respectivas
coordenadas X Y Z de pt1 a Ias de pt2. Podemos obtener eI vector as:
(setq vector
(Iist (- (car pt2) (car pt1))
(- (cadr pt2) (cadr pt1))
(- (caddr pt2) (caddr pt1))
)
)
Siendo Ia coordenada X deI vector: (- (car pt2) (car pt1)) Ia Y (- (cadr pt2) (cadr pt1)) y
Ia Z (- (caddr pt2) (caddr pt1))
Bien, pues esto mismo Io podemos hacer con MAPCAR
(setq vector (mapcar '- pt2 pt1))
La funcin que recibe mapcar es - y Io que hace apIicarIa a Ios eIementos de pt2 y
pt1, de modo que resta sus coordenadas X, Ias Y y Ias Z.
APPLY devueIve un eIemento y MAPCAR una Iista. Si tenemos:
Vamos a compIicar un poco eI tema... si quisieramos obtener eI mduIo de un vector
tendriamos que caIcuIar Ia raz cuadrada de Ia suma de sus coordenadas aI
cuadrado.
(mapcar '* vector vector) devoIver una Iista con Ias coordenadas deI vector aI
cuadrado, ya que Ias estamos muItipIicando por si mismas.
Para sumarIas utiIizamos APPLY:
(appIy '+ (mapcar '* vector vector))
Para terminar soIo nos faIta hacer Ia raiz cuadrada de Io anterior:
(setq moduIo (sqrt (appIy '+ (mapcar '* vector vector))))
Veamos otro ejempIo en eI que se combinan APPLY y MAPCAR. Sean v1 y v2 dos
vectores vamos a caIcuIar su producto escaIar.
(setq v1 (Iist 10.0 10.0 0.0))
(setq v2 (Iist 5.0 0.0 0.0))
EI producto escaIar de Ios vectores v1 y v2 es Ia suma de Ios productos de Ias
coordenadas de v1 por Ias de v2. Podriamos hacerIo as:
(setq pescaIar (+
(* (car v1) (car v2))
(* (cadr v1) (cadr v2))
(* (cadr v1) (cadr v2))
)
)
Pero resuIta ms senciIIo utiIizando MAPCAR y APPLY. Primero muItipIicamos Ias
coordenadas de ambos vectores:
(mapcar '* v1 v2)
y Iuego Ias sumamos, de modo que...
(setq pescaIar (appIy '+ (mapcar '* vec1 vec2)))
(LAMBDA (Iista_argumentos / variabIes_IocaIes) expresin1
[expresin2] ...)
TaI vez eI formato de Ia funcin LAMBDA recuerde aIgo a DEFUN. LAMBDA tambin
se utiIiza para definir una funcin, pero a diferencia de DEFUN Ia funcin no se
aImacena en ningn Iugar, en este caso es temporaI. Por tanto soIo se puede
ejecutar donde se defina. Adems Ia funcin creada no tiene nombre, por Io que
tampoco podriamos IIamarIa desde otra parte de nuestro cdigo.
UtiIizarIa soIa sin APPLY o MAPCAR no tiene sentido. Supongamos que queremos
obtener eI punto medio de dos puntos...
(setq pt1 (getpoint "\nPunto 1: "))
(setq pt2 (getpoint pt1 "\nPunto 2: "))
Las coordenadas deI punto medio sern Ias coordenadas de pt1 ms Ias de pt2
divididas por 2.0. Para sumar sus coordenadas...
(mapcar '+ pt1 pt2)
Bien... pero ahora, Cmo Ias dividimos por 2.0? Podemos hacer Io siguiente:
(mapcar '/ (mapcar '+ pt1 pt2) (Iist 2.0 2.0 2.0))
Donde creamos una Iista (Iist 2.0 2.0 2.0) y dividimos Ios eIementos de (mapcar '+ pt1
pt2) entre Ios eIementos de Ia Iista anterior (2.0 2.0 2.0).
Recordemos... (mapcar '+ pt1 pt2) devueIve Ia suma de Ias coordenadas de pt1 y pt2.
Ahora necesitariamos dividiIa por 2.0, pues podemos crear una funcin que reciba
un nmero y Io divida por 2.0 devoIviendo eI resuItado:
(defun 2/ ( num ) (/ num 2.0))
Y ahora pasarIe a MAPCAR Ia nueva funcin 2/ para que divida cada eIemento de
(mapcar '+ pt1 pt2) por 2.0
(mapcar '2/ (mapcar '+ pt1 pt2))
Pero tambin podemos hacerIo de otra forma, utiIizando Ia funcin LAMBDA en
Iugar de DEFUN. Primero veamos como sera nuestra funcin definida mediante
LAMDA:
(Iambda ( num ) (/ num 2.0))
Es muy parecido a Io que hicimos con DEFUN. Pero Ia funcin definida mediante
LAMBDA no tiene nombre y no se aImacena en ningn sitio, es temporaI, de modo
que no podemos IIamarIa. Dnde debemos utiIizar LAMBDA? Pues directamente en
MAPCAR, donde hay que indicar eI nombre de Ia funcin:
(mapcar '(Iambda ( num ) (/ num 2.0)) (mapcar '+ pt1 pt2))
Por tanto, cuando queremos apIicar APPLY o MAPCAR a una o varias Iistas y
ejecutar una funcin que no existe en AutoLISP, podemos crearIa previamente con
DEFUN o utiIizar Ia funcin LAMBDA para definirIa in situ.
(VER)
Esta funcin devueIve una cadena de texto con Ia versin de AutoLISP que se est
ejecutando. Por ejempIo: "VisuaI LISP 2000 (es)". Entre parntesis indica Ia versin
idiomtica, en este caso EspaoI.
PantaIIa de texto y pantaIIa grfica
En AutoCAD podemos pasar de pantaIIa grfica a Ia pantaIIa de texto, y aI revs,
puIsando Ia tecIa de funcin F2. En AutoLISP tambin existen aIgunas funciones
para reaIizarIo directamente desde eI cdigo de nuestras rutinas.
(TEXTSCR)
Se utiIiza para pasar a pantaIIa de texto y siempre devueIve niI. Se sueIe empIear
cuando se quiere mostrar mucha informacin en pantaIIa de texto.
(GRAPHSCR)
Pasa a pantaIIa grfica y tambin devueIve niI. Se utiIiza para asegurarnos que eI
usuario est viendo Ia pantaIIa grfica, por ejempIo para indicar un punto.
EspeciaImente se utiIizar si antes se ha pasado a pantaIIa de texto.
(TEXTPAGE)
Esta funcin es anIoga a TEXTSCR. Pasa a pantaIIa de texto y tambin devueIve niI.
TaI vez estes preguntandote... Cuntas funciones nos quedan an? Pues entre
otras cosas, Ia siguiente funcin nos servir para ver Ias funciones de AutoLISP que
hemos visto y Ias que nos quedan.
(ATOMS-FAMILY formato [Iista_simboIos])
Esta funcin devueIve una Iista con Ios smboIos que se han definido en eI dibujo
actuaI. Qu es un smboIo? Pues un nombre de variabIe de AutoLISP, eI nombre de
una funcin de usuario que haIIamos creado y tambin todos Ios nombres de Ias
funciones propias de AutoLISP.
EI argumento formato puede tener dos vaIores:
0 para que devueIva una Iista con Ios nombres de Ios smboIos.
1 para que devueIva una Iista, pero siendo sus eIementos cadenas de texto.
Veamos ahora aIgn ejempIo. AI escribir Ia Inea siguiente sabras cuantas funciones
faItan...
(atoms-famiIy 0) esto mostrar una Iista con Ios nombres de todos Ios smboIos
definidos en eI dibujo actuaI.
(atoms-famiIy 1) as Ios eIementos de Ia Iista anterior sern cadenas de texto.
En Ias Iistas anteriores es dificiI encontrar aIgo. Recuerdas Ia funcin
acad_strIsort? Permita organizar aIfabticamente una Iista de cadenas de texto.
(acad_strIsort (atoms-famiIy 1)) devoIver Ia Iista anterior ordenada
Estan todas Ias funciones de AutoLISP, pero hay otras muchas funciones que
aparecen en Ia Iista y no son funciones de AutoLISP. As que no te asustes, que no
son tantas.
Recordemos eI formato de esta funcin: (ATOMS-FAMILY formato [Iista_simboIos]) y
veamos que es eso de Ia Iista de smboIos...
Para saber si unas funciones determinadas existen, es decir si estn definidas,
creamos una Iista con sus nombres y se Io pasamos como argumento a atoms-
famiIy
(atoms-famiIy 1 (Iist "car" "cdr")) devoIver una Iista con sus nombres ("CAR"
"CDR")
Aunque Io habituaI no es empIear esta funcin para detectar si estn definidas Ias
funciones de AutoLISP, sino para detectar nuestras propias funciones y variabIes:
(atoms-famiIy 1 (Iist "car" "cdr" "variabIe")) devueIve ("CAR" "CDR" niI) ya que eI
smboIo "variabIe" no tiene asociado ninguna funcin ni variabIe de AutoLISP.
Si definimos:
(setq variabIe 12.5)
(atoms-famiIy 1 (Iist "car" "cdr" "variabIe")) devoIver ("CAR" "CDR" "VARIABLE")
devueIve eI nombre de Ia variabIe, no su vaIor.
Si definimos una funcin de usuario:
(defun 2+ ( numero / ) (+ numero 2.0))
La funcin 2+ recibe un nmero y Ie suma 2.0.
(atoms-famiIy 1 (Iist "car" "cdr" "2+")) devoIver ("CAR" "CDR" "2+")
(QUOTE expresin)
Esta funcin recibe una expresin y devueIve su IiteraI, es decir devueIve Ia
expresin taI cuaI, sin evaIuar.
(quote +) devoIver +
Esto es Io mismo que haciamos en APPLY y MAPCAR:
(appIy '+ (Iist 2.0 3.5 6.8))
pues eI apstrofe ' es eI diminutivo o eI aIias de Ia funcin QUOTE.
(quote (setq a "texto" b 10.0)) devoIver (SETQ A "texto" B 10.0)
sera Io mismo escribir:
'(setq a "texto" b 10.0)
Pero no podremos escribir esta Itima Inea en Ia ventana de comandos de
AutoCAD, por que eI interprete de comandos no detecta eI parntesis en primer
Iugar y piensa que no es una expresin de AutoLISP sino un comando de AutoCAD.
Podemos utiIizar un truco para evaIuarIa desde Ia ventana de comandos:
(progn '(setq a "texto" b 10.0))
PROGN en reaIidad no hace nada, simpIemente nos serva para saIvar Ia Iimitacin
de IF de indicar ms de 1 expresin, ya que evaIa Ias expresiones que contiene y
devueIve eI resuItado de Ia Itima expresin evaIuada. Ahora si devoIver (SETQ A
"pepe" B 10.0). Pero no hemos asignado vaIores a Ias variabIes, ya que (SETQ A
"pepe" B 10.0) no se ha evaIuado.
(quote (15.0 10.6 9.2)) devoIver (15.0 10.6 9.2) es decir, devueIve una Iista. Tambin
funcionara con '(15.0 10.6 9.2)
Por tanto en Iugar de:
(appIy '+ (Iist 2.0 3.5 6.8))
podemos poner:
(appIy '+ (quote (2.0 3.5 6.8)))
y tambin:
(appIy '+ '(2.0 3.5 6.8))
De modo que podemos usar QUOTE y ' para crear Iistas. Pero con excepciones... si
hacemos:
(setq a 2.0)
(appIy '+ '(a 3.5 6.8)) indicar: ; error: tipo de argumento errneo: numberp: A
a es eI nombre de una variabIe, es un smboIo, cuya variabIe tiene asociado eI vaIor
2.0
(appIy '+ (Iist a 3.5 6.8)) esto si funcionar porque (Iist a 3.5 6.8) devoIver (2.0 3.5
6.8), LIST se evaIa pero QUOTE no evaIua Ia expresin que recibe.
Resumiendo: Podemos crear Iistas con QUOTE o con ' pero siempre que
conozcamos Ios eIementos de dichas Iistas, y que estos sean vaIores concretos no
determinados a partir de expresiones o aImacenados en variabIes.
AIgunos ejempIos ms:
(setq maximo (appIy (quote max) (quote (10.5 15.2 9.3))))
(setq minimo (appIy 'min '(10.5 15.2 9.3)))
(foreach p '((0.0 0.0 0.0) (10.0 10.0 0.0)) (command "_.circIe" p 1.0))
(setq vector (mapcar '- '(10.0 10.0 0.0) '(5.0 0.0 0.0)))
(setq ptomed (mapcar '(Iambda ( num ) (/ num 2.0)) (mapcar '+ '(10.0 10.0 0.0) '(5.0 0.0
0.0))))
(EVAL expresin)
Esta funcin evaIa Ia expresin que recibe.
(evaI 2.5) devueIve eI resuItado de evaIuar 2.5, es decir devueIve 2.5
(evaI "Soy una cadena de texto") anaIogamente devoIver "Soy una cadena de texto"
Pero veamos un ejempIo aIgo ms compIicado:
(setq a 15.5)
(setq b (quote a))
Qu vaIor tendr asignado b? (quote a) es eI nombre de Ia variabIe a, es decir eI
smboIo. As que b tendr asociado eI nombre de Ia variabIe a.
(+ b 10.0) dar un error
(evaI b) devoIver 15.5 de modo que podemos hacer Io siguiente:
(+ (evaI b) 10.0) devoIver 25.5
(evaI '(+ 10.0 5.5)) devoIver 15.5 ya que '(+ 10.0 5.5) devueIve (+ 10.0 5.5) y evaI, Io
evaIa.
(READ texto)
Esta funcin Iee eI texto que recibe y devueIve Ia primera paIabra.
(read "AutoLISP") devueIve "AutoLISP"
(read "Curso de AutoLISP") devoIver "Curso"
(read "(15.2 9.3 15.5)") en este caso devoIver (15.2 9.3 15.5) porque aI detectar eI
parntesis Io considera un mismo trmino. Es aIgo simiIar a escribir en Ia ventana
de comandos de AutoCAD, si no se pone un parntesis deIante no dejar escribir
espacios en bIanco. Pues este es otro mtodo para crear una Iista, por tanto:
(appIy 'max (read "(15.2 9.3 15.5)")) devoIver eI mximo de Ia Iista de nmeros
indicados
Y que pasa si hacemos:
(setq txt "(setq a 5.5)")
(read txt) devoIver (setq a 5.5)
y ahora podemos evaIuarIo con EVAL
(evaI (read txt)) devoIver 5.5 y asigna a Ia variabIe a eI vaIor 5.5
Para qu sirve esto? Para soIicitarIe aI usuario una expresin de AutoLISP y
evaIuarIa:
(setq txt (getstring T "\nExpresin de AutoLISP: "))
(setq vaIor (evaI (read txt)))
En este caso asignamos a vaIor eI resuItado de evaIuar una expresin de AutoLISP
introducida por eI usuario.
(SET IiteraI_de_smboIo expresin)
Esta funcin es muy parecida a SETQ, se diferencia en que espera eI IiteraI de un
smboIo. VeamosIo con ejempIos:
(setq num1 5.0) asigna a Ia variabIe num1 5.0
(set num2 5.5) da un error, ya que espera un IiteraI
(set 'num2 5.5) asigna a Ia variabIe num2 eI vaIor 5.5
Si probamos:
(setq (read "num1") 5.0) nos da un error, ya que SETQ no acepta una expresin
como smboIo.
Sin embargo SET si Io acepta:
(set (read "num2") 15.0) asigna a Ia variabIe num2 eI vaIor 15.0
Carga automtica de Ios archivos de AutoLISP
AutoCAD carga automticamente dos archivos de AutoLISP, si es que existen y se
encuantran en Ios directorios de soporte. Se trata deI ACAD.LSP y eI
ACADDOC.LSP.
EI archivo ACAD.LSP se carga aI iniciar AutoCAD y eI ACADDOC.LSP se carga
siempre que se abre un dibujo, o se crea un dibujo nuevo. De modo que Ias
funciones cotenidas en eI ACAD.LSP tan soIo estarn cargadas en eI dibujo que se
abre aI iniciar AutoCAD, mientras que Ias funciones contenidas en eI ACADDOC.LSP
estarn cargadas en todos Ios dibujos.
Lo Igico ser entonces guardar nuestras funciones en eI ACADDOC.LSP y no en eI
ACAD.LSP.
EI ACAD.LSP se utiIizar tan soIo para aImacenar aqueIIas funciones que nos
interese ejecutar aI cargar AutoCAD. Por ejempIo, podemos utiIizar eI archivo
ACAD.LSP para mostrar una imagen, foto, aI iniciar AutoCAD.
Si tenemos aIguna rutina que se utiIice mucho, o que se sueIe ejecutar en todos Ios
dibujos Ia meteremos en eI ACADDOC.LSP
Qu riutinas meteremos en eI ACADDOC.LSP? Conviene que no sean demasiadas,
para que dicho archivo sea ms manejabIe y adems para no ocupar demasiado
espacio en Ia memoria deI ordenador. Por tanto, soIo incIuiremos en eI
ACADDOC.LSP Ias rutinas ms empIeadas. Por ejempIo una funcin de tratamiento
de errores, o Ias funciones GAR y RAG que se utiIizan bastante, y adems son
bastante pequeas.
Qu pasa si metemos tambin nuestra funcin C:CIRCPERI? Pues no pasara nada
pero... Vas a dibujar crcuIos dado su permetro en "todos" Ios dibujos? no creo,
por eso no merece Ia pena aadirIa aI ACADDOC.LSP, ya que si hacemos Io mismo
con todas nuestras rutinas... eI archivo ACADDOC.LSP tendria un tamao
descomunaI.
En cambio, podemos guargar Ia rutina CIRCPERI en un archivo independiente y
cargarIo desde eI ACADDOC.LSP. En eI caso de Ia rutina CIRCPER, podemos
guardarIa en eI archivo CIRCPERI.LSP, dentro de uno de Ios directorios de soporte
de AutoCAD, e incIuir Ia siguiente Inea en eI ACADDOC.LSP:
(Ioad "circperi.Isp" (aIert "Archivo Circperi.Isp no encontrado"))
De este modo tenemos Ia rutina CIRCPERI en un archivo independiente, Io que nos
soIuciona parte deI probIema, ya que tendremos eI archivo ACADDOC.LSP ser
bastante corto y si queremos modificar Ia rutina CIRCPERI tan soIo tenemos que
manipuIar un archivo en eI que nicamente est definida dicha funcin.
Pero seguimos teniendo aIgunos probIemas... Si nuestra coIeccin de rutinas es
muy extensa tenemos que aadir una Inea de cdigo como Ia anterior para cada
rutina, Io que se traducir en un archivo ACADDOC.LSP bastante grande y dificiI de
manipuIar. Adems, eI mayor inconveniente es que todas nuestras rutinas se
cargarian en memoria automticamente para cada archivo de dibujo, con Io que
estaremos sobrecargando Ia memoria deI ordenador.
(AUTOLOAD archivo Iista_comandos)
La funcin AUTOLOAD es simiIar a LOAD, tambin nos permite cargar archivos de
AutoLISP pero soIo aqueIIos archivos que contengan comandos, por ejempIo
C:CIRCPERI pero no servir para archivos en Ios que soIo tengamos funciones
como GAR y RAG.
Qu ventaja tiene eI utiIizar AUTOLOAD en Iugar de LOAD? AI utiIizar AUTOLOAD
Ios archivos no se cargan automticamente, simpIemente se predispone a AutoCAD
para que Ios cargue en cuanto se ejecute uno de Ios comandos indicados como
argumentos en Ia Iista de comandos.
Por ejempIo, si tenemos un archivo con 3 comandos:
(defun C:comando1 ( / ) ....)
(defun C:comando2 ( / ) ....)
(defun nosoyuncomando ( / ) ....)
(defun C:comando3 ( / ) ....)
En eI archivo ACADDOC.LSP podriamos aadir Ia siguiente Inea:
(autoIoad "archivo.Isp" '("comando1" "comando2"))
AI iniciar un dibujo, se carga eI ACADDOC.LSP y se evaIa Ia Inea anterior, pero
archivo.Isp no se cargar hasta que se ejecute eI comando1 o eI comando2. Sin
emargo no se cargar si ejecutamos eI comando3, ya que no Io hemos incIuido en Ia
Iista de comandos. AI ejecutar uno de Ios dos comandos anteriores se carga eI
archivo, de modo que Ia funcin nosoyuncomando tambin se cargar, aI iguaI que
eI comando3.
Y qu pasa con Ios archivos de AutoLISP que no tienen comandos, es decir en Ios
que soIo hay funciones? Pues tendremos que cargarIos con LOAD, con Io cuaI se
cargarian todos directamente en Ia memoria y si tenemos bastantes funciones
seguimos teniendo eI mismo probIema que antes.
Cmo podemos soIucionarIo? Pues cargando Ias funciones soIo cuando hacen
faIta. Por ejempIo, supongamos que en eI comando C:CIRPERI se utiIiza Ia funcin
RAG... tenemos dos opciones:
IncIuir Ia funcin RAG en eI archivo Circperi.Isp de este modo aI cargarse eI archivo
se cargar Ia funcin RAG. Esto se sueIe hacer para Ias funciones que soIo se
utiIizan en un comando determinado. Pero si Ia funcin RAG deseamos utiIizarIa en
otros comandos, es mejor utiIizar eI siguiente mtodo...
IncIuir Ia funcin RAG en un archivo independiente Rag.Isp y aadir Ia siguiente
Inea de cdigo dentro deI archivo Circperi.Isp:
(Ioad "Rag.Isp" (aIert "Archivo Rag.Isp no encontrado"))
De este modo, eI archivo Circperi.Isp se cargar cuando se ejecute uno de Ios
comandos indicados en Ia funcin AutoIoad deI archivo ACADDOC.LSP. Y aI
cargarse eI archivo Circperi.Isp se cargar mediante Ia funcin Load eI archivo
Rag.Isp. UtiIizando este mtodo podemos utiIizar una misma funcin en muItipIes
rutinas, tan soIo debemos asegurarnos de que dicha funcin est definida, es decir
que se haIIa cargado eI archivo en eI que se encuentre.
Los archivos ACAD.LSP y ACADDOC.LSP no tienen porque existir. Si no existen
pueden crearse, teniendo en cuenta que se deben guardar en uno de Ios directorios
de soporte de AutoCAD. En caso de que ya existan, se pueden editar para incIuir eI
cdigo deseado. Conviene hacer una copia de seguridad de estos archivos porque
muchos programadores crean sus propios archivos ACAD.LSP y ACADDOC.LSP de
modo que aI instaIar un mduIo o apIicacin para AutoCAD, podeis sobreescribir
vuestros archivos.
Existen otros dos mtodos para cargar automticamente rutinas de AutoLISP. EI
primero consiste en utiIizar Ia opcin disponibIe en eI men de AutoCAD "Herr -->
AutoLISP --> Cargar" ya que en eI Ietrero de diaIogo que aparece se pueden cargar
rutinas y se pueden seIeccionar Ias rutinas que se desean cargan aI inicio.
EI tercer mtodo para cargar automticamente Ias rutinas de AutoLISP es editando
Ios mens de AutoCAD, pero esto Io veremos ms adeIante...
Ejecucin automtica de cdigo de AutoLISP
Hemos visto que eI archivo ACADDOC.LSP se carga automticamente en todos Ios
dibujos pero... Cmo podemos ejecutar automticamente una funcin aI iniciarse
un dibujo?
Supongamos que tenemos definida Ia funcin GAR dentro deI ACADDOC.LSP:
(defun GAR ...)
Para ejecutarIa, tan soIo debemos aadir en dicho archivo Ia siguiente Inea de
cdigo:
(GAR)
En caso de que dicha funcin tenga argumentos, estos deben indicarse:
(GAR 3.141592)
Cmo ejecutariamos automaticamente eI comando C:CIRCPERI?
Una vez cargado eI comando, para ejecutarIo desde Ia ventana de comandos de
AutoCAD podemos escribir directamente su nombre CIRCPERI para ejecutarIo. Sin
embargo, desde un archivo de AutoLISP no podemos ejecutarIo as. Tenemos que
hacerIo de esta otra forma:
(C:CIRCPERI)
De modo que podriamos incIuir en eI archivo ACADDOC.LSP Ias dos siguientes
Ineas de cdigo:
(Ioad "circperi.Isp" (aIert "Archivo Circperi.Isp no encontrado")) ; Carga eI comando
(C:CIRCPERI) ; Ejecuta eI comando
Sera mejor utiIizar AUTOLOAD en Iugar que LOAD en eI ejempIo anterior? Pues
no. UtiIizar AUTOLOAD no tendra mucho sentido, puesto que aI ejecutar eI
comando eI archivo en eI que est definido se cargara, por tanto podemos cargarIo
ya antes.
Existe otro mtodo para ejecutar cdigo directamente. Se trata de escribirIo
directamente, es decir sin meterIo dentro de ninguna funcin o comando. Por
ejempIo, si incIuimos Ias siguientes Ineas de cdigo en eI archivo ACADDOC.LSP
nos permitir dibujar un circuIo dado su centro y su permetro:
(setq pto (getpoint "\nCentro deI crcuIo: "))
(setq peri (getdist pto "\nPermetro: "))
(command "_.circIe" pto (/ peri (* 2.0 PI)))
Pero en este caso, eI cdigo anterior soIo se ejecuta una vez. Si queremos dibujar
otro crcuIo dado su permetro, no tendriamos Ia funcin CIRCPERI definida.
Para qu se sueIe utiIizar este mtodo?
Por ejempIo, para mostrar mensajes informativos o de bienvenida:
(aIert "Estas seguro de que quieres utiIizar AutoCAD?")
(aIert "Estas reaImente seguro?")
(aIert "Seguro, seguro?")
Aunque no os aconsejo que utiIieis este ejempIo, os cansariais de I a Ios 5 minutos.
Adems de mensajes de bienvenida podeis hacer otras cosas ms tiIes, como
asignar vaIores iniciaIes a aIgunas variabIes:
(setq directorio "c:\\rutinas\\")
Tambin podeis modificar eI vaIor de aIguna variabIe de sistema de AutoCAD:
(setvar "osmode" 7)
S::STARTUP
Existe otro mtodo para ejecutar cdigo automticamente. Hemos visto que
AutoCAD utiIiza una funcin de tratamiento de errores por defecto que se IIamaba
*error* y tambin hemos visto que podiamos redefinirIa creando nuesta propia
funcin de tratamiento de errores. Bien, pues AutoCAD tambin tiene una funcin
interna que se ejecuta automticamente se trata de S::STARTUP.
EI que Ias funciones *error* y S::STARTUP tengan estos nombres tan raros es para
evitar que a aIguien se Ie ocurra denominar as a aIguna funcin de otro tipo.
Para definir Ia funcin S::STARTUP se utiIiza DEFUN, aI iguaI que para cuaIquier otra
funcin.
(defun S::STARTUP ( / )
(setq directorio "c:\\rutinas\\")
)
La funcin S::STARTUP podemos utiIizarIa para Ios mismos ejempIos que se daban
antes.
Por Itimo, para terminar eI tema, un consejo... AI programar hay que tener bastante
cuidado para no cometer errores, ya que eI omitir un simpIe parntesis o unas
comiIIas, por ejempIo, modificaran totaImente nuestras funciones. Cuando adems
estas funciones se van a ejecutar automticamente, como en Ios ejempIos que se
han expuesto, Ia precaucin aI programar debe ser mxima.
Operaciones con archivos
Antes de comenzar con eI tema de Iectura y escritura de archivos, veamos una
pequea rutina... CARGALISP
CARGALISP recibir una Iista como Ia siguiente: (("c:\\rutinas\\Iisp1.Isp" ("gar"
"rag")) ("c:\\rutinas\\Iisp2.Isp" ("inverso" "tg")))
En Ia que cada eIemento es a su vez otra Iista formada por eI nombre de un archivo
de AutoLISP (con su ruta, si es necesario) y una Iista con Ios nombres de Ias
funciones (o variabIes gIobaIes) definidas en dicho archivo. Por ejempIo, en eI caso
anterior se supone que en eI archivo "c:\\rutinas\\Iisp1.Isp" estn definidas Ias
funciones "gar" y "rag" y que en eI archivo "c:\\rutinas\\Iisp2.Isp" estn definidas Ias
funciones "inverso" y "tg".
CARGALISP cargar Ios archivos de AutoLISP indicados si no estaban definidas, o
cargadas que es Io mismo, Ias funciones indicadas para cada archivo.
(defun CARGALISP ( Ist / )
(whiIe Ist
(if (not (appIy 'and (atoms-famiIy 1 (cdar Ist))))
(progn
(Ioad (caar Ist))
(prompt (strcat "\nCargando archivo " (caar Ist) "..."))
)
)
(setq Ist (cdr Ist))
)
)
TaI como est funciona perfectamente. Pero... puede producirse un pequeo error.
Qu pasa si no existe, o no se encuentra, eI archivo Iisp1.Isp o cuaIquiera de Ios
archivos de Ia Iista que reciba CARGALISP?
(FINDFILE archivo)
Esta funcin nos permite comprobar Ia existencia de un archivo. Si eI archivo existe
devueIve su nombre y si no existe, o no Io encuentra en Ia ruta indicada, devoIver
niI.
En caso de que no se indique Ia ruta en Ia que debe buscar eI archivo, Io buscar en
Ios directorios de soporte de AutoCAD.
(findfiIe "c:\\autoexec.bat") debera devoIver "c:\\autoexec.bat", supongo que vuestro
PC tiene Autoexec.bat, cIaro...
(findfiIe "c:\\noexisto.bat") debera devoIver niI
FINDFILE en reaIidad no hace nada, tan soIo se utiIiza para comprobar Ia existencia
de un archivo. Entonces,...Cuando se utiIizar FINDFILE? Pues os voy a poner tres
ejempIos en Ios que se sueIe utiIizar:
1. Antes de cargar un archivo con LOAD o AUTOLOAD
2. Antes de abrir un fichero de texto, ya sea para IeerIo o escribir en I.
3. Antes de "abrir" un archivo de dibujo en AutoCAD.
4. Antes de cargar y utiIizar un archivo DCL (Letrero de diaIogo) en AutoLISP.
Por tanto, deberiamos modificar eI cdigo de Ia funcin CARGALISP para
comprobar Ia existencia de Ios archivos a cargar.
(defun CARGALISP ( Ist / )
(whiIe Ist
(if (not (appIy 'and (atoms-famiIy 1 (cdar Ist))))
;; Comprueba si todas Ias funciones deI primer eIemento de Ia Iista
;; estn cargadas
(if (not (findfiIe (caar Ist)))
(aIert (strcat "No se ha encontrado eI archivo " (caar Ist)))
;; No se encuentra eI archivo
(progn
(Ioad (caar Ist))
;; Carga eI archivo
(prompt (strcat "\nCargando archivo " (caar Ist) "..."))
;; Indica que se ha cargado eI archivo
)
;; Se encuentra eI archivo
)
)
(setq Ist (cdr Ist))
;; Pasa aI siguiente eIemento de Ia Iista
)
;; Para cada eIemento de Ia Iista
)
(GETFILED tituIo_Ietrero archivo_defecto extensin_defecto modo)
Esta funcin nos permitir seIeccionar un archivo, ya veremos ms adeIante como
seIeccionar varios archivos. GETFILED muestra un Ietrero de gestin de archivos
tipico de Windows.
Podemos pasarIe a GETFILED eI ttuIo deI Ietrero, eI archivo seIeccionado por
defecto y Ia extensin de archivos que se buscar por defecto. GETFILED devueIve
eI nombre y ruta deI archivo seIeccionado.
EI argumento modo es de tipo binario y ofrece Ios siguientes vaIores:
1 --> Para designar un archivo nuevo, es decir, que no exista.
2 --> Desactiva Ia casiIIa "TecIearIo".
4 --> Permite indicar cuaIquier extensin.
8 --> DevueIve eI nombre deI archivo, sin Ia ruta
(getfiIed "SeIecciona un archivo" "c:\\autoexec.bat" "bat" 0)
No pasa nada aI puIsar en Abrir, ya que no se abre eI archivo. GETFILED tan soIo
nos deja seIeccionarIo y devueIve su nombre.
(getfiIed "SeIecciona un archivo nuevo" "" "" 1)
Lectura y escritura de archivos de texto
AutoLISP nos permite Ieer y escribir archivos de texto ASCII.
AI utiIizar archivos de texto en nuestras rutinas debemos siempre seguir Ios
siguientes pasos:
1. Comprobar si existe eI archivo.
2. Abrir eI archivo.
3. Leer o escribir en eI archivo.
4. Cerrar eI archivo.
(OPEN archivo modo)
Esta funcin nos permite abrir un archivo de texto y devueIve un "descriptor de
archivo".
Qu es un descriptor de archivo? Es aIgo simiIar a un canaI por eI que se comunica
AutoCAD con dicho archivo. Podemos abrir varios archivos, es decir abrir varios
canaIes de comunicacin, de modo que aI Ieer o escribir en un archivo, tenemos que
saber cuaI es eI canaI de comunicacin por eI que vamos a recibir o enviar datos, es
decir necesitamos conocer eI descriptor deI archivo.
Hay tres formas de abrir un archivo de texto, en funcin de Io que se quiera hacer a
continuacin con dicho archivo. EI argumento modo es eI encargado de diferenciar
estas tres formas distintas de abrir archivos:
Podemos abrir un archivo para IeerIo --> modo "r"
Podemos abrir un archivo de texto para escribir en I comenzando desde Ia
primera Inea --> modo "w"
Podemos abrir un archivo de texto para escribir en I a partir de Ia Itima
Inea --> modo "a"
Para abrir eI archivo autoexec.bat en modo Iectura:
(open "c:\\autoexec.bat" "r")
DevueIve #<fiIe "c:\\autoexec.bat"> es decir, eI descriptor deI archivo.
Aunque en Ia Inea anterior se abre eI archivo autoexec.bat en modo Iectura, Iuego
no podriamos hacer nada con I ya que no hemos guardado eI descriptor de archivo.
Es decir, no podemos decirIe a AutoCAD que Iea texto por eI canaI de comunicacin
que hemos abierto, ya que no conocemos eI descriptor deI archivo. Cmo se utiIiza
entonces Ia funcin OPEN?
(setq darch (open "c:\\autoexec.bat" "r"))
De este modo eI vaIor devueIto por OPEN, eI descriptor de archivo, se aImacena en
Ia variabIe darch.
Antes de ver como Ieer o escribir en Ios archivos de texto, veamos como tendriamos
que cerrarIos...
(CLOSE descriptor_archivo)
Cierra eI archivo cuyo descriptor se indica y devueIve niI. Fijate en Io importante que
es guardar eI descriptor deI archivo en una variabIe, ya que si no Io hacemos no soIo
no podremos Ieer o escribir en eI archivo, tampoco podremos cerrarIo.
Hay que tener una cosa en cuenta aI trabajar con archivos de texto: AI abrir un
archivo de texto debemos indicar eI modo (Iectura, escritura, o aditivo) de modo que
debemos saber de antemano Io que vamos a hacer con eI archivo, y SOLO
podremos hacer una cosa o Ieer o escribir. Aunque podemos abrir un archivo en
modo escritura, escribir en I, cerrarIo, abrirIo en modo Iectura, Ieer y voIver a
cerrarIo.
Otra cuestin de especiaI interes es que si abrimos un archivo de texto existente en
modo escritura "w", nos habremos cargado todo Io que tena anteriormente dicho
archivo. As que mucho cuidado con Ios archivos que se abren en modo escritura.
Escritura de archivos de texto
Para crear un archivo de texto debemos abrirIo en modo escritura:
(setq darch (open "c:\\nuevo.txt" "w"))
DevueIve #<fiIe "c:\\nuevo.txt"> eI descriptor deI archivo abierto, que se aImacena en
Ia variabIe darch.
Tambin podemos abrir eI archivo en modo aditivo, para continuar escribiendo a
partir de Ia Itima Inea de texto deI archivo.
Bien, ya tenemos abierto nuestro archivo de texto, vamos a escribir en I:
(PRIN1 [expresin [descriptor_archivo]])
Esta funcin escribe una expresin en eI archivo cuyo descriptor se indique. Si no
se indica eI descriptor de archivo, Ia expresin se escribir en Ia ventana de
comandos de AutoCAD. Veamos aIgunos ejempIos:
(setq a 5.5 b "Curso de AutoLISP")
(prin1 a) escribir eI vaIor de Ia expresin a en Ia ventana de comandos de AutoCAD,
es decir, escribir 5.5
Si ejecutas Ias dos Ineas de cdigo anteriores desde Ia ventana de comandos de
AutoCAD, veras que (prin1 a) parece devoIver 5.55.5 en reaIidad devueIve 5.5 pero eI
eco de mensajes, repite eI vaIor devueIto por Ia expresin (prin1 a) es decir 5.5 Por
eso, aparece 5.55.5
(prin1 b)
Escribir en Ia ventana de comandos "Curso de AutoLISP".
Fijate que PRIN1 puede escribir tanto cadenas de texto como nmeros. Sin embargo
Ia funcin PROMPT tan soIo puede recibir como argumeto una cadena de texto.
(prin1 'a) escribe a
(prin1 (+ 15 5.5)) escribe 20.5
Hemos indicado una expresin como argumento, si utiIizamos PROMPT en Iugar de
PRIN1 dar un error.
(prin1 '(+ 15 5.5)) escribe (+ 15 5.5)
Si no se indica Ia expresin a escribir, escribe una cadena nuIa
(prin1)
Por eso se sueIe empIear como Itima expresin de Ios comandos, para que Ia
saIida de nuestras rutinas sea Iimpia y no se vea eI eco de mensajes de Ia Itima
expresin evaIuada.
(prin1 (strcat "\t" b)) devueIve "\tCurso de AutoLISP"
PRIN1 no entiende Ios caracteres de controI como "\n" "\t" etc
(PRINT [expresin [descriptor_archivo]])
Esta funcin es muy parecida a PRIN1, veamos en que se diferencian...
(progn (prin1 a) (prin1 a)) escribe 5.55.5
(progn (print a) (print a)) escribe 5.5 pasa a otra Inea y escribe 5.5
Es decir, PRINT saIta de Inea antes de escribir Ia expresin indicada. PRINT escribe
Ia expresin en una Inea nueva.
(print) devueIve una cadena nuIa, por eso tambin se empIea como Itima expresin
de Ios comandos
(print (strcat "\t" b)) devueIve "\tCurso de AutoLISP", es decir PRINT tampoco
entiende Ios caracteres de controI.
(PRINC [expresin [descriptor_archivo]])
Esta funcin tambin es muy parecida a Ias anteriores.
(progn (princ a) (princ a)) escribe 5.55.5
(princ) devueIve una cadena nuIa, por eso tambin se empIea como Itima expresin
de Ios comandos
(princ (strcat "\t" b)) ahora escribe "Curso de AutoLISP" pero tabuIado.
Por tanto, PRINC se diferencia de Ias anteriores en que si interpreta eI significado de
Ios caracteres de controI.
(WRITE-CHAR cdigo_ASCII [descriptor_archivo])
Esta funcin permite escribir un caracter, recibe como argumento su cdigo ASCII.
Si se indica eI descriptor de archivo Io escribir en eI archivo y sino Io escribir en Ia
ventana de comandos de AutoCAD.
(write-char 65) escribe A. Es Io mismo que escribir (write-char (ascii "A"))
(WRITE-LINE texto [descriptor_archivo])
Esta funcin escribe una Inea de texto entera. EI primer argumento debe ser una
cadena de texto no una expresin. Y si se indica un descriptor de archivo, escribir
Ia Inea de texto en eI archivo, en caso contrario Ia escribe en Ia ventana de
comandos de AutoCAD.
(write-Iine "Curso de AutoLISP")
Lectura de archivos de texto
Para Ieer un archivo de texto debemos abrirIo en modo Iectura:
(setq darch (open "c:\\autoexec.bat" "r"))
(READ-CHAR [descriptor_archivo])
Lee un caracter deI archivo cuyo descriptor se indica. Si no se indica eI descriptor,
Io Iee de Ia ventana de comandos de AutoCAD.
(read-char) escribe un caracter y devoIver su cdigo ASCII
(READ-LINE [descriptor_archivo])
Esta funcin Iee una Inea deI archivo de texto indicado. Si no se indica eI descriptor
de archivo, Ia Ieera de Ia ventana de comandos de AutoCAD.
(read-Iine) escribir una paIabra o frase y devoIver una cadena de texto con Io que
has escrito

También podría gustarte