• No se han encontrado resultados

Manual de Autolisp

N/A
N/A
Protected

Academic year: 2021

Share "Manual de Autolisp"

Copied!
109
0
0

Texto completo

(1)

Índice de temas del curso de AutoLISP

Tema 1 : Introducción.

Tema 2 : Las variables en AutoLISP.

Tema 3 : Operaciones matemáticas básicas.

Tema 4 : Solicitar números al usuario.

Tema 5 : Funciones de usuario y nuevos comandos.

Tema 6 : Introducción al entorno de Visual LISP.

Tema 7 : Cargar los archivos de AutoLISP.

Tema 8 : Operaciones matemáticas.

Tema 9 : Obtener textos y puntos del usuario.

Tema 10 : Funciones para manejar listas.

Tema 11 : Ejecutar comandos de AutoCAD.

Tema 12 : Operaciones de comparación.

Tema 13 : Operaciones lógicas.

Tema 14 : Estructuras condicionales.

Tema 15 : Mostrar textos en pantalla.

Tema 16 : Variables de sistema.

Tema 17 : Funciones de conversión.

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 automática de archivos de AutoLISP.

Tema 30 : Operaciones con archivos.

Tema 31 : Leer y escribir archivos de texto.

Tema 32 : La base de datos de AutoCAD.

curso de AutoLISP

Objetivos del curso

Con este curso no se pretende formar a expertos programadores en AutoLISP. Más bien, se pretende acercar este lenguaje de programación a los usuarios de AutoCAD, para que puedan crear utilidades y pequeñas aplicaciones que les ahorren tiempo y cálculos en sus trabajos.

Otro de los objetivos del curso es el de ver AutoCAD no como un programa de dibujo, sino como una potente base de datos gráficos. Y descubrir como funciona esa base de datos de AutoCAD.

¿Es rentable el AutoLISP? Desde luego que puede serlo, puede agilizar y facilitar enormemente el trabajo con AutoCAD. AutoLISP es un lenguaje sencillo de aprender y a diferencia de otros lenguajes de programación se pueden crear programas interesantes y útiles casi desde el primer momento.

(2)

Muchas veces, la mayoría del tiempo empleado en crear una rutina o programa se emplea en depurar el código (corregir errores). La planificación y el análisis previo de la rutina son de suma importancia para evitarlo. El primer paso para escribir una rutina consiste en escribir en un papel con un lenguaje simple lo que se desea que realice el programa, a esto se le denomina pseudocódigo. Un método algo más avanzado y eficaz es utilizar diagramas de flujo, puedes ver algo más sobre esta técnica en la sección de artículos: Diagramas de flujo.

Cuando ya se empieces a programar en AutoLISP por ti solo, te será muy útil reunir todas las anotaciones sobre proyectos de aplicaciones y rutinas en una libreta o bloc de notas.

Interfaces de programación

AutoCAD dispone varios entornos de programación, la selección del tipo de interfaz a emplear para crear una aplicación dependerá de las necesidades de la aplicación y de la experiencia o conocimientos del

programador/es:

AutoLISP es una adaptación del lenguaje de programación CommonLISP para AutoCAD. Es sencillo de aprender y al mismo tiempo potente. AutoCAD cuenta con un intérprete interno de LISP que permite introducir código desde la línea 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 aplicación 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 programación basado en objetos que utiliza íntegramente la sintaxis del lenguaje Visual Basic y permite usar controles ActiveX. Permite también la integración 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 programación de lenguaje compilado para el desarrollo de aplicaciones de AutoCAD. El entorno de programación ObjectARX incluye varias bibliotecas de vínculos dinámicos (DLL) que ofrecen acceso directo a las estructuras de la base de datos, el sistema de gráficos y los dispositivos de geometría de AutoCAD.

Características de AutoLISP

El LISP fue desarrollado a finales de los años 50 por John McCarthy, es el segundo lenguaje de programación más antiguo solo precedido por Fortran. Uno de los campos en los que es más empleado es en la

investigación en inteligencia artificial. Su nombre proviene de LISt Procesing (Procesado de listas), pues se basa en el uso de listas en lugar de datos numéricos. Aunque hay quien mantiene que su nombre proviene de "Lost In Stupid Parenthesis". AutoLISP añade al LISP algunas funciones especialmente diseñadas para la manipulación de entidades de AutoCAD.

AutoLISP es un lenguaje evaluado. El código se convierte a lenguaje máquina (ceros y unos) y se almacena en la memoria temporal. No es tan lento como los lenguajes interpretados, ni tan rápido como los

compilados. En los lenguajes interpretados, se va traduciendo el programa a código máquina (el idioma de los ordenadores) a medida que se ejecuta. En los lenguajes compilados, el código fuente (texto) del programa se traduce a código máquina generando un archivo ejecutable (.EXE) que es el que ejecutará el programa.

Hay quien dice que AutoLISP es lento comparándolo con otros lenguajes como Pascal o C, especialmente cuando se utilizan muchas funciones matemáticas. Sin embargo, cuando se utiliza manipulando símbolos los resultados son muy distintos. Esto hace de AutoLISP un excelente lenguaje para la programación de sistemas CAD, ya que un sistema CAD no es más que un entorno de manipulación de símbolos gráficos.

Una de las características más 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 información se puede modificar, extraer e incluso añadir más entidades al dibujo.

La mayoría de los lenguajes de programación como C o Pascal son lenguajes procedimentales, se ejecutan una serie de instrucciones paso a paso a partir de unos datos. En AutoLISP en lugar de seguir instrucciones prefijadas, se puede acceder a la información de los objetos para determinar de que información se dispone, preguntándole a los objetos por ellos mismos. AutoLISP no es estrictamente un lenguaje orientado al objeto,

