24636751 Tema AutoLISP

download 24636751 Tema AutoLISP

If you can't read please download the document

Transcript of 24636751 Tema AutoLISP

Introduccin al estudio de AutoLISP ndice de temas

Tema 1: Introduccin. Tema 2: Las variables en AutoLISP. Tema 3: Operaciones matemticas bsicas. Tema 4: Solicitar nmeros al usuario. Tema 5: Funciones de usuario y nuevos comandos. Tema 6: Introduccin al entorno de Visual LISP. Tema 7: Cargar los archivos de AutoLISP. Tema 8: Operaciones matemticas. Tema 9: Obtener textos y puntos del usuario. Tema 10: Funciones para manejar listas. Tema 11: Ejecutar comandos de AutoCAD. Tema 12: Operaciones de comparacin. Tema 13: Operaciones lgicas. Tema 14: Estructuras condicionales. Tema 15: Mostrar textos en pantalla. Tema 16: Variables de sistema. Tema 17: Funciones de conversin. Tema 18: Obtener distancias y ngulos del usuario. Tema 19: El comando deshacer en las rutinas de AutoLISP. Tema 20: Funciones de tratamiento de errores. Tema 21: Limitar las respuestas de los usuarios a las funciones de solicitud de datos (I). Tema 22: Limitar las respuestas de los usuarios a las funciones de solicitud de datos (y II). Tema 23: Estructuras repetitivas. Tema 24: Funciones para manipular cadenas de texto. Tema 25: Trabajar con ngulos y distancias. Tema 26: Funciones avanzadas para trabajar con listas. Tema 27: Aplicar funciones a los elementos de las listas. Tema 28: Literales y otras funciones de utilidad. Tema 29: Carga automtica de archivos de AutoLISP. Tema 30: Operaciones con archivos. Tema 31: Leer y escribir archivos de texto.

Interfaces de programacinAutoCAD dispone varios entornos de programacin, la seleccin del tipo de interfaz a emplear para crear una aplicacin depender de las necesidades de la aplicacin y de la experiencia o conocimientos del programador/es:

AutoLISP es una adaptacin del lenguaje de programacin CommonLISP para AutoCAD. Es sencillo de aprender y al mismo tiempo potente. AutoCAD cuenta con un intrprete interno de LISP que permite introducir cdigo desde la lnea de comando o cargar programas desde archivos externos. Puedes utilizar AutoLISP para automatizar tareas repetitivas y crear nuevos comandos de AutoCAD.

ActiveX Automation constituye una alternativa moderna al AutoLISP. Puedes acceder y controlar objetos de AutoCAD desde cualquier aplicacin que utilice un controlador Automation como Visual Basic y Delphi, o cualquiera de las aplicaciones que dispongan de Visual Basic for applications (VBA). VBA es un entorno de programacin basado en objetos que utiliza ntegramente la sintaxis del lenguaje Visual Basic y permite usar controles ActiveX. Permite tambin la integracin con otras aplicaciones que utilizan VBA como MS Office o MS Project. Las ediciones de desarrollo de MS Visual Basic, que se adquieren por separado, complementan AutoCAD VBA con componentes adicionales como un dispositivo externo de base de datos y funcionalidades de escritura de informes. ObjectARX es un entorno de programacin de lenguaje compilado para el desarrollo de aplicaciones de AutoCAD. El entorno de programacin ObjectARX incluye varias bibliotecas de vnculos dinmicos (DLL) que ofrecen acceso directo a las estructuras de la base de datos, el sistema de grficos y los dispositivos de geometra de AutoCAD.

Caractersticas de AutoLISPAutoLISP es un lenguaje evaluado. El cdigo se convierte a lenguaje mquina (ceros y unos) y se almacena en la memoria temporal. No es tan lento como los lenguajes interpretados, ni tan rpido como los compilados. En los lenguajes interpretados, se va traduciendo el programa a cdigo mquina (el idioma de los ordenadores) a medida que se ejecuta. En los lenguajes compilados, el cdigo fuente (texto) del programa se traduce a cdigo mquina generando un archivo ejecutable (.EXE) que es el que ejecutar el programa. Una de las caractersticas ms importantes del AutoLISP es la posibilidad de acceder a la base de datos de los dibujos de AutoCAD. Donde podemos acceder a las capas, estilos de texto, SCP... as como a todas las entidades del dibujo. Esta informacin se puede modificar, extraer e incluso aadir ms entidades al dibujo. AutoLISP permite crear nuevos comandos para AutoCAD, que se ejecuten como cualquier otra orden. Es posible incluso redefinir los comandos de AutoCAD para que funcionen de forma distinta, por ejemplo se puede redefinir el comando "POLIGONO" para que dibuje polgonos estrellados en lugar de los regulares. AutoLISP se ha mejorado con la creacin de Visual LISP que ofrece un entorno de desarrollo integrado dentro de AutoCAD. Visual LISP incluye un compilador, un depurador y diversas utilidades para facilitar la programacin. Adems aade nuevos comandos para permitir la interaccin con objetos que utilizan ActiveX. Otra de las novedades que aporta Visual LISP son los reactores de objetos que permiten que AutoLISP responda a eventos.

Expresiones y procedimientos de evaluacinUn programa en AutoLISP consiste en una serie de expresiones del tipo "(funcin argumentos)". Cada expresin comienza con un parntesis de apertura al que sigue el nombre de una funcin de AutoLISP (o una funcin creada por el usuario) y una serie de argumentos (a veces opcionales) que dependen de la funcin indicada y van separados por al menos un espacio en blanco. Cada expresin termina con un parntesis de cierre, esto es muy importante pues el nmero de parntesis de apertura debe ser igual al de cierre.

Cada expresin de AutoLISP devuelve un valor. Un argumento tambin puede ser una expresin, crendose as una estructura formada por expresiones (listas) anidadas unas dentro de otras; de modo que la ms interior devolver su resultado como un argumento a la lista exterior. Cuando existen listas anidadas (unas dentro de otras), primero se evalan las ms interiores. Los primeros ejemplos que vamos a ver son sencillos y cortitos, as que puedes teclearlos directamente en la ventana de comandos de AutoCAD. Ejemplo: (+ 1 2) Ejecuta la funcin + que realiza la suma de los argumentos 1 y 2 devuelve el resultado 3. (+ 31 22 -3) Ejecuta la funcin + que realiza la suma de los argumentos 31, 22 y -3 devuelve el resultado 50. Prueba tambin: (- 17 2) (+ 2.5 22.8) (- 0.25 22.5) (+ 12 -2 31 -7.5) Ejemplo: (+ (* 2 3) 2) devuelve 8. Primero evala la lista interior y devuelve su resultado a la exterior. (+ 7 (/ 5.0 2) -3) devuelve 6.5. Qu sucedera si al escribir la expresin (+ 1 (/ 5.0 2)) nos olvidsemos de escribir el ltimo parntesis? Haz la prueba, veras que AutoCAD te indica que falta 1 parntesis de cierre. Si el interprete de comandos de AutoCAD encuentra un parntesis de apertura, supone que todo lo que vaya a continuacin hasta el parntesis de cierre es una expresin de AutoLISP. De modo que enva esa expresin al interprete de AutoLISP para que la evale. En el tema 2 veremos algunas de las operaciones matemticas que se pueden realizar con AutoLISP.

Tipos de objetos y datosLos elementos de las expresiones de AutoLISP pueden ser smbolos, valores concretos y tambin otras expresiones. Se pueden distinguir los siguientes tipos de elementos:

Smbolos: Cualquier elemento que no sea un valor concreto. Por ejemplo una variable, una funcin.

Enteros: Nmeros enteros comprendidos entre -32000 y 32000. Reales: Nmeros reales (180 es un nmero entero, pero 180.0 es un nmero real). Cadenas de texto: Texto con una longitud mxima de 132 caracteres. Descriptores de archivo: Representan un archivo de texto ASCII abierto. Nombres de entidades de AutoCAD: Nombre en hexadecimal de una entidad del dibujo. Conjuntos designados por el usuario: Conjuntos de entidades de AutoCAD. Funciones de usuario: Funciones definidas por el usuario. Funciones de AutoLISP: Funciones o comandos predefinidos de AutoLISP.

Ejemplo: (+ 5 2) devuelve 7. (+ 5 2.0) devuelve 7.0. En el primer caso todos los argumentos son nmeros enteros, y el resultado de su suma es un nmero entero. En el segundo caso, tenemos un nmero real, as que el resultado es un nmero real. Para que comprendas la importancia de esta distincin, realiza el siguiente ejemplo: (/ 5 2) (/ 5 2.0) Una de las mayores virtudes de AutoLISP es que pueden ejecutarse expresiones en medio de un comando de AutoCAD. Ejemplo: Ejecuta el comando "LINEA" e indica el primer punto, activa el forzado ortogonal (F8) y teclea... (+ 11 25) Esto devuelve el resultado de la suma al comando que se estaba ejecutando. Por eso dibuja una lnea de 36 mm de longitud en la direccin que indicaba el cursor. Prueba ahora indicando el radio de la circunferencia (- 70 25) al utilizar el comando llamado "CIRCULO" (mal llamado, debera ser "circunferencia"). Podemos emplear tambin la constante PI = 3.14159... para realizar clculos. Por ejemplo, ejecuta de nuevo el comando "CIRCULO" y cuando pregunte el radio de la circunferencia, teclea (/ 6 (* 2 PI)). Obtendremos una circunferencia de permetro 6.

Notacin empleadaPara describir las funciones de AutoLISP que se expliquen a lo largo del curso se seguir la siguiente notacin: (FUNCIN Argumentos_necesarios [Argumentos_opcionales] ) Los nombres de las funciones de AutoLISP aparecen en color azul y el cdigo a teclear en cursiva.

Convenciones recomendadas

En este apartado se indicarn una serie de convenciones recomendables a la hora de programar. Alguna de ellas puede que an no las entiendas, pero no te preocupes porque las iremos recordando a medida que avancemos en el curso.

Para los comentarios incluidos en el cdigo, se recomienda utilizar el siguiente mtodo: o ;;; Antes del cdigo de las funciones, explicando su funcionamiento. o ;; En medio del cdigo del programa. o ; Para explicar una lnea de cdigo. A diferencia de las anteriores, esta no se inserta en la columna 1, se insertar al terminar el cdigo de la lnea que comenta. Es muy recomendable utilizar un formato tabulado para el cdigo. Evitar el uso de variables globales innecesarias. Utilizar los comandos de AutoCAD y sus opciones en Ingls y precedidos por "._" No abusar de la funcin "SETQ". No utilizar T, MIN, MAX, LAST como smbolos (nombres de variables y funciones). Recuperar el valor inicial de las variables de AutoCAD que han sido modificadas. Aadir unas lneas al final del programa para indicar el nombre del nuevo comando, autor... No introducir demasiado cdigo en la funcin principal. Incluir una funcin de tratamiento de errores. Evitar que el usuario pueda introducir datos errneos. En general es recomendable que, tras ejecutar el nuevo comando, si se ejecuta el comando "DESHACER" ("H") se deshagan todos los cambios realizados por el comando.

Qu es una variable?Que no sabes que es una variable? Recuerdas cuando en la escuela te decan "Tengo 3 melones, le doy uno a Juan y despus de comprar otros 2, me com uno porque tena hambre". Pues los melones son una variable. Nosotros hacamos: 1 tengo 3 melones x=3 (x es nuestra variable). Luego le 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 valor que vara (o puede hacerlo) a lo largo del tiempo. Pero podamos haber llamado a la variable "y"o "z", y por qu no "melones"?

(SETQ Variable1 Valor1 [Variable2 Valor2 ... ] )En el ejemplo anterior logramos dibujar una circunferencia de 6 unidades de permetro, pero que sucede si queremos utilizar el valor obtenido por (/ 6 (* 2 PI)) para realizar otra operacin, tendremos que volver a teclear la expresin anterior. Existe alguna opcin para almacenar en memoria los resultados de una operacin, tal como hace una calculadora? Desde luego que si, AutoLISP permite almacenar miles de datos en variables, que se almacenan en la memoria del ordenador. La funcin de AutoLISP empleada para definir variables y asignarles un valor es SETQ y permite definir varias variables en una misma expresin. La funcin SETQ devuelve el valor de la ltima variable definida. Con respecto a los nombres utilizados para designar a los smbolos creados por el usuario (variables y funciones):