(3)

pero contiene bastantes características de estos tipos de lenguajes debido a que puede interactuar con los objetos contenidos en los dibujos.

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 polígonos estrellados en lugar de los regulares.

Una mención especial merece el uso de AutoLISP en la realización de programas paramétricos y en el diseño semiautomático, ya que entre el 60% y el 80% del diseño está dedicado a la modificación de diseños previos. En los programas paramétricos, el usuario introduce una serie de datos o parámetros a partir de los cuales el programa realiza el diseño completo de un elemento u objeto. Esta es sin duda una de las mayores

aplicaciones de AutoLISP.

AutoLISP se ha mejorado con la creación 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

programación. Además añade nuevos comandos para permitir la interacción 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.

En los dos primeros capítulos del curso se trabajará desde la ventana de comandos de AutoCAD. A partir del tercer capítulo ya crearemos nuestras rutinas en archivos de texto utilizando el entorno de Visual LISP proporcionado por AutoCAD. Existen dos inconvenientes al emplear AutoLISP desde la ventana de comandos de AutoCAD:

En primer lugar el reducido espacio con el que se cuenta en la ventana de comandos de AutoCAD y la dificultad que supone el no tabular el código, es decir escribir el código todo seguido. Esto es debido a que cada vez que se pulsa Intro, AutoCAD evalúa lo que se ha escrito.

En segundo lugar, al terminar la sesión de trabajo en AutoCAD se perderán todos los datos almacenados en la memoria temporal.

Expresiones y procedimientos de evaluación

Un programa en AutoLISP consiste en una serie de expresiones del tipo "(función argumentos)". Cada expresión comienza con un paréntesis de apertura al que sigue el nombre de una función de AutoLISP (o una función creada por el usuario) y una serie de argumentos (a veces opcionales) que dependen de la función indicada y van separados por al menos un espacio en blanco. Cada expresión termina con un paréntesis de cierre, esto es muy importante pues el número de paréntesis de apertura debe ser igual al de cierre.

Cada expresión de AutoLISP devuelve un valor. Un argumento también puede ser una expresión, creándose así una estructura formada por expresiones (listas) anidadas unas dentro de otras; de modo que la más interior devolverá su resultado como un argumento a la lista exterior. Cuando existen listas anidadas (unas dentro de otras), primero se evalúan las más 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 función + que realiza la suma de los argumentos 1 y 2 devuelve el resultado 3.

(+ 31 22 -3) Ejecuta la función + que realiza la suma de los argumentos 31, 22 y -3 devuelve el resultado 50.

Prueba también:

(- 17 2)

(+ 2.5 22.8)

(4)

(+ 12 -2 31 -7.5)

Ejemplo:

(+ (* 2 3) 2) devuelve 8. Primero evalúa la lista interior y devuelve su resultado a la exterior.

(+ 7 (/ 5.0 2) -3) devuelve 6.5.

¿Qué sucedería si al escribir la expresión (+ 1 (/ 5.0 2)) nos olvidásemos de escribir el último paréntesis? Haz la prueba, veras que AutoCAD te indica que falta 1 paréntesis de cierre.

Si el interprete de comandos de AutoCAD encuentra un paréntesis de apertura, supone que todo lo que vaya a continuación hasta el paréntesis de cierre es una expresión de AutoLISP. De modo que envía esa expresión al interprete de AutoLISP para que la evalúe.

En el tema 2 veremos algunas de las operaciones matemáticas que se pueden realizar con AutoLISP.

Tipos de objetos y datos

Los elementos de las expresiones de AutoLISP pueden ser símbolos, valores concretos y también otras expresiones. Se pueden distinguir los siguientes tipos de elementos:

Símbolos: Cualquier elemento que no sea un valor concreto. Por ejemplo una variable, una función.

Enteros: Números enteros comprendidos entre -32000 y 32000.

Reales: Números reales (180 es un número entero, pero 180.0 es un número real).

Cadenas de texto: Texto con una longitud máxima 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 números enteros, y el resultado de su suma es un número entero. En el segundo caso, tenemos un número real, así que el resultado es un número real. Para que comprendas la importancia de esta distinción, 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 línea de 36 mm de longitud en la dirección que indicaba el cursor.

Prueba ahora indicando el radio de la circunferencia (- 70 25) al utilizar el comando llamado "CIRCULO" (mal llamado, debería ser "circunferencia").

(5)

Podemos emplear también la constante PI = 3.14159... para realizar cálculos. Por ejemplo, ejecuta de nuevo el comando "CIRCULO" y cuando pregunte el radio de la circunferencia, teclea (/ 6 (* 2 PI)). Obtendremos una circunferencia de perímetro 6.

Notación empleada

Para describir las funciones de AutoLISP que se expliquen a lo largo del curso se seguirá la siguiente notación:

(FUNCIÓN Argumentos_necesarios [Argumentos_opcionales] )

Los nombres de las funciones de AutoLISP aparecen en color azul y el código a teclear en cursiva.

Convenciones recomendadas

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

Para los comentarios incluidos en el código, se recomienda utilizar el siguiente método:

o

;;; Antes del código de las funciones, explicando su funcionamiento.

o

;; En medio del código del programa.

o

; Para explicar una línea de código. A diferencia de las anteriores, esta no se inserta en la columna 1, se insertará al terminar el código de la línea que comenta.

Es muy recomendable utilizar un formato tabulado para el código.

Evitar el uso de variables globales innecesarias.