No son sensibles a las maysculas. Es lo mismo bloque, BLOQUE y Bloque. No pueden contener espacios en blanco, ni los caracteres " ( ) . ; ' Pueden contener nmeros, pero no estar formados nicamente por ellos. No utilizaremos nombres de variables que coincidan con los nombres de las funciones de AutoLISP ni de las variables de sistema de AutoCAD. No existe lmite en cuanto al nmero de caracteres, pero es recomendable emplear nombre cortos y descriptivos. No es necesario declarar previamente las variables, como sucede en otros lenguajes de programacin. En AutoLISP una misma variable puede contener primero un nmero entero, luego uno real, despus una cadena de texto, etc.

Ejemplo: (SETQ a 3) Esta expresin crea la variable a y le asigna el valor 3. Devuelve el valor de la variable a. Que valor crees que devolver (SETQ b (+ 1 3) melones 23.0)? Fjate que se han definido dos variables b y melones de valor 4 y 23.0 respectivamente. Como melones ha sido la ltima variable evaluada, la expresin anterior devuelve su valor. Si el interprete de comandos de AutoCAD recibe una palabra precedida por el signo de exclamacin "!", comprobar si ese termino ha sido empleado como un smbolo (nombre de variable o una funcin de usuario) de AutoLISP. En cuyo caso devolvera su valor y en caso contrario devolvera nil, que es lo mismo que nada o vaco. Por ejemplo: !a devuelve 3. Prueba tambin las siguientes expresiones y comprueba los valores asignados a las variables: (SETQ c (+ b 3)) Los valores de las variables tambin pueden utilizarse para realizar operaciones y asignar el resultado de dichas operaciones a una variable. (SETQ d b) Se puede definir una variable igual al valor de otra variable. (SETQ a 3.5) Se puede modificar el valor asociado a una variable, por eso se llama variable. (SETQ b 2.0) Qu sucede con el valor de la variable d? Tomar el nuevo valor de b o seguir con el anterior? Al definir la variable d se le asigno el valor que tena la variable b en ese momento, no se estableci ninguna relacin entre ambas variables. Tambin se puede asignar valores no numricos a las variables. Por ejemplo, una cadena de texto. Las cadenas de texto son secuencias de uno o ms caracteres encerrados entre comillas. Dentro de una cadena de texto pueden insertarse una serie de carcteres de control:

\\ representa al smbolo \ \" representa al smbolo " \n representa un cambio de lnea (retorno del carro) \t representa una tabulacin

(SETQ a "\tBienvenido al tema de AutoLISP" )

En este caso adems, hay que notar que en la variable a primero se almacenaba un valor entero, luego uno real y ahora una cadena de texto. La posibilidad de reutilizar variables con distintos tipos de datos puede ser muy til, pues dota al programador de una gran flexibilidad al escribir el cdigo. Pero tambin supone que se requiera ms cuidado para no pasar a una funcin una variable con un tipo de dato incorrecto. Por ejemplo: (+ a b) Existen una serie de smbolos predefinidos:

T Representa al valor lgico Cierto o Verdadero. nil Representa al valor lgico Falso.

(SETQ b T) (SETQ c nil) En este caso, a la variable a se le ha asignado una cadena de texto, a b el valor Cierto o Verdadero y a c Falso. Para almacenar el radio de la circunferencia de permetro 6 unidades en una variable podemos teclear: (SETQ rad (/ 6 (* 2 PI))) Ejemplo: Por qu las siguientes expresiones estn mal? (SETQ 157 25) (SETQ rad 5 Rad 4) (SETQ b Curso de AutoLISP) Por ltimo veamos porque no debemos emplear para los nombres de las variables los nombres de las funciones de AutoLISP. (SETQ + 23) En este caso asignamos a la variable + el valor 23. Prueba (+ 5 2.5) Ahora + no representa a la funcin suma, sino a una variable de valor 23. De modo que el primer termino de la expresin anterior no es una funcin, por lo que da un error. Para recuperar el modo habitual de trabajo de la funcin + es necesario cerrar la sesin actual de AutoCAD e iniciar una nueva sesin.

Operaciones matemticas bsicasEn el tema anterior ya vimos algn ejemplo de como funcionan las funciones matemticas bsicas (suma, resta, divisin y multiplicacin). Ahora explicaremos su funcionamiento con mayor profundidad.

(+ [nmero1 nmero2 ... ] )Suma los nmeros indicados como argumentos y devuelve el resultado de dicha suma. Si todos los nmeros de la lista son enteros, el resultado tambin ser entero. (+ 3 9) devuelve 12

(+ 3.0 9) devuelve 12.0 (SETQ a (+ 3 9 4)) devuelve 16 y lo almacena en la variable a (+ 3.5 -1) devuelve 2.5 Prueba ahora la siguiente expresin: (SETQ a (+ a 2.5)) devuelve 18.5 Hemos asignado a la variable a el resultado de una operacin en la que usamos el anterior valor asignado a la variable a como uno de los argumentos de la operacin. Si le pasamos a la funcin + un nico nmero como argumento, nos devuelve ese nmero. (+ 12.5) devuelve 12.5 (+ -7.0) devuelve -7.0 Si ejecutamos la funcin suma sin argumentos, devuelve 0. (+ ) devuelve 0 La expresin (+ .5 2) nos dar un error. Los nmeros reales siempre deben comenzar por un nmero entero, incluso si es cero, seguido de la parte decimal. (+ 0.5 2) devuelve 2.5 (+ 3 -0.6) devuelve 2.4

(- [nmero1 nmero2 ... ] )Resta al primer nmero todos los siguientes nmeros pasados como argumentos. Si todos los nmeros de la lista son enteros, el resultado tambin ser entero. (- 11.0 5) devuelve 6.0 (- 11 5) devuelve 6 (SETQ a (- 12 5 4)) devuelve 3 y lo almacena en la variable a (- 3.5 -1) devuelve -4.5 (SETQ a (- a 2.5)) devuelve 0.5 y lo almacena en la variable a. Si le pasamos a la funcin - un nico nmero como argumento, nos devuelve ese nmero cambiado de signo. (- 12.5) devuelve -12.5 (- -7.0) devuelve 7.0

En la expresin anterior, el primer signo "-" representa a la funcin resta, mientras que el segundo representa el signo de un nmero negativo. Si ejecutamos la funcin resta sin argumentos, devuelve 0. (- ) devuelve 0

(* [nmero1 nmero2 ... ] )Multiplica los nmeros indicados como argumentos y devuelve el resultado de dicho producto. Si todos los nmeros de la lista son enteros, el resultado tambin ser entero. (* 3 9) devuelve 27 (* 3.0 9) devuelve 27.0 (SETQ a (* 3 9 4)) devuelve 108 y lo almacena en la variable a (* 3.5 -1) devuelve -3.5 Prueba ahora la siguiente expresin: (SETQ a (* a 2.5)) devuelve 270.0 Si le pasamos a la funcin * un nico nmero como argumento, nos devuelve ese nmero. (* 12.5) devuelve 12.5 (* -7.0) devuelve -7.0 Si ejecutamos la funcin * sin argumentos, devuelve 0. (* ) devuelve 0

(/ [nmero1 nmero2 ... ] )Divide el primer nmero entre el siguiente y devuelve el resultado. Si se pasan ms de dos nmeros como argumentos, el primer nmero se dividir entre el producto de los restantes nmeros. (/ 45 5 3) devuelve 3 (/ 11 5.5) devuelve 2.0 En esta funcin es muy importante recordar que si todos los nmeros de la lista son enteros, el resultado tambin ser entero. (/ 7 2) devuelve 3 (/ 7 2.0) devuelve 3.5

(SETQ a (/ 12.5 4 2)) devuelve 1.5625 y lo almacena en la variable a (/ 3.5 -1) devuelve -3.5 (SETQ a (/ a 0.5)) devuelve 3.125 y lo almacena en la variable a. Si le pasamos a la funcin / un nico nmero como argumento, nos devuelve ese nmero. (/ 12.5) devuelve 12.5 (/ -7.0) devuelve -7.0 Si ejecutamos la funcin / sin argumentos, devuelve 0. (/ ) devuelve 0

(1+ )Esta funcin incrementa en una unidad el nmero indicado como argumento. (1+ 5) devuelve 6. Ojo entre "1" y "+" no debe haber ningn espacio, ya que el nombre de la funcin es "1+". (1+ 2.5) devuelve 3.5 (1+ 0) devuelve 1 (1+ -7) devuelve -6 Una aplicacin bastante habitual de esta funcin es la de incrementar ndices o contadores: (SETQ i 1) (SETQ i (1+ i)) devuelve 2

(1- )Esta funcin reduce en una unidad el nmero indicado. (1- 5) devuelve 4. Ojo entre "1" y "-" no debe haber ningn espacio, ya que el nombre de la funcin es "1-". (1- 2.5) devuelve 1.5 (1- 0) devuelve -1 (1- -1) devuelve -2

Solicitar nmeros al usuarioEn este apartado veremos dos funciones de AutoLISP que no permitirn solicitar al usuario un nmero entero o real. Esto nos permitir interactuar con el usuario y pedirle informacin.

(GETINT [mensaje] )Solicita del usuario un nmero entero. En caso de que el usuario introduzca un nmero real o cualquier otro dato que no sea un nmero entero, AutoCAD recordar mediante un mensaje que est solicitando un nmero entero y no finalizar la ejecucin de la funcin hasta que se introduzca un valor entero, o se pulse ESC para cancelar su ejecucin. (GETINT) Puede indicarse un mensaje de solicitud opcional, que facilite al usuario informacin acerca de lo que se est pidiendo. El mensaje debe ser una cadena de texto y por tanto debe estar entre comillas. (GETINT "Cuantos aos tienes:") Podemos asignar el valor introducido por el usuario a una variable y as utilizarlo despus. (SETQ edad (GETINT "Cuantos aos tienes:")) (SETQ edad (+ edad 1)) nos dar la edad que tendrs el prximo ao. Tambin puedes crear una variable que contenga el mensaje de solicitud de la funcin GETINT (SETQ mens "Cuantos aos tienes:") (SETQ edad (GETINT mens)) En este caso mens es una variable que almacena una cadena de texto, pero no es una cadena de texto. Por lo tanto, no debe ir entre comillas. Prueba ahora el siguiente ejemplo: (SETQ a 27 mens "Cuantos aos tienes:") (SETQ edad (GETINT mens)) Que pasar si como respuesta a la solicitud de la edad del usuario se introduce !a. Parece lgico que le estamos indicando el valor de la variable a, que contiene el valor numrico 27, de modo que la variable edad debera tomar el valor 27, pero observaras que no es as. Haz la prueba: nos indicar que es "Imposible volver a entrar en LISP.". Esto es debido a que al ejecutar la funcin GETINT se est ejecutando el interprete de LISP, y al indicar !a como respuesta estamos diciendo que ejecute el interprete de LISP para obtener el valor asociado a la variable a. Como

el interprete de LISP ya est en ejecucin, no puede volver a ejecutarse y nos muestra el mensaje anterior.

(GETREAL [mensaje] )Solicita del usuario un nmero real. En caso de que el usuario introduzca un nmero entero, el interprete de AutoLISP lo considerar como un real. Si se introduce cualquier otro tipo de dato que no sea numrico, recordar mediante un mensaje que est solicitando un nmero real y no finalizar la ejecucin de la funcin hasta que se introduzca un valor numrico, o se pulse ESC para cancelar su ejecucin. (GETREAL) Puede indicarse un mensaje de solicitud opcional, que facilite al usuario informacin acerca de lo que se est pidiendo. El mensaje debe ser una cadena de texto y por tanto debe estar entre comillas. (SETQ peso (GETREAL "Cuantos kilos pesas:")) (SETQ peso (- peso 1)) nos dar el peso que tendrs si adelgazas un kilo. Tambin puedes crear una variable que contenga el mensaje de solicitud de la funcin GETREAL (SETQ mens "Cuantos kilos pesas:") (SETQ peso (GETREAL mens))

Definir funciones de usuarioHemos visto tan solo algunas de las funciones de AutoLISP, pero tambin es posible crear nuestras propias funciones. Es ms, podemos redefinir las funciones de AutoLISP e incluso los comandos de AutoCAD. La instruccin de AutoLISP que nos permitir crear nuestras propias funciones, denominadas funciones de usuario, se llama DEFUN.

(DEFUN ( [argumentos] / [variables_locales] ) [expr1] [expr2] ...)El primer argumento representa el nombre de la funcon de usuario que queremos definir. Hay que tener cuidado de no emplear los nombres de las funciones de AutoLISP, ya que en dicho caso se redefiniran. Despus de indicar el nombre de la funcin, se deben indicar entre parntesis los argumentos y las variables locales, separados por una barra inclinada.

Los argumentos son valores que recibir la funcin cuando sea ejecutada por el usuario, o llamada desde otras funciones. Las variables locales son aquellas variables que se emplearn tan solo dentro de la funcin que queremos definir, de modo que restringimos su uso al entorno de la funcin.

Por ltimo, se aaden las expresiones que ejecutar la funcin. Veamos algunos ejemplos: (DEFUN 2+ ( valor ) (+ valor 2)) En este caso hemos definido una nueva funcin llamada "2+", que recibe como argumento un nmero y realiza la suma de ese nmero y 2. Las funciones de AutoLISP las ejecutabamos escribiendo (1+ 5) directamente desde la lnea de comandos, bien pues las funciones de usuario se ejecutan exactamente igual. Prueba: (2+ 5) devuelve 7 (2+ 0) devuelve 2 (2+ -2) devuelve 0 Defun devuelve el resultado de la ltima expresin ejecutada, que en el caso anterior es (+ valor 2). Que sucede si tratamos de ejecutar la funcin sin pasarle ningn argumento, o pasandole un argumento que no sea de tipo numrico?. Veamoslo: (2+ ) indica "; error: argumentos insuficientes" (2+ "texto") indica "; error: tipo de argumento errneo: numberp: "texto"" (2+ 1 2) indica "; error: demasiados argumentos" Podras pensar que el nmero indicado se almacena en una variable llamada "valor", pero no es as. Compruebalo escribiendo !valor en la lnea de comandos, lo que nos devolver nil. En la funcin anterior tenemos un argumento y no hay variables locales. Vamos a modificarla un poco: (DEFUN 2+ ( valor ) (SETQ valor (+ valor 2))) Ahora seguro que estas totalmente convencido de que el resultado obtenido se almacena en la variable "valor". Pues comprobemos si tienes razn: (2+ 5) devuelve 7 !valor devuelve nil Parece que estabas equivocado. La funcin "2+" recibe como argumento un nmero, que almacena en la variable "valor". Pero el mbito de aplicacin es local, es decir una vez que salgamos de la funcin "2+" la variable "valor" recupera su valor inicial, que en este caso es nil. Vamos con otra prueba... (SETQ valor 5) devuelve 5 (2+ 4) devuelve 6

Que valor crees que tendr la variable valor? Pensemos un poco. 1. Inicialmente valor = nil 2. Al ejecutar (SETQ valor 5) valor = 5 3. Cuando llamamos a la funcin "2+" tenemos que "valor" = 4 4. Dentro de la funcin "2+" asignamos (SETQ valor (+ valor 2)) de modo que "valor" = 4 + 2 = 6 5. Pero al salir de la funcin "2+" recuperamos el valor que tena la variable "valor" antes de llamar a la funcin, valor = 5 Por tanto, si tecleamos !valor devolvera 5. Pero, que pasa si ejecutamos (SETQ valor (2+ 4)). Se repiten los puntos 1-4 anteriores, pero al salir de la funcin "2+" le asignamos a "valor" el valor devuelto por la funcin, que es 6. De modo que "valor" = 6. Retoquemos un poco ms la funcin "2+" y borremos el contenido de "valor" (DEFUN 2+ ( valor ) (SETQ inicial valor valor (+ valor 2))) (SETQ valor nil) En este caso, dentro de la funcin "2+" declaramos una variable a la que se le asigna el valor que recibe como argumento la funcin. (2+ 4) Que valor tendrn ahora las variables "valor" e "inicial"? Compruebalo: !valor devuelve nil !inicial devuelve 4 Observa que "valor" se comporta como una variable local, solo se emplea dentro de la funcin. Sin embargo "inicial" es de mbito global, es decir sigue empleandose al salir de la funcin. Vamos a modificar un poquito ms nuestra funcin: (DEFUN 2+ ( valor / inicial ) (SETQ inicial valor valor (+ valor 2))) Ahora hemos aadido la variable "inicial" a la lista de variables locales, con lo que su mbito ser local. Para comprobarlo... !inicial devuelve 4 (SETQ inicial nil) !inicial devuelve nil (2+ 3) !inicial devuelve nil Bueno, vamos con la ltima modificacin de la funcin "2+"

(DEFUN 2+ ( / valor ) (SETQ valor (GETINT "Nmero: ")) (SETQ valor (+ valor 2))) Ahora la funcin "2+" no tiene argumentos, as que para ejecutarla tan solo debemos poner su nombre entre parntesis: (2+) La variable "valor" es de mbito local y se emplea GETINT para solicitar un nmero al usuario. Lo habitual es que se trate de evitar el uso de variables globales innecesarias. De modo que las variables que no sean globales, se deberan aadir a la lista de variables locales dentro de las definiciones de las funciones de usuario.

Crear nuevos comandos de AutoCADLa funcin de AutoLISP DEFUN no solo nos permite crear funciones de usuario, tambin nos permite crear nuevos comandos de AutoCAD. Siguiendo con el ejemplo anterior... (DEFUN C:2+ ( / valor ) (SETQ valor (GETINT "Nmero: ")) (SETQ valor (+ valor 2))) Si anteponemos al nombre de la funcin a definir "C:" en lugar de crear una funcin de usuario, se crea un nuevo comando de AutoCAD. La funcin seguir funcionando exactamente igual, la nica diferencia est en el modo de ejecutarse. Ahora no es necesario poner el nombre de la funcin entre parntesis, sino que se escribe directamente. 2+ Tambin puede ejecutarse poniendo el nombre de la funcin precedido de "C:" entre parntesis. (C:2+) En caso de que el nuevo comando creado necesite algn argumento, tan solo podr ejecutarse del ltimo modo. (DEFUN C:2+ ( valor / inicial ) (SETQ inicial valor valor (+ valor 2))) (C:2+ 2) devuelve 4 La funcin que hemos creado solo nos servir para la sesin actual de AutoCAD. Es ms, tan solo est definida la funcin 2+ en el dibujo actual, de modo que si hay ms dibujos abiertos, en ellos no est definida. En el siguiente tema veremos como guardar nuestras funciones en archivos de texto, a la vez que comenzamos a trabajar con el entorno de Visual LISP.

Archivos de cdigo fuente en AutoLISPYa hemos visto que las funciones de AutoLISP se pueden ejecutar directamente desde la ventana de comandos de AutoCAD. Pero el escribir el cdigo directamente

en AutoCAD tiene varios inconvenientes, como ya dijimos en el primer tema del curso:

1. El reducido tamao de la ventana de comandos de AutoCAD.2. La dificultad de escribir todo el cdigo seguido, sin tabular. Esto es debido a que cada vez que se pulsa Intro, AutoCAD evala lo que se ha escrito. 3. El cdigo no se almacena en ningn sitio, as que se perder al cerrar el dibujo actual o AutoCAD. De modo que en la ventana de comandos de AutoCAD tan solo se escribiran pequeas lneas de cdigo que no interese guardar. Suele emplearse por tanto para hacer pruebas y depurar cdigo, aunque tambin se puede utilizar como una ayuda ms para el diseo con AutoCAD. El cdigo de las funciones de AutoLISP se escribe en un editor de textos ASCII, para que as se puedan almacenar. Se puede emplear cualquier editor de texto que permita tan solo cdigos ASCII, por ejemplo el bloc de notas de Windows. Otros editores, como MS Word, insertan cdigos para diferenciar los estilos de texto, las tabulaciones, etc. y no se pueden emplear para escribir las rutinas de AutoLISP, ya que el interprete de AutoLISP no sabe interpretar esos cdigos. Adems del bloc de notas, existen muchos otros editores de texto que se pueden emplear para escribir cdigo fuente en AutoLISP. Algunos de estos editores, disponen de utilidades para la programacin (permitiendo incluso emplearlos para distintos lenguajes de programacin). Otros editores estn ya enfocados a la programacin en LISP o AutoLISP. Desde la versin 14, AutoCAD incorpora un editor para AutoLISP, en el que tenemos entre otras las siguientes utilidades:

Evaluacin de parntesis durante la programacin. Posibilidad de compilar el cdigo, consiguiendo as aumentar su velocidad de ejecucin. Depurador de cdigo especfico para AutoLISP con opciones para: Ejecutar el cdigo paso a paso, indicar puntos de parada, evaluar expresiones y valores de variables, etc. Diferenciar el cdigo fuente con distintos colores. Tabulado automtico del cdigo. Utilidades para gestionar proyectos con varios archivos de cdigo. Carga de los archivos en AutoCAD.

Nosotros seguiremos utilizando la ventana de comandos de AutoCAD para ver como trabajan las funciones de AutoLISP, y nos iremos al editor de Visual Lisp para crear nuevas funciones y comandos. Los archivos de AutoLISP son archivos de texto con extensin LSP.

Nuestra primera funcin de usuarioAntes de comenzar con el editor de Visual LISP, vamos a crear nuestra primera funcin de usuario: Se trata de una funcin para convertir un ngulo de radianes a grados decimales. El cdigo de la funcin sera el siguiente: (defun RAG ( ang )

(/ (* ang 180.0) pi) ) El cdigo de las rutinas publicadas en el curso se escribir con el siguiente formato:

Comentarios en el cdigo Funciones de AutoLISP Nmeros Textos FUNCIONES DE USUARIO Y NUEVOS COMANDOS Nombres de variables, parntesis, etc...

Hay tres reglas bsicas que sigue AutoLISP:

1. El nmero de parntesis de apertura debe ser igual al nmero de parntesisde cierre.

2. Primero se evaluan las listas ms interiores.3. Toda funcin de AutoLISP devuelve un resultado. El interprete de AutoLISP no evala los retornos de carro (Intros), de modo que el cdigo se poda haber escrito todo seguido, en una misma lnea: (defun RAG ( ang ) (/ (* ang 180.0) pi) ) pero as es ms difcil de leer. Esta funcin tiene muy poco cdigo, pero imaginate una funcin mucho mayor escrita toda en la misma lnea... Fjate en que la segunda lnea se presenta tabulada, de modo que no comienza a la misma altura que el resto, sino que est desplazada hacia la derecha. Esto nos indica que est incluida dentro de una lista de nivel superior, la de la funcin defun. No es necesario tabular el cdigo, pero facilita su lectura y adems nos permite detectar posibles errores con los parntesis (Regla nmero 1). Pi es una constante que ya est definida en AutoLISP, pi = 3.141592... En la primera lnea "(defun RAG ( ang )" definimos la funcin RAG (Radianes A Grados) que recibe un argumento "ang" (el ngulo en radianes). Veamos como funciona la segunda lnea: Por la Regla nmero 2, primero se evaluar la lista interior (* ang 180.0) que multiplica el ngulo en radianes "ang" por 180.0 y devuelve el resultado a la lista de nivel superior (recuerda la Regla nmero 3) que lo divide entre pi = 3.141592... devolviendo a su vez el resultado de la divisin (el ngulo en grados decimales) a la lista de nivel superior, defun. La ltima lnea cierra la lista de la funcin defun, verificandose as la Regla nmero 1. Recordemos la estructura de la funcin de AutoLISP defun: (DEFUN ( [argumentos] / [variables_locales] ) [expresin1] [expresin2] ...) . En la funcin RAG tenemos un argumento y no se han declarado variables locales (por lo que no es necesario poner el caracter "/"), adems solo tenemos una expresin (/ (* ang 180.0) pi) . Como se dijo en el tema anterior, defun devuelve el resultado de la ltima expresin, que en nuestro caso resulta ser el ngulo ya convertido a grados decimales. Nuestra funcin RAG se ejecutara as: (RAG 1.57) siendo 1.57 el ngulo en radianes, y devolvera ese ngulo en grados decimales (aproximadamente 90). No es necesario poner el nombre de la funcin RAG en maysculas, ya que AutoLISP no