Utilizar los comandos de AutoCAD y sus opciones en Inglés y precedidos por "._"

No abusar de la función "SETQ".

No utilizar T, MIN, MAX, LAST como símbolos (nombres de variables y funciones).

Recuperar el valor inicial de las variables de AutoCAD que han sido modificadas.

Añadir unas líneas al final del programa para indicar el nombre del nuevo comando, autor...

No introducir demasiado código en la función principal.

Incluir una función de tratamiento de errores.

Evitar que el usuario pueda introducir datos erróneos.

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 decían "Tengo 3 melones, le doy uno a Juan y después de comprar otros 2, me comí uno porque tenía hambre". Pues los melones son una variable. Nosotros hacíamos: 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 más que un valor que varía (o puede hacerlo) a lo largo del tiempo. Pero podíamos 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 perímetro, pero que sucede si queremos utilizar el valor obtenido por (/ 6 (* 2 PI)) para realizar otra operación, tendremos que volver a teclear la expresión anterior.

¿Existe alguna opción para almacenar en memoria los resultados de una operación, 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 función de AutoLISP empleada para definir variables y asignarles un valor es SETQ y permite definir varias variables en una misma expresión. La función SETQ devuelve el valor de la última variable definida.

(6)

Con respecto a los nombres utilizados para designar a los símbolos creados por el usuario (variables y funciones):

No son sensibles a las mayúsculas. Es lo mismo bloque, BLOQUE y Bloque.

No pueden contener espacios en blanco, ni los caracteres " ( ) . ; '

Pueden contener números, 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 límite en cuanto al número de caracteres, pero es recomendable emplear nombre cortos y descriptivos.

No es necesario declarar previamente las variables, como sucede en otros lenguajes de

programación. En AutoLISP una misma variable puede contener primero un número entero, luego uno real, después una cadena de texto, etc.

Ejemplo:

(SETQ a 3) Esta expresión 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)? Fíjate 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 expresión anterior devuelve su valor.

Si el interprete de comandos de AutoCAD recibe una palabra precedida por el signo de exclamación "!", comprobará si ese termino ha sido empleado como un símbolo (nombre de variable o una función de usuario) de AutoLISP. En cuyo caso devolvera su valor y en caso contrario devolvera nil, que es lo mismo que nada o vacío. Por ejemplo: !a devuelve 3.

Prueba también las siguientes expresiones y comprueba los valores asignados a las variables:

(SETQ c (+ b 3)) Los valores de las variables también 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 tenía la variable b en ese momento, no se estableció ninguna relación entre ambas variables.

También se puede asignar valores no numéricos a las variables. Por ejemplo, una cadena de texto. Las cadenas de texto son secuencias de uno o más caracteres encerrados entre comillas. Dentro de una cadena de texto pueden insertarse una serie de carácteres de control:

\\ representa al símbolo \

\" representa al símbolo "

\n representa un cambio de línea (retorno del carro)

\t representa una tabulación

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

En este caso además, 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 código. Pero también supone que se requiera más cuidado para no pasar a una función una variable con un tipo de dato incorrecto. Por ejemplo: (+ a b)

(7)

T Representa al valor lógico Cierto o Verdadero.

nil Representa al valor lógico 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 perímetro 6 unidades en una variable podemos teclear:

(SETQ rad (/ 6 (* 2 PI)))

Ejemplo: ¿Por qué las siguientes expresiones están 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 función suma, sino a una variable de valor 23. De modo que el primer termino de la expresión anterior no es una función, por lo que da un error. Para recuperar el modo habitual de trabajo de la función + es necesario cerrar la sesión actual de AutoCAD e iniciar una nueva sesión.

Operaciones matemáticas básicas

En el tema anterior ya vimos algún ejemplo de como funcionan las funciones matemáticas básicas (suma, resta, división y multiplicación). Ahora explicaremos su funcionamiento con mayor profundidad.

(+ [número1 número2 ... ] )

Suma los números indicados como argumentos y devuelve el resultado de dicha suma. Si todos los números de la lista son enteros, el resultado también 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 expresión:

(8)

Hemos asignado a la variable a el resultado de una operación en la que usamos el anterior valor asignado a la variable a como uno de los argumentos de la operación.

Si le pasamos a la función + un único número como argumento, nos devuelve ese número.

(+ 12.5) devuelve 12.5

(+ -7.0) devuelve -7.0

Si ejecutamos la función suma sin argumentos, devuelve 0.

(+ ) devuelve 0

La expresión (+ .5 2) nos dará un error. Los números reales siempre deben comenzar por un número entero, incluso si es cero, seguido de la parte decimal.

(+ 0.5 2) devuelve 2.5

(+ 3 -0.6) devuelve 2.4

(- [número1 número2 ... ] )

Resta al primer número todos los siguientes números pasados como argumentos. Si todos los números de la lista son enteros, el resultado también 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 función - un único número como argumento, nos devuelve ese número cambiado de signo.

(- 12.5) devuelve -12.5

(- -7.0) devuelve 7.0

En la expresión anterior, el primer signo "-" representa a la función resta, mientras que el segundo representa el signo de un número negativo.

Si ejecutamos la función resta sin argumentos, devuelve 0.

(- ) devuelve 0

(* [número1 número2 ... ] )

Multiplica los números indicados como argumentos y devuelve el resultado de dicho producto. Si todos los números de la lista son enteros, el resultado también será entero.

(* 3 9) devuelve 27

(9)

(SETQ a (* 3 9 4)) devuelve 108 y lo almacena en la variable a

(* 3.5 -1) devuelve -3.5

Prueba ahora la siguiente expresión:

(SETQ a (* a 2.5)) devuelve 270.0

Si le pasamos a la función * un único número como argumento, nos devuelve ese número.

(* 12.5) devuelve 12.5

(* -7.0) devuelve -7.0

Si ejecutamos la función * sin argumentos, devuelve 0.

(* ) devuelve 0

(/ [número1 número2 ... ] )

Divide el primer número entre el siguiente y devuelve el resultado. Si se pasan más de dos números como argumentos, el primer número se dividirá entre el producto de los restantes números.

(/ 45 5 3) devuelve 3

(/ 11 5.5) devuelve 2.0

En esta función es muy importante recordar que si todos los números de la lista son enteros, el resultado también 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 función / un único número como argumento, nos devuelve ese número.

(/ 12.5) devuelve 12.5

(/ -7.0) devuelve -7.0

Si ejecutamos la función / sin argumentos, devuelve 0.

(/ ) devuelve 0

(1+ <número> )

Esta función incrementa en una unidad el número indicado como argumento.

(1+ 5) devuelve 6. Ojo entre "1" y "+" no debe haber ningún espacio, ya que el nombre de la función es "1+".

(10)

(1+ 2.5) devuelve 3.5

(1+ 0) devuelve 1

(1+ -7) devuelve -6

Una aplicación bastante habitual de esta función es la de incrementar índices o contadores:

(SETQ i 1)

(SETQ i (1+ i)) devuelve 2

(1- <número> )

Esta función reduce en una unidad el número indicado.

(1- 5) devuelve 4. Ojo entre "1" y "-" no debe haber ningún espacio, ya que el nombre de la función es "1-".

(1- 2.5) devuelve 1.5

(1- 0) devuelve -1

(1- -1) devuelve -2

Solicitar números al usuario

En este apartado veremos dos funciones de AutoLISP que no permitirán solicitar al usuario un número entero o real. Esto nos permitirá interactuar con el usuario y pedirle información.

(GETINT [mensaje] )

Solicita del usuario un número entero. En caso de que el usuario introduzca un número real o cualquier otro dato que no sea un número entero, AutoCAD recordará mediante un mensaje que está solicitando un número entero y no finalizará la ejecución de la función hasta que se introduzca un valor entero, o se pulse ESC para cancelar su ejecución.

(GETINT)

Puede indicarse un mensaje de solicitud opcional, que facilite al usuario información acerca de lo que se está pidiendo. El mensaje debe ser una cadena de texto y por tanto debe estar entre comillas.

(GETINT "Cuantos años tienes:")

Podemos asignar el valor introducido por el usuario a una variable y así utilizarlo después.

(SETQ edad (GETINT "Cuantos años tienes:"))

(SETQ edad (+ edad 1)) nos dará la edad que tendrás el próximo año.

También puedes crear una variable que contenga el mensaje de solicitud de la función GETINT