diferencia las maysculas de las minsculas (salvo en contadas excepciones que ya explicaremos). Aunque al poner los nombres de las funciones en maysculas se diferencian perfectamente del resto del cdigo.

Los comentarios en el cdigoEs imprescindible aadir comentarios al cdigo para explicar que es lo que hace y como se hace. En AutoLISP todo lo que en una lnea va despus de un punto y coma (como este ;) se considera un comentario, de modo que no se evala. Da igual poner uno, dos o 45 punto y comas seguidos, al poner el primero AutoLISP ya sabe que todo lo que est a continuacin, en esa lnea, es un comentario. Tal vez penseis que no es tan importante aadir explicaciones en el cdigo. Pero si teneis que leer una rutina que creasteis hace meses os sern muy tiles, por que seguramente no recordareis muy bien como funciona. Adems, si alguien va a leer alguna de vuestras rutinas le facilitariais mucho la labor. Al igual que a vosotros os ser ms sencillo leer y entender una rutina con abundantes comentarios. Para los comentarios incluidos en el cdigo, se recomienda utilizar el siguiente mtodo:

;;; Antes del cdigo de las funciones, explicando su funcionamiento. ;; En medio del cdigo del programa. ; Para explicar una lnea de cdigo. A diferencia de las anteriores, esta no se inserta en la columna 1, sino al terminar el cdigo de la lnea que comenta.

Por ejemplo, la funcin RAG con comentarios podra quedar as: ;;; Esta funcin recibe el valor de un ngulo en radianes y lo devuelve en grados decimales. (defun RAG ( ang ) ; Recibe un ngulo en radianes (/ (* ang 180.0) pi) ;; Multiplica el ngulo en radianes por 180.0 y lo divide por pi. )

El editor de Visual LISPEl editor de Visual Lisp se inicia desde AutoCAD de varias formas:

Ejecutando el comando de AutoCAD "VLIDE". Desde el men desplegable "Herr-->AutoLISP-->Editor de Visual Lisp"

Mostrar algo similar a la siguiente imagen:

Al abrir el editor veremos dos ventanas, "consola de Visual LISP" y "Rastreo". De momento no vamos a explicar para que se usan ni como funcionan estas ventanas. Estamos ante un editor de textos, como otro cualquiera, pero con utilidades especficas para la programacin en AutoLISP. De modo que para crear un nuevo archivo hacemos lo mismo que en cualquier editor de textos: "Archivo-->Nuevo archivo" (o pulsa Control + N). Aparece una nueva ventana, tal como puede verse en la siguiente imagen:

Es en esta pantalla donde vamos a escribir el cdigo de nuestra rutina RAG, pero antes un pequeo comentario... Es bastante habitual aadir al principio de los archivos de AutoLISP unas lneas de comentarios indicando el nombre del autor, fecha, nombre de los comandos y/o funciones definidas en el archivo, y una breve descripcin de estos. De modo que al cdigo anterior le aadiremos unas lneas en la cabecera del archivo: ;;;________________________MecaniCAD__________________________;;; ;;;_____________http://www.peletash.com/mecanicad_____________;;; ;;;_________________________RAG.LSP___________________________;;; ;;;_______________________Versin 1.0_________________________;;; ;;;________________________21/02/2002_________________________;;; ;;; Esta funcin recibe el valor de un ngulo en radianes y lo devuelve en grados decimales. (defun RAG ( ang ) ; Recibe un ngulo en radianes

(/ (* ang 180.0) pi) ;; Multiplica el ngulo en radianes por 180.0 y lo divide por pi. ) El editor de Visual LISP realiza las tabulaciones automticamente. Y aunque se pueden eliminar o modificar a vuestro gusto (aadiendo o quitando espacios y tabulaciones), lo recomendable es mantener el formato por defecto para el cdigo. Veamos como queda la funcin GAR en el editor:

En primer lugar observamos que el cdigo tiene distintos colores. Esto es simplemente una ayuda visual para diferenciar los diferentes elementos de nuestras rutinas:

Las funciones de AutoLISP se muestran de color azul. Los comentariosen morado, con gris de fondo. Los nmeros en verde. Etc.

El formato coloreado del cdigo se puede desactivar, o se pueden modificar los colores predefinidos para los diferentes elementos. Pero el mantener el formato de

colores para el cdigo, nos puede ayudar a detectar errores. Por ejemplo, si ponemos "(SETW radianes ...", SETW aparecer en negro y no en azul, por que la funcin de AutoLISP es SETQ, de modo que nos indica que hemos escrito mal el nombre de la funcin. En cuanto a la tabulacin, tal vez llame la atencin el ltimo parntesis (el de cierre de la funcin defun), ya que no est a la misma altura que su parntesis de apertura. Hay editores para AutoLISP que insertan los parntesis de cierre a la misma altura que sus correspondientes parntesis de apertura y hay otros editores que insertan los parntesis de cierre tabulados, tal como hace (por defecto) el editor de Visual LISP. Una vez escrito el cdigo de la funcin RAG, tan solo nos queda guardarlo en un archivo. Es recomendable crear un directorio (carpeta) en el que guardar todas nuestras rutinas. Se le suele dar a los archivos de AutoLISP el mismo nombre del comando o funcin que est definida en l, aunque podemos guardar esta rutina en el archivo "klhsduif.lsp" luego no la reconoceriamos. As que lo mejor ser guardar el cdigo de la funcin GAR en el archivo "RAG.lsp", dentro del directorio que hemos creado para almacenar nuestras rutinas. As que selecciona "Archivo --> Guardar como" e indica la ruta y el nombre del archivo. Ahora puedes intentar crear una funcin llamada GAR que reciba como argumento un ngulo en grados decimales y que devuelva ese ngulo en radianes. Es practicamente igual a la funcin que acabamos de ver. Pero recuerda... Antes de empezar a programar que hay q hacer? Pues pensar en lo que hay que hacer y en como lo vamos a hacer. Como esta rutina es muy sencilla no es necesario escribir el pseudocdigo (ni hacer un diagrama de flujo), tan solo hay que pensar un poco en lo que se va a hacer. Guarda el cdigo de la funcin GAR en un archivo llamado "GAR.lsp" en el directorio donde tengas tus rutinas.

Cargar los archivos de AutoLISPPara que la funcin RAG que creamos en el tema anterior se pueda ejecutar en AutoCAD, hay que cargar el archivo de AutoLISP en el que est definida. Existen varias formas de cargar los archivos de AutoLISP, pero de momento tan solo vamos a ver tres: 1. Cargar un archivo desde el editor de Visual LISP. 2. En el men desplegable de AutoCAD "Herr-->AutoLISP-->Cargar". 3. Utilizando la funcin de AutoLISP LOAD. Si estamos en el editor de Visual LISP y tenemos abierto un archivo con una rutina, para cargarla en AutoCAD podemos:

Seleccionar en los mens desplegables del Visual LISP "Herramientas --> Cargar texto en editor". Pulsando sobre el icono . Tecleando la combinacin de teclas CTRL+ALT+E.

Al cargar el archivo, aparece la Consola de Visual LISP mostrando un mensaje parecido al siguiente: "; N formularios cargado de #. En caso de que se produzca algn error en el proceso de carga del archivo, en la consola de Visual LISP se nos indicara el tipo de error que se ha producido. De

modo que habria que modificar el cdigo para corregir ese error antes de cargar la rutina. Una vez cargada la rutina en AutoCAD, podemos probar si funciona. Teclea directamente en la ventana de comandos de AutoCAD:

(rag 0) (rag pi) (rag (/ pi 4))

El segundo mtodo para cargar un archivo de AutoLISP en AutoCAD (seleccionando en el men de AutoCAD "Herr-->AutoLISP-->Cargar") muestra un letrero de dilogo en el que se selecciona el archivo a cargar (tambin se pueden seleccionar ms de un archivo) y se pulsa el botn "Cargar".

(LOAD archivo [resultado_si_falla])La funcin LOAD permite cargar en AutoCAD el archivo de AutoLISP que se indique. Por ejemplo para cargar el archivo RAG sera: (load "rag")

No hace falta indicar la extensin del archivo. Escribiendo as el nombre del archivo solo cargar el archivo RAG.LSP si est en uno de los directorios de soporte de AutoCAD o en el directorio actual. En caso contrario hay q indicar la ruta completa: (load "c:\rutinas\rag.lsp") Pero esto nos dara un error, ya que AutoCAD no reconoce el caracter "\", de modo que hay que escribirlo de forma algo especial. Para AutoLISP el caracter "\" hay que indicarlo de cualquiera de esas 2 formas: "\\" o "/". Por lo tanto: (load "c:\\rutinas\\rag.lsp") o (load "c:/rutinas/rag.lsp") En caso de que no se encuentre el archivo, la expresin load puede ejecutar lo que se indique en [resultado_si_falla]. Por ejemplo: (LOAD "rag" (setq test 0)) En este caso, si no se encuentra el archivo RAG.lsp a la variable test se le asigna el valor cero. Suele emplearse para que, cuando se ejecute LOAD desde un archivo de AutoLISP, podamos indicarle al usuario que no se ha encontrado el archivo. Como indica el siguiente pseudocdigo: Si test = 0 ==> Mensaje al usuario "Archivo no encontrado" Esto es todo, de momento, sobre la carga de archivos de AutoLISP en AutoCAD. Ms adelante veremos mtodos mucho mejores para cargar nuestras rutinas. Veamos como sera la funcin GAR propuesta en el tema anterior: ;;;________________________MecaniCAD__________________________;;; ;;;_____________http://www.peletash.com/mecanicad_____________;;; ;;;_________________________GAR.LSP___________________________;;; ;;;_______________________Versin 1.0_________________________;;; ;;;________________________21/02/2002_________________________;;; ;;; Esta funcin recibe el valor de un ngulo en grados decimales y lo devuelve en radianes. (defun GAR ( ang ) (/ (* ang pi) 180.0) ) Es muy muy parecida a la funcin RAG, no?

Crear un directorio para los archivos de AutoLISPSupongamos que el directorio que hemos creado para almacenar nuestras rutinas es "C:\Rutinas". Veamos como aadirlo a los directorios de soporte de AutoLISP: Inicia AutoCAD. En el men desplegable "Herr" selecciona "Opciones". As aparece un letrero de dilogo que nos permitir configurar AutoCAD. En la primera pestaa "Archivos" tenemos una opcin denominada "Ruta de bsqueda de archivos de soporte". Si no est expandida, para ver su contenido pulsamos con el ratn sobre el + que aparece a la izquierda. Para aadir un nuevo directorio de soporte pulsamos el botn "Aadir" que se encuentra a la derecha del cuadro de dilogo. Esto crear una nueva etiqueta, en la que podemos escribir la ruta del directorio o pulsar el botn "Examinar" para seleccionarlo. Ya hemos aadido "C:\Rutinas" a los directorios de soporte de AutoCAD.

Tambin podemos subir o bajar el nuevo directorio en la lista de directorios de soporte. Esto se hace para definir las prioridades, es decir donde buscar primero. De modo que si subimos nuestro directorio hasta el primer lugar (como en la imagen), este ser el primer directorio en el que busque algo AutoCAD.

Operaciones matemticas

Hemos visto las operaciones matemticas bsicas: suma, resta, multiplicacin y divisin y las funciones 1+ y 1-. Ahora vamos con otras funciones de AutoLISP que nos permitiran realizar casi cualquier operacin matemtica en nuestras rutinas.

(ABS numero)Esta funcin devuelve el valor absoluto del nmero que se le pase como argumento. Por ejemplo: (abs 23.8) devuelve 23.8 (abs -23.8) tb devuelve 23.8 Si el nmero que recibe como argumento es entero, devuelve un nmero entero y si es un nmero real, devuelve un real. (abs -7) devuelve 7 (abs -7.0) devuelve 7.0 (abs 0) devuelve 0

(FIX numero)Esta funcin devuelve la parte entera de un nmero. De modo que devuelve un nmero entero. (fix 15.8) devuelve 15. Ojo! no redondea, sino que elimina lo que est detras del punto decimal. (fix -15.8) devuelve -15 (fix 0.99) devuelve 0

(REM numero1 numero2 [numero3] ...)Esta funcin devuelve el resto de la divisin de numero1 entre numero 2. (rem 2.5 2) devuelve 0.5 (rem 3 2) devuelve 1 Cuando se indica ms de 2 nmeros (rem 1 2 3) es equivalente a (rem (rem 1 2) 3). Es decir, primero calcula el resto de la divisin entre 1 y 2, que es 1, y despus lo divide entre 3 y devuelve su resto, que es 1. Si todos los nmeros que recibe como argumentos son enteros, devuelve un nmero entero y si alguno de ellos es un nmero real, devuelve un real. (rem 3 2) devuelve 1.0

(SIN angulo)

Devuelve el seno de un ngulo indicado en radianes. (sin 0) devuelve 0.0 (sin (/ pi 2)) devuelve 1.0

(COS angulo)Funciona igual que la anterior, pero devuelve el coseno del ngulo, que hay que pasarselo en radianes. (cos 0) devuelve 1.0 (cos pi) devuelve -1.0

(ATAN numero 1 [numero2])Devuelve el arco cuya tangente sea numero1. Por ejemplo (atan 0) devuelve 0.0 ya que el ngulo que tiene tangente 0 es el 0.0 Si se indica un segundo nmero (ATAN num1 num2) lo que hace es dividir num1 entre num2 y devuelve el arco cuya tangente sea el resultado de la divisin. Esto se hace para facilitar lo siguiente... (atan (sin angulo) (cos angulo)) devuelve angulo

(SQRT numero)Esta funcin devuelve la raiz cuadrada del numero que recibe como argumento. Siempre devuelve un nmero real, no entero. (sqrt 4) devuelve 2.0 (sqrt 2.0) devuelve 1.41..

(EXPT num exp)Devuelve el nmero num elevado al exponente exp. (expt 2 2) devuelve 4 (expt 2 3) devuelve 8 Si todos los nmeros que recibe como argumentos son enteros, devuelve un nmero entero y si alguno de ellos es un nmero real, devuelve un real. (expt 3 2.0) devuelve 9.0

(EXP num)Devuelve el nmero e (e = 2.71828... ) elevado al nmero num. Siempre devuelve un nmero real.

(exp 1) devuelve 2.71828 (exp 2) devuelve 7.38906

(LOG numero)Esta funcin devuelve el logaritmo neperiano del nmero que recibe como argumento. (log 1) devuelve 0.0 (log 2) devuelve 0.693147

(GCD entero1 entero2)Esta funcin recibe dos nmeros enteros y devuelve su mximo comn divisor (o denominador). Siempre devuelve un nmero entero. (gcd 15 5) devuelve 5 (gcd 9 27) devuelve 9

(MAX num1 num2 ...)Devuelve el mayor de los nmeros que recibe como argumentos. (max 2 4 1 3 6) devuelve 6 (max 8 4 -9) devuelve 8 Si todos los nmeros que recibe como argumentos son enteros, devuelve un nmero entero y si alguno de ellos es un nmero real, devuelve un real. (max 8 4.0 -9) devuelve 8.0

(MIN num1 num2 ...)Devuelve el menor de los nmeros que recibe como argumentos. (min 2 3 6) devuelve 2 (min 8 4 -9) devuelve -9 Si todos los nmeros que recibe como argumentos son enteros, devuelve un nmero entero y si alguno de ellos es un nmero real, devuelve un real. (min 8 4.0 -9) devuelve -9.0 Pues ya estn vistas todas las funciones matemticas... Enhorabuena

Solicitar textos al usuario

Recuerdas las funciones GETINT y GETREAL? Nos sirven para solicitar al usuario un nmero entero y real, respectivamente. Pues la funcin que se utiliza para solicitar textos al usuario es muy parecida.

(GETSTRING [modo] [mensaje])Se puede ejecutar sin parmetros (getstring) pero no es recomendable. Se suele indicar un mensaje de texto que explique al usuario lo que se le est solicitando. Por ejemplo: (getstring "Cual es tu nombre?") Supongamos q te llamas Pepe, a (getstring "Cual es tu nombre?") responderias Pepe y ya est. Incluso se podria asignar el nombre que indique el usuario a una variable: (setq nombre (getstring "Cual es tu nombre?")) Pero que sucede si te llamas Jose Luis? Pues que en cuanto pulses el espacio es como si hubieras pulsado Intro. No nos permite insertar textos con espacios. Para que admita textos con espacios, debemos hacer un pequeo cambio: (setq nombre (getstring T "Cual es tu nombre?")) Le estamos indicando el argumento [modo] = T. Este argumento puede ser cualquier expresin de AutoLISP, en este caso le pasamos el valor T = Cierto, verdadero. Si no se indica el modo, o si al evaluarlo devuelve nil (nil = Falso, vaco) entonces no admite espacios. Y si se pone cualquier expresin que al evaluarse no devuelva nil, permite espacios. (setq nombre (getstring (+ 1 2) "Cual es tu nombre?")) permite responder con espacios, ya que (+ 1 2) devuelve 3 que es distinto de nil. (setq nombre (getstring (setq var1 nil) "Cual es tu nombre?")) no permite responder con espacios, ya que (setq var1 nil) devuelve nil.

Solicitar puntos al usuarioPara solicitar puntos se utilizan dos funciones que tambin son parecidas a GETINT y a GETREAL.

(GETPOINT [pto_base] [mensaje])Esta funcin le pide un punto al usuario y devuelve una lista con las coordenadas del punto indicado. El usuario puede indicar el punto en pantalla con el digitalizador (ratn) o tecleando sus coordenadas, tal y como se hara al dibujar en AutoCAD. Se puede ejecutar sin parmetros (getpoint) pero no es recomendable. Se suele indicar un mensaje de texto que explique al usuario lo que se le est solicitando. Por ejemplo: (getpoint "Punto inicial") Lo habitual es que adems ese punto se almacene en una variable

(setq pto (getpoint "Punto inicial")) As asignamos a la variable pto algo parecido a lo siguiente: (120.56 135.88 0.0) Veamos ahora para que sirve el argumento opcional [pto_base] aprovechando que tenemos el punto pto definido. (getpoint pto "Siguiente punto:") Aparece una lnea elstica entre el punto pto y la posicin del cursor.

(GETCORNER pto_base [mensaje])Esta funcin se utiliza tambin para solicitar puntos al usuario. En este caso el punto base no es opcional, hay que indicarlo. Veamos la diferencia entre las dos expresiones siguientes: (getpoint pto "Siguiente punto:") (getcorner pto "Siguiente punto:") Al utilizar getpoint, se muestra una lnea elstica entre el punto pto y la posicin del cursor. Si se utiliza getcorner, en lugar de una lnea elstica, aparece un rectngulo. Fijemonos un momento en lo que devuelven tanto getpoint como getcorner: (125.68 117.68 0.0). Se trata de una lista. En el prximo tema veremos algunas funciones para manejar listas.

Funciones para manejar listasAutoLISP es un lenguaje de programacin basado en listas, as que es lgico que el tratamiento que reciban las listas de elementos sea muy bueno. Vamos a ver ahora una serie de funciones para manipular listas de elementos.

(CAR lista)Esta funcin devuelve el primer elemento de la lista que recibe como argumento. De modo que si (siguiendo con el ejemplo del tema anterior) en la variable pto hemos asignado el valor devuelto por getpoint, tenemos una lista con las coordenadas X, Y y Z del punto designado. Supongamos que pto = (10.0 20.0 0.0). (car pto) devuelve la coordenada X del punto pto. Es decir 10.0

(CDR lista)Esta funcin devuelve la lista que recibe como argumento pero sin el primer elemento. (cdr pto) devolver una lista formada por las coordenadas Y y Z del punto pto. Es decir, (20.0 0.0)

(CADR lista) y otras

Cmo se obtendra la coordenada Y del punto pto??? Veamos:

CDR devuelve la lista sinel primer elemento CAR devuelve el primer elemento de una lista

De modo que (cdr pto) devuelve (Y Z). As que para obtener la coordenada Y: (car (cdr pto)) devuelve la coordenada Y del punto pto. y como obtenemos la coordenada Z?? (car (cdr (cdr pto))) devuelve la coordenada Z del punto pto. En resumen, las coordenadas del punto pto se obtendrian mediante:

X ==> (car pto) Y ==> (car (cdr pto)) Z ==> (car (cdr (cdr pto)))

Si en las coordenadas X, Y y Z ponemos las letras A y D de cAr y cDr en maysculas, lo anterior quedara:

X ==> (cAr pto) Y ==> (cAr (cDr pto)) Z ==> (cAr (cDr (cDr pto)))

Las funciones CAR y CDR se pueden agrupar. Para ello, existen una serie de funciones que se denominan juntando las Aes y las Des de cAr y cDr respectivamente. El ejemplo anterior, queda:

X ==> (cAr pto) Y ==> (cAr (cDr pto)) == (cADr pto) Z ==> (cAr (cDr (cDr pto))) == (cADDr pto)

Esto nos servir como regla mnemotcnica para recordar el nombre de estas funciones. Tan solo se permiten 4 niveles de anidacin, as que entre la c y la r solo puede haber 4 letras (Aes o Des). Supongamos que tenemos la siguiente lista asignada a la variable lst = ((a b) (c d) (e f)). OJO!! es una lista en la q sus elementos son a su vez listas. Como obtendramos a ?? (car lst) devuelve (a b) que es el primer elemento de lst, y a es el primer elemento de (a b) as que: (car (car lst)) devuelve a, o lo que es lo mismo: (cAAr lst) devuelve a y el elemento c??? (cDr lst) devuelve ((c d) (e f)). Ahora si hacemos (cAr (cDr lst)) devuelve (c d). As que:

(cAr (cAr (cDr lst))) devuelve c, o lo que es lo mismo: (cAADr lst) devuelve c Cmo obtener d ?? (cDr lst) devuelve ((c d) (e f)) y (cAr (cDr lst)) el primer elemento de ((c d) (e f)), es decir devuelve (c d). Si ahora hacemos (cDr (cAr (cDr lst))) obtenemos (d), que no es lo mismo que d. Ya que se trata de una lista cuyo primer elemento es d. As que: (cAr (cDr (cAr (cDr lst)))) devuelve d, o lo que es lo mismo: (cADADr lst) devuelve c Y cmo obtener e ?? (cDr lst) devuelve ((c d) (e f)) y (cDr (cDr lst)) devuelve ((e f)). Ojo! se trata de una lista cuyo primer (y nico) elemento es a su vez otra lista con dos elementos. As que (cAr (cDr (cDr lst))) devuelve (e f), y para obtener e: (cAr (cAr (cDr (cDr lst)))) devuelve e, o lo que es lo mismo: (cAADDr lst) devuelve e Por ltimo, veamos cmo se obtiene f. (cAr (cDr (cDr lst))) devuelve (e f) tal como se vio en el ejemplo anterior. As que (cDr (cAr (cDr (cDr lst)))) devuelve (f), que no es lo mismo que f. Por tanto: (cAr (cDr (cAr (cDr (cDr lst))))) devuelve f. Podriamos pensar que: (cADADDr lst) tambin devuelve f. Pero al ejecutar esta lnea AutoCAD nos dice que la 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 logicamente no podemos. Para obtener f podriamos hacer, por ejemplo: (cAr (cDADDr lst)) o (cADADr (cDr lst))