(SETQ mens "Cuantos años 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.

(11)

Prueba ahora el siguiente ejemplo:

(SETQ a 27 mens "Cuantos años tienes:")

(SETQ edad (GETINT mens))

Que pasará si como respuesta a la solicitud de la edad del usuario se introduce !a. Parece lógico que le estamos indicando el valor de la variable a, que contiene el valor numérico 27, de modo que la variable edad debería 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 función 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 ejecución, no puede volver a ejecutarse y nos muestra el mensaje anterior.

(GETREAL [mensaje] )

Solicita del usuario un número real. En caso de que el usuario introduzca un número entero, el interprete de AutoLISP lo considerará como un real. Si se introduce cualquier otro tipo de dato que no sea numérico, recordará mediante un mensaje que está solicitando un número real y no finalizará la ejecución de la función hasta que se introduzca un valor numérico, o se pulse ESC para cancelar su ejecución.

(GETREAL)

Puede indicarse un mensaje de solicitud opcional, que facilite al usuario información 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 tendrás si adelgazas un kilo.

También puedes crear una variable que contenga el mensaje de solicitud de la función GETREAL

(SETQ mens "Cuantos kilos pesas:")

(SETQ peso (GETREAL mens))

Definir funciones de usuario

Hemos visto tan solo algunas de las funciones de AutoLISP, pero también es posible crear nuestras propias funciones. Es más, podemos redefinir las funciones de AutoLISP e incluso los comandos de AutoCAD. La instrucción de AutoLISP que nos permitirá crear nuestras propias funciones, denominadas funciones de usuario, se llama DEFUN.

(DEFUN <función> ( [argumentos] / [variables_locales] ) [expr1] [expr2] ...)

El primer argumento representa el nombre de la funcíon 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 redefinirían.

Después de indicar el nombre de la función, se deben indicar entre paréntesis los argumentos y las variables locales, separados por una barra inclinada.

Los argumentos son valores que recibirá la función cuando sea ejecutada por el usuario, o llamada desde otras funciones.

Las variables locales son aquellas variables que se emplearán tan solo dentro de la función que queremos definir, de modo que restringimos su uso al entorno de la función.

Por último, se añaden las expresiones que ejecutará la función. Veamos algunos ejemplos:

(12)

En este caso hemos definido una nueva función llamada "2+", que recibe como argumento un número y realiza la suma de ese número y 2. Las funciones de AutoLISP las ejecutabamos escribiendo (1+ 5)

directamente desde la línea 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 expresión ejecutada, que en el caso anterior es (+ valor 2).

¿Que sucede si tratamos de ejecutar la función sin pasarle ningún argumento, o pasandole un argumento que no sea de tipo numérico?. Veamoslo:

(2+ ) indica "; error: argumentos insuficientes"

(2+ "texto") indica "; error: tipo de argumento erróneo: numberp: "texto""

(2+ 1 2) indica "; error: demasiados argumentos"

Podrías pensar que el número indicado se almacena en una variable llamada "valor", pero no es así. Compruebalo escribiendo !valor en la línea de comandos, lo que nos devolverá nil.

En la función 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 razón:

(2+ 5) devuelve 7

!valor devuelve nil

Parece que estabas equivocado. La función "2+" recibe como argumento un número, que almacena en la variable "valor". Pero el ámbito de aplicación es local, es decir una vez que salgamos de la función "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 función "2+" tenemos que "valor" = 4

4. Dentro de la función "2+" asignamos (SETQ valor (+ valor 2)) de modo que "valor" = 4 + 2 = 6 5. Pero al salir de la función "2+" recuperamos el valor que tenía la variable "valor" antes de llamar a

la función, 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 función "2+" le asignamos a "valor" el valor devuelto por la función, que es 6. De modo que "valor" = 6.

(13)

Retoquemos un poco más la función "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 función "2+" declaramos una variable a la que se le asigna el valor que recibe como argumento la función.

(2+ 4)

¿Que valor tendrán 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 función. Sin embargo "inicial" es de ámbito global, es decir sigue empleandose al salir de la función. Vamos a modificar un poquito más nuestra función:

(DEFUN 2+ ( valor / inicial ) (SETQ inicial valor valor (+ valor 2)))

Ahora hemos añadido 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 modificación de la función "2+"

(DEFUN 2+ ( / valor ) (SETQ valor (GETINT "Número: ")) (SETQ valor (+ valor 2)))

Ahora la función "2+" no tiene argumentos, así que para ejecutarla tan solo debemos poner su nombre entre paréntesis:

(2+)

La variable "valor" es de ámbito local y se emplea GETINT para solicitar un número 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 añadir a la lista de variables locales dentro de las definiciones de las funciones de usuario.

Crear nuevos comandos de AutoCAD

La función de AutoLISP DEFUN no solo nos permite crear funciones de usuario, también nos permite crear nuevos comandos de AutoCAD.

(14)

(DEFUN C:2+ ( / valor ) (SETQ valor (GETINT "Número: ")) (SETQ valor (+ valor 2)))

Si anteponemos al nombre de la función a definir "C:" en lugar de crear una función de usuario, se crea un nuevo comando de AutoCAD. La función seguirá funcionando exactamente igual, la única diferencia está en el modo de ejecutarse. Ahora no es necesario poner el nombre de la función entre paréntesis, sino que se escribe directamente.

2+

También puede ejecutarse poniendo el nombre de la función precedido de "C:" entre paréntesis.

(C:2+)

En caso de que el nuevo comando creado necesite algún 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 función que hemos creado solo nos servirá para la sesión actual de AutoCAD. Es más, tan solo está definida la función 2+ en el dibujo actual, de modo que si hay más 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 código fuente en AutoLISP

Ya hemos visto que las funciones de AutoLISP se pueden ejecutar directamente desde la ventana de comandos de AutoCAD. Pero el escribir el código directamente en AutoCAD tiene varios inconvenientes, como ya dijimos en el primer tema del curso:

1. El reducido tamaño de la ventana de comandos de AutoCAD.

2. La dificultad de escribir todo el código seguido, sin tabular. Esto es debido a que cada vez que se pulsa Intro, AutoCAD evalúa lo que se ha escrito.

3. El código no se almacena en ningún 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 pequeñas líneas de código que no interese guardar. Suele emplearse por tanto para hacer pruebas y depurar código, aunque también se puede utilizar como una ayuda más para el diseño con AutoCAD.

El código 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 códigos ASCII, por ejemplo el bloc de notas de Windows. Otros editores, como MS Word, insertan códigos 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 códigos.

Además del bloc de notas, existen muchos otros editores de texto que se pueden emplear para escribir código fuente en AutoLISP. Algunos de estos editores, disponen de utilidades para la programación (permitiendo incluso emplearlos para distintos lenguajes de programación). Otros editores están ya enfocados a la programación en LISP o AutoLISP.

Desde la versión 14, AutoCAD incorpora un editor para AutoLISP, en el que tenemos entre otras las siguientes utilidades:

Evaluación de paréntesis durante la programación.

Posibilidad de compilar el código, consiguiendo así aumentar su velocidad de ejecución.

Depurador de código específico para AutoLISP con opciones para: Ejecutar el código paso a paso, indicar puntos de parada, evaluar expresiones y valores de variables, etc.

Diferenciar el código fuente con distintos colores.

Tabulado automático del código.

(15)

Utilidades para gestionar proyectos con varios archivos de código.

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 extensión LSP.

Nuestra primera función de usuario

Antes de comenzar con el editor de Visual LISP, vamos a crear nuestra primera función de usuario: Se trata de una función para convertir un ángulo de radianes a grados decimales. El código de la función sería el siguiente:

(defun RAG ( ang )

(/ (* ang 180.0) pi)

)

El código de las rutinas publicadas en el curso se escribirá con el siguiente formato:

Comentarios en el código

Funciones de AutoLISP

Números

Textos

FUNCIONES DE USUARIO Y NUEVOS COMANDOS

Nombres de variables, paréntesis, etc... Hay tres reglas básicas que sigue AutoLISP:

1. El número de paréntesis de apertura debe ser igual al número de paréntesis de cierre. 2. Primero se evaluan las listas más interiores.

3. Toda función de AutoLISP devuelve un resultado.

El interprete de AutoLISP no evalúa los retornos de carro (Intros), de modo que el código se podía haber escrito todo seguido, en una misma línea: (defun RAG ( ang ) (/ (* ang 180.0) pi) ) pero así es más difícil de leer. Esta función tiene muy poco código, pero imaginate una función mucho mayor escrita toda en la misma línea...

Fíjate en que la segunda línea 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 función defun. No es necesario tabular el código, pero facilita su lectura y además nos permite detectar posibles errores con los paréntesis (Regla número 1). Pi es una constante que ya está definida en AutoLISP, pi = 3.141592...

En la primera línea "(defun RAG ( ang )" definimos la función RAG (Radianes A Grados) que recibe un argumento "ang" (el ángulo en radianes).

Veamos como funciona la segunda línea: Por la Regla número 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 número 3) que lo divide entre pi = 3.141592... devolviendo a su vez el resultado de la división (el ángulo en grados decimales) a la lista de nivel superior, defun.