(LENGTH lista)En la variable pto teniamos una lista con las coordenadas de un punto, pero si solo trabajamos en 2D, la Z no nos interesa. As que muchas veces los puntos tan solo tendran 2 coordenadas (X Y). Pero para un programa no es lo mismo que tenga 2 que 3 coordenadas, a lo mejor va a buscar la coordenada Z y no existe produciendose un error en nuestra rutina. As que necesitamos conocer el nmero de elementos que tienen las listas. Para ello se utiliza la funcin length, que devuelve el nmero de elementos de la lista que recibe como argumento. Por ejemplo: (length pto) devuelve 3. y si el pto estuvuiera en 2D (X Y) devolvera 2.

Y qu devolvera (length lst) ??? siendo lst = ((a b) (c d) (e f)). Pues devolvera 3, ya que lst es una lista con 3 elementos que a su vez son listas. Qu devolvera (length (car lst)) ??? El nmero de elementos del primer elemento de lst, es decir el nmero de elementos de (a b), que es 2.

(LIST elemento1 elemento2 ...)Esta funcin devuelve una lista formada por los elementos indicados. De modo que se utiliza para crear listas. Por ejemplo: (list 1 2 3) devuelve (1 2 3) (list "pepe" 2 "Juan") devuelve ("pepe" 2 "Juan") Veamos que hace la siguiente expresin: (list (list "a" "b") "c" (list "d" "e") "f") Veamos (list "a" "b") devuelve ("a" "b") y (list "d" "e") devuelve ("d" "e"). As que (list (list "a" "b") "c" (list "d" "e") "f") devuelve (("a" "b") "c" ("d" "e") "f").

Ejecutar comandos de AutoCADUna de las mayoresventajas de la programacin en AutoLISP es la posibilidad de ejecutar comandos de AutoCAD en nuestras rutinas.

(COMMAND "comando" [datos])Esta es la funcin que nos permite ejecutar comandos de AutoCAD. Hay que destacar que siempre devuelve nil. Los nombres de los comandos de AutoCAD, y sus opciones, se indican como textos por lo que van incluidos entre comillas. (command "linea" (list 0.0 0.0) (list 100.0 200.0)) Dibujar una lnea desde el origen al punto 100,200. Pero, nos falta algo: Al dibujar lneas en AutoCAD se van indicando puntos y siempre pide "Siguiente punto: " de modo que para terminar el comando "LINEA" hay que pulsar INTRO. Pues ese Intro tambin hay que pasarselo a command: (command "linea" (list 0.0 0.0) (list 100.0 200.0) "") o as (command "linea" (list 0.0 0.0) (list 100.0 200.0) " ") Lo realmente potente de COMMAND es que podemos ejecutar casi todos los comandos de AutoCAD. Cuales no? Son muy pocos, por ejemplo "Nuevo" para empezar un dibujo nuevo. Pero todos los comandos de dibujo, edicin, etc se pueden ejecutar. Los datos dependeran del comando de AutoCAD indicado. Por ejemplo para el comando "circulo", ser: (command "circulo" (list 0.0 0.0) 25.0) Esto dibujar una circunferencia de radio 25 con centro en el origen.

Los idiomas de AutoCADSupongamos que no disponemos de una versin en castellano de AutoCAD, sino que est en ingls, o en Francs, o Chino Mandarn... Qu pasa si ejecutamos esto... (command "linea" (list 0.0 0.0) (list 100.0 200.0) "") AutoCAD no conocer el comando "linea", as que nos dar un error. Por suerte se puede solucionar, ya que sino un programa realizado para AutoCAD en Ingls slo servira para las versiones en Ingls. AutoCAD en realidad no "habla" un nico idioma, sino que es bilingue, dispone de una lengua que es la que muestra (que corresponde con la versin idiomtica del programa: Castellano, Francs, etc) y una lengua interna, el Ingls. De modo que los comandos de AutoCAD (y sus opciones) se pueden escribir en Castellano o en ingls. Pero para diferenciar unos de otros a los comandos en la lengua nativa de AutoCAD (Ingls) se les antepone un guin bajo: (command "_circle" (list 0.0 0.0) 25.0) (command "_line" (list 0.0 0.0) (list 100.0 200.0) "") Las opciones de los comandos tambin se deben indicar en ingls anteponiendoles un guin bajo. Por ejemplo: (command "_circle" (list 0.0 0.0) "_d" 25.0) Esta lnea dibuja una circunferencia de Dimetro 25 con centro en el origen.

Comandos de AutoCAD redefinidosPor otra parte, ya se ha dicho anteriormente que los comandos de AutoCAD se podrn redefinir para que funcionen de forma distinta. As se puede cambiar el comando "circulo" para que dibuje pentagonos y el comando "linea" para que dibuje circulos. Si redefinimos el comando lnea para que dibuje circulos, entonces debemos indicar (command "linea" centro radio) y no (command "linea" pt0 pt1"") que no funcionara, puesto que le estamos pasando unos parmetros que no espera. Pero cmo hacemos ahora para dibujar una lnea? Para ejecutar los comandos originales de AutoCAD, y no los redefinidos (si lo estn) debemos anteponer al nombre del comando un punto, por ejemplo: (command ".circulo" (list 0.0 0.0) 25.0) (command ".linea" (list 0.0 0.0) (list 100.0 200.0) "") Podemos adems indicar los comandos en Ingls anteponiendoles un guin bajo as que tambin podriamos escribirlo as: (command "._circle" (list 0.0 0.0) 25.0) (command "_.circle" (list 0.0 0.0) 25.0)

Da igual si se pone antes el punto o el guin bajo. Para redefinir un comando de AutoCAD: 1. Ejecutar el comando "ANULADEF" (En Ingls "undefine") indicando el nombre del comando a redefinir. De este modo se elimina la definicin del comando de AutoCAD, y la nica forma de ejecutarlo ser anteponiendo al nombre del comando un punto. 2. Crear y cargar una rutina en la que est definido un nuevo comando con el nombre del comando que acabamos de anular. Veamoslo con un ejemplo: Primero anulamos la definicin del comando lnea. Podemos hacerlo desde AutoCAD con el comando "ANULADEF" (En ingls "undefine") o desde AutoLISP: (command "_undefine" "linea") Ahora podemos comprobar que el comando lnea no funciona en AutoCAD, y la nica forma de ejecutarlo es anteponiendo a su nombre un punto ".linea". Cargamos la siguiente funcin: (defun C:LINEA ( ) (setq pt (getpoint "Centro del crculo: ")) (setq rad (getreal "Radio del crculo")) (command "._circle" pt rad) ) Ahora el comando "linea" dibujar crculos. Para recuperar el valor original del comando podemos hacer dos cosas: 1. Cerrar AutoCAD y abrirlo de nuevo de modo que la rutina que hemos creado se borre de la memoria del ordenador. 2. Ejecutar el comando de AutoCAD "redefine" (En Ingls es igual) e indicarle el nombre del comando del que queremos recuperar su definicin original, es decir "linea". Bueno, por ltimo un ejercicio: Crear un nuevo comando llamado CIRCPERI que dibuje una circunferencia indicando su centro y la longitud de su permetro.

Operaciones de comparacinQu es una operacin de comparacin?? Pues comparar, por ejemplo, si algo es mayor que algo, o menor, o si es igual.

(= expr1 expr2 ...)Compara si expr1 devuelve el mismo resultado que expr2, en caso afirmativo devuelve T y en caso ontrario devuelve nil. (= 5 (+ 1 4)) devuelve T porque (+ 1 4) devuelve 5

(= 5 (+ 1 4.0)) devuelve T aunque (+ 1 4.0) devuelve 5.0 y no 5. Pero 5 y 5.0 valen lo mismo, no? (= 5 5.0) devuelve T No solo podemos evaluar nmeros, tambin textos: (setq txt1 "Curso de Lisp") (= txt1 "Curso de Lisp") devuelve T (= txt1 "Curso de LISP") devuelve nil. No es lo mismo un texto en maysculas que en minsculas. (= "LISP" "Lisp") devuelve nil Estamos comparando expresiones, as que: (= (+ 1 5) (/ 12 2)) devuelve T porque ambas expresiones devuelven como resultado 6. La funcin = puede aceptar ms de dos expresiones: (= 6 (+ 1 5) 6.0 (/ 12 2)) devuelve T, pues las cuatro expresiones devuelven 6 o 6.0 (que vale lo mismo).

(/= expr1 expr2 ...)Es muy similar a la anterior. Devuelve T si las expresiones no devuelven el mismo valor y devuelve nil si todas las expresiones devuelven el mismo valor. (/= 6 6.0) devuelve nil, porque 6 y 6.0 no son distintos (valen lo mismo). (/= (+ 5 5) (/ 12 2)) devuelve T, pues la primera expresin devuelve 10 y la segunda 6. (/= "LISP" "Lisp") devuelve T

(< expr1 expr2 ...)Compara si expr1 es menor q expr2 (< 4 5) devuelve T, ya que 4 es menor que 5 (< 4 -5) devuelve nil (< 5 5.0) devuelve nil Si se ponen ms de 2 expresiones, se comprueba que esten ordenadas de menor a mayor y devuelve T si lo estn y nil si no lo estn. (< (< 1 1 2 2 3) 0) devuelve devuelve T nil

(< (+ 1 2) (* 2 2.0) (/ 12 2)) devuelve T Tambin podemos comparar textos. El interprete de AutoLISP evalua los cdigos ASCII de los textos. Es decir los ordena alfabticamente de la "a" a la "z". (< "Albacete" "Barcelona") devuelve T (< "a" "c") devuelve T (< "d" "c") devuelve nil (< "C" "c") devuelve T, puesto que los cdigos ASCII de la maysculas son inferiores a los de las minsculas. Los cdigos ASCII, son una serie de nmeros que se asignaron a las letras del alfabeto y a algunos de los caracteres ms usuales (al menos en Occidente). El caracter "a" tiene asociado el cdigo 97, la "b" el 98, etc hasta la "z". El caracter "A" tiene asociado el cdigo 65, la "B" el 66, etc hasta la "Z".

(> expr1 expr2 ...)Supongo que ya os imaginais como funciona, no? Comprueba si las expresiones estn ordenadas de mayor a menor. (> 5 3) devuelve T (> -2 3) devuelve nil (> 5 2 3) devuelve nil (> 5 4 3) devuelve T Y ahora con los textos: (> "a" "c") devuelve nil, pues el cdigo ASCII de "a" es menor que el de "c".

(= 3 1.0 2 1) devuelve nil (>= 3 3 3 3) devuelve T Veamos como se hara el ejercicio propuesto en el tema anterior: Crear un nuevo comando llamado CIRCPERI que dibuje una circunferencia indicando su centro y la longitud de su permetro. Qu es lo primero que hay que hacer ??? Esta respuesta tiene que ser instintiva, como un acto reflejo: El pseudocdigo. Siempre comenzaremos nuestras rutinas escribiendo el pseudocdigo (o haciendo un diagrama de flujo) de lo que se pretende hacer. Bueno, cmo podria ser el pseudocdigo de esta rutina, vamos a ver: 1. 2. 3. 4. Pedir al usuario el centro de la circunferencia. Pedir al usuario el permetro de la circunferencia. Calcular el radio de la circunferencia a partir de su permetro. Dibujar la circunferencia.

Una vez que terminamos el pseudocdigo, ya tenemos el 80% de la rutina. Si el pseudocdigo es correcto, el resto es de lo ms simple. Primero hay que aadir la definicin del nuevo comando CIRCPERI: (defun C:CIRCPERI ( ) 1) Pedir al usuario el centro de la circunferencia. Podriamos poner (getpoint "Centro de la circunferencia") pero eso no servira de nada, por que no almacenamos el punto que indica el usuario en ningn sitio. Tendriamos que hacer, entonces... (setq pto (getpoint "Centro de la circunferencia")) asi almacenamos el punto indicado en la variable pto. 2) Pedir al usuario el permetro de la circunferencia. Por ejemplo (setq peri (getint "Permetro:")) pero al usar getint, solo permite obtener nmero enteros. As que podriamos cambiarlo por: (setq peri (getreal "Permetro:")) 3) Calcular el radio de la circunferencia a partir de su permetro. Peri = 2* pi * rad as que rad = Peri / ( 2 * pi). Traduciendolo a cdigo: (setq rad (/ peri (* pi 2))) 4) Dibujar la circunferencia (command "_.circle" pto rad) Slo nos falta una cosa. Pista: El nmero de parntesis de apertura tiene que ser igual al nmero de parntesis de cierre. As que: )

El cdigo completo de la rutina sera: (defun C:CIRCPERI ( ) (setq pto (getpoint "Centro de la circunferencia"))

(setq peri (getreal "Permetro:")) (setq rad (/ peri (* pi 2))) (command "_.circle" pto rad) ) Tambin deberias aadir comentarios al cdigo y una cabecera con varias lneas de comentarios en el archivo LSP indicando El nombre de la rutina, fecha, autor, etc. Te das cuenta de la importancia del pseudocdigo? Al programar nos ha guiado paso a paso.

Operaciones lgicasExste una serie de funciones de AutoLISP que nos permiten realizar operaciones lgicas. Suelen emplearse en combinacin con las operaciones de comparacin.

(AND expr1 expr2 ...)Esta funcin devuelve T si ninguna de las expresiones que recibe como argumento es (devuelve) nil. Si una sola de las expresiones devuelve nil, la funcin AND devolver nil. Es decir, comprueba que se cumplan todas las expresiones que recibe como argumento. (and (< 3 4) (= 5 5.0)) devuelve T, porque las dos expresiones devuelven T (and (> 3 4) (= 5 5.0)) devuelve nil, porque (> 3 4) devuelve nil En el ejemplo anterior, como la primera expresin (> 3 4) devuelve nil, ya no se continuan evaluando el resto de expresiones. Cmo hay una expresin que devuelve nil, AND devolver nil. De modo que la expresin (= 5 5.0) ya no se evala. Vamos a complicarlo un poco... Qu devolver la siguiente expresin? (and (= 5 5.0) (< 3 4) "Soy un texto" 5.8) Preguntndolo de otra forma: Alguna de las expresiones que recibe AND como argumentos es nil? No, as que AND devuelve T. (setq a "Soy otro texto" b 15 c T d nil) (and a b) devolver T (and a d)

(and a b c d) devolver nil, porque d es nil

(OR expr1 expr2 ...)Devuelve nil si todas las expresiones son nil. En caso de que alguna de las expresiones no devuelva nil, OR devuelve T. Es decir, comprueba si alguna de las expresiones se cumple. (or (/= 5 5.0) (> 3 4)) devuelve nil, porque ambas expresiones son nil (or (= 5 5.0) (> 3 4)) devuelve T, pues la primera expresin se cumple En el ejemplo anterior, como la primera expresin (= 5 5.0) devuelve T, ya no se continuan evaluando el resto de expresiones. Cmo hay una expresin que devuelve T, OR devolver T. De modo que la expresin (> 3 4) ya no se evala. (setq a "Soy otro texto" b 15 c T d nil) (or a b) devuelve T (or c d) devuelve nil (or d d) devuelve nil

(EQUAL expr1 expr2 [precision])En el tema anterior vimos la funcin de comparacin = que nos sirve para determinar si dos nmeros o textos son iguales. Pero que pasa si queremos comparar otra cosa, por ejemplo dos listas (como dos puntos). (setq pt1 (list 10.0 20.0 0.0) pt2 (list 10.0 (* 10.0 2) 0.0) pt3 (list 9.99 20.0 0.0) pt4 (list 9.99 20.02 0.0)) Al comparar estas listas (puntos) con la funcin = siempre nos devuelve nil. Aunque pt1 y pt2 sean iguales, y muy parecidos a pt3 y pt4. Por tanto, la funcin = no nos servir para comparar listas. Para comparar dos listas se utilizar la funcin EQUAL. (equal 5 5.0) devuelve T, al igual q la funcin =, porque 5 vale lo mismo que 5.0 (equal pt1 pt2) devuelve T EQUAL adems ofrece un argumento opcional... [precisin]. Veamos como funciona : (equal 4.99 5.0 0.1) devuelve 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 la precisin... (equal 4.99 5.0 0.001) devuelve nil Y que pasa con las listas? Tambin podemos indicarle una precisin? Veamoslo..

(equal pt1 pt3 0.1) devuelve T, porque compara los elementos de las listas (coordenadas) con la precisin que hemos indicado, 0.1 Si subimos la precisin... (equal pt1 pt3 0.001) devuelve nil (equal pt1 pt4 0.01) devuelve nil (equal pt1 pt4 0.02) devuelve T, porque la precisin es 0.02 que es exactamente la diferencia entre 20.02 y 20 El utilizar una precisin muy elevada no implica que todas las comparaciones devuelvan T, todo depender de los valores a comparar: (equal 15 20 100) devuelve T (equal 5000 4200 100) devuelve nil

(NOT expr)A esta funcin le gusta llevarle la contraria a la expresin que recibe como argumento.

Si la expresin devuelve nil, entonces NOT devuelve T. Si la expresin devuelve cualquier cosa que no sea nil, entonces NOT devuelve nil.

(not 5) devuelve nil (not "Texto") devuelve nil (not (+ 5 1)) devuelve nil Si hacemos... (setq a 5 b nil c T d "Nuevo texto") (not b) devolver T, porque b es nil (not c) devolver nil. Veamos que devuelve la siguiente expresin: (and (not c) 5) Como c es T, (not c) devuelve nil. Al no cumplirse la primera expresin de AND, esta devuelve nil y no contina evaluando.

Mostrar textos en pantallaHay varias funciones para mostrar textos en pantalla. De momento tan solo vamos a ver un par de ellas, pero habr ms.

(PROMPT mensaje)Muestra el texto indicado como argumento en pantalla, y siempre devuelve nil. (prompt "Bienvenidos al Curso")

(ALERT mensaje)Muestra el texto que recibe como argumento en un letrero. Tambin devuelve nil. Se utiliza principalmente para avisar al usuario en caso de error, o para mostrarle alguna informacin importante. (alert "Error: Dato no vlido")

(TERPRI)En el tema 12, creamos un nuevo comando para AutoCAD denominado CIRCPERI. Si habeis cargado y ejecutado el comando, habreis observado que los mensajes para solicitar el centro de la circunferencia y su permetro aparecen en la misma lnea y pegados. Para que los mensajes aparezcan en lneas distintas, se puede emplear la funcin TERPRI. Ya que esta funcin mueve el cursor a una nueva lnea en la ventana de comandos de AutoCAD, y devuelve nil. El cdigo de la rutina quedara as: (defun C:CIRCPERI ( ) (setq pto (getpoint "Centro de la circunferencia")) (terpri) (setq peri (getreal "Permetro:")) (terpri) (setq rad (/ peri (* pi 2))) (command "_.circle" pto rad) ) As los mensajes de solicitud aparecern en lneas separadas.

Los caracteres de controlCreo que ya se dijo que AutoLISP no reconoce una serie de caracteres, por ejemplo al indicar la ruta de un archivo no reconoce el caracter "\" y hay que indicarselo as: "\\". Pues existen ms caracteres de control predefinidos:

\\ Equivale al caracter \ \" Equivale al caracter " \e Equivale a ESCape \n Equivale al retorno de carro \r Equivale a pulsar Intro \t Equivale a pulsar la tecla del tabulador

\" nos permite escribir las comillas dentro de un texto. Por ejemplo:

(alert "Esto son un par de comillas \" o no?") La nica comilla q se tiene q ver es la que est escrita as: \" . Las otras nos indican donde comienza y termina el texto, nada ms. (alert "Texto en lnea 1\nTexto en lnea 2") Se pone 1\nTexto todo junto. Para qu poner espacios? (alert "Texto en lnea 1\n Texto en lnea 2") Si lo ponemos as, aade un espacio en blanco al principio de la segunda lnea. Por eso se pone todo seguido. (alert "Texto en lnea 1\n\tTexto en lnea 2") En este ejemplo la segunda lnea est tabulada. Entonces, cmo quedara el cdigo de la rutina CIRCPERI utilizando caracteres de control, en lugar de la funcin (TERPRI)??? (defun C:CIRCPERI ( ) (setq pto (getpoint "\nCentro de la circunferencia")) (setq peri (getreal "\nPermetro:")) (setq rad (/ peri (* pi 2))) (command "_.circle" pto rad) ) Un par de cosas ms con respecto a esta rutina... Cuando se crea un archivo LISP en el que est definido un nuevo comando es bastante til aadir al final de todo el cdigo algo similar a... (prompt "\nNuevo comando CIRCPERI cargado") Esta lnea se pondra despus del parntesis de cierre de defun. Es decir, que cuando se ejecuta CIRCPERI desde AutoCAD esta lnea no se evala. Para qu ponerla entonces?? Pues muy sencillo... para que cuando se cargue el archivo en AutoCAD muestre en pantalla: Nuevo comando CIRCPERI cargado. As el usuario sabe cual es el nombre del comando definido en el archivo que se acaba de cargar. De modo que el mensaje slo se mostrar al cargar el archivo. Por otro lado... si recordamos la estructura de la funcin DEFUN: (DEFUN nombre_funcin ( argumentos / variables_locales ) expr1 expr2 ...) Veremos que en la rutina CIRCPERI no hemos indicado variables locales, as que todas las variables sern globales. Es decir que al ejecutar CIRCPERI y dibujar un crculo, luego nos quedan accesibles los valores de las variables pto peri y rad desde AutoCAD, ocupando y malgastando memoria. As que vamos a ponerlas como locales. Slo habra que cambiar la siguiente lnea...