La última línea cierra la lista de la función defun, verificandose así la Regla número 1.

Recordemos la estructura de la función de AutoLISP defun: (DEFUN <función> ( [argumentos] /

(16)

declarado variables locales (por lo que no es necesario poner el caracter "/"), además solo tenemos una expresión (/ (* ang 180.0) pi) . Como se dijo en el tema anterior, defun devuelve el resultado de la última expresión, que en nuestro caso resulta ser el ángulo ya convertido a grados decimales.

Nuestra función RAG se ejecutaría así: (RAG 1.57) siendo 1.57 el ángulo en radianes, y devolvería ese ángulo en grados decimales (aproximadamente 90º). No es necesario poner el nombre de la función RAG en

mayúsculas, ya que AutoLISP no diferencia las mayúsculas de las minúsculas (salvo en contadas excepciones que ya explicaremos). Aunque al poner los nombres de las funciones en mayúsculas se diferencian

perfectamente del resto del código.

Los comentarios en el código

Es imprescindible añadir comentarios al código para explicar que es lo que hace y como se hace. En AutoLISP todo lo que en una línea va después de un punto y coma (como este ;) se considera un comentario, de modo que no se evalúa. Da igual poner uno, dos o 45 punto y comas seguidos, al poner el primero AutoLISP ya sabe que todo lo que está a continuación, en esa línea, es un comentario.

Tal vez penseis que no es tan importante añadir explicaciones en el código. Pero si teneis que leer una rutina que creasteis hace meses os serán muy útiles, por que seguramente no recordareis muy bien como funciona. Además, si alguien va a leer alguna de vuestras rutinas le facilitariais mucho la labor. Al igual que a vosotros os será más sencillo leer y entender una rutina con abundantes comentarios.

Para los comentarios incluidos en el código, se recomienda utilizar el siguiente método:

;;; Antes del código de las funciones, explicando su funcionamiento.

;; En medio del código del programa.

; Para explicar una línea de código. A diferencia de las anteriores, esta no se inserta en la columna 1, sino al terminar el código de la línea que comenta.

Por ejemplo, la función RAG con comentarios podría quedar así:

;;; Esta función 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

El 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:

(17)

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 específicas para la programación 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:

(18)

Es en esta pantalla donde vamos a escribir el código de nuestra rutina RAG, pero antes un pequeño comentario...

Es bastante habitual añadir al principio de los archivos de AutoLISP unas líneas de comentarios indicando el nombre del autor, fecha, nombre de los comandos y/o funciones definidas en el archivo, y una breve descripción de estos. De modo que al código anterior le añadiremos unas líneas en la cabecera del archivo:

;;;________________________MecaniCAD__________________________;;;

;;;_____________http://www.peletash.com/mecanicad_____________;;;

;;;_________________________RAG.LSP___________________________;;;

;;;_______________________Versión 1.0_________________________;;;

;;;________________________21/02/2002_________________________;;;

;;; Esta función recibe el valor de un ángulo en radianes y lo devuelve en grados decimales.

(19)

(/ (* 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 automáticamente. Y aunque se pueden eliminar o modificar a vuestro gusto (añadiendo o quitando espacios y tabulaciones), lo recomendable es mantener el formato por defecto para el código. Veamos como queda la función GAR en el editor:

En primer lugar observamos que el código 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 números en verde.

Etc.

El formato coloreado del código se puede desactivar, o se pueden modificar los colores predefinidos para los diferentes elementos. Pero el mantener el formato de colores para el código, nos puede ayudar a detectar

(20)

errores. Por ejemplo, si ponemos "(SETW radianes ...", SETW aparecerá en negro y no en azul, por que la función de AutoLISP es SETQ, de modo que nos indica que hemos escrito mal el nombre de la función.

En cuanto a la tabulación, tal vez llame la atención el último paréntesis (el de cierre de la función defun), ya que no está a la misma altura que su paréntesis de apertura. Hay editores para AutoLISP que insertan los paréntesis de cierre a la misma altura que sus correspondientes paréntesis de apertura y hay otros editores que insertan los paréntesis de cierre tabulados, tal como hace (por defecto) el editor de Visual LISP.

Una vez escrito el código de la función 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 función 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 código de la función 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 función llamada GAR que reciba como argumento un ángulo en grados decimales y que devuelva ese ángulo en radianes. Es practicamente igual a la función 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 pseudocódigo (ni hacer un diagrama de flujo), tan solo hay que pensar un poco en lo que se va a hacer. Guarda el código de la función GAR en un archivo llamado "GAR.lsp" en el directorio donde tengas tus rutinas.

Cargar los archivos de AutoLISP

Para que la función 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 función 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 menús desplegables del Visual LISP "Herramientas --> Cargar texto en editor".

Pulsando sobre el icono .

Tecleando la combinación 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 #<editor "RUTA/rag.lsp">. En caso de que se produzca algún error en el proceso de carga del archivo, en la consola de Visual LISP se nos indicaría el tipo de error que se ha producido. De modo que habria que modificar el código 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 método para cargar un archivo de AutoLISP en AutoCAD (seleccionando en el menú de AutoCAD "Herr-->AutoLISP-->Cargar") muestra un letrero de diálogo en el que se selecciona el archivo a cargar (también se pueden seleccionar más de un archivo) y se pulsa el botón "Cargar".

(21)

(LOAD archivo [resultado_si_falla])

La función LOAD permite cargar en AutoCAD el archivo de AutoLISP que se indique. Por ejemplo para cargar el archivo RAG sería:

(load "rag")

No hace falta indicar la extensión 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 daría 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

(22)

En caso de que no se encuentre el archivo, la expresión 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 pseudocódigo:

Si test = 0 ==> Mensaje al usuario "Archivo no encontrado"

Esto es todo, de momento, sobre la carga de archivos de AutoLISP en AutoCAD. Más adelante veremos métodos mucho mejores para cargar nuestras rutinas.

Veamos como sería la función GAR propuesta en el tema anterior:

;;;________________________MecaniCAD__________________________;;;

;;;_____________http://www.peletash.com/mecanicad_____________;;;

;;;_________________________GAR.LSP___________________________;;;

;;;_______________________Versión 1.0_________________________;;;

;;;________________________21/02/2002_________________________;;;

;;; Esta función 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 función RAG, no?

Crear un directorio para los archivos de AutoLISP

Supongamos que el directorio que hemos creado para almacenar nuestras rutinas es "C:\Rutinas". Veamos como añadirlo a los directorios de soporte de AutoLISP:

Inicia AutoCAD. En el menú desplegable "Herr" selecciona "Opciones". Así aparece un letrero de diálogo que nos permitirá configurar AutoCAD. En la primera pestaña "Archivos" tenemos una opción denominada "Ruta de búsqueda de archivos de soporte". Si no está expandida, para ver su contenido pulsamos con el ratón sobre el + que aparece a la izquierda. Para añadir un nuevo directorio de soporte pulsamos el botón "Añadir" que se encuentra a la derecha del cuadro de diálogo. Esto creará una nueva etiqueta, en la que podemos escribir la ruta del directorio o pulsar el botón "Examinar" para seleccionarlo. Ya hemos añadido "C:\Rutinas" a los directorios de soporte de AutoCAD.

(23)

También 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 matemáticas

Hemos visto las operaciones matemáticas básicas: suma, resta, multiplicación y división y las funciones 1+ y 1-. Ahora vamos con otras funciones de AutoLISP que nos permitiran realizar casi cualquier operación matemática en nuestras rutinas.

(ABS numero)

Esta función devuelve el valor absoluto del número que se le pase como argumento. Por ejemplo:

(abs 23.8) devuelve 23.8

(abs -23.8) tb devuelve 23.8

Si el número que recibe como argumento es entero, devuelve un número entero y si es un número real, devuelve un real.

(abs -7) devuelve 7

(24)

(abs 0) devuelve 0

(FIX numero)

Esta función devuelve la parte entera de un número. De modo que devuelve un número 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 función devuelve el resto de la división de numero1 entre numero 2.

(rem 2.5 2) devuelve 0.5

(rem 3 2) devuelve 1

Cuando se indica más de 2 números (rem 1 2 3) es equivalente a (rem (rem 1 2) 3). Es decir, primero calcula el resto de la división entre 1 y 2, que es 1, y después lo divide entre 3 y devuelve su resto, que es 1.

Si todos los números que recibe como argumentos son enteros, devuelve un número entero y si alguno de ellos es un número 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 número (ATAN num1 num2) lo que hace es dividir num1 entre num2 y devuelve el arco cuya tangente sea el resultado de la división. Esto se hace para facilitar lo siguiente...

(atan (sin angulo) (cos angulo)) devuelve angulo

(25)

Esta función devuelve la raiz cuadrada del numero que recibe como argumento. Siempre devuelve un número real, no entero.

(sqrt 4) devuelve 2.0

(sqrt 2.0) devuelve 1.41..

(EXPT num exp)

Devuelve el número num elevado al exponente exp.

(expt 2 2) devuelve 4

(expt 2 3) devuelve 8

Si todos los números que recibe como argumentos son enteros, devuelve un número entero y si alguno de ellos es un número real, devuelve un real.

(expt 3 2.0) devuelve 9.0

(EXP num)

Devuelve el número e (e = 2.71828... ) elevado al número num. Siempre devuelve un número real.

(exp 1) devuelve 2.71828

(exp 2) devuelve 7.38906

(LOG numero)

Esta función devuelve el logaritmo neperiano del número que recibe como argumento.

(log 1) devuelve 0.0

(log 2) devuelve 0.693147

(GCD entero1 entero2)

Esta función recibe dos números enteros y devuelve su máximo común divisor (o denominador). Siempre devuelve un número entero.

(gcd 15 5) devuelve 5

(gcd 9 27) devuelve 9

(MAX num1 num2 ...)

Devuelve el mayor de los números que recibe como argumentos.

(max 2 4 1 3 6) devuelve 6

(max 8 4 -9) devuelve 8

Si todos los números que recibe como argumentos son enteros, devuelve un número entero y si alguno de ellos es un número real, devuelve un real.

(26)

(max 8 4.0 -9) devuelve 8.0

(MIN num1 num2 ...)

Devuelve el menor de los números que recibe como argumentos.

(min 2 3 6) devuelve 2

(min 8 4 -9) devuelve -9

Si todos los números que recibe como argumentos son enteros, devuelve un número entero y si alguno de ellos es un número real, devuelve un real.

(min 8 4.0 -9) devuelve -9.0

Pues ya están vistas todas las funciones matemáticas... Enhorabuena

Solicitar textos al usuario

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

(GETSTRING [modo] [mensaje])

Se puede ejecutar sin parámetros (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 pequeño cambio:

(setq nombre (getstring T "Cual es tu nombre?"))

Le estamos indicando el argumento [modo] = T. Este argumento puede ser cualquier expresión 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, vacío) entonces no admite espacios. Y si se pone cualquier expresión 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 usuario

Para solicitar puntos se utilizan dos funciones que también son parecidas a GETINT y a GETREAL.

(27)

Esta función 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 (ratón) o tecleando sus coordenadas, tal y como se haría al dibujar en AutoCAD.

Se puede ejecutar sin parámetros (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 además 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 línea elástica entre el punto pto y la posición del cursor.

(GETCORNER pto_base [mensaje])

Esta función se utiliza también 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 línea elástica entre el punto pto y la posición del cursor. Si se utiliza getcorner, en lugar de una línea elástica, aparece un rectángulo.

Fijemonos un momento en lo que devuelven tanto getpoint como getcorner: (125.68 117.68 0.0). Se trata de una lista. En el próximo tema veremos algunas funciones para manejar listas.

Funciones para manejar listas

AutoLISP es un lenguaje de programación basado en listas, así que es lógico 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 función 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 función devuelve la lista que recibe como argumento pero sin el primer elemento.

(28)

(CADR lista) y otras

Cómo se obtendría 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 mayúsculas, lo anterior quedaría:

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 mnemotécnica para recordar el nombre de estas funciones. Tan solo se permiten 4 niveles de anidación, 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 obtendríamos 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:

(29)

Cómo 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 cómo 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 cómo 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) también devuelve f. Pero al ejecutar esta línea AutoCAD nos dice que la función 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 número de elementos que tienen las listas. Para ello se utiliza la función length, que devuelve el número de elementos de la lista que recibe como argumento. Por ejemplo:

(length pto) devuelve 3. y si el pto estuvuiera en 2D (X Y) devolvería 2.

Y qué devolvería (length lst) ??? siendo lst = ((a b) (c d) (e f)). Pues devolvería 3, ya que lst es una lista con 3 elementos que a su vez son listas.

Qué devolvería (length (car lst)) ??? El número de elementos del primer elemento de lst, es decir el número de elementos de (a b), que es 2.

(LIST elemento1 elemento2 ...)

Esta función devuelve una lista formada por los elementos indicados. De modo que se utiliza para crear listas. Por ejemplo:

(30)

(list 1 2 3) devuelve (1 2 3)

(list "pepe" 2 "Juan") devuelve ("pepe" 2 "Juan")

Veamos que hace la siguiente expresión:

(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 AutoCAD

Una de las mayoresventajas de la programación en AutoLISP es la posibilidad de ejecutar comandos de AutoCAD en nuestras rutinas.

(COMMAND "comando" [datos])

Esta es la función 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 línea desde el origen al punto 100,200. Pero, nos falta algo: Al dibujar líneas 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 también 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, edición, 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 AutoCAD

Supongamos que no disponemos de una versión en castellano de AutoCAD, sino que está en inglés, o en Francés, o Chino Mandarín... 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 Inglés sólo serviría para las versiones en Inglés. 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 versión idiomática del programa: Castellano, Francés, etc) y una lengua interna, el Inglés.

De modo que los comandos de AutoCAD (y sus opciones) se pueden escribir en Castellano o en inglés. Pero para diferenciar unos de otros a los comandos en la lengua nativa de AutoCAD (Inglés) se les antepone un guión bajo:

(command "_circle" (list 0.0 0.0) 25.0)

(31)

Las opciones de los comandos también se deben indicar en inglés anteponiendoles un guión bajo. Por ejemplo:

(command "_circle" (list 0.0 0.0) "_d" 25.0) Esta línea dibuja una circunferencia de Diámetro 25 con centro en el origen.

Comandos de AutoCAD redefinidos

Por otra parte, ya se ha dicho anteriormente que los comandos de AutoCAD se podrán 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 línea para que dibuje circulos, entonces debemos indicar (command "linea" centro radio) y no (command "linea" pt0 pt1"") que no funcionaría, puesto que le estamos pasando unos parámetros que no espera. Pero cómo hacemos ahora para dibujar una línea?

Para ejecutar los comandos originales de AutoCAD, y no los redefinidos (si lo están) 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 además indicar los comandos en Inglés anteponiendoles un guión bajo así que también 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 guión bajo.

Para redefinir un comando de AutoCAD:

1. Ejecutar el comando "ANULADEF" (En Inglés "undefine") indicando el nombre del comando a redefinir. De este modo se elimina la definición 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 definición del comando línea. Podemos hacerlo desde AutoCAD con el comando "ANULADEF" (En inglés "undefine") o desde AutoLISP: (command "_undefine" "linea")

Ahora podemos comprobar que el comando línea no funciona en AutoCAD, y la única forma de ejecutarlo es anteponiendo a su nombre un punto ".linea".

Cargamos la siguiente función:

(defun C:LINEA ( )

(setq pt (getpoint "Centro del círculo: "))

(setq rad (getreal "Radio del círculo"))

(command "._circle" pt rad)

Referencias

Documento similar