(defun C:CIRCPERI ( / pto peri rad ) OJO! la barra inclinada / hay que ponerla, sino seran argumentos y no variables locales. El cdigo completo de la rutina es el siguiente: ;;;________________________MecaniCAD__________________________;;; ;;;_____________http://www.peletash.com/mecanicad_____________;;; ;;;_______________________CIRCPERI.LSP________________________;;; ;;;_______________________Versin 1.1_________________________;;; ;;;________________________26/02/2002_________________________;;; ;;; Comando para dibujar una circunferencia indicando su centro y la longitud ;;; de su permetro. (defun C:CIRCPERI ( / pto peri rad ) (setq pto (getpoint "\nCentro de la circunferencia")) (setq peri (getreal "\nPermetro:")) (setq rad (/ peri (* pi 2))) (command "_.circle" pto rad) ) (prompt "\nNuevo comando CIRCPERI cargado")

Estructuras condicionales simplesHasta ahora nuestro cdigo ha sido completamente lineal, las lneas de cdigo que escribamos se ejcutaban despus una tras otra en el mismo orden. En este tema veremos un tipo de funciones que nos permitiran bifurcar el cdigo, de modo que ya no exista un nico camino sino dos o ms. Veamos un ejemplo en pseudocdigo: 1. Introducir el lmite inferior 2. Introducir el lmite superior 3. El lmite superior es menor que el inferior? 1. SI--> Mensaje "El lmite superior debe ser mayor que el inferior" 2. NO --> intervalo = lmite superior - lmite inferior

(IF condicin expr_si_cumple [expr_no_cumple])

La funcin IF es una de las ms empleadas al programar. Devuelve el valor de la ltima expresin evaluada. Si condicin es distinto de nil, entonces evala la expr_si_cumple. Si condicin devuelve nil evala la expr_no_cumple, si existe y si no existe no hace nada. Veamos algunos ejemplos: (if (= 2 2.0) (alert "Los nmeros son iguales")) La condicin a evaluar es: (= 2 2.0) en la que tenemos un nmero entero 2 y uno real 2.0, pero su valor es el mismo. Aunque sean de distinto tipo 2 y 2.0 valen igual. As que la condicin devuelve T, evaluandose la condicin si cumple que muestra un mensaje de alerta. La funcin IF devuelve el valor de la ltima expresin evaluada, es decir alert, que es nil. (if (= 2 3) (alert "Los nmeros son iguales")) En este caso la condicin devuelve nil y al no existir expresin no cumple, no hara nada ms. Qu valor devolvera IF? El de siempre, el valor de la ltima expresin evaluada, que en este caso ha sido la propia condicin que devuelve nil. De modo que IF devolver nil. (if (= 2 3)

(alert "Los nmeros son iguales") (alert "Los nmeros son distintos")) En este caso el cdigo se ha escrito en varias lneas y tabulado para facilitar su comprensin. Ahora si tenemos una expresin no cumple, que ser evaluada ya que la condicin devuelve nil. Veamos el siguiente ejemplo: (setq liminf (getint "\nLmite inferior")) (setq limsup (getint "\nLmite superior")) (if (> liminf limsup) (alert "El lmite superior debe ser mayor que el inferior") (setq limsup (getint "\nLmite superior")) (setq intervalo (- limsup liminf)) (setq intervalo (- limsup liminf)) ) Viendo el cdigo anterior, tal vez pienses que si la condicin (> liminf limsup) se cumple, entonces se evaluar la lnea siguiente de cdigo. Pero no es as, se evala la expresin si cumple, que es la primera expresin (alert "El lmite superior debe ser mayor que el inferior"). Si la condicin no se cumple, devuelve nil, se evaluar la expresin no cumple, que en este caso ser (setq limsup (getint "\nLmite superior")).

Tanto la expresin si cumple, como la no cumple solo pueden ser una nica expresin. El ejemplo de cdigo anterior nos dara un error ya que IF no puede tener ms que 3 expresiones:

La condicin La expresin si cumple La expresin no cumple

(PROGN expr1 expr2 ...)Para que se pueda indicar ms de una expresin si cumple, o no cumple, en la funcin IF se suele emplear la funcin PROGN. El valor devuelto por PROGN es el de la ltima expresin que recibe como argumento. Esta funcin en realidad no hace nada, tan solo nos permite agrupar una serie de expresiones. Cmo quedara el ejemplo anterior? (setq liminf (getint "\nLmite inferior")) (setq limsup (getint "\nLmite superior")) (if (> liminf limsup)

(progn (alert "El lmite superior debe ser mayor que el inferior") (setq limsup (getint "\nLmite superior")) (setq intervalo (- limsup liminf)) )(setq intervalo (- limsup liminf)) ) En este caso la condicin si cumple es todo lo siguiente:

(progn (alert "El lmite superior debe ser mayor que el inferior") (setq limsup (getint "\nLmite superior")) (setq intervalo (- limsup liminf)) )Si se cumple la condicin, se evala la condicin si cumple, es decir el progn. De modo que se van evaluando las expresiones contenidas en la funcin PROGN, que

devuelve el valor de la ltima expresin (setq intervalo (- limsup liminf)), que ser el valor de la variable intervalo. En caso de que la condicin no se cumpla, se evala la condicin no cumple, (setq intervalo (- limsup liminf)) que curiosamente tambin devuelve el valor de la variable intervalo. Pasemos ahora a unos ejemplos ms de estructuras condicionales: (if (and (= 2 2.0) (< 2 3)) (alert "Las dos condiciones se cumplen") (alert "Al menos una condicin no se cumple") ) En este caso la condicin es (and (= 2 2.0) (< 2 3)) que en este caso devolvera T, ya que se verifican las dos expresiones que recibe la funcin AND. (if (not var1) (alert "Variable no definida") (alert "Variable definida") ) En este caso si var1 es nil, (not var1) devolver T, indicando que la variable no se ha definido. En caso contrario, (not var1) devolver nil evaluandose la expresin no cumple. Otro mtodo para hacer lo mismo, sera: (if var1 (alert "Variable definida") (alert "Variable no definida") ) Si var1 es distinto de nil, se evala la expresin si cumple. En caso de que var1 sea nil, se evaluara la expresin no cumple.

Estructuras condicionales mltiplesCon la funcin IF tan solo podemos indicar una condicin y dos opciones, si cumple y no cumple. Pero tambin tenemos la posibilidad de indicar varias condiciones con sus respectivas expresiones si cumple.

(COND (condicion1 [expr1_1] [expr1_2] ... ) [ (condicion2 [expr2_1] [expr2_2] ... ) ] ... )Esta funcin es similar a IF en cuanto a que se indican condiciones y una serie de expresiones que se evaluaran si se verifica cada condicin. n este caso no existe la

limitacin de indicar tan slo una nica expresin si cumple, se pueden indicar tantas como se desee. COND evaluar la primera condicin encontrada, si se verifica evaluar las expresiones si cumple de dicha condicin. En caso de que no se verifique, evaluar la siguiente expresin. Por lo tanto, COND evaluar las expresiones si cumple de la primera condicin que se verifique. Y devolver el resultado de evaluar la ltima expresin si cumple. Pongamos un ejemplo: (cond ((= a b) (alert "A y B son iguales") (setq b (getreal "Introduzca de nuevo B: ")) ) ((< a c) (alert "A es menor que C") ) ((< a b)) (T (alert "A no es igual a B") (alert "A no es menor que C") (alert "A no es menor que B") ) ) Supongamos ahora que antes de la expresin COND, hemos definido (setq a 2 b 2.0 c 3.5). En este caso, al entrar en COND se evaluar la primera condicin (= a b) que se verifica, de modo que se evaluaran las expresiones si cumple de esta condicin: (alert "A y B son iguales") y (setq b (getreal "Introduzca de nuevo B: ")) finalizando la expresin COND que devuelve el nuevo valor de b. Aunque la siguiente condicin (< a c) se cumple, no se evala, ya que existe una condicin anterior que tambin se cumpla. En caso de que se hubiera definido (setq a 2 b 2.5 c 3.5) la primera condicin (= a b) no se verifica, de modo que se evala la segunda condicin (< a c) que si se cumple. Evalundose sus expresiones si cumple (alert "A es menor que C") que devuelve nil. Si fuera (setq a 2 b 2.5 c 1.5) la primera condicin en cumplirse sera la tercera (< a b) que no tiene expresiones si cumple. Qu devolver entonces la funcin COND?

Pues el valor de la ltima expresin evaluada, es decir el valor devuelto por la condivin (< a b) que es T. Por ltimo, si tenemos (setq a 2 b 1.0 c 1.5) ninguna de las tres condiciones anteriores se verifica, de modo que pasamos a la siguiente condicin T, que lgicamente siempre devuelve T, as que siempre se verifica. Esto se suele utilizar mucho en la funcin COND, aadir como ltima condicin una que se verifique siempre. En lugar de T se poda haber puesto (not nil) o (= 1 1.0) que tambin son expresiones que siempre se cumplen. Para qu aadir una expresin que siempre se cumple? Muy sencillo, para incluir el cdigo que se desea ejecutar en caso de que no se verifique ninguna de las condiciones anteriores. Y qu sucede si no se pone la condicin T como ltima condicin? Pues sucede que las que estn a continuacin nunca se evaluarn, ya que T siempre se cumplir. Si en el ejemplo anterior hubieramos puesto: (cond

(T (alert "A no es igual a B") (alert "A no es menor que C") (alert "A no es menor que B") )((= a b) (alert "A y B son iguales") (setq b (getreal "Introduzca de nuevo B: ")) ) ((< a c) (alert "A es menor que C") ) ((< a b)) ) Independientemente de los valores de las variables a b y c siempre nos dira que A no es igual a B, A no es menor que C y A no es menor que B.

Qu es una variable de sistema?El modo en que funciona el entorno de AutoCAD, y la forma de trabajar de muchos de sus comandos, se ven afectados por los valores asignados a las variables de

sistema. Podra decirse que controlan como trabaja AutoCAD. Por lo tanto, se pueden modificar los valores asignados a las variables de sistema para personalizar AutoCAD para un usuario en concreto, para un tipo de trabajo determinado, e incluso para un archivo de dibujo. De modo que nos facilite el trabajar con AutoCAD.

Tipos de variables de sistemaLas variables de sistema pueden almacenar distintos tipos de datos, en funcin de la informacin que contengan. Podran clasificarse del siguiente modo:

Activada / Desactivada. Muchas variables de sistema slo admiten dos opciones: Activada y Desactivada. Normalmente tienen asignado el valor "0" cuando estn desactivadas, y "1" cuando estn activadas. Un ejemplo de este tipo de variables es "blipmode". Nmeros enteros. Otras variables tienen ms de dos posibilidades, para lo que asignan un nmero entero para cada opcin. Normalmente emplean nmeros correlativos, empezando desde el cero. Una variable que utiliza este tipo de datos es "coords". Cdigos binarios. Algunas variables pueden emplear varias opciones a la vez, para lo que suelen emplear cdigos binarios. A cada opcin se le asigna el nmero resultante de elevar 2 a n. Asignando a n nmeros entero correlativos a partir del cero. Es decir, los valores para las distintas opciones sern: 1,2,4,8,16,32,etc. De modo que para seleccionar la primera y cuarta opciones, hay que asignar a la variable la suma de sus valores: 1+8 = 9. Un ejemplo muy interesante de este tipo de variables es "osmode". Nmeros reales. Las variables que almacenan valores de ngulos o distancias, por ejemplo, utilizan este tipo de valores. Un ejemplo de este tipo es la variable "chamfera". Puntos. Este tipo de entidades almacenan las coordenadas de un punto, un buen ejemplo es "ucsorg". Cadenas de texto. Hay bastantes variables que almacenan cadenas de texto, como nombres de archivos o rutas de directorios. Ejemplos de este tipo de variables son "acadver" y "acadprefix".

Modificar los valores de las variables de sistemaPodramos clasificar las variables de sistema en funcin del lugar en el que se guardan:

No guardadas. La informacin asignada a este tipo de entidades no se guarda. Un ejemplo de este tipo de variables es "acadver". En el dibujo. La mayora de las variables de sistema son de este tipo, de modo que cada dibujo trabajar con unos valores determinados para las variables de sistema. Esto hace sumamente importante la definicin de los valores de las variables de sistema en las plantillas utilizadas para crear nuevos dibujos. Un ejemplo de variable guardada en el dibujo es "luprec". En el registro. Algunas variables de sistema se guardan en el registro de Windows. Por ejemplo "attdia".

La mayora de las variables de sistema de AutoCAD pueden editarse, modificando el valor que tengan asignado. Pero algunas variables son de solo lectura, de modo que no se pueden modificar, tan solo leer. Un ejemplo de variable de solo lectura es "cdate".

Hay varios mtodos para modificar los valores asignados a las variables de sistema de AutoCAD:

Tecleando el nombre de la variable, como si fuese un comando ms de AutoCAD. Ejecutando el comando "MODIVAR" e indicando la variable a modificar. Algunos comandos de AutoCAD permiten modificar los valores asignados a algunas variables de sistema. Por ejemplo el comando "MARCAAUX" permite modificar el valor asignado a la variable "blipmode". Algunas variables se modifican al ejecutar algn comando de AutoCAD. Por ejemplo "circlerad" almacena el radio de la ltima circunferencia creada con el comando "crculo".

Las variables de sistema en los programas de AutoLISPLos programadores suelen leer y modificar el contenido de algunas variables de sistema de AutoCAD, ya que esto les permite definir el modo en el que desean que se comporte AutoCAD o algunos comandos de AutoCAD. Esto puede ocasionar cambios en los valores asignados a algunas de las variables de sistema. Al programar deberas seguir los siguientes consejos para que esto no suceda: Deberas guardar los valores iniciales de las variables de sistema que se necesite modificar, y asignarles sus valores iniciales al terminar el programa. Crear una funcin de tratamiento de errores, de modo que si se produce algn error al ejecutar el programa se restablezcan los valores iniciales de las variables de sistema. La creacin de funciones de tratamiento de errores la trataremos ms adelante.

(GETVAR variable)Esta funcin devuelve el valor asociado a la variable que recibe como argumento. Por ejemplo: (getvar "osmode") (getvar "blipmode") (getvar "acadver")

(SETVAR variable nuevo_valor)Asigna a la vaiable indicada un nuevo valor, y devuelve dicho valor. (setvar "blipmode" 0) (setvar "osmode" 32) Veamos un ejemplo combinando las funciones GETVAR y SETVAR. Escribe lo siguiente en la lnea de comandos de AutoCAD: (getvar "luprec")

(setvar "luprec" 2) (getvar "luprec")

Func