Sie sind auf Seite 1von 215

AutoCAD

1- Primeros pasos con AutoLISP


Interfaces de programacin
AutoLISP es una adaptacin del lenguaje de programacin CommonLISP para AutoCAD. ActiveX
Automation constituye una alternativa moderna al AutoLISP.
VBA es un entorno de programacin basado en objetos que utiliza ntegramente la sintaxis del
lenguaje Visual Basic y permite usar controles ActiveX
ObjectARX es un entorno de programacin de lenguaje compilado para el desarrollo de
aplicaciones de AutoCAD.

Caractersticas de AutoLISP
Su nombre proviene de LISt Procesing (Procesado de listas), se basa en el uso de listas en lugar
de datos numricos.
AutoLISP 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

AutoLISP puede acceder a la base de datos de los dibujos de AutoCAD. Donde podemos
acceder a las capas, estilos de texto, sistemas de coordenadas personales (SCP) as como a
todas las entidades del dibujo. Esta informacin se puede modificar, extraer e incluso aadir ms
entidades al dibujo o informacin adicional.
AutoLISP no sigue instrucciones prefijadas, accede a la informacin de los objetos de AutoCAD
determina de que informacin se dispone, preguntndole a los objetos por ellos mismos.
AutoLISP puede interactuar con los objetos contenidos en los dibujos.
AutoLISP permite crear nuevos comandos para AutoCAD
AutoLISP en la realizacin de programas paramtricos y en el diseo semiautomtico, ya que
entre el 60% y el 80% del diseo
AutoLISP 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.
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 evaluacin


Un 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, 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; 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:
(+ 1 2) Ejecuta la funcin + realiza la suma de los argumentos 1 y 2, devuelve resultado 3.
(+ 31 22 -3) Ejecuta la funcin + realiza la suma de los argumentos y devuelve el resultado 50.
Prueba tambin: (- 17 2)
Ejemplo: (+ (* 2 3) 2) devuelve 8.

(+ 2.5 22.8)

(- 0.25 22.5)

(+ 12 -2 31 -7.5)

evala la lista interior y devuelve su resultado a la exterior.

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

Tipos de objetos y datos

Los 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. Ej. 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. los argumentos son nmeros enteros y devuelve un entero
(+ 5 2.0) devuelve 7.0. tenemos un nmero real, as que el resultado es un nmero real
AutoLISP puede ejecutar expresiones en medio de un comando de AutoCAD.
Ejemplo: Ejecuta comando LINEA e indica el primer punto, activa forzado ortogonal (F8) y
teclea (+ 11 25) Esto devuelve el resultado de la suma al comando que se estaba ejecutando.
Dibuja una lnea de 36 mm de longitud en la direccin que indicaba el cursor.
Prueba indicando el radio de la circunferencia (- 70 25) al utilizar el comando CIRCULO
La constante PI = 3.14159 ejemplo, ejecuta comando CIRCULO y cuando pregunte el radio de
la circunferencia, teclea (/ 6 (* 2 PI)). Obtiene circunferencia de permetro 6.

Notacin empleada

(FUNCIN Argumentos_necesarios [Argumentos_opcionales] )


Los nombres de las funciones de AutoLISP y el cdigo a teclear se mostrarn en negrita.

Convenciones recomendadas

para los comentarios incluidos en el cdigo:


o
;;; Antes del cdigo de las funciones, explicando su funcionamiento
o
o

;; 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, 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 sistema de AutoCAD que se modificaron

aadir unas lneas al final del programa e indicar nombre del nuevo comando, autor, etc.

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

Convenciones utilizadas en el curso

El cdigo en AutoLISP se mostrar en negrita y con los siguientes colores:


o
los parntesis de apertura y cierre se mostrarn en rojo ( )
o

las funciones de AutoLISP se mostrarn en azul setq

los nmeros se mostrarn en verde 125.6 12

los textos se mostrarn en rosa /nDesigne un punto:

los comentarios se mostrarn en prpura ;Esto es un comentario

las funciones de usuario se mostrarn en maysculas (GAR 90.0)

2- Las variables en AutoLISP


Qu 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. 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 a lo largo del
tiempo. Pero podamos haber llamado a la variable yo z, y por qu no melones?

(SETQ Variable1 Valor1 [Variable2 Valor2 ... ] )


Almacena en memoria los resultados de una operacin y permite definir varias variables en una
misma expresin. La funcin SETQ devuelve el valor de la ltima variable definida.
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 nombres


cortos y descriptivos.

no es necesario declarar previamente las variables. 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 asigna el valor 3. Devuelve el valor de a.
Que valor devolver (setq b (+ 1 3) melones 23.0)? se han definido dos variables b y melones de
valor 4 y 23.0 respectivamente. Como melones es la ltima variable evaluada, devuelve su valor.
Si la barra de comandos recibe una palabra precedida por el signo de exclamacin !, comprueba si
el termino fue empleado como un smbolo (nombre de variable o una funcin de usuario) de
AutoLISP. Devolver su valor y en caso contrario devolver nil, Por ejemplo: !a devuelve 3.
Prueba las siguientes expresiones y comprueba los valores asignados a las variables:
(setq c (+ b 3)) Los valores de las variables pueden usarse para realizar operaciones y asignar el
resultado 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 asignado a la
variable 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.
Se puede asignar valores no numricos a las variables. Por ejemplo, una cadena de texto, que 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 Curso Introduccin a la programacin en AutoCAD )


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 requiere ms cuidado para no pasar
a una funcin una variable con un tipo de dato incorrecto. Por ejemplo: (+ a b) ya que ahora la
variable a contiene una cadena de texto en lugar de un nmero.
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)
A la variable a se le asigna una cadena de texto, a la variable b el valor Cierto o Verdadero y a la
variable c el valor Vaco o Falso.

Almacenar el radio del circulo de permetro 6 en una variable, teclear: (setq rad (/ 6 (* 2 PI)))
Podramos crear un circulo e indicar !rad a AutoCAD cuando nos pregunte por el radio deseado.
Ejemplo: Por qu las siguientes expresiones estn mal?
(setq 157 25)

(setq rad 5 Rad 4)

(setq b Curso de AutoLISP)

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. lo que da
error. Para recuperar el modo habitual de trabajo de la funcin + cerrar la sesin actual de AutoCAD
e iniciar una nueva sesin.

3- Operaciones matemticas bsicas

(+ [nmero1 nmero2 ... ] )


Suma los nmeros indicados como argumentos y devuelve el resultado.
(+ 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 la siguiente expresin:
(setq a (+ a 2.5)) devuelve 18.5
Se asigna 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 da error. Los nmeros reales deben iniciar 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 nmeros pasados como argumentos.


(- 11.0 5) devuelve 6.0

numero real

; (- 11 5) devuelve 6

numero entero

(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 de argumento, devuelve el nmero cambiado de
signo.
(- 12.5) devuelve -12.5

el primer signo - representa a la funcin resta

(- -7.0) devuelve 7.0

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.
(* 3 9) devuelve 27

numero entero ;

(* 3.0 9) devuelve 27.0

numero real

(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

(/ 7 2) devuelve 3

(setq a (/ 12.5 4 2)) devuelve 1.5625 y lo almacena en a


(setq a (/ a 0.5)) devuelve 3.125 y lo almacena en la variable a

(/ 7 2.0) devuelve 3.5


(/ 3.5 -1) devuelve -3.5

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+ <nmero> )

incrementa en una unidad el nmero indicado como argumento.

(1+ 5) devuelve 6. entre 1 y + no hay espacio, 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- <nmero> )

Esta funcin reduce en una unidad el nmero indicado.

(1- 5) devuelve 4. Ojo entre 1 y - no debe haber espacio, ya que el nombre de la funcin es 1-.
(1- 2.5) devuelve 1.5

(1- 0) devuelve -1

(1- -1) devuelve -2

4- Solicitar nmeros al usuario


(GETINT [mensaje] )

Solicita un nmero entero, AutoCAD recordar con un mensaje

y no finalizar la ejecucin de la funcin hasta que se introduzca un valor entero, o se pulse ESC.
(getint) Puede indicarse un mensaje de solicitud opcional,
(getint Cuntos aos tienes?:)

Podemos asignar el valor a una variable y utilizarlo despus.

(setq edad (getint Cuntos 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 Cuntos aos tienes?:)
(setq edad (getint mens))
mens es una variable que almacena una cadena de texto, pero no es
una cadena de texto. Por lo que, no debe ir entre comillas.
Prueba ahora el siguiente ejemplo:
(setq a 27 mens Cuntos aos tienes?:)
(setq edad (getint mens))
Que pasa si como respuesta a la solicitud de la edad se introduce !
a. Parece lgico que le estamos indicando el valor de la variable a, que contiene el valor 27, de
modo que la variable edad debera tomar el valor 27, pero no es as. Nos indicar que es Imposible
volver a entrar en LISP.. Esto es por 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 ejecutarse.

(GETREAL [mensaje] ) Solicita un nmero real. En caso que el usuario


introduzca un nmero entero, el interprete de AutoLISP lo considerar como un real. Si se introduce
otro tipo de dato no numrico, recordar por un mensaje que est solicitando un nmero real y no
finaliza la ejecucin de la funcin hasta que se de un valor numrico, o se pulse ESC.

(getreal)
Puede indicarse un mensaje de solicitud opcional, El mensaje debe ser cadena de texto y estar
entre comillas.
(setq peso (getreal Cuntos kilos pesas?:))
(setq peso (- peso 1)) 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 Cuntos kilos pesas?:)
(setq peso (getreal mens))

5- Funciones de usuario y nuevos comandos


Definir funciones de usuario
Es posible crear nuestras propias funciones. Redefinir las funciones de AutoLISP e incluso los
comandos de AutoCAD.

(DEFUN <funcin> ( [argumentos] / [variables_locales]


) [expr1] [expr2] )
El primer argumento representa el nombre de la funcin de usuario que queremos definir.
no emplear los nombres de las funciones de AutoLISP, ya que en dicho caso se redefiniran.

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)) hemos definido una nueva funcin llamada 2+, que recibe como
argumento un nmero y realiza la suma de ese nmero y 2.
(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).
si tratamos de ejecutar la funcin sin argumento, o con argumento que no sea de tipo numrico?:
(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 se almacena en la variable llamada valor, pero no es as. Puedes
comprobarlo escribiendo !valor en la lnea de comandos, lo que devolver nil.

En la funcin anterior tenemos un argumento y sin variables locales. La vamos a modificar:


(defun 2+ ( valor ) (setq valor (+ valor 2)))
Ahora seguro que estas convencido que el resultado se almacena en la variable valor. Pues
comprobemos:
(2+ 5) devuelve 7
!valor devuelve nil
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.

inicialmente valor era nil


al ejecutar (setq valor 5) asignamos a la variable valor el nmero entero 5

cuando llamamos a la funcin 2+ con la expresin (2+ 4) tenemos que valor es 4

dentro de la funcin 2+ asignamos (setq valor (+ valor 2)) de modo que valor ser 6

pero como se trata de una variable local, al salir de la funcin 2+ recuperamos el valor que
tena la variable valor antes de llamar a la funcin, de modo que valor ser 5

por tanto, si tecleamos !valor devolver 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 ser 6.
Retoquemos un poco ms la funcin 2+
(defun 2+ ( valor ) (setq inicial valor valor (+ valor 2)))
y borremos el contenido de valor. Para ello simplemente le asignamos nil.
(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? Vamos a comprobarlo:
!valor devuelve nil tal como suceda en el ejemplo anterior
!inicial devuelve 4

El valor se comporta como variable local, solo se emplea dentro de la funcin. Sin embargo
inicial es de mbito global, se sigue empleando al salir de la funcin. modificamos ms la
funcin:
(defun 2+ ( valor / inicial ) (setq inicial valor valor (+ valor 2)))
Se aade la variable inicial a la lista de variables locales, con lo que su mbito ser local. Para
comprobarlo
!inicial devuelve 4
(setq inicial nil)
(2+ 3)

!inicial devuelve nil

!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, para ejecutarla solo debemos ponerla 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 debern aadir a la lista de variables locales dentro de las
definiciones de las funciones de usuario.

Crear nuevos comandos de AutoCAD

La funcin DEFUN tambin 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 funciona igual, la diferencia est en el modo de
ejecutarse. No es necesario poner el nombre de la funcin entre parntesis, se escribe directamente
en la ventana de comandos de AutoCAD.
2+
Tambin se puede ejecutar poniendo el nombre de la funcin precedido de C: entre parntesis.
(C:2+)
Si 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
Si escribimos directamente 2+ AutoCAD mostrar el mensaje error: argumentos insuficientes.

Si se escribe 2+ 2 en la ventana de comandos de AutoCAD veremos que al escribir el espacio


entre el nombre de la funcin y el argumento, AutoCAD ejecuta lo que cree que es un comando. Por
este motivo slo podramos ejecutar la funcin si se escribe (C:2+ 2) en la ventana de comandos.
La funcin creada solo servir para la sesin actual. Es ms, solo est definida la funcin 2+ en el
dibujo actual, de modo que si hay ms dibujos abiertos, en ellos no estar 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.

6- Introduccin al entorno de Visual LISP


Archivos de cdigo fuente en AutoLISP

Se ha visto que las funciones de AutoLISP se pueden ejecutar directamente desde la ventana de
comandos de AutoCAD. Pero se tiene varios inconvenientes:

el reducido tamao de la ventana de comandos de AutoCAD


la dificultad de escribir todo el cdigo seguido, sin tabular. es debido a que cada vez que se
pulsa Intro, AutoCAD evala lo que se ha escrito
el cdigo no se almacena en ningn sitio, se perder al cerrar el dibujo actual

En la ventana de comandos de AutoCAD slo se escribirn pequeas lneas de cdigo que no


interese guardar, para hacer pruebas y depurar cdigo, 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 se puedan
almacenar. Se puede emplear cualquier editor de texto que permita 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 interpreta esos cdigos.
Desde la versin 14, AutoCAD incorpora un editor para AutoLISP, el que tiene las 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

seguiremos usando 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 usuario

Antes de comenzar con el editor de Visual LISP, crearemos una primera funcin de usuario: Es una
funcin para convertir un ngulo de radianes a grados decimales, nos ser til en muchas de las
macros. El cdigo de la funcin sera el siguiente:
(defun RAG ( ang )
(/ (* ang 180.0) pi)
)
Hay tres reglas bsicas que sigue AutoLISP:
1.
2.

el nmero de parntesis de apertura debe ser igual al nmero de parntesis de cierre


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) )
(RAG 1.57)
as es difcil de leer. la funcin tiene poco cdigo, imagina una funcin mayor escrita toda en la
misma lnea.
La segunda lnea esta tabulada, no comienza a la misma altura que el resto, est desplazada hacia
la derecha. Esto indica que est incluida dentro de una lista de nivel superior, de la funcin defun.
No es necesario tabular el cdigo, pero facilita su lectura y permite detectar posibles errores con
los parntesis (Regla nmero 1).
Pi es una constante que ya est definida en AutoLISP, pi equivale al nmero 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).
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 entrepi = 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, cumpliendo con la Regla nmero 1.
Recordemos la estructura de la funcin de AutoLISP defun: (DEFUN <funcin> ( [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 al trabajar con textos, como ya
veremos). A lo largo de los artculos del curso se mostrarn los nombres de las funciones de usuario
en maysculas simplemente para que se diferencien perfectamente del resto del cdigo.

Los comentarios en el cdigo


Es imprescindible aadir comentarios al cdigo para explicar qu es lo que hace y cmo 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 puntos 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 pienses que no es tan importante aadir explicaciones en el cdigo. Pero si tienes que leer
una rutina que creaste hace meses sern muy tiles, por que seguramente no recordaras muy bien
como funciona. Adems, si alguien va a leer alguna de vuestras rutinas le facilitaras mucho la labor.
Al igual que a ti te 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 LISP

El editor de Visual LISP se inicia desde AutoCAD de varias formas:

Ejecutando el comando de AutoCAD VLIDE.


Desde el men desplegable de AutoCAD Herr>AutoLISP>Editor de Visual LISP

Mostrar algo similar a la siguiente imagen:

El editor de Visual LISP


Al abrir el editor veremos dos ventanas, consola de Visual LISP y Rastreo. De momento no nos
vamos a parar a ver para qu sirven o cmo 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:

Nueva ventana de cdigo en el editor Visual LISP


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:
;;;____________________Eduardo Magdalena____________________;;;
;;;_________________________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 nuestro gusto (aadiendo o quitando espacios y tabulaciones), lo recomendable es
mantener el formato por defecto para el cdigo. Veamos como queda la funcin RAG en el editor:

La funcin RAG en el editor de Visual LISP


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 setq


los comentarios en morado ;Esto es un comentario

los parntesis en color rojo (setq a 2.0)

los nmeros en color verde 2.0

los textos en color rosa (en este ejemplo no aparece ningn texto, pero veremos algunos
ejemplos ms adelante) Soy un texto

el resto de elementos, como los nombres de las funciones y de las variables utilizadas, se
muestran en color negro

Adems, las funciones de usuario se destacarn escribindose en maysculas RAG.


Este formato de colores se utilizar tambin en los artculos de este curso, tal como se muestra en
el cdigo de la funcin RAG anterior.

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 1.57)
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.
Veremos ms adelante que se pueden guardar varias funciones y varios comandos en un mismo
archivo de AutoLISP, aunque en este caso slo se ha definido una nueva funcin de usuario.
Se le suele dar a los archivos de AutoLISP el mismo nombre del comando o funcin que est
definida en l, podemos guardar esta rutina en el archivo klhsduif.lsp pero luego no
la reconoceramos. As que lo mejor ser guardar el cdigo de la funcin RAG 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 prcticamente igual a la funcin que
acabamos de ver. Pero recuerda Antes de empezar a programar (como antes de hacer casi
cualquier cosa) conviene pensar en lo que se va a hacer y en cmo 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.

7- Cargar los archivos de AutoLISP


Para que la funcin RAG que creamos en el artculo 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.
2.

Cargar un archivo desde el editor de Visual LISP


En el men desplegable de AutoCAD Herr>AutoLISP>Cargar aplicacin.

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 #<editor RUTA/rag.lsp>. 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 aplicacin) muestra un letrero de dilogo en el que se
selecciona el archivo a cargar y se pulsa el botn Cargar.

Cargar / Descargar aplicaciones


Este mtodo ofrece dos ventajas:

se puede seleccionar ms de un archivo


permite descargar las funciones de AutoLISP definidas en los archivos seleccionados

(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 que indicar la ruta completa:
(load c:\rutinas\rag.lsp)

Pero si lo hiciramos as nos dara un error, ya que AutoCAD no reconoce el carcter \, 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 escribiremos:
(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 dentro de una funcin 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 otros mtodos para cargar nuestras rutinas.
Veamos como sera la funcin GAR propuesta en el tema anterior:
;;;_____________________Eduardo Magdalena_____________________;;;
;;;_________________________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 ) ; Recibe un ngulo en grados decimales
(/ (* ang pi) 180.0)
;; Multiplica el ngulo en grados decimales por Pi y lo divide por 180.0.
)
Es muy muy parecida a la funcin 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 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.

Opciones 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
AutoCAD.

8- Operaciones matemticas en AutoLISP


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) tambin 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. Ojo!
esta funcin no redondea, sino que elimina lo que est detrs del punto decimal.
(fix 15.8) devuelve 15.
(fix -15.8) devuelve -15
(fix 0.99) devuelve 0
(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 indican 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.0) 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 recibe 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 33) devuelve 3

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

9- Solicitar textos y puntos 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 Cul es tu nombre?)
Supongamos que te llamas Pepe, a (getstring Cul es tu nombre?) responderas Pepe y ya
est. Incluso se podra asignar el nombre que indique el usuario a una variable:
(setq nombre (getstring Cul es tu nombre?))
Pero que sucede si te llamas Jos 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 Cul 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 = 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) Cul es tu nombre?)) permite responder con espacios, ya
que (+ 1 2) devuelve 3 que es distinto de nil.
(setq nombre (getstring (setq var1 nil) Cul es tu nombre?)) no permite responder con
espacios, ya que (setq var1 nil)devuelve nil.
Para 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 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.
Fijmonos un momento en lo que devuelven tanto getpoint como getcorner: (125.68 117.68 0.0).
Se trata de una lista, una lista con las corrdenadas de un punto. Bien, pues en el prximo artculo
veremos algunas funciones para manejar listas.

10- Funciones para manejar listas


AutoLISP es un lenguaje de programacin basado en listas as que es lgico que el tratamiento
que reciban las listas de elementos sea muy bueno. Por otra parte, en AutoCAD nos encontraremos
listas continuamente y en todas partes, desde las coordenadas de los puntos como se indicaba en
el artculo anterior, hasta los datos de las entidades que son almacenados en la base de datos de
AutoCAD. As que vamos a introducir 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)
Basndonos en las dos funciones anteriores y recordando que podemos ejecutar listas de
instrucciones dentro de otras (a esto le llamamos anidamiento): Cmo se obtendra la coordenada
Y del punto pto? Veamos:

CDR devuelve la lista sin el 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 podemos escribir:
(car (cdr pto)) devuelve la coordenada Y del punto pto.
y, cmo obtenemos la coordenada Z? Pues, volviendo a aplicar la funcin CDR para llegar a la
coordenada Z

(cdr pto) devuelve (Y Z)


(cdr (cdr pto)) devuelve (Z)

Podras pensar que escribiendo (cdr (cdr pto)) obtenemos la coordenada Z, sin embargo no es as.
La expresin (cdr (cdr pto))devuelve una lista con un nico elemento, la coordenada Z del punto
pto. Para obtener la coordenada Z del punto pto tenemos que escribir:
(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)))

Otras funciones combinando CAR y


CDR
Si en las expresiones indicadas anteriormente para obtener 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)))

Este ejemplo es simplemente para introducir una simple regla de mnemotecnia ya que 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 para recordar el nombre de estas funciones. Debes recordar tambin
que 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 que sus elementos son a su vez listas.
Puedes definir la variable lst escribiendo: (setq lst (list (list a b) (list c d) (list e f)))

Cmo 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 la lista sin el primer elemento, es decir ((c d) (e f)).
Ahora si hacemos (cAr (cDr lst)) devuelve el primer elemento de la lista anterior, es
decir (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))


(cAr (cDr lst)) devuelve 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 d

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), de modo que

(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 os recuerdo que se trata de una lista
y que no es lo mismo que f.
Por tanto (cAr (cDr (cAr (cDr (cDr lst))))) devuelve f.

Podramos 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 aqu estamos
intentando agrupar 5, y lgicamente no podemos. Para obtener f podramos escribir, por ejemplo:

(cAr (cDADDr lst))


(cADADr (cDr lst))

(LENGTH lista)
En la variable pto tenamos una lista con las coordenadas de un punto, pero si solo trabajamos en
2D, la coordenada Z no nos interesa. As que muchas veces los puntos tan slo tendrn 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 producindose 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 punto pto estuviera 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 de dos elementos cada una.

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)
Recuerda que en AutoLISP cuando nos encontramos con listas anidadas unas dentro de otras,
siempre se evalan primero las listas interiores.

(list a b) devuelve (a b)
(list d e) devuelve (d e)

As que (list (list a b) c (list d e) f) devuelve la siguiente lista ((a b) c (d e)


f).

11- Ejecutar comandos de AutoCAD


Una de las mayores ventajas de la programacin en AutoLISP es la posibilidad de ejecutar
directamente comandos de AutoCAD en nuestras rutinas.

(COMMAND comando [datos])


Esta es la funcin que nos permite ejecutar comandos de AutoCAD. Hay dos cosas a tener en
cuenta con esta funcin:

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 pasrlo a la funcin command:
(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. Cules 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 dependern 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 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 Francs slo servira para las
versiones en Francs.
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 anteponiendo 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 originales


Por otra parte, ya se ha dicho anteriormente que los comandos de AutoCAD se podran redefinir
para que funcionen de forma distinta. As se podra cambiar el comando circulo para que
dibuje pentgonos y el comando linea para que dibuje circunferencias.
Si redefinimos el comando lnea para que dibuje circunferencias, entonces deberamos indicar algo
similar a (command linea centro radio) en lugar de (command linea pt0 pt1). Pero
cmo haramos entonces 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 anteponiendo un guin bajo as que tambin
los podramos escribir 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.

Redefinir un comando de AutoCAD


Para redefinir un comando de AutoCAD debemos:
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 macro en la que est definido un nuevo comando con el nombre del
comando que acabamos de anular.
Veamos un ejemplo:
1.

primero anulamos la definicin del comando lnea.


1.
Podemos hacerlo desde AutoCAD con el comando ANULADEF (En ingls
undefine)
2.

2.

o desde AutoLISP ejecutando: (command anuladef


linea) o (command _undefine _line)
podemos comprobar que el comando lnea ya no funciona

1.

Puedes tratar de ejecutarlo en castellano, en ingls, directamente en AutoCAD o en


una expresin de AutoLISP

2.

la nica forma de ejecutarlo es anteponiendo a su nombre un punto .linea.

3.

Iniciamos el editor de Visual LISP: Herr. >AutoLISP > Editor de Visual LISP
1.

Creamos la macro que se indica a continuacin, la guardamos y la cargamos en


AutoCAD

(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 macro que hemos creado se borre de la
memoria del ordenador
2.
ejecutar el comando de AutoCAD redefine (En Ingls es igual, pero con un guin bajo
delante) e indicarel nombre del comando del que queremos recuperar su definicin original, es
decir linea.
Bueno, por ltimo un ejercicio: Crear una macro que defina un nuevo comando de Autocad
llamado CIRCPERI que dibuje una circunferencia indicando su centro y la longitud de su permetro.

12- Operaciones lgicas en AutoLISP


Existe 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 continan 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)
Preguntando 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) devolver nil porque d es nil


(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 continan 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 que 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 qu pasa con las listas? Tambin podemos indicarle una precisin? Veamos..

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

13- Operaciones de comparacin


En este artculo veremos las funciones de AutoLISP que nos permiten realizar comparaciones, por
ejemplo, para ver 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
contrario 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 estn ordenadas de menor a mayor y


devuelve T si lo estn y nil si no lo estn.
(< 1 2 3) devuelve T
(< 1 2 0) devuelve nil
(< (+ 1 2) (* 2 2.0) (/ 12 2)) devuelve T
Tambin podemos comparar textos. El interprete de AutoLISP evala 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
letras minsculas.
Los cdigos ASCII, son una serie de nmeros que se asignaron a las letras del alfabeto y a algunos
de los carcteres ms usuales.
El carcter a tiene asociado el cdigo 97, la b el 98, etc. hasta la z.
El carcter A tiene asociado el cdigo 65, la B el 66, etc. hasta la Z.

(> expr1 expr2 )


Supongo que ya os imaginis 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.

(<= expr1 expr2 )


Comprueba si las expresiones son menores o iguales que las anteriores.
(<= 1 2 2.0 3) devuelve T
(<= 1 3.0 2 3) devuelve nil

(>= expr1 expr2 )


Comprueba si las expresiones son mayores o iguales que las anteriores
(>= 3 2 2.0 1) devuelve T
(>= 3 1.0 2 1) devuelve nil
(>= 3 3 3 3) devuelve T

Macro de ejemplo
Veamos como se hara el ejercicio propuesto en el artculo 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. Bien, cmo podra ser el pseudocdigo de esta rutina?, vamos a
ver:
2.

1. Pedir al usuario el centro de la circunferencia.


Pedir al usuario el permetro de la circunferencia.

3.

Calcular el radio de la circunferencia a partir de su permetro.

4.

Dibujar la circunferencia.

Una vez que terminamos el pseudocdigo, ya tenemos el 80% de la rutina. Si el pseudocdigo es


correcto, el traducirlo a cdigo es de lo ms simple.
Iniciamos en editor de Visual LISP Herr. > AutoLISP > Editor de Visual LISP y creamos una
nueva macro. Primero hay que aadir la definicin del nuevo comando CIRCPERI:
(defun C:CIRCPERI ( )
Vamos a ver que es lo que nos indica el pseudocdigo:
1) Pedir al usuario el centro de la circunferencia. Podramos escribir (getpoint Centro de la
circunferencia) pero tendramos que almacenar el punto indicado en una variable, as que
aadiremos
(setq pto (getpoint Centro de la circunferencia)) almacena el punto centro de la circunferencia
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 podramos cambiarlo por:

(setq peri (getreal Permetro:)) almacena el permetro de la circunferencia en la variable peri


3) Calcular el radio de la circunferencia a partir de su permetro. Peri = 2* pi * rad as que rad = Peri /
( 2 * pi). Traduciendo esta frmula a cdigo:
(setq rad (/ peri (* pi 2))) calcula el valor del radio de la circunferencia
4) Dibujar la circunferencia
(command _.circle pto rad) dibuja la circunferencia
Slo nos falta una cosa. Recuerda: 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 deberas 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.

14- Estructuras condicionales simples


Hasta ahora nuestro cdigo ha sido completamente lineal, las lneas de cdigo que escribamos
se ejecutaban una tras otra en el mismo orden. En este tema veremos un tipo de funciones que
nos permitirn bifurcar el cdigo, de modo que ya no exista un nico camino sino dos o ms.
Veamos un ejemplo en pseudocdigo:
1.
2.

Introducir el lmite inferior


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 denil, 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, evalundose 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 completa. 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.
Veamos ahora algunos 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) devolvernil evalundose 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.

15- Estructuras condicionales mltiples


Con la funcin IF tan solo podemos indicar una condicin y dos opciones, si cumple y no cumple.
Veamos ahora como se pueden 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. En 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 condicin (< 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 se pone la condicin T como primera condicin? Pues sucede que las que estn a
continuacin nunca se evaluarn, ya que T siempre se cumplir. Si en el ejemplo
anterior hubiramos 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 mostrar los mensajes de
alerta indicando que A no es igual a B, A no es menor que C y A no es menor que B.

16- Mostrar textos al usuario en AutoLisp


Hay varias funciones para mostrar textos al usuario en AutoLisp. De momento 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 mostrar alguna informacin
importante.
(alert Error: Dato no vlido)

(TERPRI)
En artculo correspondiente a las Operaciones de comparacin, creamos un nuevo comando para
AutoCAD denominado CIRCPERI. Si has cargado y ejecutado el comando, habrs observado que
los mensajes para solicitar el centro de la circunferencia y su permetro aparecen en la misma lnea
de la ventana de comandos y sin separacin entre s, estn pegados.
Para que los mensajes aparezcan en lneas distintas, se puede emplear la funcin TERPRI. 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 control


Como ya se ha comentado anteriormente, AutoLISP no reconoce una serie de caracteres. Por
ejemplo, al indicar la ruta de un archivo no reconoce el carcter \ y hay que indicarlo 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 que se tiene que 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:
;;;____________________Eduardo Magdalena____________________;;;
;;;______________________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)

17- Las variables de sistema de AutoCAD


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 trabajo.

Tipos de variables de sistema


Las 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 enteros 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


sistema
Podramos 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 AutoLISP
Los 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 variable 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)

18- Funciones de conversin de datos en AutoLISP


Vamos a ver una serie de funciones que nos permitirn pasar un entero a real, a un texto o al
revs

(ITOA entero)
Convierte un entero en un texto. Integer TO Atom.
(itoa 24) devuelve 24

(ATOI texto)
Hace justo lo contrario que la funcin anterior. Convierte un texto en un nmero. Atom TO Integer
(atoi 24) devuelve 24
(atoi -7) devuelve -7
Y que pasa si hacemos (atoi soy un texto) pues que devuelve 0. Siempre que escribes algo
que no sea un nmero devuelve cero.
(atoi 15.3) devuelve 15
(atoi 15.99999) devuelve 15

(FLOAT numero)
Convierte un nmero en real, as que lo lgico es que reciba un entero como argumento.

(float 5) devuelve 5.0


pero tambin podemos pasar un nmero real como argumento (float 5.36) que devuelve 5.36 lo
cual sera una tontera porque en ese caso la funcin float no hace nada.

(ATOF texto)
Convierte un texto en real.
(atof 15.7) devuelve 15.7
(atof 15) devuelve 15.0
(atof -15.7) devuelve -15.7
(atof soy un texto) devuelve 0.0

(RTOS numero [modo [precision]])


La ltima funcin de este tipo que vamos a ver es algo ms complicada, pero no mucho. Convierte
un real en texto. Real TO String.
(rtos 2.5) devuelve 2.5
(rtos 2) devuelve 2 y no 2.0
Veamos para qu sirven los argumentos opcionales [modo [precisin]]. Modo, permite indicar un
tipo para expresar los nmeros, es decir, permite seleccionar el formato utilizado para los
nmeros. Hay 5 opciones:

Formato cientfico.
Decimal. Es el que se usa habitualmente.

Pies y pulgadas.

Pies y pulgadas en fracciones.

Fracciones.

Por ejemplo
(rtos 2.5 5) devuelve 2 1/2
(rtos 2.5 1) devuelve 2.5000E+00
Precisin nos permite definir el nmero de decimales que deseamos, por ejemplo:
(rtos 1.23456789 2 3) devuelve 1.235 as que redondea el nmero para que tenga 3 decimales.
(rtos 9.99 2 0) devuelve 10

19- Obtener distancias y ngulos del usuario

Hemos visto como se obtienen nmeros, puntos y textos del usuario. Ahora le vamos a solicitar
directamente una distancia o un ngulo.

(GETDIST [pto_base] [mensaje])


Solicita una distancia y devuelve esa distancia como un nmero real. El usuario podr indicar la
distancia por medio de un nmero o indicando 2 puntos en pantalla.
(getdist Distancia de desplazamiento:)
El mensaje es opcional, pero casi siempre se utiliza. Tambin podemos asignar el resultado a una
variable:
(setq dist1 (getdist Distancia de desplazamiento:))
En muchas ocasiones se puede reemplazar a la funcin GETREAL por GETDIST si lo que se pide
se puede relacionar con alguna distancia del dibujo. Por ejemplo, en nuestra
rutina CIRCPERI podramos dibujar una circunferencia de permetro la longitud de una recta.
El argumento opcional [pto_base] funciona de modo similar a como lo hace
en GETPOINT permitiendo indicar la distancia a partir de un punto de origen ya predefinido:
(setq pto (getpoint Punto base))
(setq dist1 (getdist pto Distancia de desplazamiento:))

(GETANGLE [pto_base] [mensaje])


Solicita un ngulo al usuario que puede escribirlo o designarlo por medio de dos puntos. Devuelve el
ngulo en radianes, aunque el usuario lo escribira en las unidades actuales (generalmente grados
decimales). Por ejemplo, a la expresin:
(getangle ngulo: )
el usuario responde 180.0
y getangle, devuelve pi.
Esta funcin toma como origen de ngulos el actual, que suele coincidir con el sentido positivo del
eje X del SCU (Sistema de Coordenadas Universal). Pero siempre considerar como sentido
positivo de los ngulos el antihorario.
El parmetro opcional [pto_base] permite indicar un punto a partir del cual indicar el ngulo.

(GETORIENT [pto_base] [mensaje])


Es casi igual a GETANGLE, y tambin se utiliza para solicitar un ngulo al usuario. La nica
diferencia es que el origen de ngulos siempre es el del sentido positivo del eje X del SCU (Sistema
de Coordenadas Universal).

(getangle ngulo: )

Aadir algunos cambios a nuestra


macro CIRCPERI
Vamos ahora a modificar un poco la macro CIRCPERI. Tenamos el siguiente cdigo:
(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)
Si sustituimos la funcin getreal por getdist adems de poder escribir un permetro directamente,
tambin podremos indicarlo mediante dos puntos.

Eco de mensajes en las macros de AutoLISP


Por otra parte, Si habis ejecutado el comando CIRCPERI veris que lo de los mensajes queda
mejor que al principio pero tampoco es perfecto ya que aparecen unos textos en la ventana de
comandos que no se sabe de dnde salen:
Centro de la circunferencia:
Permetro: Designe segundo punto: _.circle Precise punto central para crculo o
[3P/2P/Ttr (tangente tangente radio)]:
Precise radio de crculo o [Dimetro]: 23.00636765228087
Esto queda bastante feo y como hay que ser profesionales, vamos a ponerlo bien. Hemos visto las
funciones GETVAR y SETVAR que nos permiten acceder a las variables de sistema de AutoCAD.
Pues hay una variable que controla el eco de mensajes, es decir, el que aparezcan esos
mensajes en pantalla. La variable se llama CMDECHO y solo admite dos valores posibles:

0 Desactivada
1 Activada

Por defecto debera estar activada (1) as que se veran los mensajes raros de antes.
Cmo evitamos que aparezcan estos mensajes? Pues desactivando la variable.

Pero no conviene modificar los valores de las variables de sistema, porque tal vez el usuario los
quiera mantener como estaban. De modo que se desactivar momentneamente el valor de la
variable en medio de la macro y al terminar la rutina se dejar con su valor inicial, es decir tal como
estaba.
Esto es ms bien una filosofa de vida: Si al entrar en un sitio, la puerta estaba cerrada, vuelve
a cerrarla
As que nuestro cdigo quedara
(defun C:CIRCPERI ( / pto peri rad )
(setvar cmdecho 0) ; Desactiva el eco de mensajes
(setq pto (getpoint \nCentro de la circunferencia: ))
(setq peri (getdist \nPermetro: ))
(setq rad (/ peri (* pi 2)))
(command _.circle pto rad)
(setvar cmdecho 1) ; Vuelve a activar el eco de mensajes
)
(prompt \nNuevo comando CIRCPERI cargado)
Efectivamente los mensajes raros desaparecen, pero Qu pasa si al entrar en una habitacin, la
puerta ya estaba abierta? la cerramos o la dejamos abierta de nuevo?. Lo mejor es que todo
quede tal como lo encontramos. As nadie nos dir Por qu cerraste la puerta?. Y si lo dice, le
respondes: Perdona, pero mi macro, deja las cosas tal y como estaban, as que o ya estaba
cerrada antes o la cerraron despus.
Si cmdecho est inicialmente desactivada nuestra rutina la desactiva, o lo intenta, y luego la activa
al final de la macro. Quedando por lo tanto cmdecho activada. As que vamos a modificar el cdigo
para que cmdecho quede con el valor que tena antes de ejecutar la macro
Lo primero que tenemos que saber es si la puerta est cerrada, si est cerrada la abrimos y si ya
est abierta no hacemos nada, simplemente pasamos.
(getvar cmdecho) me dir si cmdecho est activada o desactivada. Veamos que es lo que hay
que hacer:
1.
2.
3.

Si la puerta est cerrada, la abro. Es decir, si cmdecho est activada, la desactivo.


Aqu metemos el cdigo de la macro CIRCPERI
Si antes de entrar la puerta estaba cerrada, entonces la cierro. Es decir, si cmdecho estaba
activada, entonces la vuelvo a activar.

El punto 1 suena claramente a una estructura condicional simple, as que emplearemos la


funcin IF:

(if (= (getvar cmdecho) 1)


(setvar cmdecho 0)
)
Y cmo haramos al final de la rutina en el punto 3? Sera otro condicional, pero necesitamos
conocer el valor que tena inicialmente la variable cmdecho para saber si estaba activada o
desactivada. De modo que hay que modificar el cdigo anterior para que en el punto 1 se almacene
el valor de cmdecho.
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
De este modo la variable cmd0 almacena el valor inicial de cmdecho. Es bastante habitual
almacenar los valores iniciales en variables cuyo nombre sea del tipo cmd0, osm0 o blip0 pues el 0
nos indica que almacena el valor inicial.
Ahora ya podemos poner el cdigo del punto 3. Podramos hacerlo de dos formas:
(setvar cmdecho cmd0)
Esta lnea de cdigo asignara a cmdecho el valor que tena inicialmente.
(if (= cmd0 1)
(setvar cmdecho 1)
)
En este caso, si cmdecho estaba inicialmente activada entonces la activa. Si no estaba inicialmente
activada, es decir estaba desactivada, entonces no hace nada porque cmdecho ya est
desactivada, al igual que al principio.
El cdigo quedara as:
(defun C:CIRCPERI ( / pto peri rad cmd0 )
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
(setq pto (getpoint \nCentro de la circunferencia: ))
(setq peri (getdist \nPermetro: ))
(setq rad (/ peri (* pi 2)))
(command _.circle pto rad)
(if (= cmd0 1)

(setvar cmdecho 1)
)
)
(prompt \nNuevo comando CIRCPERI cargado)

Salida limpia de las macros de AutoLISP


Al ejecutar ahora la rutina los mensajes son ms limpios. Sin embargo al final muestra el valor
devuelto por la ltima expresin evaluada de la funcin:

Si la variable cmdecho inicialmente es 0. La condicin del if devuelve nil, se termina la


funcin y se muestra en la pantalla nil
Si la variable cmdecho inicialmente es 1. La condicin del if devuelve T, se evala la
condicin-si-cumple del if(setvar cmdecho 1) que devuelve 1, se termina la funcin y se
muestra en la pantalla 1

Para que la salida de nuestras macros sea limpia aadiremos al final del cdigo una funcin que
devuelva una cadena de texto vaca, as no escribir nada.
Podramos pensar en utilizar la expresin (prompt ) al terminar nuestras macros. Sin embargo la
expresin anterior no devuelve una cadena de texto vaca sino que devuelve nil.
Suelen emplearse las funciones (princ) o (prin1) que an no hemos visto, pero que devuelven una
cadena de texto vaca.
Finalmente el cdigo resultante ser:
(defun C:CIRCPERI ( / pto peri rad cmd0 )
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
(setq pto (getpoint \nCentro de la circunferencia: ))
(setq peri (getdist \nPermetro: ))
(setq rad (/ peri (* pi 2)))
(command _.circle pto rad)
(if (= cmd0 1)
(setvar cmdecho 1)
)
(prin1)
)

(prompt \nNuevo comando CIRCPERI cargado)

20- El comando deshacer en las rutinas de AutoLISP


En este artculo no vamos a ver ninguna funcin de AutoLISP. Vamos a crear un nuevo comando y a
repasar un poco la macro deCIRCPERI.
Comenzaremos creando un nuevo comando para dibujar arandelas en 2D:

El programa solicitar al usuario el centro de la arandela, el dimetro interior y el exterior


Se dibujarn dos circunferencias concncricas con los dimetros indicados

Recuerda, antes de ponerse a escribir cdigo hay que: escribir el pseudocdigo. Veamos,
podamos hacer algo as:
1.
2.

Obtener el centro de la circunferencia


Obtener el radio de la circunferencia interior

3.

Dibujar la circunferencia interior

4.

Obtener el radio de la circunferencia exterior

5.

Dibujar la circunferencia exterior

AutoCAD ya tiene un comando que se llama arandela (en ingls donuts) as que buscaremos otro
nombre para nuestra rutina, por ejemplo ARAND. Es mejor utilizar nombres ms bien cortos y que
evoquen a la funcin que tiene el comando.
La primera lnea de cdigo es la definicin de la funcin:
(defun C:ARAND ( )
Ms adelante podremos aadir las variables locales, si es que existen.
1) Obtener el centro de la circunferencia. Podra ser algo as:
(setq pto (getpoint \nCentro de la arandela: ))
2) Obtener el radio de la circunferencia interior:
(setq radi (getreal \nRadio interior: ))
3) Dibujar el circulo interior
(command _.circle pto radi)
4) Obtener el radio del crculo exterior:
(setq rade (getreal \nRadio exterior: ))
5) Dibujar el circulo exterior

(command _.circle pto rade)


Y por ltimo cerramos el parntesis de la funcin defun
)
El cdigo completo queda as:
(defun C:ARAND ( )
(setq pto (getpoint \nCentro de la arandela: ))
(setq radi (getreal \nRadio interior: ))
(command _.circle pto radi)
(setq rade (getreal \nRadio exterior: ))
(command _.circle pto rade)
)
Ahora vamos a retocar un poco el comando, le aadiremos las siguientes mejoras:

Desactivar el eco de mensajes, es decir desactivar la variable cmdecho al iniciar la rutina.


Recuperar el valor inicial de cmdecho al terminar la macro.
Aadir una lnea al final del cdigo para que muestre un mensaje indicando el nombre del
nuevo comando al cargar la funcin.
Poner las variables como locales.
En lugar de utilizar GETREAL para obtener el radio, usaremos GETDIST con el centro de
las circunferencias como punto base.
Aadir una lnea al final de la funcin para que la salida del programa sea limpia.

El cdigo despus de realizar las mejoras anteriores sera:


(defun C:ARAND ( / pto rad cmd0 )
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
(setq pto (getpoint \nCentro de la arandela: ))
(setq rad (getdist pto \nRadio interior: ))
(command _.circle pto rad)
(setq rad (getdist pto \nRadio exterior: ))
(command _.circle pto rad)

(if (= cmd0 1)
(setvar cmdecho 1)
)
(princ)
)
(prompt \nNuevo comando ARAND cargado)
Adems de las mejoras indicadas anteriormente, ahora la variable rad se utiliza tanto para
almacenar el radio de la circunferencia interior como el de la exterior. Puede dar lugar esto a algn
problema? Veamos:
En primer lugar obtenemos el centro de la circunferencia y la asignamos a la variable pto.
(setq pto (getpoint \nCentro de la arandela: ))
Solicitamos el radio de la circunferencia interior y lo asignamos a la variable rad.
(setq rad (getdist pto \nRadio interior: ))
y dibujamos la circunferencia interior
(command _.circle pto rad)
El radio de la circunferencia interior no lo vamos a volver a utilizar en nuestra rutina, de modo que
podemos reutilizar esa variable y asignarle otro valor, el radio de la circunferencia exterior.
(setq rad (getdist pto \nRadio exterior: ))
Ahora la variable rad almacena el radio de la circunferencia exterior y pto el centro de las dos
circunferencias, de modo que dibujamos la circunferencia exterior.
(command _.circle pto rad)
De este modo ahorramos una variable. As que recuerda:
Si es posible, conviene reutilizar las variables.
Si cargamos la macro y ejecutamos el comando ARAND dibujaremos una arandela formada por dos
circunferencias. Pero qu pasa si despus de dibujar la circunferencia ejecutamos el comando H
(deshacer) de AutoCAD? Pues que deshace el ltimo comando ejecutado que no
es ARAND sino (command _.circle pto rad) de modo que deshace la circunferencia exterior.
Pero la interior no.

Control de deshacer comandos


El comando DESHACER de AutoCAD es distinto al comando H. En realidad, H es una opcin
de DESHACER. Al ejecutar este comando, AutoCAD muestra el siguiente mensaje: Indique el
nmero de operaciones a deshacer o [Auto/Control/Inicio/Fin/Marca/Retorno] <1>:. Veamos
como funcionan estas opciones:

Nmero de operaciones a deshacer


La opcin por defecto es indicar el nmero de operaciones a deshacer, que por defecto tiene el valor
1. Esta opcin funciona exactamente igual que el comando H. Pero, podemos indicarle un nmero
de operaciones superior a 1 (cualquier nmero entero entre 1 y 32.767). Esta opcin es til para
deshacer los cambios realizados por los ltimos n comandos.

Control
Al seleccionar Control nos ofrece las siguientes posibilidades: Indique una opcin de control
DESHACER [Todas/Ninguna/Una] <Todas>:

Con la opcin Todas seleccionada (es la opcin por defecto), AutoCAD almacena en el
archivo temporal UNDO.ac$ la informacin sobre los comandos ejecutados en el dibujo actual
y por tanto que se pueden deshacer. Tambin almacena en el archivo temporal REDO.ac$ la
informacin sobre los comandos del dibujo actual que se han deshecho. Estos archivos se
almacenan en el directorio temporal del sistema operativo. Esta opcin permite deshacer todos
los comandos realizados en el dibujo durante la sesin actual.
Si se selecciona la opcin Una, tan slo se podr deshacer el ltimo comando ejecutado.
Quedando desactivadas todas las opciones del comando DESHACER excepto Control e
Indique el nmero de operaciones a deshacer <1>:
Seleccionando la opcin Ninguna se elimina la capacidad de revocar de los comandos H
y DESHACER, quedando estos desactivados. Y ya no se utilizan los archivos temporales
anteriormente citados.

Lo recomendable es tener siempre activada la opcin Todas.

Marca y Retorno
Estas dos opciones funcionan en pareja. Supongamos que vamos a ejecutar una serie de
comandos en el dibujo actual, pero no sabemos si el resultado obtenido ser el deseado. En este
caso, antes de comenzar puedes ejecutar el comando DESHACER y seleccionar la opcin
Marca. De este modo activas una marca, a la que podrs volver en cualquier momento ejecutando
DESHACER con la opcin Retorno. Al encontrar una marca AutoCAD mostrar el mensaje
Marca encontrada.
Si en lugar de volver a la marca lo que quieres es deshacer un nmero determinado de comandos,
puedes ejecutar el comando H o DESHACER indicando el nmero de comandos a deshacer.
Adems, puedes definir tantas marcas como desees, y cada vez que ejecutes DESHACER con la
opcin Retorno volvers a la marca anterior. Si no existen ms marcas, o si no se ha definido
ninguna marca, AutoCAD preguntar si se desea deshacer todo.

Auto

Algunos comandos de AutoCAD, estn formadas por un grupo de rdenes. De modo que el
comando H no anulara todo el grupo de comandos ejecutados, sino slo el ltimo. Activando esta
opcin se agrupan estos comandos en uno slo, a efectos de la aplicacin de los comandos H y
DESHACER.

Inicio y Fin
Estas dos opciones tambin funcionan juntas. Con ellas podemos agrupar una serie de comandos,
de modo que sean tratados como uno solo al ejecutar H o DESHACER.

Si DESHACER con la opcin Auto est activada, AutoCAD coloca automticamente un


DESHACER Inicio y un DESHACER Fin al principio y final de las opciones de los mens,
y deja inutilizadas estas opciones de forma manual.
Con la opcin Auto desactivada, las opciones Inicio y Fin se ejecutan de forma
anloga a como se hace con Marca y Retorno. Si se vuelve a ejecutar la opcin Inicio sin
haber ejecutado la opcin Fin para cerrar un grupo anterior, AutoCAD entiende que se quiere
cerrar el grupo anterior y abrir uno nuevo.

El comando deshacer en las rutinas de


AutoLISP
Utilizando las opciones anteriores del comando deshacer, se puede lograr que todo el cdigo de
nuestras rutinas funcione como si se tratase de un nico comando.
Aadiremos al inicio de nuestra rutina deshacer inicio y al final de la rutina deshacer fin.
Veamos:
(defun C:ARAND ( / pto rad cmd0 )
(command _.undo _begin)
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
(setq pto (getpoint \nCentro de la arandela: ))
(setq rad (getdist pto \nRadio interior: ))
(command _.circle pto rad)
(setq rad (getdist pto \nRadio exterior: ))
(command _.circle pto rad)
(if (= cmd0 1)
(setvar cmdecho 1)

)
(command _undo _end)
(princ)
)
(prompt \nNuevo comando ARAND cargado)
Deberamos aadir estas dos lneas en la macro CIRCPERI? Pues no es necesario, puesto que
en CIRCPERI tan solo utilizamos un comando. As que el comando de AutoCAD H va a deshacer
ese comando. En cambio en ARAND se dibujan dos circunferencias con dos comandos de
AutoCAD.

21-Funciones de tratamiento de errores en AutoLISP


Las rutinas que hemos creado (CIRCPERI y ARAND) no estn terminadas todava. Para terminarlas
debemos realizar dos modificaciones:

Controlar lo que hace la rutina en caso de que se produzca un error durante su ejecucin.
Impedir que el usuario introduzca datos errneos. Por ejemplo, que indique cero como radio
de una circunferencia.

En este artculo se tratar el primero de los dos puntos anteriores, y en el siguiente se ver el
segundo punto.
Si nos fijamos en el cdigo de la macro ARAND: Qu sucede si el usuario como respuesta a la
peticin del radio interior pulsa Intro? Pues que se asigna a la variable rad el valor nil. De modo
que se producir un error al evaluar la siguiente lnea de cdigo: (command_.circle pto rad). En
el siguiente tema veremos cmo se puede evitar que el usuario introduzca datos errneos. Por
ejemplo, evitar que como respuesta a la peticin del radio interior se introduzca Intro.
Pero una cosa est clara, no siempre vamos a poder controlar todos los posibles errores en
nuestras macros. De modo que necesitamos una funcin de tratamiento de errores que informe al
usuario del tipo de error que se produce. Por ejemplo, indicarle al usuario que ha introducido un
dato incorrecto. AutoCAD en este caso nos dice: ; error: tipo de argumento errneo: numberp: nil
AutoLISP dispone de una funcin de tratamiento de errores por defecto. Dicha funcin se
llama *error* y recibe como argumento una cadena de texto con la descripcin del error que se ha
producido.
Podemos redefinir la funcin de tratamiento de errores que ofrece AutoLISP, de modo que se puede
personalizar a nuestro gusto en funcin de nuestros intereses. As pues, vamos a crear una funcin
de tratamiento de errores a la que llamaremos ERRORES:
(defun ERRORES ( mens )

(if (= mens quitar / salir abandonar)


(princ)
(princ (strcat \nError: mens ))
)
(princ)
)
No nos paremos demasiado aqu ya lo veremos bien ms adelante. Hemos creado una funcin
llamada ERRORES para el tratamiento de errores en nuestras rutinas. Ahora habra que decirle al
comando ARAND que utilice esta nueva funcin de tratamiento de errores.
Pero antes, conviene explicar cmo se pueden redefinir las funciones de AutoLISP. Hay dos
mtodos:
1.

Crear una funcin con el mismo nombre. Por ejemplo, (defun SIN Esto redefinir la
funcin SIN de AutoLISP.
2.
Asignarle un valor distinto mediante setq. Por ejemplo, si hacemos (setq sin cos) la
funcin SIN de AutoLISP pasar a funcionar como la funcin COS, devolviendo el coseno de un
ngulo en lugar de el seno. (sin 0.0) ahora devolvera 1.0 en lugar de 0.
Veamos ahora el cdigo de la funcin ARAND ya modificada:
(defun C:ARAND ( / pto rad cmd0 error0 )
(command _.undo _begin)
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
(setq error0 *error* *error* ERRORES)
(setq pto (getpoint \nCentro de la arandela: ))
(setq rad (getdist pto \nRadio interior: ))
(command _.circle pto rad)
(setq rad (getdist pto \nRadio exterior: ))
(command _.circle pto rad)
(setq *error* error0)
(if (= cmd0 1)
(setvar cmdecho 1)
)

(command _.undo _end)


(princ)
)
(prompt \nNuevo comando ARAND cargado)
En la lnea (setq error0 *error* *error* ERRORES) se asigna a la variable error0 la antigua funcin
de tratamiento de errores, *error*. Y se define la funcin de tratamiento de errores como nuestra
funcin ERRORES.
Por supuesto, le decimos que use nuestra funcin de tratamiento de errores al principio del cdigo.
Pero siempre despus de desactivar el eco de mensajes.
Hemos redefinido la funcin de tratamiento de errores, pero al terminar la rutina debemos dejarlo
todo como estaba antes. As que recuperamos la funcin de tratamiento de errores inicial, la que
ofrece AutoLISP por defecto. Lo haramos con la siguiente lnea: (setq*error* erro0) que se debe
poner antes de volver a activar el eco de mensajes.
Para probar la funcin de tratamiento de errores debemos cargarla en AutoCAD.
En la rutina CIRCPERI haramos exactamente lo mismo:
(defun C:CIRCPERI ( / pto peri rad cmd0 error0 )
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
(setq error0 *error* *error* ERRORES)
(setq pto (getpoint \nCentro de la circunferencia: ))
(setq peri (getdist \nPermetro: ))
(setq rad (/ peri (* pi 2)))
(command _.circle pto rad)
(setq *error* error0)
(if (= cmd0 1)
(setvar cmdecho 1)
)
(princ)
)
(prompt \nNuevo comando CIRCPERI cargado)

Repasemos un poco el funcionamiento de la rutina CIRCPERI: Lo primero que hacemos es


desactivar el eco de mensajes, a continuacin redefinimos la funcin de tratamiento de errores,
despus viene el cdigo de la funcin, se restituye la funcin de tratamiento de errores de AutoLISP
y se recupera el valor inicial de cmdecho (que controla el eco de mensajes).
Qu diferencia existe entre nuestra funcin de tratamiento de errores y la ofrecida por defecto por
AutoLISP?
Pues casi ninguna, de momento tan slo se diferencia en que si el error que se ha producido tiene
por descripcin quitar / salir abandonar, que equivale a pulsar la tecla de ESCape, no hace
nada. Si el error no se ha producido por pulsar ESC, sino por otra causa, entonces mostrar un
mensaje indicando: Error: Descripcin del error. Un gran cambio, no? Bueno los cambios
vamos a hacerlos ahora que ya sabemos como funciona la funcin ERRORES.
Cada tipo de error ofrece una descripcin especfica y adems existe un cdigo numrico asociado
a la variable de sistema ERRNO en la que se almacena el cdigo correspondiente al ltimo error
que se ha producido. Puedes ver en este enlace una lista de los cdigos y mensajes de error de
AutoLISP.
Qu sucede si el usuario introduce un dato incorrecto al solicitarle el permetro? En ese caso, en la
siguiente lnea (setq rad (/ peri (* pi 2))) se producira un error, inicindose la funcin de tratamiento
de errores. Cuando se produce el error, ya se ha evaluado la lnea(setq error0 *error* *error*
ERRORES) en CIRCPERI, de modo que hemos redefinido la funcin de tratamiento de errores. As
que se ejecuta la funcin ERRORES, que muestra la descripcin del error que se produjo. Pero,
salimos de la funcin ERRORES y no hemos recuperado el valor de la funcin de tratamiento de
errores que nos ofrece por defecto AutoLISP. Y tambin se ha desactivado el eco de mensajes, pero
no recuperamos su valor inicial.
De modo que vamos a modificar la funcin ERRORES para aadir estos pequeos cambios:
(defun ERRORES ( mens )
(setq *error* error0)
(if (= mens quitar / salir abandonar)
(princ)
(princ (strcat \nError: mens ))
)
(if (= cmd0 1)
(setvar cmdecho 1)
)
(princ)
)

Ahora nuestra funcin ERRORES restituye el valor inicial del eco de mensajes y la funcin de
tratamiento de errores inicial. Puede extraar que se utilicen las variables cmd0 y error0 dentro de
la funcin ERRORES, ya que estaban definidas como variables locales enCIRCPERI.
Cuando definimos una variable local en una funcin, esta variable se puede utilizar slo dentro de
esa funcin. Pero, si desde CIRCPERIllamamos a otra funcin, por ejemplo ERRORES, en
realidad estamos dentro de ERRORES, que est dentro de CIRCPERI. As que seguimos dentro
de CIRCPERI.
Otra de las principales aplicaciones de redefinir la funcin de tratamiento de errores tiene que ver
con el tema anterior, los comandos deshacer en las rutinas de AutoLISP.
Si nos fijamos en el cdigo de la rutina ARAND, vemos que la primera lnea
es (command _.undo _begin) Qu sucedera si se produce un error despus de dibujar el
segundo crculo? Dara un error, y terminara el comando sin ejecutar la lnea (command_.undo
_end). Con lo cual para deshacer la arandela deberamos ejecutar el comando H (deshacer)
dos veces, una por cada crculo. Es ms, imagina que nuestra rutina no dibuja 2 circunferencias
sino 120 y que el error se produce al dibujar la circunferencia ensima
Podramos entonces modificar la funcin de tratamiento de errores y aadir la lnea de cdigo:
(command _.undo _end)
Ahora, bastara con ejecutar el comando deshacer una nica vez para que se deshaga todo lo que
hizo el comando ARAND.
Podemos incluso decirle a la funcin ERRORES que si se produce un error, ejecute el comando
deshacer directamente:
(defun ERRORES ( mens )
(setq *error* error0)
(if (= mens quitar / salir abandonar)
(princ)
(princ (strcat \nError: mens ))
)
(command _.undo _end)
(command _.undo )
(if (= cmd0 1)
(setvar cmdecho 1)
)
(princ)
)

En este caso si se produce un error ni siquiera hace falta ejecutar el comando deshacer, la
funcin ERRORES ya lo hace por nosotros.
Para terminar este artculo, vamos a aadir una nueva opcin a CIRCPERI. Se trata de que ofrezca
por defecto el permetro de la ltima circunferencia dibujada. Podramos hacer lo siguiente:
(defun C:CIRCPERI ( / pto peri cmd0 )
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
(setq pto (getpoint \nCentro de la circunferencia: ))
(if (not rad)
(prompt \nPermetro: )
(progn
(prompt \nPermetro <)
(prompt (rtos (* rad 2 pi) 2 2))
(prompt >: )
)
)
(if (setq peri (getdist))
(setq rad (/ peri (* 2 pi)))
)
(command _.circle pto rad)
(if (= cmd0 1)
(setvar cmdecho 1)
)
(princ)
)
(prompt \nNuevo comando CIRCPERI cargado)
Ponemos la variable rad como global, as se puede recuperar el valor que tena en la anterior
ejecucin de CIRCPERI. Veamos ahora cmo funciona el siguiente trozo de cdigo:
(if (not rad)
(prompt \nPermetro: )

(progn
(prompt \nPermetro <)
(prompt (rtos (* rad 2 pi) 2 2))
(prompt >: )
)
)
Si rad es igual a nil, no se ha definido, significa que es la primera vez que se ejecuta el
comando CIRCPERI en el dibujo actual. En este caso se muestra un mensaje solicitando el
permetro del crculo.
Si no es la primera vez que se ejecuta CIRCPERI, la variable rad tendr asociado un valor,
correspondiente al radio del circulo creado en la ltima ejecucin de CIRCPERI. Tambin muestra
un mensaje solicitando el permetro, pero entre los caracteres < y > se indica adems el valor de
la variable global rad.
(if (setq peri (getdist))
(setq rad (/ peri (* 2 pi)))
)
A continuacin se solicita una distancia. No se ha indicado ningn mensaje en la funcin getdist, ya
que el mensaje de solicitud se muestra en las lneas anteriores. Si se indica un permetro, ya sea
por medio de dos puntos o escribindolo directamente, entonces se calcula su radio. Si como
respuesta a getdist se pulsa Intro, a la variable peri se asigna el valor nil, que es devuelto por setq.
De modo que en este caso no hace nada, por lo tanto la variable rad sigue almacenando el radio
del ltimo crculo creado con CIRCPERI.
(command _.circle pto rad)
Por ltimo dibuja el crculo.
AutoCAD dispone de una variable de sistema llamada CIRCLERAD en la que almacena el valor del
ltimo circulo dibujado. As que podemos utilizar esta variable de sistema para obtener el radio del
ltimo crculo, en lugar de utilizar la variable rad como global. El cdigo sera el siguiente:
(defun C:CIRCPERI ( / pto rad peri cmd0 )
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
(setq pto (getpoint \nCentro de la circunferencia: ))
(if (= (getvar circlerad) 0.0)
(prompt \nPermetro: )

(progn
(prompt \nPermetro <)
(prompt (rtos (* (getvar circlerad) 2 pi) 2 2))
(prompt >: )
)
)
(if (setq peri (getdist))
(setq rad (/ peri (* 2 pi)))
(setq rad (getvar circlerad))
)
(command _.circle pto rad)
(if (= cmd0 1)
(setvar cmdecho 1)
)
(princ)
)
(prompt \nNuevo comando CIRCPERI cargado)
Ahora ofrecer por defecto el permetro del ltimo crculo dibujado en AutoCAD,
independientemente de si dicho crculo se creo con la rutina CIRCPERI, con el
comando CIRCULO o por cualquier otro medio. Veamos como funcionan los cambios que hemos
realizado:
(if (= (getvar circlerad) 0.0)
(prompt \nPermetro: )
(progn
(prompt \nPermetro <)
(prompt (rtos (* (getvar circlerad) 2 pi) 2 2))
(prompt >: )
)
)

Si an no se ha creado ningn crculo en el dibujo, la variable circlerad tendr asociado el valor 0.0.
En este caso solicita el permetro sin ofrecer ningn valor por defecto, y en caso contrario ofrece por
defecto el permetro del ltimo crculo creado.
(if (setq peri (getdist))
(setq rad (/ peri (* 2 pi)))
(setq rad (getvar circlerad))
)
Si se introduce un permetro, por medio de dos puntos o escribindolo se calcula el radio
correspondiente. En caso de que se pulse Intro, se asocia a la variable rad el radio del ltimo crculo
dibujado.

22- Limitar las respuestas de los usuarios


En el artculo anterior vimos las funciones de tratamiento de errores, que nos permiten controlar lo
que sucede cuando se produce un error en nuestras macros. En esta ocasin intentaremos que no
se produzcan alguno de los posibles errores en las macros.
Los errores pueden deberse a que el cdigo no funciona bien por que se ha empleado mal alguna
funcin de AutoLISP o se ha ejecutado incorrectamente un comando de AutoCAD, por ejemplo,
pero estos no son los tipos de errores que corregiremos en este tema. Ms adelante veremos
mtodos de depuracin de nuestras rutinas y corregiremos los errores debidos a un cdigo fuente
incorrecto.
Ahora trataremos otro tipo de errores, los que se producen cuando el usuario introduce
datos errneos Por ejemplo, cuando se solicita un nmero positivo y el usuario indica cero o un
nmero negativo.

(INITGET [modo] [palabras_clave])


Esta funcin se utiliza para modificar el funcionamiento de otras funciones de AutoLISP, en concreto
aquellas funciones en las que se solicitan datos al usuario. Por
ejemplo: GETpoint, GETreal, GETint, casi todas comienzan por GET as que se suelen
denominarfunciones de tipo GET.
Initget siempre devuelve nil. Y si se indica solo, sin argumentos, no hace nada. Tan solo
devuelve nil. As que vamos a ver para que sirven los argumentos de Initget:

modo
Es un nmero entero que nos permitir limitar los datos que se puedan introducir en la siguiente
solicitud de datos al usuario. InitgetNUNCA funciona por si sola, siempre se utiliza para modificar el
funcionamiento de otra funcin.

El argumento modo es en realidad un cdigo binario, que puede tener los siguientes valores:

1 > No admite valores nulos, es decir que se indique Intro como respuesta
2 > No admite el 0 como respuesta

4 > No admite valores negativos como respuesta

8 > Permite indicar un punto fuera de los lmites del dibujo. An cuando estos estn
activados.

16 > Este valor no se utiliza actualmente

32 > Dibuja la lnea o rectngulo elsticos con lneas discontnuas en lugar de contnuas

64 > Hace que GETdist devuelva la distancia en 2D. Es como si proyectase la distancia
real sobre el plano XY.
128 > Permite introducir como respuesta una expresin de AutoLISP.

Bien, veamos como se utiliza initget. Por ejemplo, si queremos que el usuario introduzca un
nmero entero y que no pueda pulsar Intro como respuesta, haramos lo siguiente:
(initget 1)
(setq numero (getint \nNmero entero: ))
Initget modifica a la siguiente funcin de solicitud de datos, es decir, getint.
Si adems queremos que no pueda indicar 0 como respuesta, entonces sumamos sus respectivos
cdigos, el 1 para que no se pueda indicar Intro como respuesta y el 2 para que no se pueda
indicar 0.
(initget (+ 1 2))
(setq numero (getint \nNmero entero: ))
Tambin podemos indicar directamente (initget 3) en lugar de (initget (+ 1 2)). Si el usuario indica
como respuesta 0 o Intro, AutoCAD le dir que ese dato no es vlido y que introduzca un dato
correcto.
Si queremos que adems se indique un nmero positivo, entonces deberamos poner:
(initget 7)
(setq numero (getint \nNmero entero: ))
Ya que 7 = 1 + 2 + 4
Veamos ahora como funciona el cdigo 8 como argumento modo de Initget.

8 > Permite indicar un punto fuera de los lmites del dibujo. An cuando estos estn
activados.

Supongamos que tenemos los lmites del dibujo de AutoCAD activados (comando LIMITES) en ese
caso no podemos indicar puntos fuera de esos lmites. De modo que si se solicita un punto al
usuario con GETPOINT deber indicarlo dentro de los lmites del dibujo. Pero si antes de solicitar el
punto se ejecuta (initget 8) entonces si nos dejara.

El cdigo 16 no se utiliza.
El cdigo 32 se utiliza en funciones de solicitud en las que se indica un punto base, por
ejemplo:

(getpoint pto \nIndicar punto:)


(getcorner pto \nIndicar punto:)
En estos casos aparece una lnea, o un rectngulo, elstico con origen en el punto base pto. Estas
lneas y rectngulos elsticos se muestran con lnea continua. Pero si antes de la funcin de
solicitud se aade (initget 32) se mostraran con lneas discontinuas. Por ejemplo:
(setq pt1 (getpoint \nPunto base: ))
(initget 32)
(setq pt2 (getpoint pt1 \nSegundo punto: ))
En este ejemplo aparece una lnea discontinua. Y en el siguiente un rectngulo con lneas
discontinuas.
(setq pt1 (getpoint \nPunto base: ))
(initget 32)
(setq pt2 (getcorner pt1 \nSegundo punto: ))
Veamos ahora como funciona el cdigo 64

64> Hace que GETdist devuelva la distancia en 2D. Es como si proyectase la distancia
real sobre el plano XY.

Getdist solicita una distancia, que se puede escribir directamente, o se pueden indicar dos puntos
en pantalla. En este caso, getdistdevolver la distancia real entre esos dos puntos. Si lo que nos
interesa obtener es la distancia de sus proyecciones sobre el plano XY actual se
aadir (initget 64) antes de la ejecutar getdist. Por ejemplo:
(setq pt1 (getpoint \nPunto base: ))
(initget 64)
(setq dist12 (getdist pt1 \nSegundo punto: ))
Por ltimo, el cdigo 128 permite indicar una expresin de AutoLISP como respuesta. Por ejemplo,
podemos utilizar nuestra rutina RAG(Radianes A Grados decimales) para indicar un ngulo en
grados decimales cuando nosotros lo tenemos en radianes.
(initget 128)

(setq ang (getreal \nIntroducir ngulo: ))


En este caso el usuario podra indicar como respuesta a la solicitud del ngulo: (RAG (/ pi 4)) Es
decir, un ngulo de 45.
Pues llegados a este punto, antes de ver el segundo argumento de (INITGET [modo]
[palabras_clave]), es decir, las palabras clave. Vamos a modificar nuestras
rutinas ARAND y CIRCPERI.
Si revisamos el cdigo de la macro CIRCPERI encontraremos la siguiente lnea:
(setq pto (getpoint \nCentro de la circunferencia: ))
deberamos aadir alguna limitacin como respuesta del usuario? Veamos:

Si el usuario pulsa Intro como respuesta a la variable pto se le asocia el valor nil, que es lo
que devolvera Getpoint. Despus al intentar dibujar el crculo (command _.circle pto
rad) se producira un error. As que debemos impedir que el usuario introduzca Intro como
respuesta, de modo que aadiramos (initget 1) antes de la funcin getpoint.
Como estamos solicitando un punto, el cdigo 2 no tiene sentido y lo mismo sucede con el
4.
El cdigo 8 permite indicar un punto fuera de los lmites del dibujo, an cuando estos estn
activados. Este cdigo si podramos utilizarlo, aunque si el usuario trabaja con los lmites
activados, estn activados y ya est. Si quiere que los desactive l, no? Porque supongo que
los tendr activados por algn motivo. As que no le aadimos a initget el cdigo 8.

El cdigo 32 no tiene sentido aqu, pues no aparece la lnea base.

Y el cdigo 64 tampoco ya que estamos solicitando un punto, no una distancia.

El cdigo 128 permite introducir como respuesta una expresin de AutoLISP. Este cdigo
tambin se podra indicar, pero lo habitual es no hacerlo. Se podra utilizar en casos en los que
el usuario pudiera utilizar una expresin de AutoLISP para calcular el dato. Como en el ejemplo
que vimos antes, si tiene un ngulo en radianes y lo tiene que indicar en grados
decimales. Aqu nos pide un punto, as que no tiene demasiado sentido.

Definitivamente el cdigo quedara:


(initget 1)
(setq pto (getpoint \nCentro de la circunferencia: ))
Sigamos modificando la rutina CIRCPERI: Unas lneas despus de la solicitud del centro de la
circunferencia, se solicita su permetro:
(if (setq peri (getdist))
(setq rad (/ peri (* 2 pi)))
(setq rad (getvar circlerad))

)
Deberamos aadir la funcin initget con el cdigo 1 antes de la funcin getdist?
Veamos como funciona esta parte del cdigo: Si el usuario introduce una distancia, se evala la
condicin si cumple del IF es decir:
(setq rad (/ peri (* 2 pi)))
Y si el usuario pulsa Intro, se asigna a peri el valor nil y evala la condicin no cumple del IF, es
decir:
(setq rad (getvar circlerad))

Si aadimos antes del getdist la expresin (initget 1), el usuario no podr indicar Intro, as
que nunca se ejecutara la expresin no cumple. Por tanto no aadimos el cdigo 1 a Initget.
El permetro del crculo no puede ser ni cero ni un nmero negativo, de modo que podemos
aadir a initget los cdigos 2 y 4.
Tambin podramos aadir el cdigo 64 para que GETdist devuelva la distancia en 2D. Pero
normalmente no conviene aadir este cdigo, excepto cuando la distancia deba ser siempre
ser en 2D.

Una ltima nota sobre CIRCPERI: Cuando ejecutamos la macro por primera vez en un dibujo en el
que no se ha dibujado ningn crculo, la variable de sistema circlerad tiene el valor 0.0. En este
caso, no ofrecemos la opcin de seleccionar el radio del ltimo crculo dibujado pulsando Intro, ya
que no existe ningn crculo dibujado previamente. En este caso, no deberamos indicar el modo 6 a
Initget, sino el 7 para que tampoco permita al usuario indicar Intro como respuesta. Veamos como
se soluciona en el cdigo completo de la rutina:
(defun C:CIRCPERI ( / pto rad peri cmd0 )
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
(initget 1)
(setq pto (getpoint \nCentro de la circunferencia: ))
(if (= (getvar circlerad) 0.0)
(progn
(prompt \nPermetro: )
(initget 7)
)
(progn

(prompt \nPermetro <)


(prompt (rtos (* (getvar circlerad) 2 pi) 2 2))
(prompt >: )
(initget 6)
)
)
(if (setq peri (getdist))
(setq rad (/ peri (* 2 pi)))
(setq rad (getvar circlerad))
)
(command _.circle pto rad)
(if (= cmd0 1)
(setvar cmdecho 1)
)
(princ)
)
(prompt \nNuevo comando CIRCPERI cargado)
Vamos ahora a modificar la rutina ARAND. La primera solicitud que tenemos en ARAND es la del
centro de la arandela. Prcticamente es igual que la solicitud del centro del crculo en CIRCPERI,
as que le aadimos tambin el cdigo 1 a Initget:
(initget 1)
(setq pto (getpoint \nCentro de la arandela: ))
A continuacin solicita los radios interior y exterior de la arandela. En los que podemos evitar que el
usuario indique como respuesta Intro, 0 o un nmero negativo. Por lo tanto aadiremos Initget con
el modo 7. Veamos el cdigo completo:
(defun C:ARAND ( / pto rad cmd0 )
(command _.undo _begin)
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
(initget 1)

(setq pto (getpoint \nCentro de la arandela: ))


(initget 7)
(setq rad (getdist pto \nRadio interior: ))
(command _.circle pto rad)
(initget 7)
(setq rad (getdist pto \nRadio exterior: ))
(command _.circle pto rad)
(if (= cmd0 1)
(setvar cmdecho 1)
)
(command _undo _end)
(princ)
)
(prompt \nNuevo comando ARAND cargado)

23- Limitar las respuestas de los usuarios (II)

(initget [modo] [palabras_clave])

En el ltimo artculo del curso comenzamos a ver la funcin INITGET y vimos como funcionaba el
argumento [modo] ahora vamos con[palabras_clave]:
[palabras_clave] nos permite indicar una serie de textos (palabras) que tambin sern aceptados
como respuesta en la siguiente funcin de solicitud de datos. Por ejemplo:
(initget 7 Dimetro Permetro)
(setq rad (getdist \nRadio del circulo / Dimetro / Permetro :))
como respuesta a getdist podemos indicar una distancia, ya sea escribiendo un valor numrico o
mediante dos puntos, pero ahora tambin aceptar como respuesta Dimetro y Permetro. El
modo 7 impide que se indique como respuesta Intro, cero o un nmero negativo.

Si indicamos como respuesta una distancia, asocia esa distancia a la varible rad.
Si indicamos como respuesta Dimetro, asocia a la variable rad la cadena de texto
Dimetro.
Si indicamos como respuesta Permetro, asocia a la variable rad la cadena de texto
Permetro.

En [palabras_clave] indicamos una serie de palabras, separadas por espacios, que servirn como
respuesta a la siguiente funcin de solicitud de datos.
No hace falta escribir el nombre completo de la palabra, como hicimos antes, basta con que el
usuario introduzca como respuesta las letras que aparecen en maysculas. Es decir, la D o la P.
En el siguiente ejemplo:
(initget 7 Dimetro desHacer)
(setq rad (getdist \nRadio del circulo / Dimetro / desHacer: ))
Para seleccionar la opcin Dimetro habr que escribir al menos la D. Pero para seleccionar
desHacer al menos habr que escribirH. Tambin aceptara di para el dimetro y desh para
deshacer.
Sin embargo no aceptar de ni des para seleccionar desHacer. Fjate que al menos deben
indicarse las letras en maysculas.
Por otra parte, aceptar tanto di como dia sin tilde para seleccionar Dimetro.
Supongamos que tenemos el siguiente cdigo:
(initget 7 Dimetro desHacer)
(setq rad (getdist \nRadio del circulo: ))
En este caso getdist aceptar como respuestas a la peticin del radio de la circunferencia
Dimetro y desHacer. Pero al no indicar estas opciones en el mensaje de getdist, el usuario no
sabr que existen. De modo que es recomendable indicar al usuario las opciones que puede
seleccionar:
(initget 7 Dimetro desHacer)
(setq rad (getdist \nRadio del circulo / Dimetro / desHacer :))
Como mejor se ve es con un ejemplo as que, vamos a modificar la rutina ARAND aadiendo una
opcin para indicar el dimetro en lugar del radio. Tenemos que modificar las siguientes lneas:
(initget 7)
(setq rad (getreal \nRadio interior: ))
Primero aadimos Dimetro a la lista de palabras clave de initget:
(initget 7 Dimetro)
Y a continuacin le decimos al usuario que existe una opcin llamada Dimetro que puede
seleccionar como respuesta:
(setq rad (getreal \nRadio interior / Diametro: ))
De esta forma ya hemos aadido la opcin Dimetro

Pero, qu sucede si el usuario indica como respuesta la opcin Dimetro? Pues que asignamos
a la variable rad la cadena de texto Dimetro y en la siguiente lnea (command _.circle pto
rad) al intentar dibujar la circunferencia, nos da un error.
As que hay que modificar la rutina aadiendo a continuacin algo parecido a:

Si el usuario selecciona la opcin Dimetro > Preguntamos por el dimetro.

Pues esto en AutoLISP, sera:


(if (= rad Dimetro)
(setq rad (getreal \nDimetro interior: ))
)
Hay que tener especial cuidado con la condicin del IF (= rad Dimetro) ya que hay que indicar la
palabra clave tal y como aparece en la lista de palabras clave de initget.
Es decir, no funcionara si ponemos (= rad dimetro) o (= rad Diametro) ya que en el primer
caso no ponemos la D en maysculas y en el segundo no hemos tildado la a.
Fjate en lo que hace el cdigo anterior:

Si el usuario indica una distancia la asigna a la variable rad y luego (if (= rad Dimetro)
devuelve nil, puesto que rad es distinto de Dimetro.
Si el usuario indica D o Diam, o dimetro, entonces asigna a la variable rad la cadena de
texto Dimetro. Luego al entrar en elIF, (= rad Diametro) devuelve T as que evala la
expresin si cumple (setq rad (getreal \nDimetro interior: )) que pide un dimetro al
usuario y lo asigna a la variable rad.
Pero rad viene de radio, porque en esta variable almacenamos el radio de la circunferencia
y no el dimetro. As que al dibujar la circunferencia (command _.circle pto rad) dibujara
una circunferencia del doble del dimetro de lo que ha dicho el usuario.

El cdigo debera ser:


(initget 7 Dimetro)
(setq rad (getreal \nRadio interior / Dimetro: ))
(if (= rad Dimetro)
(setq rad (/ (getreal \nDimetro interior: ) 2.0))
)
Pero, Qu pasa si el usuario hace lo siguiente?

Indica D como respuesta al radio interior.


Indica -50 o 0 como dimetro.

Pues que asignara a la variable rad el resultado de dividir -50 o 0 entre 2.0. Por tanto tendramos
una circunferencia con radio negativo o cero.
Recuerda que initget solo tiene efecto sobre la siguiente funcin de solicitud de datos, de modo que
tenemos que aadir de nuevo la funcin Initget antes de preguntar por el dimetro:
(initget 7 Dimetro)
(setq rad (getreal \nRadio interior / Dimetro: ))
(if (= rad Dimetro)
(progn
(initget 7)
(setq rad (/ (getreal \nDimetro interior: ) 2.0))
)
)
Se ha aadido la funcin Progn ya que sino, solo se puede ejecutar una expresin como condicin
si-cumple del IF.
Para el radio o dimetro exterior se hara exactamente lo mismo. Por tanto el cdigo completo ser:
(defun C:ARAND ( / pto rad cmd0 )
(command _.undo _begin)
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
(initget 1)
(setq pto (getpoint \nCentro de la arandela: ))
(initget 7 Dimetro)
(setq rad (getdist pto\nRadio interior / Dimetro: ))
(if (= rad Dimetro)
(progn
(initget 7)
(setq rad (/ (getreal \nDimetro interior: ) 2.0))
)
)
(command _.circle pto rad)

(initget 7 Dimetro)
(setq rad (getdist pto \nRadio exterior / Dimetro: ))
(if (= rad Dimetro)
(progn
(initget 7)
(setq rad (/ (getreal \nDimetro exterior: ) 2.0))
)
)
(command _.circle pto rad)
(if (= cmd0 1)
(setvar cmdecho 1)
)
(command _undo _end)
(princ)
)
(prompt \nNuevo comando ARAND cargado)

(GETKWORD [mensaje])
Esta funcin de AutoLISP se utiliza para obtener una opcin indicada por el usuario. Se utiliza en
combinacin con INITGET, por ejemplo:
(initget DEShacer Nuevo Repetir)
(setq opc (getkword \nDEShacer / Nuevo / Repetir: ))
En este caso el usuario tan slo podr indicar como respuesta una de las palabras clave de la
funcin Initget y se la asigna a la variableopc.
No hemos indicado el modo en Initget, tal solo las palabras clave. En la rutina ARAND nos
interesaba que apareciera el modo 7 para que no se indique como respuesta Intro, 0 o un nmero
negativo. Pero no es obligatorio indicar siempre un modo.
Un ejemplo bastante habitual en las macros es el siguiente:
(initget DEShacer Nuevo Repetir)
(setq opc (getkword \nDEShacer / Nuevo / Repetir: ))
(cond

((= opc DEShacer)


(alert Has seleccionado la opcin DEShacer)
)
((= opc Nuevo)
(alert Has seleccionado la opcin Nuevo)
)
(T
(alert Has seleccionado la opcin Repetir)
)
)
As en funcin de la opcin que indique el usuario se hace una cosa u otra.

24- Estructuras repetitivas: Bucles


Hasta hace poco tan slo podamos crear programas cuya ejecucin fuera lineal:

Haz esto
Ahora esto otro

Luego vimos las estructuras condicionales IF y COND que ya nos permiten jugar un poco ms y
hacer que nuestros programas no fueran tan lineales. Ahora vamos a ver funciones que nos
permitir crear repeticiones de cdigo y algo que tal vez te suene, los bucles, que se utilizan mucho
en programacin.

(WHILE condicin [expr1] [expr2] )


La funcin while ejecuta las expresiones indicadas MIENTRAS se cumpla la condicin, y devuelve
el valor de la ltima expresin evaluada. Por ejemplo:
(setq i 0)
(while (< i 10)
(prompt \n)
(prompt (itoa i))
(setq i (1+ i))

)
Mientras i sea menor que 10, ejecuta las expresiones. Es decir, escribir en la ventana de
comandos de AutoCAD los nmeros del 0 al 9. Cuando (setq i (1+ i)) asigna a la variable i el valor
10, la condicin del bucle ya no se verifica, de modo que termina el bucle. La
funcinWhile devolver el valor de la ltima expresin evaluada, es decir 10.
Este es un tpico ejemplo de bucle, una estructura repetitiva con un ndice o contador, en este
caso i, que puede ir aumentando o disminuyendo.
Fjate que una de las expresiones que se ejecutan dentro del bucle es (setq i (1+ i)) es decir,
movemos el contador. Si no lo hiciramos isiempre sera menor que 10 y se entrara en un bucle
sin fin, que da lugar a un error.
Veamos el siguiente ejemplo:
(setq i 10)
(while (< i 10)
(prompt \n)
(prompt (itoa i))
(setq i (1+ i))
)
En este caso i tiene asignado el valor 10 antes de entrar en el bucle, de modo que la
condicin (< i 10) no se cumplira y por tanto no se ejecutarn las expresiones
siguientes. While devuelve el valor de la ltima expresin evaluada, que en este caso es la
condicin as que devuelve nil.
Las expresiones en While son opcionales, de modo que podemos crear un bucle en el que solo se
indique la condicin:
(while (not (setq pt (getpoint \nPunto inicial: ))))
En este caso la condicin es (not (setq pt (getpoint \nPunto inicial: ))) es decir, pide un punto al
usuario y lo almacena en la variable pt.

Si el usuario indica un punto, pt = (X Y Z) que es distinto


de nil, (not (setq pt (getpoint \nPunto inicial: ))) devolver nil y saldr de la funcin While.
Si el usuario indica Intro, getpoint devolver nil y lo almacenar en la variable pt, de modo
que (not (setq pt (getpoint \nPunto inicial: ))) devolver T, y preguntar de nuevo por un
punto.

Por lo tanto, mientras no se indica un punto, sigue preguntando.


Otro ejemplo tpico de bucles es en el que se utilizan algunas variables como flags (banderas o
banderillas) para indicar si algo est activado o desactivado o para controlar distintos valores.
Veamos un ejemplo, supongamos que a y b son dos variables que almacenan dos nmeros reales:

(if (< a b)
(setq flag1 nil)
(setq flag1 T)
)
(while flag1
(prompt \na NO es menor que b)
(setq b (getreal \nIntroduzca un nmero: ))
(if (< a b)
(setq flag1 nil)
)
)
En este caso:

Si a es menor que b > flag1 = nil


Si a NO es menor que b > flag1 = T

Luego la funcin While evala la condicin flag1 que devolver su valor nil o T.

Si es flag1 = nil (a es menor que b) no evala las expresiones pues no se verifica la


condicin.
Si es flag1 = T (a NO es menor que b) se verifica la condicin as que se ejecutan las
expresiones. Primero nos dice que a no es menor que b, nos vuelve a pedir el valor de b y
comprueba si a es menor que el nuevo valor de b en cuyo caso asigna a la banderilla flag1 el
valor nil para salir del bucle.

Es decir, mientas a NO sea menor que b, nos pedir un nuevo valor de b.


En la funcin While, al igual que vimos con IF y COND, como condicin podemos utilizar
expresiones lgicas. Por ejemplo:
(while (or (< a b) (< b 0.0))
(prompt \na NO es menor que b, o b es negativo)
(setq b (getreal \nIntroduzca un nmero positivo: ))
)
En este ejemplo, el bucle se ejecutar hasta que se indique un valor para b positivo y mayor que a.

(REPEAT cantidad [expr1] [expr2])

La funcin repeat ejecuta las expresiones indicadas el nmero de veces que se indique
en cantidad y devuelve el resultado de la ltima expresin evaluada.
(repeat 10 (prompt \nEste curso es demasiado fcil para mi))
Tambin podramos asignar la cantidad a repetir a una variable:
(setq Bart_Simpson (getint \nNmero de repeticiones para Bart: ))
(repeat Bart_Simpson (prompt \nNo hace falta fuego en un simulacro de incendio))
En este caso escribira en la pizarra, es decir la ventana de comandos de AutoCAD, esa frase tantas
veces como le indiquemos.
Tambin podemos obtener la cantidad por medio de una funcin de AutoLISP, como resultado de
una operacin:
(repeat (+ 4 5) (prompt Este curso me parece muy sencillo))
o suponiendo que las variables a y b tengan asignados dos nmeros enteros:
(prompt Inspector Gadget, este mensaje se autodestruir en)
(setq i 0)
(repeat (+ a b)
(prompt \t)
(prompt (itoa i))
(setq i (1+ i))
)
Pero qu sucede si a o b son un nmero real y no un entero? repetir las expresiones 2.5 veces?
Pues no, nos dar un error. Por eso hay que estar bien seguros de que la cantidad indicada es un
nmero entero y no un real. Incluso si como cantidad indicamos un nmero entero sin decimales,
como 2.0, dar un error.
Vamos a modificar la rutina ARAND para hacer que el segundo radio siempre sea mayor que el
primero. El cdigo correspondiente al crculo exterior era el siguiente:
(initget 7 Dimetro)
(setq rad (getdist pto \nRadio exterior / Dimetro: ))
(if (= rad Dimetro)
(progn
(initget 7)
(setq rad (/ (getreal \nDimetro exterior: ) 2.0))
)

)
(command _.circle pto rad)
Lo primero que vamos a cambiar es el nombre de las variables. En lugar de utilizar la
variable rad tanto para el radio interior como para el exterior, vamos a utilizar la variable radi para el
radio interior y la variable rade para el exterior. As podremos comparar si rade es mayor que radi.
Podramos sustituir el cdigo anterior por el siguiente:
(while (or (not rade) (not (< radi rade)))
(initget 7 Dimetro)
(setq rade (getreal \nRadio exterior / Dimetro: ))
(if (= rade Dimetro)
(progn
(initget 7)
(setq rade (/ (getreal \nDimetro exterior: ) 2.0))
)
)
)
(command _.circle pto rade)
La primera vez que se evala la condicin del bucle, no se ha asignado an ningn valor al radio
exterior. De modo que rade = nil y (notrade) devolver T.
Como (or (not rade) (not (< radi rade))) comprueba que al menos se verifique una de las dos
condiciones, al verificarse la primera condicin (not rade) la segunda ni siquiera se evala (por
suerte, puesto que al no estar definida rade nos dara un error). La condicin se verifica y ejecuta
las expresiones que estn a continuacin, que nos piden un valor para el radio exterior.
Es decir, mientras no se indique el radio exterior o este sea menor que el radio interior se ejecuta el
bucle, que nos pide un nuevo valor para el radio exterior. Al salir del bucle ya tenemos un radio
exterior vlido as que dibujamos la circunferencia exterior. El cdigo completo sera:
(defun C:ARAND ( / pto radi rade cmd0 )
(command _.undo _begin)
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
(initget 1)

(setq pto (getpoint \nCentro de la arandela: ))


(initget 7 Dimetro)
(setq radi (getdist pto \nRadio interior / Dimetro: ))
(if (= radi Dimetro)
(progn
(initget 7)
(setq radi (/ (getreal \nDimetro interior: ) 2.0))
)
)
(command _.circle pto radi)
(while (or (not rade) (not (< radi rade)))
(initget 7 Dimetro)
(setq rade (getdist pto \nRadio exterior / Dimetro: ))
(if (= rade Dimetro)
(progn
(initget 7)
(setq rade (/ (getreal \nDimetro exterior: ) 2.0))
)
)
)
(command _.circle pto rade)
(if (= cmd0 1)
(setvar cmdecho 1)
)
(command _.undo _end)
(princ)
)
(prompt \nNuevo comando ARAND cargado)

25- Funciones para manipular cadenas de texto

En este artculo veremos las funciones que incorpora AutoLISP para manipular cadenas de texto.

(CHR entero)
Esta funcin devuelve el carcter al que le corresponde el cdigo ASCII indicado. Por ejemplo:
(chr 65) devuelve A
(chr 97) devuelve a

(ASCII texto)
Devuelve el cdigo ASCII (un nmero entero) correspondiente al primer carcter de la cadena de
texto indicada.
(ascii Abcde) devuelve 65
(ascii A) tambin devuelve 65 porque lo nico que importa es el primer carcter de la cadena de
texto.

(STRLEN texto1 [texto2] )


Esta funcin devuelve la longitud (nmero de caracteres) de la cadena de texto que recibe como
argumento.
(strlen AutoLISP) devuelve 8
Tambin podemos asignar una cadena de texto a una variable y comprobar despus su longitud
con strlen:
(setq txt1 AutoLISP)
(strlen txt1)
Si se indica ms de una cadena de texto, devolver la suma de sus longitudes:
(strlen AutoLISP AutoCAD) devuelve 15

(STRCASE texto [modo])


Se utiliza para convertir un texto en maysculas o minsculas. Por ejemplo:
(strcase AutoLISP) devuelve AUTOLISP
Si se indica el argumento opcional [modo] con un valor distinto de nil, entonces devuelve el texto en
minsculas.
(strcase AutoLISP T) devuelve autolisp

(STRCAT texto1 [texto2] )


Esta funcin concatena (une) varias cadenas de texto.
(strcat Hola Mundo) devolvera HolaMundo
Para que las dos palabras anteriores aparezcan separadas se pueden hacer dos cosas:

Aadir el espacio en una de las palabras: (strcat Hola Mundo)


Aadir el espacio como otra cadena de texto: (strcat Hola Mundo)

Esta funcin se utiliza mucho para concatenar los mensajes que se muestran al usuario. Por
ejemplo:
(setq i 10)
(setq rad (getreal (strcat \nRadio < (itoa i) >: )))
Pedir un nmero real al usuario y mostrar el siguiente mensaje en la ventana de AutoCAD: Radio
<10>:

(SUBSTR texto pos_inicial [longitud])


Esta funcin devuelve parte de la cadena de texto que recibe como argumento, a partir de la
posicin inicial que se indique.
(substr AutoLISP 5) devuelve el texto a partir del quinto carcter, es decir LISP.
(substr AutoLISP 1) devuelve el texto entero AutoLISP.
(substr AutoLISP 15) devuelve es decir, una cadena de texto vaca puesto que el texto
indicado tiene menos de 15 caracteres.
Tambin se puede indicar la longitud, es decir el nmero de caracteres que se desean obtener.
(substr AutoLISP 5 2) devuelve LI. A partir del quinto carcter devuelve 2 caracteres.
(substr AutoLISP 5 10) devolver LISP, porque tan slo tenemos 4 caracteres ms, a partir del
quinto, y no diez.

(WCMATCH cadena patrn)


Esta funcin se utiliza para comparar si una cadena de texto verifica o cumple un patrn, en caso de
que lo verifique devuelve T y si no lo verifica devuelve nil.
(wcmatch AutoLISP A*) devolver T ya que comprueba si AutoLISP comienza por A.
(wcmatch AutoLISP a*) devolver nil, puesto que A es distinto de a.
Los patrones son cadenas de texto en las que se pueden emplear determinados smbolos comodn:

# Equivale a un dgito.
@ Equivale a una letra.

. Equivale a un carcter que no sea alfanumrico (ni letras ni nmeros).

* Equivale a una cadena de caracteres.

? Equivale a un carcter cualquiera.

~ Equivale a una negacin.

Por ejemplo (wcmatch AutoLISP ~B*) comprueba que el texto no empieza por

B.
[...] Nos permite indicar varios caracteres.

Por ejemplo (wcmatch AutoLISP [AB]*) comprueba si el texto comienza por


A o por B.

Tambin podramos indicar un rango: (wcmatch AutoLISP [A-F]*) comprueba


si el texto comienza por A, B, C, hasta la F.

Incluso podemos comprobar con dos patrones distintos, separados por una
coma: (wcmatch AutoLISP A*,*LISP) devolvera T.
Pero cmo hacemos entonces para saber si un texto tiene una coma? no podemos hacer los
siguiente: (wcmatch Curso, de AutoLISP *,*) ya que en este caso le estamos indicando dos
patrones, como en el ejemplo anterior.
Tendremos que hacerlo as: (wcmatch Curso, de AutoLISP *,*) al anteponer el
apstrofo delante de uno de los caracteres comodines de los patrones, le estamos diciendo que
queremos usar el literal, es decir, lo que ponemos a continuacin tal cual est.
Pues tema visto. As que podemos ahora modificar la macro CIRCPERI. Tenamos las siguientes
lneas en la macro:
(prompt \nPermetro <)
(prompt (rtos (* (getvar circlerad)2 pi) 2 2))
(prompt >: )
Podramos concatenar las cadenas de texto y ejecutar una nica vez la funcin prompt:
(prompt (strcat \nPermetro < (rtos (* (getvar circlerad) 2 pi) 2 2) >: ))
Vamos ahora a crear un nuevo comando llamado CIRCULOM que nos permitir dibujar mltiples
circunferencias concntricas. Y comenzaremos como siempre por el pseudocdigo. Podra ser algo
as:
1.
2.

Pedir el centro de las circunferencias.


Mientras se indique un punto o radio.

1.

Dibujar un crculo.

Al escribir el cdigo, lo primero es definir el nuevo comando:


(defun C:CIRCULOM ( / )
De momento no ponemos las variables locales, porque an no tenemos ni variables ni nada. Las
aadiremos al terminar la macro.
1. Pedir el centro de los crculos. Por ejemplo as:
(setq pto (getpoint \nCentro: ))
Tal vez pienses no deberamos poner antes un INITGET? Pues seguramente, pero no nos
paremos ahora con eso. Primero a ver si hacemos que funcione la rutina, despus ya nos
preocuparemos de que funcione bien.
2. Mientras se indique un punto o radio. Esto lo podemos hacer con While:
(while (setq rad (getdist pto \nRadio [Intro para terminar]: ))
Pide puntos o distancias, para usarlas como radio, hasta que se pulse Intro. Fjate que no se ha
cerrado el while, porque an tenemos que aadir las expresiones que van dentro.
Y nos falta solo dibujar la circunferencia. As de sencillo:
(command _.circle pto rad)
nos faltan dos cosas para terminar: El parntesis de cierre de While y el de la funcin. El cdigo
completo queda as:
(defun C:CIRCULOM ( / )
(setq pto (getpoint \nCentro: ))
(while (setq rad (getdist pto \nRadio [Intro para terminar]: ))
(command _.circle pto rad)
)
)
Ahora es cuando vamos a introducir las mejoras y a retocar el cdigo. Vamos a comenzar limitando
las posibles respuestas de los usuarios con Initget:

Aadimos (initget 1) antes de la solicitud Getpoint, para que el usuario no pueda indicar
Intro como respuesta.
Y aadimos (initget 6) antes de getdistpara que no permita ni cero ni un nmero negativo.
o

Observa que (initget 6) se vuelve a poner otra vez dentro del bucle While. Si no
lo hiciramos al indicar el primer radio no permitira responder con cero ni con un nmero
negativo. Sin embargo, para el segundo radio y todos los siguientes si que nos dejara. Para

que no lo permita, hay que incluir la funcin Initget antes de que se ejecute de
nuevo Getdist, de modo que se aade dentro del bucle While.
Otras mejoras seran:

Aadir las variables a la lista de variables locales de la funcin.


Desactivar el eco de mensajes.

Aadir una salida limpia a la funcin.

Aadir una lnea fuera de la funcin para que indique el nombre del comando al cargar la
macro.

Aadir el comando Deshacer Inicio al principio de la rutina y Deshacer Fin al terminarla.

El cdigo de la macro queda as:


(defun C:CIRCULOM ( / pto rad cmd0 )
(command _.undo _begin)
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
(initget 1)
(setq pto (getpoint \nCentro: ))
(initget 6)
(while (setq rad (getdist pto \nRadio [Intro para terminar]: ))
(command _.circle pto rad)
(initget 6)
)
(if (= cmd0 1)
(setvar cmdecho 1)
)
(command _.undo _end)
(princ)
)
(prompt \nNuevo comando CIRCULOM cargado)

26- Trabajar con ngulos y distancias


AutoLISP proporciona una serie de funciones para trabajar con ngulos y distancias,
comenzaremos viendo los ngulos:

(ANGLE pt1 pt2)


Esta funcin devuelve el ngulo formado por la lnea que va desde pt1 hasta pt2. El origen de
ngulos ser el eje X y el sentido antihorario se considera positivo. Por ejemplo:
(setq pt1 (getpoint \nPunto1: ))
(setq pt2 (getpoint pt1 \nPunto2: ))
(setq ang (angle pt1 pt2))
Hay que fijarse en cual es el punto que se indica primero en la funcin angle, porque si hacemos:
(setq ang2 (angle pt2 pt1))
Obtendremos un ngulo distinto, el anterior ms pi o menos pi. Por lo tanto: No es lo mismo el
ngulo de pt1 a pt2 que el ngulo de pt2a pt1.
Si los puntos estn en 3D, los proyecta sobre el plano XY y devuelve el ngulo formado por sus
proyecciones

(DISTANCE pt1 pt2)


Devuelve la distancia en 3D entre los puntos pt1 y pt2. Si uno de los puntos est en 2D, es decir no
tiene coordenada Z, se ignora la coordenada Z del otro punto devolviendo la distancia en 2D.
(setq pt1 (getpoint \nPunto1: ))
(setq pt2 (getpoint pt1 \nPunto2: ))
(setq dist12 (distance pt1 pt2))
En este caso, (setq dist21 (distance pt2 pt1)) sera igual a dist12. Ya que la distancia del
punto pt1 al pt2 es igual que la distancia del punto pt2 al pt1.

(POLAR ptobase ang dist)


Esta funcin se utiliza para obtener un punto por medio de coordenadas polares a partir de un punto
base. Por ejemplo:
(setq pt1 (getpoint \nPunto1: ))
(setq pt2 (polar pt1 0.0 50.0))

Esto asignara a la variable pt2 un punto que est a 50 unidades en la direccin del eje X a partir del
punto base pt1. Si hiciramos:
(command _.line pt1 pt2 )
Dibujaramos una lnea horizontal de 50 unidades, desde pt1 hasta pt2.
Hay que observar que en (polar pt1 0.0 50.0) se indica primero el punto base, luego un ngulo en
radianes y por ltimo una distancia. De modo que:
(setq pt2 (polar pt1 (/ pi 2.0) 50.0))
Devolver un punto que est a 50 unidades en la direccin del eje Y a partir del punto base pt1. Ya
que en este caso se ha indicado un ngulo de (/ pi 2.0) es decir, 90.

27- Funciones avanzadas para manejar listas


Ya hemos visto algunas funciones para manejar listas: CAR, CDR, LIST pero hay muchas ms. En
este tema veremos algunas de las que nos faltan.

(LAST lista)
Esta funcin devuelve el ltimo elemento de la lista que recibe como argumento. De modo que si
hacemos:
(setq pto (getpoint \nPunto de insercin: ))
(setq z (last pto))
En la variable z almacenamos la coordenada Z del punto pto, siempre que el punto est en 3D
porque si est en 2D almacenara la coordenada Y. Los puntos son listas del tipo (10.0 20.0 0.0).

(NTH numero lista)


El ejemplo anterior no sera muy til para obtener la coordenada Y, ya que si indicamos un punto en
3D devolver la coordenada Z. Entonces, cmo podemos obtener la coordenada Y? ya vimos un
mtodo:
(CADR pto)
Pero supongamos que tenemos una lista de 27 elementos, y queremos obtener el elemento 22.
Cmo lo haramos? No podemos utilizar (cADDD..DDDr pto) ya que slo nos permite agrupar 4
funciones cAr y cDr. De modo que tendramos que hacer (cADDD (cDDDD (cDDDDr .. pto). Pero
hacerlo as es bastante engorroso.
Devuelve el elemento cuyo nmero de orden se indica de la lista.

(nth 2 pto) devolver la coordenada Y, no? Pues no!. Los elementos de una lista se empiezan a
numerar desde cero.
Por ejemplo:

(nth 0 pto) devolver la coordenada X del punto pto.


(nth 1 pto) devolver la coordenada Y del punto pto.

(nth 2 pto) devolver la coordenada Z del punto pto, si existe y si no existe devolver nil.

(MEMBER elemento lista)


Supongamos que tenemos una lista como la siguiente:
(setq lst (list peras melones sandias perros pltanos))
para comprobar si perros pertenece a la lista lst se utiliza la funcin MEMBER.
Con esta funcin, si el elemento indicado pertenece a la lista devolver la lista a partir de ese
elemento. Por ejemplo:
(member perros lst) devolver (perros pltanos)
Si el elemento no pertenece a la lista, devolver nil.
(member gatos lst) devuelve nil

(SUBST elem_nuevo elem_antiguo lista)


Esta funcin reemplaza un elemento de una lista por su nuevo valor. Por ejemplo, para reemplazar
perros por naranjas:
(subst naranjas perros lst) devuelve la lista con el elemento que se ha modificado (peras
melones sandias naranjas pltanos). Pero la variable lst sigue almacenando la lista
anterior (peras melones sandias perros pltanos).
Para modificar la lista almacenada en la variable lst tenemos que asignarle el valor devuelto
por SUBST:
(setq lst (subst naranjas perros lst))

(CONS elemento lista)


Supongamos que queremos aadir un nuevo elemento limones a la siguiente lista:
(setq lst (list peras naranjas manzanas))
Podramos hacerlo con list, pero sera algo complicado:
(setq lst (list limones (car lst) (cadr lst) (caddr lst)))

Para una lista de 3 elementos se puede hacer, pero Y si tenemos 30 elementos?


La funcin cons aade un elemento a la lista indicada. El nuevo elemento se sita en el primer
lugar. Es decir:
(cons limones lst) devolver (limones peras naranjas manzanas)
Y al igual que suceda con SUBST, si slo hacemos (cons limones lst) no estamos asignando la
lista resultante a la variablelst. Deberamos hacerlo as:
(setq lst (cons limones lst))
Pero y si lo que queremos es aadir un elemento al final de la lista? Antes de ver como sera,
veamos otra funcin:

(REVERSE lista)
Devuelve la lista que recibe como argumento pero en orden inverso.
(reverse lst) devolver (manzanas naranjas peras limones)
Bien, pues para aadir un elemento al final de una lista podemos utilizar cons y reverse:
(setq lst (reverse (cons pltanos (reverse lst))))
Veamos como funciona la lnea de cdigo anterior:

(reverse lst) devuelve la lista en orden inverso


(cons pltanos (reverse lst)) aade pltanos como primer elemento de la lista
invertida
por ltimo volvemos a invertir el orden de la lista y lo asignamos a la
variable lst: (setq lst (reverse (cons platanos (reverselst))))

(ACAD_STRLSORT lista)
Esta funcin devuelve una lista con sus elementos, que debern ser cadenas de texto, ordenados
alfabticamente. Por ejemplo:
(acad_strlsort lst) devolver (limones manzanas naranjas peras pltanos)

(APPEND lista1 [lista2] )


Esta funcin une dos o ms listas y devuelve la lista resultante. Si tenemos dos listas:
(setq lst1 (list peras naranjas manzanas))
(setq lst2 (list fresas limones))
y que queremos unirlas

(append lst1 lst2) devolver (peras naranjas manzanas fresas limones)

28-Aplicar funciones a los elementos de una lista


Supongamos que tenemos una lista de puntos:
(setq lstptos (list (list 0.0 0.0) (list 10.0 0.0) (list 10.0 10.0) (list 0.0 10.0)))
Es decir, lstptos es una lista con cuatro elementos correspondientes a los vrtices de un cuadrado
de lado 10. Supongamos que queremos dibujar un crculo en cada uno de los puntos de lstptos.
Hasta ahora podamos hacerlo as:
(setq i 0 nent (length lstptos))
(while (< i nent)
(setq pt (nth i lstptos))
(command _.circle pt 1.0)
(setq i (1+ i))
)
La variable i nos servir como ndice o contador en el bucle While, por eso le asignamos
inicialmente el valor inicial 0, porque los elementos de una lista se numeran empezando desde cero.
Es bastante habitual que los nombres de las variables utilizadas como contadores sean i j k
Tambin asignamos a nent el nmero de elementos de la lista lstptos, porque sino no sabremos
como salir del bucle ni hasta que elemento llegar.
El bucle se ejecutar mientras el contador sea menor que nent es decir, se ejecutar para cada
elemento de lstptos. La primera lnea de cdigo dentro del bucle (setq pt (nth i lstptos)) obtiene el
elemento nmero i de lstptos, que es un punto, y a continuacin dibuja una circunferencia en l de
radio 1.0. Finalmente aumentamos el contador para que pase al siguiente punto (setq i (1+ i)). Esta
ltima lnea es muy importante, si no estuviera la variable i sera siempre igual a cero y el bucle no
tendra fin. Por lo que dibujara infinitos crculos en el primer punto de lstptos y dara lugar a un
error.
Veamos otro mtodo para dibujar los crculos en los vrtices de lstptos:
(while lstptos
(setq pt (car lstptos))
(command _.circle pt 1.0)
(setq lstptos (cdr lstptos))
)

En este caso, el bucle se ejecutar mientras tengamos puntos en la lista es decir,


mientras lstptos sea distinto de nil. Se define pt como el primer punto de la lista lstptos, se dibuja
una circunferencia de radio 1.0 con centro en pt y por ltimo se mueve el contador. Pero, qu
contador? Si no existe! Pues, (setq lstptos (cdr lstptos)) eliminamos el primer elemento de la
lista lstptos. De modo que lstptosva perdiendo un elemento (punto) cada vez que se ejecuta el
bucle. Llega un momento en el que lstptos = ((0.0 10.0)) y al
evaluarse(setq lstptos (cdr lstptos)) se asignar a lstptos el valor devuelto por CDR, es decir nil.
Con lo cual deja de ejecutarse el bucle.
El inconveniente de este segundo mtodo es que se vara el valor asignado a la variable lstptos,
que finalmente valdr nil. Por lo que la lista de puntos inicial se perder.
Bien, pero AutoLISP es un excelente lenguaje de programacin para trabajar con listas. De modo
que tenemos algunos mtodos que son mejores, y eso es lo que vamos a ver en este artculo.

(FOREACH variable lista expresion)


Esta funcin permite aplicar una expresin para cada elemento de la lista que recibe como
argumento. La variable simboliza a un elemento de dicha lista, por lo que se suele utilizar en la
expresin. Por ejemplo:
(foreach p lstptos (command _.circle p 1.0))
La lnea de cdigo anterior representa el tercer mtodo para dibujar los crculos en los puntos
de lstptos. A la variable la llamamos p y la expresin a ejecutar para cada elemento de la lista
es: (command _.circle p 1.0) dnde p es un elemento de la lista.
En caso de tener una lista de cadenas de texto, podria hacerse lo siguiente:
(setq lsttxt (list Curso de AutoLISP))
(foreach p lsttxt (prompt p))
Con lo cual, escribira todos los textos en la ventana de comandos de AutoCAD. Se ha utilizado el
mismo nombre de variable p, pero podra haberse cambiado:
(foreach pepe lsttxt (princ pepe))
Supongamos ahora que tenemos una lista de nmeros:
(setq lst (list 5.0 -1.5 2.6 3.8 9.7))
Para sumar los nmeros podramos hacer lo siguiente:
(setq i 0 nent (length lst) total 0.0)
(while (< i nent)
(setq num (nth i lst))
(setq total (+ total num))
(setq i (1+ i))

)
Inicialmente definimos la variable total como 0.0, el bucle se ejecutar para cada elemento de lst y
se define num como el nmero que est en la posicin i. Sumamos a total ese nmero y movemos
el contador. Cuando se entra por primera vez en el bucle, num = 5.0 de modo que total = 0.0 + 5.0.
Al volver a entrar en el bucle num = -1.5 de modo que total = 5.0 + (-1.5) y as hasta que se llega al
ltimo elemento de lst.
Tambin podra hacerse sin emplear contadores, como hicimos antes. Y tambin podemos hacerlo
con FOREACH, veamos:
(foreach p lst (setq total (+ total p)))
Todo lo que antes ponamos en un bucle se pone ahora en una sola lnea de cdigo.

(APPLY nombre_funcin lista)


Aplica la funcin que recibe como argumento a todos los elementos de la lista. El nombre de la
funcin a utilizar en APPLY se indicar precedida por el smbolo para que AutoCAD interprete que
le estamos pasando ese texto tal cual. El ejemplo anterior sera:
(setq total (apply + lst))
En (apply + lst) estamos aplicando la funcin + a todos los elemento de lst, equivale a (+ 5.0 -1.5
2.6 3.8 9.7), y el resultado se lo asignamos a la variable total.
Digamos que + es el nombre que utilizamos en AutoLISP para hacer referencia a la funcin +, ya
que + es la funcin propiamente y no su nombre. Prueba lo siguiente en la ventana de comando de
AutoCAD:
(list pepe + 5.0) y fjate en lo que devuelve (pepe #<SUBR @0244f5a8 +> 5.0)
Y ahora prueba con el literal, es decir con el carcter delante del +
(list pepe + 5.0) devuelve (pepe + 5.0)
Entiendes ahora porque ponemos +? Para que no evale la funcin, ya que devolvera #<SUBR
@0244f5a8 y nos dara un error.
Veamos un par de ejemplos ms:
(apply max lst) devolver el mayor nmero de lst
(apply min lst) devolver el menor nmero de lst
Si tuviramos una lista cuyos elementos fueran textos:
(setq lsttxt (list Curso de AutoLISP))
para unir los textos:
(setq txt (apply strcat lsttxt))

De modo que txt = CursodeAutoLISP todo junto.

(MAPCAR nombre_funcin lista1 [lista2]


)
Esta funcin aplica la funcin de AutoLISP que recibe como argumento a los elementos de las
listas. Como as no se va a entender veamos algunos ejemplos:
Supongamos que tenemos dos puntos:
(setq pt1 (getpoint \nPunto 1: ))
(setq pt2 (getpoint pt1 \nPunto 2: ))
Los puntos son listas con 2 o 3 elementos, en funcin de si tienen 2 o 3 coordenadas.
Vamos a determinar el vector con origen en pt1 y final en pt2. Tenemos que calcular las
coordenadas X Y Z del vector, que son el resultado de restar las respectivas coordenadas X Y Z
de pt1 a las de pt2. Podemos obtener el vector as:
(setq vector
(list (- (car pt2) (car pt1))
(- (cadr pt2) (cadr pt1))
(- (caddr pt2) (caddr pt1))
)
)
Siendo:

la coordenada X (- (car pt2) (car pt1))


la coordenada Y (- (cadr pt2) (cadr pt1))

la coordenada Z (- (caddr pt2) (caddr pt1))

Bien, pues esto mismo lo podemos hacer con MAPCAR


(setq vector (mapcar - pt2 pt1))
La funcin que recibe mapcar es - y lo que hace es aplicarla a los elementos de pt2 y pt1, de modo
que resta sus coordenadas X, las Y y las Z.
APPLY devuelve un elemento y MAPCAR una lista.

Clculo del mdulo de un vector

Vamos a complicar un poco el tema. Si quisiramos obtener el mdulo de un


vector tendramos que calcular la raz cuadrada de la suma de sus coordenadas al cuadrado:
(mapcar * vector vector) devolver una lista con las coordenadas del vector al cuadrado,
ya que las estamos multiplicando por si mismas.
2.
Para sumarlas utilizamos APPLY (apply + (mapcar * vector vector))
1.

3.

Para terminar solo nos falta hacer la raz cuadrada de lo anterior

(setq modulo (sqrt (apply + (mapcar * vector vector))))

Clculo del producto escalar de dos


vectores
Veamos otro ejemplo en el que se combinan APPLY y MAPCAR. Sean v1 y v2 dos vectores vamos
a calcular su producto escalar.
(setq v1 (list 10.0 10.0 0.0))
(setq v2 (list 5.0 0.0 0.0))
El producto escalar de los vectores v1 y v2 es la suma de los productos de las coordenadas
de v1 por las de v2. Podramos hacerlo as:
(setq pescalar
(+
(* (car v1) (car v2))
(* (cadr v1) (cadr v2))
(* (cadr v1) (cadr v2))
)
)
Pero resulta ms sencillo utilizando MAPCAR y APPLY:
1.
2.

Primero multiplicamos las coordenadas de ambos vectores (mapcar * v1 v2)


y luego las sumamos, de modo que

(setq pescalar (apply + (mapcar * v1 v2)))

(LAMBDA (lista_argumentos /
variables_locales) expresin1
[expresin2] )
Tal vez el formato de la funcin LAMBDA recuerde algo a DEFUN.
LAMBDA tambin se utiliza para definir una funcin, pero a diferencia de DEFUN la funcin no se
almacena en ningn lugar, en este caso es temporal. Por tanto solo se puede ejecutar donde se
defina. Adems la funcin creada no tiene nombre, por lo que tampoco podramos llamarla desde
otra parte de nuestro cdigo.
Utilizarla sola sin APPLY o MAPCAR no tiene sentido.
Supongamos que queremos obtener el punto medio de dos puntos:
(setq pt1 (getpoint \nPunto 1: ))
(setq pt2 (getpoint pt1 \nPunto 2: ))
Las coordenadas del punto medio sern las coordenadas de pt1 ms las de pt2 divididas por 2.0.
Para sumar sus coordenadas: (mapcar + pt1 pt2)
Bien pero ahora, Cmo las dividimos por 2.0? Podemos hacer lo siguiente:
(mapcar / (mapcar + pt1 pt2) (list 2.0 2.0 2.0))
Donde creamos una lista (list 2.0 2.0 2.0) y dividimos los elementos de (mapcar + pt1 pt2) entre
los elementos de la lista anterior (2.0 2.0 2.0).
Recordemos (mapcar + pt1 pt2) devuelve la suma de las coordenadas de pt1 y pt2. Si
necesitamos dividirla por 2.0. podemos crear una funcin que reciba un nmero y lo divida por 2.0
devolviendo el resultado:
(defun 2/ ( num ) (/ num 2.0))
Y ahora pasar a MAPCAR la nueva funcin 2/ para que divida cada elemento de (mapcar + pt1
pt2) por 2.0
(mapcar 2/ (mapcar + pt1 pt2))
Pero tambin podemos hacerlo de otra forma, utilizando la funcin LAMBDA en lugar de DEFUN.
Primero veamos como sera nuestra funcin definida mediante LAMDA:
(lambda ( num ) (/ num 2.0))
Es muy parecido a lo que hicimos con DEFUN. Pero la funcin definida mediante LAMBDA no tiene
nombre y no se almacena en ningn sitio, es temporal, de modo que no podemos llamarla. Dnde

debemos utilizar LAMBDA? Pues directamente en MAPCAR, donde hay que indicar el nombre de la
funcin:
(mapcar (lambda ( num ) (/ num 2.0)) (mapcar + pt1 pt2))
Por tanto, cuando queremos aplicar APPLY o MAPCAR a una o varias listas y ejecutar una funcin
que no existe en AutoLISP, podemos crearla previamente con DEFUN o utilizar la
funcin LAMBDA para definirla in situ.

29- Literales y otras funciones de utilidad

(VER)
Esta funcin devuelve una cadena de texto con la versin de AutoLISP que se est ejecutando. Por
ejemplo: Visual LISP 2000 (es). Entre parntesis indica la versin idiomtica, en este caso
Espaol.

Pantalla de texto y pantalla grfica


En AutoCAD podemos pasar de pantalla grfica a la pantalla de texto, y al revs, pulsando la tecla
de funcin F2. En AutoLISP tambin existen algunas funciones para hacerlo directamente desde el
cdigo de nuestras rutinas.

(TEXTSCR)
Se utiliza para pasar a pantalla de texto y siempre devuelve nil. Se suele emplear cuando se quiere
mostrar mucha informacin en pantalla de texto.

(GRAPHSCR)
Pasa a pantalla grfica y tambin devuelve nil. Se utiliza para asegurarnos que el usuario est
viendo la pantalla grfica, por ejemplo para indicar un punto. Especialmente se utilizar si antes se
ha pasado a pantalla de texto.

(TEXTPAGE)
Esta funcin es anloga a TEXTSCR. Pasa a pantalla de texto y tambin devuelve nil.
Tal vez te ests preguntando Cuntas funciones nos quedan an? Pues entre otras cosas, la
siguiente funcin nos servir para ver las funciones de AutoLISP que hemos visto y las que nos
quedan.

(ATOMS-FAMILY formato
[lista_simbolos])
Esta funcin devuelve una lista con los smbolos que se han definido en el dibujo actual. Qu es un
smbolo? Pues un nombre de variable de AutoLISP, el nombre de una funcin de usuario que hemos
creado y tambin todos los nombres de las funciones propias de AutoLISP.
El argumento formato puede tener dos valores:

0 para que devuelva una lista con los nombres de los smbolos.
1 para que devuelva una lista, pero siendo sus elementos cadenas de texto.

Veamos ahora algn ejemplo. Al escribir la lnea siguiente sabrs cuantas funciones faltan:

(atoms-family 0) esto mostrar una lista con los nombres de todos los smbolos definidos
en el dibujo actual.
(atoms-family 1) as los elementos de la lista anterior sern cadenas de texto.

En las listas anteriores es difcil encontrar algo. Recuerdas la funcin acad_strlsort? Permita
organizar alfabticamente una lista de cadenas de texto.
(acad_strlsort (atoms-family 1)) devolver la lista anterior ordenada alfabticamente
Estn todas las funciones de AutoLISP, pero hay otras muchas funciones que aparecen en la lista y
no son funciones de AutoLISP. As que no te asustes, que no son tantas.
Recordemos el formato de esta funcin: (ATOMS-FAMILY formato [lista_simbolos]) y veamos que
es eso de la lista de smbolos
Para saber si unas funciones determinadas existen, es decir si estn definidas, creamos una lista
con sus nombres y se lo pasamos como argumento a atoms-family
(atoms-family 1 (list car cdr)) devolver una lista con sus nombres (CAR CDR)
Aunque lo habitual no es emplear esta funcin para detectar si estn definidas las funciones de
AutoLISP, sino para detectar nuestras propias funciones y variables:
(atoms-family 1 (list car cdr variable)) devuelve (CAR CDR nil) ya que el smbolo
variable no tiene asociado ninguna funcin, ni variable de AutoLISP.
Si definimos:
(setq variable 12.5)
(atoms-family 1 (list car cdr variable)) devolver (CAR CDR VARIABLE) devuelve el
nombre de la variable, no su valor.
Si definimos una funcin de usuario:
(defun 2+ ( numero / ) (+ numero 2.0))

La funcin 2+ recibe un nmero y le suma 2.0.


(atoms-family 1 (list car cdr 2+)) devolver (CAR CDR 2+)

(QUOTE expresin)
Esta funcin recibe una expresin y devuelve su literal, es decir devuelve la expresin tal cual, sin
evaluar.
(quote +) devolver +
Esto es lo mismo que hacamos en APPLY y MAPCAR:
(apply + (list 2.0 3.5 6.8))
pues el apstrofo es el diminutivo o el alias de la funcin QUOTE.
(quote (setq a texto b 10.0)) devolver (SETQ A texto B 10.0)
sera lo mismo escribir:
(setq a texto b 10.0)
Pero no podremos escribir esta ltima lnea en la ventana de comandos de AutoCAD, por que el
interprete de comandos no detecta el parntesis en primer lugar y piensa que no es una expresin
de AutoLISP sino un comando de AutoCAD. Podemos utilizar un truco para evaluar la expresin
desde la ventana de comandos:
(progn (setq a texto b 10.0))
PROGN en realidad no hace nada, simplemente nos serva para salvar la limitacin de IF de indicar
ms de 1 expresin, ya que evala las expresiones que contiene y devuelve el resultado de la ltima
expresin evaluada. En este caso nos sirve para contener la expresin de AutoLISP anterior.
Ahora si devolver (setq A pepe B 10.0). Pero no hemos asignado valores a las variables, ya
que (setq A pepe B 10.0) no se ha evaluado.Puedes hacer la prueba escribiendo !a o !b en la
ventana de comandos de AutoCAD.
(quote (15.0 10.6 9.2)) devolver (15.0 10.6 9.2) es decir, devuelve una lista. Tambin funcionara
con (15.0 10.6 9.2)
Por tanto en lugar de:
(apply + (list 2.0 3.5 6.8))
podemos poner:
(apply + (quote (2.0 3.5 6.8)))
y tambin:
(apply + (2.0 3.5 6.8))

De modo que podemos usar QUOTE y para crear listas. Pero con excepciones, ya que si
hacemos:
(setq a 2.0)
(apply + (a 3.5 6.8)) indicar: ; error: tipo de argumento errneo: numberp: A
a es el nombre de una variable, es un smbolo, cuya variable tiene asociado el valor 2.0
(apply + (list a 3.5 6.8)) esto si funcionar porque (list a 3.5 6.8) devolver (2.0 3.5 6.8), LIST se
evala pero QUOTE no evala la expresin que recibe.
Resumiendo: Podemos crear listas con QUOTE o con pero siempre que conozcamos los
elementos de dichas listas, y que estos sean valores concretos no determinados a partir de
expresiones o almacenados en variables.
Algunos ejemplos ms:
(setq maximo (apply (quote max) (quote (10.5 15.2 9.3))))
(setq minimo (apply min (10.5 15.2 9.3)))
(foreach p ((0.0 0.0 0.0) (10.0 10.0 0.0)) (command _.circle p 1.0))
(setq vector (mapcar - (10.0 10.0 0.0) (5.0 0.0 0.0)))
(setq ptomed (mapcar (lambda ( num ) (/ num 2.0)) (mapcar + (10.0 10.0 0.0) (5.0 0.0 0.0))))

(EVAL expresin)
Esta funcin evala la expresin que recibe.
(eval 2.5) devuelve el resultado de evaluar 2.5, es decir devuelve 2.5
(eval Soy una cadena de texto) devolver Soy una cadena de texto
Pero veamos un ejemplo algo ms complicado:
(setq a 15.5)
(setq b (quote a))
Qu valor tendr asignado b?

(quote a) es el nombre de la variable a, es decir el smbolo.


As que b tendr asociado el nombre de la variable a.

(+ b 10.0) dar un error


(eval b) devolver 15.5 de modo que podemos hacer lo siguiente:
(+ (eval b) 10.0) devolver 25.5
(eval (+ 10.0 5.5)) devolver 15.5 ya que (+ 10.0 5.5) devuelve (+ 10.0 5.5) y eval, lo evala.

(READ texto)
Esta funcin lee el texto que recibe y devuelve la primera palabra pero como un literal, un smbolo,
no como una cadena de texto.
(read AutoLISP) devuelve AUTOLISP
(read Curso de AutoLISP) devolver CURSO
(read (15.2 9.3 15.5)) en este caso devolver (15.2 9.3 15.5) porque al detectar el parntesis lo
considera un mismo trmino. Es algo similar a escribir en la ventana de comandos de AutoCAD, si
no se pone un parntesis delante no dejar escribir espacios en blanco. Pues este es otro mtodo
para crear una lista, por tanto:
(apply max (read (15.2 9.3 15.5))) devolver el mximo de la lista de nmeros indicados
Y que pasa si hacemos:
(setq txt (setq a 5.5))
(read txt) devolver (setq a 5.5)
y ahora podemos evaluarlo con EVAL
(eval (read txt)) devolver 5.5 y asigna a la variable a el valor 5.5
Para qu sirve esto? Por ejemplo para solicitar al usuario una expresin de AutoLISP y evaluarla:
(setq txt (getstring T \nExpresin de AutoLISP: ))
(setq valor (eval (read txt)))
En este caso asignamos a valor el resultado de evaluar una expresin de AutoLISP introducida por
el usuario.

(SET literal_de_smbolo expresin)


Esta funcin es muy parecida a SETQ, se diferencia en que espera el literal de un smbolo. Veamos
algunos ejemplos:
(setq num1 5.0) asigna a la variable num1 el valor 5.0
(set num2 5.5) da un error, ya que espera un literal
(set num2 5.5) asigna a la variable num2 el valor 5.5
Si probamos:
(setq (read num1) 5.0) nos da un error, ya que SETQ no acepta una expresin como smbolo.
Sin embargo SET si lo acepta:
(set (read num2) 15.0) asigna a la variable num2 el valor 15.0

30- Carga automtica de los archivos de AutoLISP


AutoCAD carga automticamente dos archivos de AutoLISP, si es que existen y se encuentran en
los directorios de soporte. Se trata delACAD.LSP y el ACADDOC.LSP.
El archivo ACAD.LSP se carga al iniciar AutoCAD y el ACADDOC.LSP se carga siempre que se
abre un dibujo, o se crea un dibujo nuevo. De modo que las funciones contenidas en el
ACAD.LSP tan slo estarn cargadas en el dibujo que se abre al iniciar AutoCAD, mientras
que las funciones contenidas en el ACADDOC.LSP estarn cargadas en todos los dibujos.
Lo lgico ser entonces guardar nuestras funciones en el ACADDOC.LSP y no en el ACAD.LSP.
El ACAD.LSP se utilizar tan solo para almacenar aquellas funciones que nos interese ejecutar al
cargar AutoCAD. Por ejemplo, podemos utilizar el archivo ACAD.LSP para mostrar una imagen, foto,
al iniciar AutoCAD.
Si tenemos alguna rutina que se utilice mucho, o que se suele ejecutar en todos los dibujos la
meteremos en el ACADDOC.LSP
Qu rutinas meteremos en el ACADDOC.LSP? Conviene que no sean demasiadas, para que dicho
archivo sea ms manejable y adems para no ocupar demasiado espacio en la memoria del
ordenador. Por tanto, solo incluiremos en el ACADDOC.LSP las rutinas ms empleadas. Por
ejemplo una funcin de tratamiento de errores, o las funciones GAR y RAG que se utilizan bastante,
y adems son bastante pequeas.
Qu pasa si metemos tambin nuestra funcin C:CIRCPERI? Pues no pasara nada pero Vas a
dibujar circunferencias dadas por su permetro en todos los dibujos? no creo, por eso no merece la
pena aadirla al ACADDOC.LSP, ya que si hacemos lo mismo con todas nuestras rutinas el archivo
ACADDOC.LSP tendra un tamao descomunal.
Podemos guardar la rutina CIRCPERI en un archivo independiente y cargarlo desde el
ACADDOC.LSP. En el caso de la rutina CIRCPER, podemos guardarla en el
archivo CIRCPERI.LSP, dentro de uno de los directorios de soporte de AutoCAD, e incluir la
siguiente lnea en el ACADDOC.LSP:
(load circperi.lsp (alert Archivo Circperi.lsp no encontrado))
De este modo tenemos la rutina CIRCPERI en un archivo independiente, lo que nos soluciona parte
del problema, ya que el archivo ACADDOC.LSP ser bastante corto y si queremos modificar la
rutina CIRCPERI tan solo tenemos que manipular un archivo en el que nicamente est definida
dicha funcin.
Pero seguimos teniendo algunos problemas: Si nuestra coleccin de rutinas es muy extensa
tenemos que aadir una lnea de cdigo como la anterior para cada rutina, lo que se traducir en un
archivo ACADDOC.LSP bastante grande y difcil de manipular. Adems, el mayor inconveniente es
que todas nuestras rutinas se cargaran en memoria automticamente para cada archivo de dibujo,
con lo que estaremos sobrecargando la memoria del ordenador de forma innecesaria.

(AUTOLOAD archivo lista_comandos)


La funcin AUTOLOAD es similar a LOAD, tambin nos permite cargar archivos de AutoLISP pero
slo aquellos archivos que contengan comandos, por ejemplo C:CIRCPERI pero no servir para
archivos en los que solo tengamos funciones como GAR y RAG.
Qu ventaja tiene el utilizar AUTOLOAD en lugar de LOAD? Al utilizar AUTOLOAD los archivos no
se cargan automticamente, simplemente se predispone a AutoCAD para que los cargue en cuanto
se ejecute uno de los comandos indicados como argumentos en la lista de comandos.
Por ejemplo, si tenemos un archivo con 3 comandos:
(defun C:comando1 ( / ) .)
(defun C:comando2 ( / ) .)
(defun nosoyuncomando ( / ) .)
(defun C:comando3 ( / ) .)
En el archivo ACADDOC.LSP podramos aadir la siguiente lnea:
(autoload archivo.lsp (comando1 comando2))
Al iniciar un dibujo, se carga el ACADDOC.LSP y se evala la lnea anterior, pero archivo.lsp no se
cargar hasta que se ejecute elcomando1 o el comando2. Sin embargo no se cargar si
ejecutamos el comando3, ya que no lo hemos incluido en la lista de comandos. Adems, al ejecutar
uno de los dos comandos anteriores se carga el archivo, de modo que la
funcin nosoyuncomandotambin se cargar, al igual que el comando3.
Y qu pasa con los archivos de AutoLISP que no tienen comandos, es decir en los que solo hay
funciones? Pues tendremos que cargarlos con LOAD, con lo cual se cargaran todos directamente
en la memoria y si tenemos bastantes funciones seguimos teniendo el mismo problema que antes.
Cmo podemos solucionarlo? Pues cargando las funciones solo cuando hacen falta. Por ejemplo,
supongamos que en el comandoC:CIRPERI se utiliza la funcin RAG. Tenemos dos opciones:
Incluir la funcin RAG en el archivo Circperi.lsp. De este modo al cargarse el archivo se
cargar la funcin RAG. Esto se suele hacer para las funciones que slo se utilizan en un
comando determinado.
2.
Pero si la funcin RAG deseamos utilizarla en otros comandos, es mejor utilizar el siguiente
mtodo: Incluir la funcin RAG en un archivo independiente Rag.lsp y aadir la siguiente lnea
de cdigo dentro del archivo Circperi.lsp: (load Rag.lsp (alertArchivo Rag.lsp no
encontrado))
1.

En el segundo modo, el archivo Circperi.lsp se cargar cuando se ejecute uno de los comandos
indicados en la funcin Autoload del archivo ACADDOC.LSP. Y al cargarse el archivo Circperi.lsp
se cargar mediante la funcin Load el archivo Rag.lsp. Utilizando este mtodo podemos utilizar
una misma funcin en mltiples rutinas, tan solo debemos asegurarnos de que dicha funcin est
definida, es decir que se ha cargado el archivo en el que se encuentre.

Los archivos ACAD.LSP y ACADDOC.LSP no tienen porque existir. Si no existen pueden crearse,
teniendo en cuenta que se deben guardar en uno de los directorios de soporte de AutoCAD. En
caso de que ya existan, se pueden editar para incluir el cdigo deseado. Conviene hacer una copia
de seguridad de estos archivos porque muchos programadores crean sus propios archivos
ACAD.LSP y ACADDOC.LSP de modo que al instalar un mdulo o aplicacin para
AutoCAD, podis sobreescribir vuestros archivos.
Existen otros dos mtodos para cargar automticamente rutinas de AutoLISP. El primero consiste en
utilizar la opcin disponible en el men de AutoCAD Herr > AutoLISP > Cargar ya que en el
letrero de dialogo que aparece se pueden cargar rutinas y se pueden seleccionar las rutinas que se
desean cargan al inicio.
El tercer mtodo para cargar automticamente las rutinas de AutoLISP es editando los mens de
AutoCAD, pero esto lo veremos ms adelante.

Ejecucin automtica de cdigo de


AutoLISP
Hemos visto que el archivo ACADDOC.LSP se carga automticamente en todos los dibujos pero
Cmo podemos ejecutar automticamente una funcin al iniciarse un dibujo?
Supongamos que tenemos definida la funcin GAR dentro del archivo ACADDOC.LSP:
(defun GAR )
Para ejecutarla, tan slo debemos aadir en dicho archivo la siguiente lnea de cdigo:
(GAR)
En caso de que dicha funcin tenga argumentos, estos deben indicarse:
(GAR 3.141592)
Cmo ejecutaramos automticamente el comando C:CIRCPERI?
Una vez cargado el comando, para ejecutarlo desde la ventana de comandos de AutoCAD podemos
escribir directamente su nombre CIRCPERI para ejecutarlo. Sin embargo, desde un archivo de
AutoLISP no podemos ejecutarlo as. Tenemos que hacerlo de esta otra forma:
(C:CIRCPERI)
De modo que podramos incluir en el archivo ACADDOC.LSP las dos siguientes lneas de cdigo:
(load circperi.lsp (alert Archivo Circperi.lsp no encontrado)) ; Carga el comando
(C:CIRCPERI) ; Ejecuta el comando
Sera mejor utilizar AUTOLOAD en lugar que LOAD en el ejemplo anterior? Pues no.
Utilizar AUTOLOAD no tendra mucho sentido, puesto que al ejecutar el comando el archivo en el
que est definido se cargara, por tanto podemos cargarlo ya antes.

Existe otro mtodo para ejecutar cdigo directamente. Se trata de escribirlo directamente, es decir
sin meterlo dentro de ninguna funcin o comando. Por ejemplo, si incluimos las siguientes lneas de
cdigo en el archivo ACADDOC.LSP nos permitir dibujar un circulo dado su centro y su permetro:
(setq pto (getpoint \nCentro del crculo: ))
(setq peri (getdist pto \nPermetro: ))
(command _.circle pto (/ peri (* 2.0 PI)))
Pero en este caso, el cdigo anterior solo se ejecuta una vez. Si queremos dibujar otro crculo dado
su permetro, no tendramos la funcin CIRCPERI definida.
Para qu se suele utilizar este mtodo?
Por ejemplo, para mostrar mensajes informativos o de bienvenida:
(alert Estas seguro de que quieres utilizar AutoCAD?)
(alert Estas realmente seguro?)
(alert Seguro, seguro?)
Aunque no os aconsejo que utilicis este ejemplo, os cansarais de l a los 5 minutos.
Adems de mensajes de bienvenida podis hacer otras cosas ms tiles, como asignar valores
iniciales a algunas variables:
(setq directorio c:\\rutinas\\)
Tambin podis modificar el valor de alguna variable de sistema de AutoCAD:
(setvar osmode 7)

S::STARTUP
Existe otro mtodo para ejecutar cdigo automticamente. Hemos visto que AutoCAD utiliza una
funcin de tratamiento de errores por defecto que se llamaba *error* y tambin hemos visto
que podamos redefinirla creando nuestra propia funcin de tratamiento de errores. Bien, pues
AutoCAD tambin tiene una funcin interna que se ejecuta automticamente se trata
de S::STARTUP.
El que las funciones *error* y S::STARTUP tengan estos nombres tan raros es para evitar que a
alguien se le ocurra denominar as a alguna funcin de otro tipo.
Para definir la funcin S::STARTUP se utiliza DEFUN, al igual que para cualquier otra funcin.
(defun S::STARTUP ( / )
(setq directorio c:\\rutinas\\)
)
La funcin S::STARTUP podemos utilizarla para los mismos ejemplos que se daban antes.

Por ltimo, para terminar el tema, un consejo: Al programar hay que tener bastante cuidado para no
cometer errores, ya que el omitir un simple parntesis o unas comillas, por ejemplo, modificaran
totalmente nuestras funciones. Cuando adems estas funciones se van a ejecutar automticamente,
como en los ejemplos que se han expuesto, la precaucin al programar debe ser mxima.

31- Operaciones con archivos


Antes de comenzar con el tema de lectura y escritura de archivos, veamos una pequea
rutina: CARGALISP
CARGALISP recibir una lista como la siguiente: ((c:\\rutinas\\lisp1.lsp (gar rag))
(c:\\rutinas\\lisp2.lsp (inverso tg)))
En la que cada elemento es a su vez otra lista formada por el nombre de un archivo de AutoLISP
(con su ruta, si es necesario) y una lista con los nombres de las funciones (o variables globales)
definidas en dicho archivo. Por ejemplo, en el caso anterior se supone que en el archivo
c:\\rutinas\\lisp1.lsp estn definidas las funciones gar y rag y que en el archivo
c:\\rutinas\\lisp2.lsp estn definidas las funciones inverso y tg.
CARGALISP cargar los archivos de AutoLISP indicados si no estaban definidas, o cargadas que
es lo mismo, las funciones indicadas para cada archivo.
(defun CARGALISP ( lst / )
(while lst
(if (not (apply and (atoms-family 1 (cdar lst))))
(progn
(load (caar lst))
(prompt (strcat \nCargando archivo (caar lst) ))
)
)
(setq lst (cdr lst))
)
)
Tal como est la macro funciona perfectamente. Pero puede producirse un pequeo error. Qu
pasa si no existe, o no se encuentra, el archivo lisp1.lsp o cualquiera de los archivos de la lista que
reciba CARGALISP?

(FINDFILE archivo)

Esta funcin nos permite comprobar la existencia de un archivo. Si el archivo existe devuelve su
nombre y si no existe, o no lo encuentra en la ruta indicada, devolver nil.
En caso de que no se indique la ruta en la que debe buscar el archivo, lo buscar en los directorios
de soporte de AutoCAD.
(findfile c:\\autoexec.bat) debera devolver c:\\autoexec.bat, suponiendo que vuestro PC tiene
Autoexec.bat, claro
(findfile c:\\noexisto.bat) debera devolver nil
FINDFILE en realidad no hace nada, tan solo se utiliza para comprobar la existencia de un archivo.
Entonces, Cuando se utilizar FINDFILE? Pues os voy a poner varios ejemplos en los que se
suele utilizar:
1.
2.

Antes de cargar un archivo con LOAD o AUTOLOAD


Antes de abrir un fichero de texto, ya sea para leerlo o escribir en l.

3.

Antes de abrir un archivo de dibujo en AutoCAD.

4.

Antes de cargar y utilizar un archivo DCL (Letrero de dialogo) en AutoLISP.

Por tanto, deberamos modificar el cdigo de la funcin CARGALISP para comprobar la existencia
de los archivos a cargar.
(defun CARGALISP ( lst / )
(while lst
(if (not (apply and (atoms-family 1 (cdar lst))))
;; Comprueba si todas las funciones del primer elemento de la lista
;; estn cargadas
(if (not (findfile (caar lst)))
(alert (strcat No se ha encontrado el archivo (caar lst)))
;; No se encuentra el archivo
(progn
(load (caar lst))
;; Carga el archivo
(prompt (strcat \nCargando archivo (caar lst) ))
;; Indica que se ha cargado el archivo
)
;; Se encuentra el archivo
)

)
(setq lst (cdr lst))
;; Pasa al siguiente elemento de la lista
)
;; Para cada elemento de la lista
)

(GETFILED titulo_letrero
archivo_defecto extensin_defecto
modo)
Esta funcin nos permitir seleccionar un archivo, ya veremos ms adelante como seleccionar
varios archivos. GETFILED muestra un letrero de gestin de archivos tpico de Windows.
Podemos pasar a GETFILED el ttulo del letrero, el archivo seleccionado por defecto y la extensin
de archivos que se buscar por defecto. GETFILED devuelve el nombre y ruta del archivo
seleccionado.
El argumento modo es de tipo binario y ofrece los siguientes valores:

1 > Para designar un archivo nuevo, es decir, que no exista.


2 > Desactiva la casilla Teclearlo.

4 > Permite indicar cualquier extensin.

8 > Devuelve el nombre del archivo, sin la ruta

(getfiled Selecciona un archivo c:\\autoexec.bat bat 0)


No pasa nada al pulsar en Abrir, ya que no se abre el archivo. GETFILED tan solo nos deja
seleccionarlo y devuelve su nombre.
(getfiled Selecciona un archivo nuevo 1)

32- Leer y escribir archivos de texto


AutoLISP nos permite leer y escribir archivos de texto ASCII. Al utilizar archivos de texto en nuestras
rutinas debemos siempre seguir los siguientes pasos:
1.
2.

Comprobar si existe el archivo.


Abrir el archivo.

3.

Leer o escribir en el archivo.

4.

Cerrar el archivo.

(OPEN archivo modo)


Esta funcin nos permite abrir un archivo de texto y devuelve un descriptor de archivo.
Qu es un descriptor de archivo? Es algo similar a un canal por el que se comunica AutoCAD con
dicho archivo. Podemos abrir varios archivos, es decir abrir varios canales de comunicacin, de
modo que al leer o escribir en un archivo, tenemos que saber cual es el canal de comunicacin por
el que vamos a recibir o enviar datos, es decir necesitamos conocer el descriptor del archivo.
Hay tres formas de abrir un archivo de texto, en funcin de lo que se quiera hacer a continuacin
con dicho archivo. El argumento modo es el encargado de diferenciar estas tres formas distintas de
abrir archivos:

Podemos abrir un archivo para leerlo > modo r


Podemos abrir un archivo de texto para escribir en l comenzando desde la primera lnea
> modo w
Podemos abrir un archivo de texto para escribir en l a partir de la ltima lnea > modo a

Para abrir el archivo autoexec.bat en modo lectura:


(open c:\\autoexec.bat r)
Devuelve #<file c:\\autoexec.bat> es decir, el descriptor del archivo o nil si el archivo no existe.
Aunque en la lnea anterior se abre el archivo autoexec.bat en modo lectura, luego
no podramos hacer nada con l ya que no hemos guardado el descriptor de archivo. Es decir, no
podemos decirle a AutoCAD que lea texto por el canal de comunicacin que hemos abierto, ya que
no conocemos el descriptor del archivo. Incluso tampoco podramos cerrarlo y quedar abierto en la
memoria hasta que se cierre la sesin de AutoACD. Cmo se debe utilizar entonces la funcin
OPEN?
(setq darch (open c:\\autoexec.bat r))
De este modo el valor devuelto por OPEN, el descriptor de archivo, se almacena en la
variable darch.
Antes de ver como leer o escribir en los archivos de texto, veamos como tendriamos que cerrarlos.

(CLOSE descriptor_archivo)
Cierra el archivo cuyo descriptor se indica y devuelve nil. Fjate en lo importante que es guardar el
descriptor del archivo en una variable, ya que si no lo hacemos no slo no podremos leer o escribir
en el archivo, tampoco podremos cerrarlo.

(close darch)
Hay que tener una cosa en cuenta al trabajar con archivos de texto: Al abrir un archivo de texto
debemos indicar el modo (lectura, escritura, o adiccin) de modo que debemos saber de
antemano lo que vamos a hacer con el archivo, y SLO podremos hacer una cosa, o leer o escribir.
Aunque podemos abrir un archivo en modo escritura, escribir en l, cerrarlo, abrirlo en modo lectura,
leer y volver a cerrarlo.
Otra cuestin de especial inters es que si abrimos un archivo de texto existente en modo escritura
w, nos habremos cargado todo lo que tena anteriormente dicho archivo. As que mucho cuidado
con los archivos que se abren en modo escritura.

Escritura de archivos de texto


Para crear un archivo de texto debemos abrirlo en modo escritura:
(setq darch (open c:\\nuevo.txt w))
Devuelve #<file c:\\nuevo.txt> el descriptor del archivo abierto, que se almacena en la
variable darch.
Tambin podemos abrir el archivo en modo aditivo, para continuar escribiendo a partir de la ltima
lnea de texto del archivo.
Bien, ya tenemos abierto nuestro archivo de texto, vamos a escribir en l:

(PRIN1 [expresin [descriptor_archivo]])


Esta funcin escribe una expresin en el archivo cuyo descriptor se indique. Si no se indica el
descriptor de archivo, la expresin se escribir en la ventana de comandos de AutoCAD. Veamos
algunos ejemplos:
(setq a 5.5 b Curso de AutoLISP)
(prin1 a) escribir el valor de la expresin a en la ventana de comandos de AutoCAD, es decir,
escribir 5.5
Si ejecutas las dos lneas de cdigo anteriores desde la ventana de comandos de AutoCAD, veras
que (prin1 a) parece devolver 5.55.5en realidad devuelve 5.5 pero el eco de mensajes, repite el
valor devuelto por la expresin (prin1 a) es decir 5.5 Por eso, aparece5.55.5
(prin1 b darch)
Escribir en Curso de AutoLISP con las comillas incluidas en el archivo C:\Nuevo.txt.
Fjate que PRIN1 puede escribir tanto cadenas de texto como nmeros. Sin embargo la
funcin PROMPT tan slo puede recibir como argumento una cadena de texto.
(prin1 a) escribe A
(prin1 (+ 15 5.5)) escribe 20.5

Hemos indicado una expresin como argumento, si utilizamos PROMPT en lugar de PRIN1 dar un
error.
(prin1 (+ 15 5.5)) escribe (+ 15 5.5)
Si no se indica la expresin a escribir, escribe una cadena nula
(prin1)
Por eso se suele emplear como ltima expresin de los comandos, para que la salida de nuestras
rutinas sea limpia y no se vea el eco de mensajes de la ltima expresin evaluada.
(prin1 (strcat \t b)) devuelve \tCurso de AutoLISP
PRIN1 no entiende los caracteres de control como \n \t etc.

(PRINT [expresin [descriptor_archivo]])


Esta funcin es muy parecida a PRIN1, veamos en que se diferencian.
(progn (prin1 a) (prin1 a)) escribe 5.55.5
(progn (print a) (print a)) escribe 5.5 pasa a otra lnea y escribe 5.5
Es decir, PRINT salta de lnea antes de escribir la expresin indicada. PRINT escribe la expresin
en una lnea nueva.
(print) devuelve una cadena nula, por eso tambin se emplea como ltima expresin de los
comandos
(print (strcat \t b)) devuelve \tCurso de AutoLISP, es decir PRINT tampoco entiende los
caracteres de control.
Por supuesto, al igual que sucede con PRIN1 si se indica un descriptor de archivo en lugar de
escribir en la ventana de comandos de AutoCAD lo har en un archivo.

(PRINC [expresin [descriptor_archivo]])


Esta funcin tambin es muy parecida a las anteriores.
(progn (princ a) (princ a)) escribe 5.55.5
(princ) devuelve una cadena nula, por eso tambin se emplea como ltima expresin de los
comandos.
(princ (strcat \t b)) ahora escribe Curso de AutoLISP pero tabulado.
Por tanto, PRINC se diferencia de las anteriores en que si interpreta el significado de los
caracteres de control.
Al igual que las funciones anteriores, si se indica un descriptor de archivo escribir en dicho
archivo en lugar de hacerlo en la ventana de comandos de AutoCAD.
(princ \nBienvenido al curso darch)

(WRITE-CHAR cdigo_ASCII [descriptor_archivo])


Esta funcin permite escribir un carcter recibe como argumento su cdigo ASCII. Si se indica el
descriptor de archivo lo escribir en el archivo y sino lo escribir en la ventana de comandos de
AutoCAD.
(write-char 65) escribe A.
Es lo mismo que escribir (write-char (ascii A))

(WRITE-LINE texto [descriptor_archivo])


Esta funcin escribe una lnea de texto entera. El primer argumento debe ser una cadena de texto,
no una expresin. Y si se indica un descriptor de archivo, escribir la lnea de texto en el archivo, en
caso contrario la escribe en la ventana de comandos de AutoCAD.
(write-line Curso de AutoLISP)
Tambin se puede escribir en un archivo indicando el descriptor correspondiente
(write-line Muchas gracias darch)
Ahora podemos cerrar el archivo de texto que hemos abierto
(close darch)

Lectura de archivos de texto


Para leer un archivo de texto debemos abrirlo en modo lectura y guardar su descriptor en una
variable que podamos utilizar despus:
(setq darch (open c:\\nuevo r))

(READ-CHAR [descriptor_archivo])
Lee un carcter del archivo cuyo descriptor se indica y devuelve su cdigo ASCII.
(read-char darch) devuelve 34, que es el cdigo ASCII del primer caracter del archivo de texto, que
es unas comillas
Si no se indica el descriptor, lo lee de la ventana de comandos de AutoCAD.
(read-char) espera a que introduzcas un caracter y devolver su cdigo ASCII

(READ-LINE [descriptor_archivo])
Esta funcin lee una lnea del archivo de texto indicado.
(read-line darch) devolver Curso de AutoLISP\

Observa que las comillas iniciales del archivo ya las habamos ledo con la funcin anterior readchar.
Al leer un archivo de texto vamos avanzando en l, de modo que si volvemos a escribir la linea
anterior
(read-line darch) devolver Bienvenido al curso Muchas gracias
Esta es la ltima lnea de nuestro archivo as que si volvemos a repetir la lnea anterior
(read-line darch) devolver nil
De este modo sabremos que hemos llegado al final del archivo y podremos cerrarlo
(close darch)
Si intentamos volver a leer ahora en el archivo obtendremos un error.
Si no se indica el descriptor de archivo, la leer de la ventana de comandos de AutoCAD.
(read-line) escribe una palabra o frase y devolver una cadena de texto con lo que has escrito.

Seleccin de entidades
This entry was posted in Programacin en AutoCAD and tagged AutoCADAutoLISPCADProgramacinProgramacin en AutoCADVisual
LISP onNovember 27, 2012 by emagdalena.

Programacin en AutoCAD: La base de


datos de AutoCAD
Tabla de contenidos de Programacin en AutoCAD: La base
de datos de AutoCAD
1.
2.

Seleccin de entidades
Conjuntos de seleccin de entidades

3.

Opciones avanzadas en la creacin de conjuntos de seleccin

4.

La base de datos de AutoCAD

5.

Las listas de asociaciones de las entidades de AutoCAD

6.

Las listas de filtros de la funcin SSGET

7.

Modificar entidades a partir de la base de datos de AutoCAD

8.

Crear nuevas entidades a partir de su lista de asociaciones

9.

Las listas de asociaciones de las entidades polilnea

10.

Las listas de asociaciones de los bloques

1- Seleccin de entidades
Sin duda una de las mejores caractersticas de la programacin en AutoLISP es la posibilidad de
acceder a las entidades grficas de AutoCAD y de este modo poder modificarlas u obtener
informacin directamente de ellas, sin necesidad de solicitar datos al usuario.
En este curso accederemos, crearemos y modificaremos los datos de las entidades de AutoCAD,
pero antes tenemos que ver los mtodos existentes para seleccionar entidades y obtener sus
nombres, que son asignados automticamente por AutoCAD.

Seleccionar una entidad por


designacin
(ENTSEL [mensaje])
Al ejecutar esta funcin se solicita la designacin de una entidad, que debe seleccionarse de
forma directa por designacin en un punto, tras lo cual devuelve una lista compuesta por el
nombre que internamente AutoCAD ha asignado a la entidad y el punto de designacin.
(entsel) devuelve (<Nombre de entidad: 40063d70> (171.401 73.5344 0.0))
En caso de que no se designe una entidad, sino que se indique un punto en una zona vaca de la
ventana grfica, la funcin ENTSELdevuelve nil.
Normalmente lo que interesa es obtener el nombre de la entidad designada y no el punto de
designacin, de modo que podemos hacer lo siguiente:
(car (entsel)) devuelve <Nombre de entidad: 40063d70>
Lgicamente para utilizar esta entidad en nuestros programas, es muy probable que queramos
asignar el valor anterior a una variable:
(setq ent1 (car (entsel)))

Esta funcin slo admite como argumento una cadena de texto que servir al usuario a modo de
informacin para hacer la seleccin.
(setq ent1 (car (entsel Designe una entidad de la capa a borrar)))
Veamos un pequeo ejemplo:
1.
2.

En un archivo de dibujo en blanco creamos una circunferencia.


Ejecutamos (setq ent1 (car (entsel))) y seleccionamos la circunferencia anterior. De
modo que la variable ent1 contiene el nombre de la entidad crculo.

3.

Ejecutamos el comando DESPLAZA y cuando solicite la designacin de entidades,


escribimos !ent1

4.

Veremos que la entidad Crculo se ha seleccionado y estar lista para desplazarse.

Redibujar entidades
(REDRAW [entidad [modo]])
Si se ejecuta esta funcin sin argumentos, realiza un redibujado del archivo de dibujo actual.
(redraw)
Para comprobar su funcionamiento, se puede activar la variable de AutoCAD BLIPMODE,
indicar una serie de puntos en pantalla de modo que se observen las marcas auxiliares y a
continuacin ejecutar la funcin (redraw) que redibujar la pantalla desapareciendo las marcas
auxiliares.
Si se indica un nombre de entidad como argumento, tan solo se redibujar esa entidad y no la
ventana grfica actual tal como sucede en el ejemplo anterior.
(setq ent (car (entsel)))
(redraw ent)
Adems, existe otro argumento opcional mediante el cual se indica a la funcin el modo en el
que se desea que se redibuje la entidad. Dicho argumento puede tener los siguientes valores:

1 Redibuja la entidad en la ventana grfica.


2 Oculta la entidad.

3 Redibuja la entidad resaltada o en relieve.

4 Elimina la visualizacin en relieve de la entidad.

Veamos un pequeo ejemplo:


(setq ent (car (entsel)))
(redraw ent 2)
(redraw ent 1)
(redraw ent 3)

(redraw ent 4)
Los efectos de los redibujados de las entidades se pueden eliminar regenerando el dibujo con el
comando REGEN de AutoCAD.
Si la entidad es compuesta (bloque con atributos o polilnea) la funcin REDRAW afectar tanto
a la entidad principal como a sus componentes. Si se indica el modo con un signo negativo, la
funcin REDRAW afectar nicamente a la entidad principal, y no a sus componentes simples.

Recorrer las entidades del dibujo


actual
(ENTLAST)
Devuelve el nombre de la ltima entidad creada, y no eliminada, en el dibujo actual.
Sigamos con el ejemplo anterior:
1.

Al ejecutar (setq ent1 (entlast)) en el dibujo anterior, devuelve lgicamente el nombre de


la entidad crculo ya que no slo es la ltima entidad dibujada sino que adems es la primera
y la nica. Se puede comprobar fcilmente desplazando ent1
2.
Dibujemos ahora una lnea.
3.
4.
5.

Al ejecutar nuevamente (setq ent1 (entlast)) se asignar a la variable ent1 el nombre de


la entidad lnea que acaba de crearse.
Borremos ahora la entidad lnea.
Probemos nuevamente (setq ent1 (entlast)) para comprobar que devuelve el nombre de
la entidad crculo, ya que la lnea se ha borrado.

(ENTNEXT [entidad])
Esta funcin devuelve la primera entidad creada, y no eliminada, en el dibujo actual.
Para ver correctamente su funcionamiento, seguiremos con el ejemplo de antes:
1.

Si se ejecuta directamente (setq ent1 (entnext)) se obtendr el nombre de la entidad


crculo, ya que adems de ser la primera es la nica entidad en el dibujo. Para comprobarlo
se puede desplazar la entidad ent1
2.
Crearemos ahora una lnea y un arco, por ese orden. Podemos comprobar que (setq ent1
(entnext)) devuelve otra vez la entidad crculo inicial.
3.
4.

Borramos la entidad Crculo.


Lgicamente ahora al ejecutar (setq ent1 (entnext)) devolver el nombre de la entidad
lnea.

El argumento que admite esta funcin es un nombre de una entidad de dibujo de AutoCAD. En
caso de que se indique un nombre de entidad vlido, la funcin devolver la entidad creada a
continuacin de la indicada.

1.

En el dibujo anterior tenamos dos entidades: Una lnea y un arco (creados en ese orden).
Aadimos ahora una entidad crculo.
2.
La variable ent1 utilizada en el ejemplo anterior contiene el nombre de la primera entidad
del dibujo, la lnea. Y si no es as, podemos repetir el ejemplo anterior (setq ent1 (entnext))
3.

Al ejecutar (setq ent2 (entnext ent1)) se asignar a la variable ent2 el nombre de la


siguiente entidad a ent1, es decir la entidad siguiente a la lnea, el arco.

4.

Y si hacemos ahora (setq ent2 (entnext ent2)) que suceder? Recordemos que en
AutoLISP primero se evalan las listas interiores, de modo que (entnext ent2) devuelve la
entidad siguiente a ent2, es decir la entidad siguiente al arco, que es el crculo. Despus
asigna ese valor a la variable ent2.

5.

Si volvemos a ejecutar (setq ent2 (entnext ent2)) veremos que devuelve nil. Veamos que
sucede, primero se evala la expresin(entnext ent2) que devuelve nil puesto que ent2 es el
crculo y no se ha creado ninguna entidad despus de esta.

Vamos a crear algn sencillo ejemplo de cdigo basndonos en lo visto en el caso anterior:
(setq ent (entnext))
(while ent
(redraw ent 3)
(setq ent (entnext ent))
)
Paremonos un poco en el cdigo anterior. La primera lnea obtiene la primera entidad del dibujo
actual y asigna su nombre a la variableent. A continuacin, entramos en un bucle dentro del cual
redibujamos en relieve la entidad ent. Posteriormente obtenemos la entidad siguiente y la
asignamos nuevamente a la variable ent, de modo que recorremos todas las entidades del dibujo
redibujndolas en relieve.
En el momento en que se llegue a la ltima entidad, la expresin (setq ent (entnext
ent)) devolver nil, con lo cual salimos del bucle.
En caso de que en el dibujo actual no exista ninguna entidad, la expresin (setq ent
(entnext)) devolver nil por lo cual no se entrar en el bucle.
Un ejemplo similar al anterior sera el siguiente:
(setq ent (entnext))
(redraw ent 3)
(while (setq ent (entnext ent))
(redraw ent 3)
)

Hay que notar que en este caso, si en el dibujo actual no existen entidades, la expresin (setq ent
(entnext)) devolver nil. De modo que en la siguiente lnea (redraw ent 3) la rutina dar lugar a
un error. Puede evitarse del siguiente modo:
(setq ent (entnext))
(if ent (redraw ent 3))
(while (setq ent (entnext ent))
(redraw ent 3)
)

2- Conjuntos de seleccin de entidades


Hasta ahora hemos visto como obtener el nombre de una entidad, ya sea por designacin directa o
recorriendo todas las entidades del dibujo. Esto nos permitir posteriormente trabajar con las
propiedades de las entidades. Pero, en muchas ocasiones nuestros programas no van a trabajar
con una, sino con varias entidades seleccionadas por el usuario.

(SSGET [modo] [punto1] [punto2]


[lista_puntos] [lista_filtros])
Esta funcin permite crear un conjunto de entidades a partir de una designacin realizada por el
usuario.
(ssget)
Si se ejecuta sin argumentos, permite designar entidades con cualquiera de los mtodos de
designacin de AutoCAD (captura, ventana, borde, etc.). Veremos que devuelve algo similar a lo
siguiente: <Selection set: 58>
Antes de comenzar a explicar como se puede utilizar esta funcin en AutoLISP, me gustara parar
un momento y explicar cmo nos puede ayudar al dibujar con AutoCAD. Veamos un pequeo
ejemplo:
1.
2.

Iniciamos un dibujo nuevo y creamos en l algunas entidades (lneas, arcos y crculos).


Ahora ejecutamos la funcin (ssget) y seleccionamos slo algunas de las entidades. Se
puede verificar que podemos emplear cualquiera de los tipos de designacin de AutoCAD
(Borde, polgono captura, etc.)

3.

Si ejecutamos ahora el comando de AutoCAD DESPLAZA y cuando solicite la designacin


de entidades, seleccionamos la opcin Previo veremos que se han seleccionado las entidades
designadas al ejecutar la expresin (ssget).

4.

Vamos ahora a ejecutar la expresin (setq ss1 (ssget)) de este modo el conjunto de
seleccin se asignar a la variable ss1. Seleccionamos slo alguna de las entidades del dibujo.

5.

Volvamos a ejecutar de nuevo el comando DESPLAZA y cuando solicite la designacin de


entidades escribimos !ss1. Veremos que el conjunto de entidades designado anteriormente
queda seleccionado.

El ejemplo anterior puede ser una alternativa al uso de los grupos dibujando con AutoCAD. Se crean
de un modo sencillo y rpido, por contra hay que observar que debemos recordar los nombres de
las variables y especialmente, que al terminar la sesin con ese dibujo se pierden los valores
asignados a las variables, lo cual no sucede con los grupos de AutoCAD.
En lugar de comentar ahora los numerosos argumentos que pueden asociarse a la funcin SSGET,
los dejaremos para el siguiente artculo. Antes veremos algunas funciones que nos permitirn
trabajar con los grupos de seleccin creados con SSGET.

(SSLENGTH conjunto_de_seleccin)
Esta sencilla funcin nos indica el nmero de entidades que contiene el conjunto de seleccin que
recibe como argumento.
1.
2.

Creamos en un dibujo nuevo una serie de entidades (lneas, arcos y crculos).


Ejecutamos la expresin (setq ss1 (ssget)) para crear un conjunto de seleccin, y
seleccionamos slo algunas entidades.

3.

Al ejecutar la expresin (sslength ss1) nos devolver el nmero de entidades del conjunto
de seleccin ss1.

El nmero de entidades es siempre un entero positivo.

(SSADD [nombre_entidad
[conjunto_de_seleccin]])
Mediante esta funcin se puede aadir una entidad a un conjunto de seleccin existente. Tambin
se puede utilizar para crear conjuntos de seleccin nuevos y vacos.
Si se ejecuta esta funcin sin argumentos crear un conjunto de seleccin nuevo y vaco. Es
importante guardar dicho conjunto de seleccin en una variable, para poder trabajar despus con l.
(setq ss1 (ssadd))
Devuelve algo similar a <Selection set: 22>. Si ejecutamos el comando DESPLAZA y al designar
entidades indicamos !ss1 nos dir: 0 encontrados. Vamos ahora a aadir algunas entidades al
conjunto de seleccin anterior.
(setq ent (entnext))
(ssadd ent ss1)
(sslength ss1)

(setq ent (entlast))


(ssadd ent ss1)
(sslength ss1)
(setq ent (car (entsel)))
(ssadd ent ss1)
(sslength ss1)
Veamos paso a paso que es lo que hacen las expresiones anteriores:
1.
2.

Primero obtenemos el nombre de la primera entidad del dibujo actual.


En la lnea siguiente se aade la entidad anterior al conjunto ss1. Es importante observar
que no es necesario declarar nuevamente la variable ss1, si lo hacemos (setq ss1 (ssadd ent
ss1)) no pasa nada, pero sera una redundancia.

3.

Para comprobar que se ha aadido la entidad, obtenemos el nmero de entidades del


conjunto mediante la funcin SSLENGTH, que devolver 1. Tambin conviene recordar que en
la expresin (ssadd ent ss1) los argumentos de la funcin deben ser un nombre de entidad
vlido y un conjunto de seleccin ya existente, aunque puede estar vaco.

4.

Hacemos lo mismo con la ltima entidad del dibujo actual, con lo cual el conjunto de
seleccin tendr ahora dos entidades.

5.

Por ltimo, obtenemos una entidad ms, pero esta vez siendo designada directamente por el
usuario, y la aadimos tambin al conjunto. Aqu puede suceder que la entidad designada por el
usuario sea adems la primera o la ltima del dibujo actual, con lo cual esa entidad ya
pertenecer al conjunto ss1. En este caso, la ltima expresin indicar que en el conjunto de
seleccin ss1 hay2 y no 3 entidades.

Como en este caso sabemos cuales son las entidades del conjunto, la primera y la ltima del
dibujo, podramos comprobar que la entidad designada por el usuario no sea ninguna de ellas antes
de aadirla al conjunto. Pero podemos hacerlo mejor con la funcin que se explica a continuacin.

(SSMEMB nombre_entidad
conjunto_de_seleccin)
Esta funcin indica si una entidad pertenece a un conjunto de seleccin. En caso afirmativo
devuelve el nombre de la entidad y si no pertenece al conjunto de seleccin devuelve nil. Podemos
ahora modificar el ejemplo de cdigo anterior:
(setq ss1 (ssadd))
(setq ent (entnext))
(ssadd ent ss1)

(sslength ss1)
(setq ent (entlast))
(ssadd ent ss1)
(sslength ss1)
(while (ssmemb (setq ent (car (entsel))) ss1)
(alert Esa entidad ya pertenece al conjunto de seleccin)
)
(ssadd ent ss1)
(sslength ss1)
Este ejemplo es muy parecido al anterior, pero ahora en lugar de designar la ltima entidad
directamente, se aade un bucle. Veamos que sucede dentro de ese bucle:
1.

Primero se designa una entidad por parte del usuario (setq ent (car (entsel))) al igual que
se haca en el ejemplo anterior.
2.
Y comprobamos si esa entidad pertenece al conjunto de seleccin (ssmemb (setq ent (car
(entsel))) ss1). En caso de que ya pertenezca al conjunto de seleccin mostrar un letrero de
alerta y en caso contrario la expresin anterior devuelve nil, con lo cual salimos del bucle y
aadimos la entidad al conjunto ss1.

(SSDEL nombre_entidad
conjunto_de_seleccin)
Adems de aadir, tambin se pueden eliminar entidades de un conjunto de seleccin. Para eso se
utiliza esta funcin, que recibe como argumentos la entidad y el conjunto de seleccin del cual
eliminarla. Funciona de un modo muy similar a SSADD.
Siguiendo con el ejemplo anterior, podemos eliminar la ltima entidad del dibujo del conjunto de
seleccin ss1.
(setq ent (entlast))
(ssdel ent ss1)
(sslength ss1)
Primero obtenemos la ltima entidad del dibujo actual, y luego se elimina del conjunto de seleccin.
Por ltimo se muestra en nmero de entidades contenidas en el conjunto, que debera ser 2.

(SSNAME conjunto_de_seleccin
ndice_posicin)
Mediante esta funcin se obtiene el nombre de una entidad contenida en un conjunto de seleccin.
Dentro de un conjunto de seleccin, las entidades se ordenan, segn se aaden al conjunto, por
medio de un ndice de posicin que comienza desde cero.
(ssname ss1 0)
La expresin anterior devuelve el nombre de la primera entidad del conjunto de seleccin ss1, que
ser en este caso la primera entidad del dibujo.
(ssname ss1 1)
En este caso devolver el nombre de la entidad designada por el usuario, ya que la ltima entidad la
hemos eliminado del conjunto de seleccin en el apartado anterior.
(ssname ss1 2)
Esta expresin devolver nil puesto que el conjunto de seleccin ss1 tan slo tiene 2 entidades.
Vamos con otro pequeo ejemplo de cdigo:
(setq ss1 (ssget))
(setq i 0)
(while (setq ent (ssname ss1 i))
(redraw ent 3)
(setq i (1+ i))
)
En este ejemplo:
1.

Primero creamos un conjunto de seleccin y un contador, asignndole a este inicialmente el


valor cero.
2.
Una vez en el bucle, obtenemos el nombre de la entidad situada en la posicin i del conjunto
de seleccin y la redibujamos en relieve.
3.

Por ltimo, movemos el contador para recorrer as todas las entidades del conjunto de
seleccin.

4.

Despus de pasar por la ltima entidad, la expresin (setq ent (ssname ss1
i)) devolver nil, con lo que saldremos del bucle.

3-Opciones avanzadas en la creacin de conjuntos de


seleccin
Vamos a terminar con los artculos sobre la seleccin de entidades de AutoCAD viendo las opciones
avanzadas de la funcin SSGETpara crear conjuntos de seleccin.

(SSGET [modo] [punto1] [punto2]


[lista_puntos] [lista_filtros])
Como hemos visto anteriormente, si se ejecuta la funcin SSGET sin argumentos permite designar
entidades utilizando cualquiera de los modos de seleccin de AutoCAD (Captura, borde, etc.). Pero
tambin se puede especificar el modo de designacin directamente:

Indicando nicamente el modo de seleccin


(ssget p)
Equivale al modo de seleccin Previo de AutoCAD. Por tanto, la expresin anterior crea un
conjunto de seleccin con las entidades seleccionadas en el comando utilizado previamente.
Lgicamente, si no existe un conjunto Previo, devolver nil.
(ssget l)
Equivale al modo de seleccin ltimo (Last) de AutoCAD. Por tanto, la expresin anterior crea un
conjunto de seleccin con la ltima entidad creada. Lgicamente, si no existen entidades,
devolver nil.
(ssget x)
Equivale al modo de seleccin Todo de AutoCAD. Por tanto, la expresin anterior crea un conjunto
de seleccin con todas las entidades del dibujo actual. Lgicamente, si no existen entidades,
devolver nil.
(ssget i)
Crea un conjunto de seleccin con las entidades que estn previamente seleccionadas en
AutoCAD. Si no hay ninguna entidad previamente seleccionada, devolver nil. Debe estar activada
la variable PICKFIRST de AutoCAD, que controla si el usuario puede designar objetos antes
(designacin nombre/verbo) y despus de ejecutar un comando.

Seleccin por un punto


(setq pt1 (getpoint \nDesigne punto:))

(ssget pt1)
En este caso, previamente se designa un punto y despus se crea un conjunto de seleccin
con UNA de las entidades que pasan por ese punto. Si por ese punto no pasa ninguna entidad
devuelve nil. Como es lgico, la designacin del punto depender del valor que tenga asociado la
variable OSMODE, que controla los modos de referencia de AutoCAD.
Puede ser interesante, antes de la designacin del punto, activar el modo de referencia cercano.
El ejemplo anterior tambin se podra realizar del siguiente modo:
(ssget (getpoint \nDesigne punto:))

Seleccin por dos puntos


(setq pt1 (getpoint \nDesigne punto inicial:))
(setq pt2 (getcorner pt1 \nDesigne punto final:))
(ssget _w pt1 pt2)
Realiza un seleccin por ventana entre los dos puntos indicados.
(setq pt1 (getpoint \nDesigne punto inicial:))
(setq pt2 (getcorner pt1 \nDesigne punto final:))
(ssget _c pt1 pt2)
Realiza un seleccin por captura entre los dos puntos indicados.

Seleccin por una lista de puntos


(setq pt (getpoint \nDesigne punto inicial:))
(setq lstpt (list pt))
(while (setq pt (getpoint pt \nDesigne siguiente punto:))
(setq lstpt (cons pt lstpt))
)
(setq lstpt (reverse lstpt))
(setq ss1 (ssget _wp lstpt))
Realiza una seleccin por medio de un Polgono Ventana.
(setq pt (getpoint \nDesigne punto inicial:))
(setq lstpt (list pt))
(while (setq pt (getpoint pt \nDesigne siguiente punto:))
(setq lstpt (cons pt lstpt))

)
(setq lstpt (reverse lstpt))
(setq ss1 (ssget _cp lstpt))
Realiza una seleccin por medio de un Polgono Captura.
(setq pt (getpoint \nDesigne punto inicial:))
(setq lstpt (list pt))
(while (setq pt (getpoint pt \nDesigne siguiente punto:))
(setq lstpt (cons pt lstpt))
)
(setq lstpt (reverse lstpt))
(setq ss1 (ssget _f lstpt))
Realiza una seleccin de tipo Borde.
Un ejemplo interesante para diferenciar los tres casos anteriores es el siguiente:
(setq pt (getpoint \nDesigne punto inicial:))
(setq lstpt (list pt))
(while (setq pt (getpoint pt \nDesigne siguiente punto:))
(setq lstpt (cons pt lstpt))
)
(setq lstpt (reverse lstpt))
(setq ss1 (ssget _wp lstpt))
(setq ss2 (ssget _cp lstpt))
(setq ss3 (ssget _f lstpt))
A partir de la misma lista de puntos se crean tres conjuntos de seleccin:

El primero por medio de un polgono ventana


el segundo por un polgono captura

y el ltimo por un Borde.

Despus de haber visto todos los modos de designacin que se pueden emplear con SSGET, nos
queda por ver el ltimo argumento que admite esta funcin: Las listas de filtros. Pero eso lo
dejaremos para ms adelante. Antes veremos, a partir del siguiente artculo, cmo acceder a la
informacin de las entidades de AutoCAD.

4-La base de datos de AutoCAD


Los dibujos de AutoCAD, son en realidad una base de datos de objetos grficos (lneas, arcos,..)
y no grficos (capas, estilos de texto,).
Todas las entidades de un dibujo estn contenidas en la base de datos de AutoCAD. Cada entidad
recibe un nombre en hexadecimal, y se define en una lista. La lista de cada entidad es a su vez un
conjunto de listas de asociaciones. Cada asociacin contiene dos valores: El primero es un cdigo
que identifica al tipo de dato contenido en el segundo elemento, y ste contiene el dato concreto.
Segn el tipo de dato, la lista de asociaciones podra tener ms de 2 elementos.
El siguiente ejemplo es la lista de asociaciones para una entidad lnea:
((-1 . <Nombre de objeto: 2030500>) (0 . LINE) (5 . 20) (100 . AcDbEntity) (67 . 0) (8 . 0)
(100 . AcDbLine) (10 150.536 108.925 0.0) (11 314.276 204.659 0.0) (210 0.0 0.0 1.0))
Para acceder a las propiedades de una entidad es necesario ante todo conocer los cdigos que la
base de datos utiliza para representar los distintos datos que almacena. Estos cdigos pueden ser
comunes a todas las entidades o especficos del tipo de entidad.
A travs de estas listas se puede acceder a todos los datos disponibles de cualquier entidad.
Para las entidades compuestas, como polilneas y splines la estructura de las listas vara
ligeramente, por eso lo veremos ms adelante.

Los pares punteados


Los pares punteados son simplemente listas de dos elementos separados por un punto. Por
ejemplo: (0 . 27)
Qu diferencia a un par punteado de una lista normal? Veamos:
1.
2.

Aunque el punto nos pueda engaar, tienen slo dos elementos. En este caso 0 y 27.
Podemos obtener el primer elemento, como en cualquier lista,
mediante (car par_punteado). Pero, si intentamos obtener el segundo elemento
mediante (cadr par_punteado) nos indicar error: tipo de argumento errneo: Para obtener
el segundo elemento utilizaremos CDR en lugar de CADR. As que
escribiramos (cdr par_punteado). Ojo! (cdr par_punteado) devolver 27y no (27).

Para qu se usan los pares punteados? Pues principalmente para crear listas de asociaciones.

Listas de asociaciones
Vale, Y qu es una lista de asociaciones? Pues una lista cuyos elementos son pares punteados.
Por ejemplo: ((perro . 0) (gato . 1) (ratn . 5))

Al primer elemento de los pares punteados le denominaremos cdigo, y al segundo


elemento valor. En el ejemplo anterior perro, gato y ratn son los cdigos y 0, 1 y 5 sus
respectivos valores.
En una lista de asociaciones, generalmente no existen cdigos duplicados. Un ejemplo de lista de
asociacin con un cdigo duplicado sera:
((perro . 0) (gato . 1) (ratn . 5) (gato . 7))
Siendo gato el cdigo que est duplicado.
Cmo se crear los pares punteados? Con una funcin que ya hemos visto, CONS.
Antes se explic (CONS elemento lista) que permite aadir un elemento nuevo como primer
elemento de la lista indicada. Si en lugar de una lista se indica otro elemento, creamos un par
punteado.

(CONS cdigo valor)


(setq par_punteado (cons sandias 7)) asignar a par_punteado el par punteado (sandias .
7)
Para crear una lista de asociaciones, por ejemplo:
(setq lst (list (cons perro 0) (cons gato 1) (cons ratn 5)))
Por ltimo veamos una funcin que utilizaremos mucho, sobre todo al trabajar con las entidades de
AutoCAD.

(ASSOC cdigo lista_asociaciones)


La funcin ASSOC nos servir para obtener el par punteado, cuyo cdigo se indique, de la lista de
asociaciones que recibe como argumento. Por ejemplo:
(assoc gato lst) devolver (gato . 1)
Si lo que queremos obtener es el valor asociado a ese cdigo, es decir del par punteado (gato .
1) queremos obtener el 1. Entonces, podemos hacer lo siguiente:
(cdr (assoc gato lst))
Pero, Por qu son tan importantes las listas de asociaciones y los pares punteados? Por lo
siguiente:
((-1 . <Nombre de entidad: 19e0958>) (0 . LINE) (330 . <Nombre de entidad: 19e08f8>) (5 .
2B) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDbLine) (10 0.0 0.0 0.0)
(11 100.0 100.0 0.0) (210 0.0 0.0 1.0))
Esta lista de asociaciones, compuesta por pares punteados, es la lista de asociaciones de una
entidad lnea tal y como se almacena en la base de datos de AutoCAD.

En dicha lista de asociaciones, el cdigo 0 nos indica el tipo de entidad. De modo que:
(assoc 0 lista_de_entidad) devolver (0 . LINE)
(cdr (assoc 0 lista_de_entidad)) devolver LINE
El cdigo 8 nos indica la capa en la que est la entidad, en este caso en la capa 0. El cdigo
10 indica el punto inicial de la lnea y elcdigo 11 el punto final.
Por eso son tan importantes las listas de asociaciones y los pares punteados, porque a travs de
ellas podemos navegar por las propiedades de las entidades que se almacenan en la base de datos
de AutoCAD.
En los artculos anteriores hemos visto como se obtienen los nombres de las entidades de
AutoCAD, y como se crean conjuntos de seleccin de entidades. En el siguiente artculo vamos a
acceder a las propiedades de las entidades.

5-Las listas de asociaciones de las entidades de AutoCAD

(ENTGET nombre_entidad
[lista_aplicaciones])
Mediante esta funcin se obtiene la lista de asociaciones de la entidad que recibe como argumento.
Veamos un ejemplo:
1.
2.

Iniciamos un dibujo nuevo y dibujamos una lnea, un arco y una circunferencia.


Mediante la expresin (setq ent (car (entsel))) y seleccionando la lnea, se obtiene el
nombre de dicha entidad.

3.

Ahora, al ejecutar (entget ent) se obtiene la lista de asociaciones de la entidad lnea. Para
ver la lista completa puede ser til pulsar la tecla F2 para mostrar la ventana de texto de
AutoCAD.

4.

Repetimos los dos pasos anteriores pero seleccionando primero la entidad arco y despus
con la entidad crculo.

Si observamos las listas de asociaciones de las entidades anteriores se pueden observar


considerables diferencias entre ellas.
El argumento opcional de la funcin ENTGET no lo trataremos de momento, se ver ms adelante.

En las listas de asociaciones de las entidades estn reflejadas las propiedades de dichas entidades.
Por ejemplo

en el par punteado correspondiente al cdigo 8 el valor que tiene asociado representa la


capa a la que pertenece la entidad
asociado al cdigo 0 est el tipo de entidad
el cdigo 10 representa el punto inicial de las entidades lnea, mientras que para los arcos y
crculos se corresponde con su centro.

En el artculo Cdigos de las listas de asociaciones de las entidades de AutoCAD se pueden


ver los cdigos empleados por las distintas entidades de AutoCAD, ordenados alfabticamente en
funcin del tipo de entidad.
Ahora ya podemos acceder a las propiedades de las entidades y trabajar con la informacin que
tienen.
Vamos a crear una pequea rutina para borrar todas las entidades existentes en una capa,
simplemente designando una de las entidades de dicha capa. El pseudocdigo sera algo as:
1.
2.
3.
4.

Designar una entidad que pertenezca a la capa que se desea borrar.


Obtener el nombre de dicha capa.
Crear un conjunto de seleccin en el que estn todas las entidades que pertenezcan a la
capa anterior.
Borrar el conjunto de seleccin anterior.

(defun C:DELCAP ( / cmd0 ent capa ss )


(command _.undo _begin)
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
;; Desactiva el eco de mensajes.
(princ \nSeleccione una entidad de la capa a borrar:)
(while (not (setq ent (car (entsel))))
(princ \nSeleccione una entidad de la capa a borrar:)
)
;; Designa una entidad.
(setq capa (cdr (assoc 8 (entget ent))))
;; Obtiene la capa de la entidad designada.

(setq ss (ssadd))
(setq ent (entnext))
(while ent
(if (= capa (cdr (assoc 8 (entget ent))))
(ssadd ent ss)
)
(setq ent (entnext ent))
)
;; Crea un conjunto de seleccin con todas las entidades de la capa.
(command _erase ss )
(princ (strcase \nSe han borrado las entidades de la capa capa))
;; Borra el conjunto de seleccin anterior.
(if (= cmd0 1)
(setvar cmdecho 1)
)
(command _.undo _end)
(princ)
)
(prompt \nNuevo comando DELCAP cargado)
Veamos entonces paso a paso como funciona esta rutina:
(while (not (setq ent (car (entsel))))
(princ \nSeleccione una entidad de la capa a borrar:)
)
Este primer bucle nos permite designar una entidad por medio de la funcin ENTSEL.
El bucle obliga al usuario a designar una entidad, por si al evaluar la funcin ENTSEL se indica un
punto en una zona vaca de la ventana grfica. Se obtiene el nombre de la entidad designada y se
almacena en la variable ent.
(setq capa (cdr (assoc 8 (entget ent))))
Esta lnea obtiene la lista de asociaciones de la entidad designada. Y por medio
de (cdr (assoc 8 (entget ent))) se obtiene el valor asociado al cdigo 8, correspondiente a la capa
de la entidad, que es almacenada en la variable capa.

(setq ss (ssadd))
(setq ent (entnext))
(while ent
(if (= capa (cdr (assoc 8 (entget ent))))
(ssadd ent ss)
)
(setq ent (entnext ent))
)
En esta parte del cdigo creamos un conjunto de seleccin vaco y mediante un bucle recorremos
todas las entidades del dibujo.
En cada entidad se obtiene su capa, de igual modo que se hizo anteriormente con la entidad
designada, y se compara con la capa almacenada en la variable capa.
En caso de que coincidan, se aade la entidad evaluada al conjunto de seleccin ss y se mueve el
bucle para que evale la siguiente entidad.
De este modo, una vez evaluadas todas las entidades del dibujo, se ha creado un conjunto de
seleccin que contiene a todas las entidades que pertenecen a la capa deseada.
(command _erase ss )
(princ (strcase \nSe han borrado las entidades de la capa capa))
Por ltimo, se borra el conjunto de seleccin ss mediante el comando de AutoCAD BORRA. Y se
avisa al usuario de que todas las entidades de esa capa se han borrado.

(ENTDEL nombre_entidad)
Esta funcin permite borrar la entidad que recibe como argumento.
Si la entidad ya ha sido borrada previamente en la misma sesin de dibujo, lo que hace es
recuperarla.
Veamos un pequeo ejemplo:
1.
2.

Iniciamos un dibujo nuevo y creamos en l una entidad lnea.


Mediante la expresin (setq ent (entlast)) obtenemos el nombre de dicha entidad.

3.

Ahora la borramos al evaluar la expresin (entdel ent)

4.

Si volvemos a ejecutar la expresin anterior (entdel ent) se recupera la entidad borrada.

En la rutina del ejemplo anterior, podemos utilizar esta funcin para ir borrando las entidades. El
resultado sera el siguiente:

(defun C:DELCAP ( / cmd0 ent capa ss )


(command _.undo _begin)
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
;; Desactiva el eco de mensajes.
(princ \nSeleccione una entidad de la capa a borrar:)
(while (not (setq ent (car (entsel))))
(princ \nSeleccione una entidad de la capa a borrar:)
)
;; Designa una entidad.
(setq capa (cdr (assoc 8 (entget ent))))
;; Obtiene la capa de la entidad designada.
(setq ent (entnext))
(while ent
(if (= capa (cdr (assoc 8 (entget ent))))
(entdel ent)
)
(setq ent (entnext ent))
)
;; Borra las entidades de la capa deseada.
(if (= cmd0 1)
(setvar cmdecho 1)
)
(command _.undo _end)
(princ)
)
(prompt \nNuevo comando DELCAP cargado)

6-Las listas de filtros de la funcin


SSGET
Ya hemos visto la funcin SSGET y los diversos modos de seleccin que se pueden emplear, pero
nos quedaba por ver como funciona su ltimo parmetro, la lista de filtros.

(SSGET [modo] [punto1] [punto2]


[lista_puntos] [lista_filtros])
Las listas de filtros son listas de asociaciones que modifican el funcionamiento de SSGET de
modo que las entidades seleccionadas deban verificar los filtros o patrones establecidos.
Lo veremos mejor con un ejemplo:
1.

Creamos un dibujo nuevo y en l dibujamos varias lneas, arcos y circunferencias.

Supongamos que nos interesa crear un conjunto de seleccin en el que estn incluidas slo las
entidades crculo del dibujo. Podramos recorrer la base de datos entera y aadir a un conjunto de
seleccin las entidades crculo, esto se hara de un modo similar al empleado en la rutina DELCAP
del artculo anterior.
Aunque tambin podemos emplear las listas de filtros. Veamos el cdigo primero y despus lo
comentamos:
(setq ss (ssget x (list (cons 0 circle))))
Si ejecutamos esta expresin se crear el conjunto de seleccin que buscamos. Se puede
comprobar, por ejemplo, desplazando el conjunto ss en AutoCAD.
Fijmonos que lo que estamos haciendo en realidad es una designacin de tipo Todo, pero con una
lista de filtros (list (cons 0circle)) que ya dijimos que es una lista de asociaciones, es decir una
lista cuyos elementos son pares punteados.
En este caso tenemos un nico par punteado (cons 0 circle) que devolver (0 . circle).
Al indicar esta lista de filtros, lo que realmente hacemos es aplicar al modo de seleccin escogido
(Todos = x) el filtro (0 . circle). Es decir, estamos seleccionando slo las entidades cuyo
cdigo 0, el correspondiente al tipo de entidad, sea igual a circle.
En lugar de un solo par punteado se podran indicar ms. De este modo se restringira ms la
seleccin de entidades.
(setq ss (ssget x (list (cons 0 circle) (cons 8 Contorno))))
En este caso se seleccionaran las entidades crculo de todo el dibujo, que adems estn en la capa
Contorno.

(setq ss (ssget (list (cons 0 circle) (cons 40 20))))


Aqu se seleccionaran aquellas entidades de entre las designadas por el usuario que sean crculos
y que adems tengan un radio de20. En este caso no se ha utilizado el mtodo de seleccin Todo,
sino que se ha dejado la seleccin de las entidades al usuario.
Las listas de filtros se aplican a SSGET con independencia del modo de seleccin que se ha
definido. Se podran aplicar con selecciones por ventana, captura, borde, etc. Otro caso curioso es
el siguiente:
(setq ss (ssget x (list (cons 0 circle,arc) (cons 40 20))))
En este ejemplo se seleccionan de entre todas las entidades del dibujo aquellas que sean arcos o
crculos y cuyo radio sea 20.
(setq ss (ssget x (list (cons 0 circle,arc) (cons 8 Cotas, Contorno))))
Aqu se creara un conjunto de seleccin con las entidades, de entre todas las del dibujo, que sean
arcos o crculos y que estn en la capa Cotas o Contorno.
Podemos ahora modificar el cdigo de la rutina DELCAP para utilizar las listas de filtros de SSGET:
(defun C:DELCAP ( / cmd0 ent capa ss )
(command _.undo _begin)
(if (= (setq cmd0 (getvar cmdecho)) 1)
(setvar cmdecho 0)
)
;; Desactiva el eco de mensajes.
(princ \nSeleccione una entidad de la capa a borrar:)
(while (not (setq ent (car (entsel))))
(princ \nSeleccione una entidad de la capa a borrar:)
)
;; Designa una entidad.
(setq capa (cdr (assoc 8 (entget ent))))
;; Obtiene la capa de la entidad designada.
(setq ss (ssget x (list (cons 8 capa))))
(command _erase ss )
(princ (strcase \nSe han borrado las entidades de la capa capa))
;; Borra las entidades de la capa deseada.
(if (= cmd0 1)

(setvar cmdecho 1)
)
(command _.undo _end)
(princ)
)
(prompt \nNuevo comando DELCAP cargado)
Se puede apreciar que de este modo la rutina queda mucho ms sencilla.

Listas de filtros con operadores para la


funcin SSGET
En las listas de filtros que hemos visto se pueden incluir varios pares punteados que funcionan
como condiciones de igualdad: El tipo de entidad debe ser IGUAL a crculo.
Adems las condiciones de igualdad de los distintos pares punteados se unen por medio de una
conjuncin Y. El tipo de entidad debe ser IGUAL crculo Y su radio debe ser IGUAL a 20.
Solo en los ltimos ejemplos hemos visto una variacin, la inclusin de conjunciones de tipo O. El
tipo de entidad debe ser IGUAL a crculo O ser IGUAL a arco Y su capa debe ser IGUAL a Contorno
O ser IGUAL a Cotas.
Veamos ahora que existen muchas ms posibilidades, ya que existe un cdigo especfico el -4 que
nos permite aplicar otro tipo de operadores a las listas de filtros. Veamos primero un ejemplo y
despus lo comentamos:
(setq ss (ssget x (list (cons 0 circle,arc) (cons -4 <=) (cons 40 20))))
Esta expresin crea un conjunto de seleccin con todas las entidades del dibujo que sean IGUAL a
crculo O sean IGUAL a arco y cuyo radio sea MENOR O IGUAL que 20.
El cdigo -4 se acompaa del operador que se desea aplicar, en este caso <= (menor o igual). Y
este operador es aplicado al siguiente par punteado en la lista de filtros, en este caso (cons 40
20) el que indica radio 20.
Estos son los operadores que podemos utilizar:
*

Cualquier valor (siempre verdadero).

Igual que

!=

Distinto de

+/-

Distinto de

<>

Distinto de

<

Menor que

>

Mayor que

<=

Menor o igual que

>=

Mayor o igual que

&

AND binario (slo grupos de nmeros enteros)

&=

Igual a enmascarado binario (slo grupos de nmeros enteros)

(setq ss (ssget x (list (cons 0 circle) (cons -4 <>) (cons 40 20))))


En este ejemplo se seleccionan las entidades crculo de todo el dibujo cuyo radio sea distinto de 20.
Cuando las condiciones afectan a puntos en lugar de datos numricos, se pueden separar los
operadores por comas. Vamos con algn ejemplo:
(setq ss (ssget x (list (cons 0 circle) (cons 10 (50 100 0)))))
Esta expresin crea un conjunto de seleccin con todas las entidades crculo del dibujo cuyo centro
sea el punto (50,100,0).
(setq ss (ssget x (list (cons 0 circle) (cons -4 >,>,*) (cons 10 (50 100 0)))))
En este caso, se crea un conjunto de seleccin con las entidades crculo de todo el dibujo cuyo
centro tenga unas coordenadas X e Y mayores que 50 y 100 respectivamente, y cualquier
coordenada Z.
Cuando las condiciones afectan a cadenas de texto en lugar de nmeros o puntos, se pueden
emplear los caracteres comodn explicados con la funcin WCMATCH en el artculo dedicado a
las funciones para manipular cadenas de texto.
(setq ss (ssget x (list (cons 0 circle,arc) (cons 8 C*))))
La expresin anterior crea un conjunto de seleccin con las entidades crculo o arco que
pertenezcan a una capa cuyo nombre comience por C.

Listas de filtros con operadores


booleanos para la funcin SSGET
Adems de los operadores que vimos en el apartado anterior, existen otros operadores que nos
permitirn realizar filtros an ms avanzados:
Operador inicial

Operandos intermedios

Operador final

<AND

Uno o ms operandos

AND>

<OR

Uno o ms operandos

OR>

<XOR

Dos operandos

XOR>

<NOT

Un operando

NOT>

Veamos algn ejemplo:


(setq ss
(ssget x
(list
(cons -4 <or)
(cons -4 <and) (cons 0 line) (cons 8 Contorno) (cons -4 and>)
(cons -4 <and) (cons 0 circle) (cons 40 20) (cons -4 and>)
(cons -4 or>)
)
)
)
De este modo se crea un conjunto de seleccin con todas las entidades lnea del dibujo que estn
en la capa Contorno y con todos los crculos del dibujo que tengan radio 20. Veamos que sucedera
si se eliminasen los operadores AND en el ejemplo anterior:
(setq ss
(ssget x

(list
(cons -4 <or)
(cons 0 line) (cons 8 Contorno)
(cons 0 circle) (cons 40 20)
(cons -4 or>)
)
)
)
En este caso se seleccionaran: Todas las entidades lnea del dibujo, todas las entidades de la
capa Contorno (sean lneas u otro tipo de entidad), todos los crculos del dibujo y todas las
entidades del dibujo cuyo cdigo 40 (el correspondiente al radio) tenga un valor de20, es decir tanto
crculos como arcos de radio 20.

7- Modificar entidades a partir de la base de datos de


AutoCAD
Hasta ahora hemos visto que se puede acceder a la informacin de las entidades por medio de la
base de datos de AutoCAD, y tambin que podemos eliminar entidades obtenindolas a partir de
dicha base de datos. En esta ocasin vamos a modificar las entidades editando directamente la
informacin existente en la base de datos de AutoCAD.
Vamos a realizar un ejemplo sencillo: Seleccionar una entidad y cambiarla de su capa actual a la
capa Contorno modificando la informacin almacenada en la base de datos de AutoCAD. Podemos
dar unos pasos generales para este tipo de operaciones:
1.
2.

Obtener el nombre de la entidad a modificar.


Mediante ENTGET conseguir la lista de asociaciones de dicha entidad. Esta lista debe
generalmente almacenarse en una variable.

3.

Crear, a partir de la lista de asociaciones anterior, una nueva lista con los valores
modificados que se deseen.

4.

Actualizar la lista de la entidad en la base de datos de AutoCAD.

Los tres primeros puntos ya sabemos como hacerlos.


(setq ent (car (entsel \nEntidad a modificar: )))
(setq lent (entget ent))
El cdigo anterior realiza los dos primeros pasos: Obtener el nombre de una entidad y luego su lista
de asociaciones. Supongamos que la lista de asociaciones devuelta es la siguiente:

((-1 . <Nombre de entidad: 4006bd68>) (0 . LINE) (330 . <Nombre de entidad: 4006bcf8>) (5 .


2D) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . Cotas) (100 . AcDbLine) (10 283.075
109.629 0.0) (11 389.193 184.039 0.0) (210 0.0 0.0 1.0))
Se trata de una entidad lnea que pertenece a la capa Cotas. Ahora intentaremos crear una lista
modificando el par punteado original de la entidad (8 . Cotas) por el siguiente: (8 . Contorno).
Existe una funcin mediante la cual se puede reemplazar un elemento de una lista, la
funcin SUBST.

(SUBST elem_nuevo elem_antiguo lista)


Esta funcin reemplaza un elemento de una lista por su nuevo valor. Podramos hacerlo del
siguiente modo:
(subst (cons 8 Contorno) (cons 8 Cotas) lent)
En efecto, la lista que devuelve es la siguiente:
((-1 . <Nombre de entidad: 4006bd68>) (0 . LINE) (330 . <Nombre de entidad: 4006bcf8>) (5 .
2D) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . Contorno) (100 . AcDbLine) (10
283.075 109.629 0.0) (11 389.193 184.039 0.0) (210 0.0 0.0 1.0))
Donde se puede apreciar que ha reemplazado el par punteado que queramos.
Pero, en este ejemplo nosotros sabamos el valor asociado al par punteado, la capa Cotas, porque
lo habamos ledo en la lista de asociaciones. En caso de que no supiramos dicho valor, se poda
obtener. La expresin (cdr (assoc 8 lent)) nos dar el valor original asociado al cdigo 8, el
correspondiente a la capa de la entidad.
(subst (cons 8 Contorno) (cons 8 (cdr (assoc 8 lent))) lent)
Aunque en realidad estamos haciendo operaciones innecesarias. El elemento que se quiere
reemplazar de la lista es el par punteado, que se puede obtener con la expresin (assoc 8 lent) de
modo que podemos reducir la expresin anterior:
(subst (cons 8 Contorno) (assoc 8 lent) lent)
Puede ser til almacenar esta lista en una variable para poder utilizarla en el paso final, la
actualizacin de la lista de asociaciones de la entidad en la base de datos del dibujo.
(setq lent (subst (cons 8 Contorno) (assoc 8 lent) lent))
En este caso hemos aprovechado la misma variable lent para almacenar la nueva lista.

(ENTMOD lista_entidad)
Esta es la funcin que nos permitir actualizar la lista de asociaciones de una entidad en la base de
datos de AutoCAD. El argumento que recibe es la lista de asociaciones modificada de la entidad.
(entmod lent)

Vamos a reunir todo el cdigo de este ejemplo y adems vamos a resumirlo an ms:
(setq lent (entget (car (entsel \nEntidad a modificar: ))))
(entmod (subst (cons 8 Contorno) (assoc 8 lent) lent))
Vamos con otro ejemplo, en este caso modificaremos todas las entidades arco y crculo del dibujo
actual para que su radio sea 10.
(setq ss (ssget x (list (cons 0 arc,circle))))
(setq i 0)
(while (setq ent (ssname ss i))

(entmod (subst (cons 40 10) (assoc 40 (entget ent)) (entget ent)))


(setq i (1+ i))
)
1.

En primer lugar se crea un conjunto de seleccin con todas las entidades arco y crculo del
dibujo.
2.
se crea un contador, con el valor inicial 0, que ser el encargado de mover el bucle que se
encuentra a continuacin.
3.

4.

en dicho bucle:
1.

se obtiene el nombre de cada entidad

2.

se reemplaza el par punteado correspondiente al radio, de cdigo 40

3.

se actualiza la base de datos de AutoCAD

4.

y se mueve el contador.

en el momento que se pase por la ltima entidad, la condicin del bucle devuelve nil y no
entra en l de nuevo.

Podramos pensar que el siguiente cdigo tambin funcionara:


(setq ss (ssget x (list (cons 0 arc,circle))))
(setq i 0)
(while (setq lent (entget (ssname ss i)))

(entmod (subst (cons 40 10) (assoc 40 lent) lent))


(setq i (1+ i))
)

En realidad funciona, pero al pasar por la ltima entidad y evaluar nuevamente la condicin del
bucle, la expresin (ssname ss i)devuelve nil, como era de esperar. Pero (entget (ssname ss
i)) da lugar a un error: ; error: tipo de argumento errneo: lentityp nil

8- Crear nuevas entidades a partir de su lista de


asociaciones
En el artculo anterior hemos visto como acceder a las listas de asociaciones de las entidades, que
se almacenan en la base de datos de AutoCAD. Esto nos permite modificar dichas entidades. Ahora
veremos que tambin es posible crear nuevas entidades a partir de su lista de asociaciones.

(ENTMAKE [lista_asociaciones])
Esta funcin es la encargada de crear una nueva entidad a partir de una lista de asociaciones.
Si la lista de asociaciones que recibe como argumento es incorrecta devuelve nil, en caso contrario
devuelve dicha lista de asociaciones. Si se ejecuta esta funcin sin argumentos tambin
devuelve nil.
La lista de asociaciones debe contener todos los pares punteados necesarios para definir la entidad.
En caso de que alguno de ellos se omita o tenga un formato (o valores) incorrectos, la funcin
devuelve nil.
Es posible omitir algn par punteado, por ejemplo el correspondiente a la capa de la entidad, de
modo que se crear la entidad tomando los valores por defecto, en ese caso en la capa actual.
Para comprender mejor el funcionamiento de la funcin, crearemos una rutina que realice lo
siguiente:
1.
2.

Designar una entidad.


Obtener la capa de dicha entidad.

3.

Crear un conjunto de seleccin con todas las entidades del dibujo que pertenezcan a la
misma capa que la entidad anterior.

4.

Realizar una copia de todas las entidades del conjunto de seleccin, pero situndolas en la
capa 0.

Veremos que gran parte del cdigo es similar al de la rutina DELCAP que ya hemos visto
anteriormente:
(defun C:COPY0 ( / cmd0 ent capa ss )

(command _.undo _begin)


(if (= (setq cmd0 (getvar cmdecho)) 1)

(setvar cmdecho 0)
)
;; Desactiva el eco de mensajes.
(princ \nSeleccione una entidad de la capa a copiar:)
(while (not (setq ent (car (entsel))))
(princ \nSeleccione una entidad de la capa a copiar:)
)
;; Designa una entidad.
(setq capa (cdr (assoc 8 (entget ent))))
;; Obtiene la capa de la entidad designada.
(setq ss (ssget x (list (cons 8 capa))))
(setq i 0)
(while (setq ent (ssname ss i))
(entmake (subst (cons 8 0) (assoc 8 (entget ent)) (entget ent)))
(setq i (1+ i))
)
;; Copia las entidades de la capa deseada.
(if (= cmd0 1)
(setvar cmdecho 1)
)
(command _.undo _end)
(princ)
)
(prompt \nNuevo comando COPY0 cargado)
Fijmonos en la expresin en la que empleamos la funcin entmake:
(entmake (subst (cons 8 0) (assoc 8 (entget ent)) (entget ent)))
Esta expresin es similar a la que se vio como ejemplo de la funcin ENTMOD:

se obtiene la lista asociaciones de una entidad


se modifica uno de sus pares punteados por medio de la funcin SUBST, en este caso se
sustituye la capa original de la entidad por la capa 0
por ltimo, mediante la funcin ENTMAKE creamos la nueva entidad.

9- Las listas de asociaciones de las entidades


polilnea
Hasta ahora hemos visto como acceder a la base de datos de AutoCAD para obtener las listas de
asociaciones de entidades sencillas: lneas, arcos y crculos. Vamos ahora a comenzar con
entidades algo ms complejas.

Las listas de asociaciones de las entidades polilnea


Las entidades polilnea son entidades compuestas por otras subentidades: Segmentos rectos y
arcos. Parece lgico que la lista de asociaciones de las entidades polilnea sean algo diferentes que
las de las entidades que hasta ahora hemos visto.
Antes de comenzar con ejemplos de cdigo hay que observar que AutoCAD dispone de dos tipos
bien diferenciados de polilneas:

Las polilneas tradicionales de AutoCAD (entidad POLYLINE)


y las polilneas ligeras (entidad LWPOLYLINE) que se aadieron a AutoCAD en sus ltimas
versiones.

Por defecto en las ltimas versiones de AutoCAD se crearn polilneas ligeras. La variable de
sistema de AutoCAD PLINETYPE controla la creacin de polilneas optimizadas y la conversin de
polilneas ya existentes en dibujos de versiones anteriores. Esta variable puede tener los siguientes
valores:

0 Al abrir dibujos anteriores, las polilneas de estos dibujos no se convierten; crea polilneas
de formatos anteriores.
1 Al abrir dibujos anteriores, las polilneas de estos dibujos no se convierten; crea polilneas
optimizadas.
2 Al abrir dibujos anteriores, las polilneas de estos dibujos se convertirn; crea polilneas
optimizadas.

Para obtener ms informacin sobre estos dos formatos, vase el comando de


AutoCAD CONVERTIR.
PLINETYPE controla tambin el tipo de polilnea que crean los siguientes comandos de AutoCAD:

CONTORNO (cuando el tipo de objeto se establece como Polilnea)


ARANDELA

EDITPOL (al seleccionar una lnea o arco)

POLIGONO

BOCETO (cuando la variable SKPOLY se define como 1).

Las entidades POLYLINE


Vamos a comenzar viendo las polilneas de toda la vida de AutoCAD (entidad POLYLINE). De modo
que antes de comenzar debemos asignar a la variable de sistema PLINETYPE el valor 0.
(setvar plinetype 0)
Ahora crearemos dos entidades POLYLINE, una con todos sus segmentos rectos y la segunda que
contenga adems de segmentos rectos algn arco.
En el artculo Cdigos de las listas de asociaciones de las entidades de
AutoCAD encontraremos una tabla, en la que se pueden ver los cdigos especficos empleados por
las entidades POLYLINE.

Entidad POLYLINE con todos sus tramos rectos


Veamos como son las listas de asociaciones de estas entidades, comenzando con la polilnea con
todos sus segmentos rectos:
(entget (car (entsel Designe la polilnea de tramos rectos: )))
Esta expresin devolver una lista de asociaciones similar a la siguiente:
((-1 . <Nombre de entidad: 40065f78>) (0 . POLYLINE) (330 . <Nombre de entidad: 40065cf8>)
(5 . 14FF) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDb2dPolyline) (66 .
1) (10 0.0 0.0 0.0) (70 . 0) (40 . 0.0) (41 . 0.0) (210 0.0 0.0 1.0) (71 . 0) (72 . 0) (73 . 0) (74 . 0) (75 .
0))
A simple vista parece que en la lista de asociaciones no existe suficiente informacin para definir por
completo la polilnea. dnde estn los datos de sus vrtices?
Bien, los vrtices (VERTEX) son considerados como entidades que estn contenidas en la polilnea.
La lista de asociaciones anterior es la correspondiente a la entidad principal, la polilnea en s.
Las entidades compuestas se almacenan en la base de datos de AutoCAD del siguiente modo:

La lista de asociaciones de la entidad principal.


Cada una de las listas de asociaciones de las entidades componentes, en este
caso VERTEX.

Una lista de asociaciones que indica el fin de la secuencia de entidades componentes de la


principal, esta lista corresponde a un tipo de entidad especial denominado SEQEND.

Veamos el siguiente ejemplo:


(setq ent (car (entsel Designe la polilnea de tramos rectos: )))
(entget ent)
De este modo se obtiene la lista de asociacin de la entidad principal.

((-1 . <Nombre de entidad: 40065f78>) (0 . POLYLINE) (330 . <Nombre de entidad: 40065cf8>)


(5 . 14FF) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDb2dPolyline) (66 .
1) (10 0.0 0.0 0.0) (70 . 0) (40 . 0.0) (41 . 0.0) (210 0.0 0.0 1.0) (71 . 0) (72 . 0) (73 . 0) (74 . 0) (75 .
0))
Ahora, para obtener las siguientes listas de asociaciones, las correspondientes a las entidades
componentes de la principal, utilizaremos la funcin ENTNEXT para ir a la entidad siguiente que en
este caso ser un VERTEX.
(setq ent (entnext ent))
(entget ent)
Ahora esta expresin devolver la lista de asociaciones de la primera entidad VERTEX.
((-1 . <Nombre de entidad: 40065f80>) (0 . VERTEX) (330 . <Nombre de entidad: 40065f78>)
(5 . 1500) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDbVertex) (100 .
AcDb2dVertex) (10 -73.8683 231.122 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (70 . 0) (50 . 0.0))
Si repetimos las dos expresiones anteriores iremos recorriendo todas las entidades VERTEX que
contiene la polilnea, hasta que se llega al fin de la secuencia, es decir llegamos a la
entidad SEQEND.
(setq ent (entnext ent))
(entget ent)
Devuelve algo similar a:
((-1 . <Nombre de entidad: 40065fa0>) (0 . SEQEND) (330 . <Nombre de entidad: 40065f78>)
(5 . 1504) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (-2 . <Nombre de entidad:
40065f78>))
Veamos ahora un ejemplo para obtener una lista con todos los vrtices de una polilnea.
(setq ent (car (entsel Designe la polilnea de tramos rectos: )))
(setq lst nil)
(while (/= SEQEND (cdr (assoc 0 (entget (setq ent (entnext ent))))))

(setq lst (cons (cdr (assoc 10 (entget ent))) lst))


)
(reverse lst)
En primer lugar, obtenemos el nombre de la entidad polilnea y nos aseguramos de que la
variable lst en la que vamos a crear la lista de puntos est inicialmente vaca. Veamos con
detenimiento lo que sucede en el bucle:

Al entrar por primera vez en la condicin del bucle se obtiene la entidad siguiente a la
polilnea y se comprueba que no es una entidad SEQEND, verificndose la condicin ya que se
tratar de una entidad VERTEX.
Una vez en el bucle se obtiene el punto de esa entidad VERTEX y se aade a la listas lst.
Al volverse a evaluar la condicin del bucle se comprueba la entidad siguiente al vrtice
anterior, de este modo se recorren todas las entidades VERTEX de la polilnea hasta que
llegamos a la entidad SEQEND y la condicin del bucle no se cumple.

Por ltimo, tras haber salido del bucle, se invierte la lista para tener los puntos ordenados segn la
definicin de la polilnea. La ltima expresin devuelve algo similar a lo siguiente:
((-73.8683 231.122 0.0) (17.5964 347.342 0.0) (103.389 305.531 0.0) (34.6131 188.603 0.0))

Entidad POLYLINE con algn tramo en arco


La lista de asociacin de la entidad principal correspondiente a la polilnea con arcos es muy similar
a la anterior:
((-1 . <Nombre de entidad: 40065fa8>) (0 . POLYLINE) (330 . <Nombre de entidad: 40065cf8>)
(5 . 1505) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDb2dPolyline) (66 .
1) (10 0.0 0.0 0.0) (70 . 0) (40 . 0.0) (41 . 0.0) (210 0.0 0.0 1.0) (71 . 0) (72 . 0) (73 . 0) (74 . 0) (75 .
0))
Las listas de asociaciones de los vrtices correspondientes a los tramos rectos tambin son
similares a los de la polilnea anterior. Pero en los vrtices pertenecientes a los arcos cambia
ligeramente:
((-1 . <Nombre de entidad: 40065fb8>) (0 . VERTEX) (330 . <Nombre de entidad: 40065fa8>)
(5 . 1507) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDbVertex) (100 .
AcDb2dVertex) (10 183.509 221.201 0.0) (40 . 0.0) (41 . 0.0) (42 . -0.943383) (70 . 0) (50 . 0.0))

Las polilneas ligeras o entidades


LWPOLYLINE
Ahora vamos a ver que sucede con las polilneas ligeras o polilneas optimizadas. Primero debemos
restaurar el valor de la variable de sistema PLINETYPE.
(setvar plinetype 0)
Dibujamos dos polilneas como las anteriores, una con todos sus segmentos rectos y la otra con
algn arco.

Polilnea ligera con todos los tramos rectos


(setq ent (car (entsel Designe la polilnea de tramos rectos: )))

(entget ent)
La lista de asociaciones que devuelve la ltima expresin es:
((-1 . <Nombre de entidad: 40089028>) (0 . LWPOLYLINE) (330 . <Nombre de entidad:
40065cf8>) (5 . 150D) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 .
AcDbPolyline) (90 . 4) (70 . 0) (43 . 0.0) (38 . 0.0) (39 . 0.0) (10 -69.6142 207.737) (40 . 0.0) (41 .
0.0) (42 . 0.0) (10 26.8138 331.043) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 117.569 295.61) (40 . 0.0) (41 .
0.0) (42 . 0.0) (10 5.54289 160.257) (40 . 0.0) (41 . 0.0) (42 . 0.0) (210 0.0 0.0 1.0))
En las listas de asociaciones de estas entidades, el valor asociado al cdigo 90 indica el nmero de
vrtices.
Y los vrtices estn ya incluidos, de modo que no existen entidades componentes. Se considera
como una entidad simple, al contrario que las entidades POLYLINE.
Sin embargo los vrtices, que se incluyen asociados al cdigo 10 (que tiene mltiples entradas),
solo tienen dos coordenadas, las correspondientes a X e Y. La elevacin de los vrtices y por
consiguiente de la polilnea optimizada, est asociada al cdigo 38, que en este caso es 0.0.

Polilnea ligera con algn tramo en arco


Si realizamos la misma operacin con la polilnea con arcos:
(setq ent (car (entsel Designe la polilnea con arcos: )))
(entget ent)
Veremos que la lista de asociaciones es muy similar. La diferencia est en los puntos iniciales del
arco a los que se asocia la curvatura de dicho arco al cdigo 42.
((-1 . <Nombre de entidad: 40089030>) (0 . LWPOLYLINE) (330 . <Nombre de entidad:
40065cf8>) (5 . 150E) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 .
AcDbPolyline) (90 . 4) (70 . 0) (43 . 0.0) (38 . 0.0) (39 . 0.0) (10 98.4257 111.36) (40 . 0.0) (41 .
0.0) (42 . 0.0) (10 187.763 239.626) (40 . 0.0) (41 . 0.0) (42 . -0.996497) (10 272.847 180.808) (40 .
0.0) (41 . 0.0) (42 . 0.0) (10 196.981 80.1788) (40 . 0.0) (41 . 0.0) (42 . 0.0) (210 0.0 0.0 1.0))

10-Las listas de asociaciones de los bloques


Las inserciones de bloques son consideradas internamente como entidades compuestas, al igual
que sucede con las entidades POLYLINE, como hemos visto en el artculo anterior.
En un dibujo nuevo creamos dos bloques, como se muestra en la imagen. El primer bloque sin
atributos y el segundo bloque con un atributo de cada tipo (normal, invisible, constante, verificable y
predefinido).

Veamos pues como son las listas de asociaciones de dos inserciones de estos bloques.
Comenzaremos por el que no tiene atributos.

Inserciones de bloques sin atributos


(setq ent (car (entsel Designe la insercin del bloque sin atributos: )))
(entget ent)
Esta ltima expresin devuelve la lista de asociaciones de la insercin del bloque, que ser similar a
esta:
((-1 . <Nombre de entidad: 40063de8>) (0 . INSERT) (330 . <Nombre de entidad: 40063cf8>)
(5 . 3D) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDbBlockReference) (2
. bloque1) (10 233.111 131.841 0.0) (41 . 1.0) (42 . 1.0) (43 . 1.0) (50 . 0.0) (70 . 0) (71 . 0) (44 .
0.0) (45 . 0.0) (210 0.0 0.0 1.0))
Hay que diferenciar las inserciones de un bloque (entidades INSERT) con las definiciones de dicho
bloque (BLOCK), que se vern ms adelante.

En el artculo Cdigos de las listas de asociaciones de las entidades de


AutoCAD encontraremos una tabla, en la que se pueden ver los cdigos especficos empleados por
las entidades INSERT.
Segn esta tabla de cdigos, el nombre del bloque es bloque1, se ha insertado a escala
real (1.0) y sin rotar. Adems, el par punteado correspondiente al cdigo 66 no est en la lista de
asociaciones anterior, con lo cual sabemos que dicho bloque no contiene atributos variables.
Este tipo de bloques, sin atributos, es tratado por la base de datos de AutoCAD como una entidad
normal. Sin embargo veamos que sucede con el bloque que si contiene atributos.

Inserciones de bloques con atributos


(setq ent (car (entsel Designe la insercin del bloque con atributos: )))
(entget ent)
La lista que se obtiene ser similar a la siguiente:
((-1 . <Nombre de entidad: 40063e48>) (0 . INSERT) (330 . <Nombre de entidad: 40063cf8>)
(5 . 49) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDbBlockReference)
(66 . 1) (2 . bloque2) (10 271.408 131.841 0.0) (41 . 1.0) (42 . 1.0) (43 . 1.0) (50 . 0.0) (70 . 0)
(71 . 0) (44 . 0.0) (45 . 0.0) (210 0.0 0.0 1.0))
En este caso, el bloque se llama bloque2 y existe el par punteado de cdigo 66 que indica que
contiene atributos variables. Estos atributos son considerados como un componente de la entidad
principal INSERT, al igual que suceda con los vrtices de las entidadesPOLYLINE.
(setq ent (entnext ent))
(entget ent)
Con esta expresin se obtiene la lista de asociaciones del primer atributo del bloque:
((-1 . <Nombre de entidad: 40063e58>) (0 . ATTRIB) (330 . <Nombre de entidad: 40063e48>)
(5 . 4B) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDbText) (10 284.019
138.966 0.0) (40 . 2.5) (1 . 1) (50 . 0.0) (41 . 1.0) (51 . 0.0) (7 . Standard) (71 . 0) (72 . 0) (11 0.0
0.0 0.0) (210 0.0 0.0 1.0) (100 . AcDbAttribute) (2 . NORMAL) (70 . 0) (73 . 0) (74 . 0))
En el artculo Cdigos de las listas de asociaciones de las entidades de
AutoCAD encontraremos una tabla, en la que se pueden ver los cdigos especficos empleados por
las entidades ATTRIB.
La lista de asociaciones anterior corresponde a un atributo denominado NORMAL cuyo valor es
1 y como indica el valor 0 asociado al cdigo 70, es de tipo Normal.
Veamos el resto de atributos del bloque:
(setq ent (entnext ent))
(entget ent)

Devuelve la lista de asociaciones de un atributo denominado INVISIBLE de valor 2 y de


tipo Invisible, tal como indica el valor 2asociado al cdigo 70 en la lista de asociaciones.
((-1 . <Nombre de entidad: 40063e60>) (0 . ATTRIB) (330 . <Nombre de entidad: 40063e48>)
(5 . 4C) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDbText) (10 284.019
134.799 0.0) (40 . 2.5) (1 . 2) (50 . 0.0) (41 . 1.0) (51 . 0.0) (7 . Standard) (71 . 0) (72 . 0) (11 0.0
0.0 0.0) (210 0.0 0.0 1.0) (100 . AcDbAttribute) (2 . INVISIBLE) (70 . 1) (73 . 0) (74 . 0))
(setq ent (entnext ent))
(entget ent)
La lista que se obtiene corresponde a un atributo de nombre VERIFICABLE y de valor 4, que es
de tipo Verificable.
((-1 . <Nombre de entidad: 40063e68>) (0 . ATTRIB) (330 . <Nombre de entidad: 40063e48>)
(5 . 4D) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDbText) (10 284.019
126.466 0.0) (40 . 2.5) (1 . 4) (50 . 0.0) (41 . 1.0) (51 . 0.0) (7 . Standard) (71 . 0) (72 . 0) (11 0.0
0.0 0.0) (210 0.0 0.0 1.0) (100 . AcDbAttribute) (2 . VERIFICABLE) (70 . 0) (73 . 0) (74 . 0))
(setq ent (entnext ent))
(entget ent)
Esta vez obtenemos la lista de asociaciones de un atributo llamado PREDEFINIDO de valor 5 y
de tipo Predefinido.
((-1 . <Nombre de entidad: 40063e70>) (0 . ATTRIB) (330 . <Nombre de entidad: 40063e48>)
(5 . 4E) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (100 . AcDbText) (10 284.019
122.299 0.0) (40 . 2.5) (1 . 5) (50 . 0.0) (41 . 1.0) (51 . 0.0) (7 . Standard) (71 . 0) (72 . 0) (11 0.0
0.0 0.0) (210 0.0 0.0 1.0) (100 . AcDbAttribute) (2 . PREDEFINIDO) (70 . 0) (73 . 0) (74 . 0))
(setq ent (entnext ent))
(entget ent)
Parece lgico pensar que esta expresin devuelve la lista de asociaciones del atributo que falta, el
de tipo constante. Sin embargo, no es as:
((-1 . <Nombre de entidad: 40063e50>) (0 . SEQEND) (330 . <Nombre de entidad: 40063e48>)
(5 . 4A) (100 . AcDbEntity) (67 . 0) (410 . Model) (8 . 0) (-2 . <Nombre de entidad:
40063e48>))
Devuelve la lista de asociaciones de la entidad SEQEND, o de fin de secuencia. La cual nos indica
que ya hemos recorrido toda la informacin existente en la base de datos relativa a la entidad
principal, la insercin del bloque con atributos.
Qu ha pasado con el atributo Constante? Nada, simplemente AutoCAD lo trata como si fuera un
texto y no un atributo. Por eso no se puede acceder a la informacin de dicho atributo a travs de la
base de datos, al igual que sucede con el resto de entidades que forman parte del bloque (el crculo
y las lneas).

Curso de Programacin en AutoCAD:


Letreros de dilogo DCL
En este curso se explicar cmo incorporar letreros de dilogo a las macros realizadas en AutoLISP
por medio del lenguaje de programacin DCL.
1.

Curso de Programacin en AutoCAD:


Visual LISP
1.

Utilidades

ndice de trminos del curso de Programacin en AutoCAD


Como hacer (BIEN) una macro en AutoLISP

Las variables de sistema de AutoCAD


o

Listado de variables de sistema de AutoCAD

Listado de variables de sistema de acotacin de AutoCAD


Las variables de entorno de AutoCAD

Listado de variables de entorno de AutoCAD

Cdigos de las listas de asociaciones de las entidades de AutoCAD

Lista de cdigos y mensajes de error de AutoLISP

Macros
Macros en AutoLISP

Macros en Visual Basic

ndice de trminos del curso de Programacin en


AutoCAD
This entry was posted in Programacin en AutoCAD and tagged AutoCADAutoLISPCADProgramacinProgramacin en AutoCADVisual
LISP onDecember 14, 2012 by emagdalena.

A continuacin se incluye un ndice de los trminos empleados en el Curso de programacin en


AutoCAD ordenado alfabticamente y con unos enlaces a los artculos del curso en los que
aparecen.
Se mantiene la misma convencin de colores utilizada a lo largo del curso para destacar las
funciones de AutoLISP, las funciones de usuario, etc.
Este ndice de trminos se comenzar a aadir en breve con los trminos utilizados en los
artculos ya publicados y se ir completando poco a poco a medida que avance el curso.
Avisar cuando est completo.
NDICE DE TRMINOS DEL CURSO DE PROGRAMACIN EN AUTOCAD
Trmino

Referencias

A continuacin se muestra una lista con los cdigos de error que puede contener la variable de
sistema ERRNO y una breve descripcin. En la variable de sistema ERRNO se almacena el cdigo
correspondiente al ltimo error que se ha producido en AutoLISP.
Los listados de cdigos y mensajes de error se comenzarn a aadir en breve y se irn
completando poco a poco. Avisar cuando estn completos.

LISTA DE CDIGOS DE ERRORES


Valor

Descripcin

El nombre de la tabla de smbolos no es vlido

El nombre de la entidad o conjunto de seleccin no es vlido

Se ha superado el nmero mximo de conjuntos de seleccin permitidos

El conjunto de seleccin no es vlido

Uso no adecuado de una definicin de un bloque

A continuacin se muestra una tabla con los mensajes de error de AutoLISP que mostrar la funcin
de tratamiento de errores *error* definida inicialmente en AutoCAD.

LISTA DE MENSAJES DE ERROR EN AUTOLISP


Mensaje

Descripcin

Como hacer (BIEN) una macro en


AutoLISP
This entry was posted in Programacin en AutoCAD and tagged AutoCADAutoLISPCADProgramacinProgramacin en
AutoCAD on October 6, 2012 byemagdalena.

Aprovechando que he aadido los primeros artculos del Curso de Introduccin a la


programacin en AutoCAD aadir una pequea macro que es tan sencilla que se podra
crear prcticamente despus de leer el primer artculo del curso. En realidad, es uno de los
ejemplos del primer artculo del curso. Sin embargo, la utilizar como ejemplo para aadir varias
mejoras y aplicar diversas recomendaciones a la hora de crear macros en AutoLISP.

La macro define un nuevo comando en AutoCAD para crear una circunferencia de un permetro
indicado por el usuario y podra ser tan sencilla como el siguiente cdigo:

Esta macro de tan slo 4 lneas de cdigo funcionar perfectamente tal y como est, sin embargo
es recomendable aadir varios cambios para optimizar su funcionamiento. Estos son los cambios
que se podran incluir:

Aadir un encabezado de comentarios al inicio del cdigo, un historial de versiones de


la macro con los cambios realizados y una descripcin de las funciones definidas
aadir comentarios al cdigo
utilizar los comandos de AutoCAD originales y en ingls. De este modo nos
aseguramos de que se utiliza el comando original en caso de que este se hubiera redefinido, y
adems de que nuestra macro funcione en cualquier versin idiomtica de AutoCAD

poner las variables utilizadas en la funcin como variables locales

desactivar el eco de mensajes de AutoCAD durante la ejecucin de la macro

hacer que la salida de la funcin sea limpia. Para lo cual se aade como ltima lnea de
la funcin la expresin (princ) o (prin1)

indicar al usuario el nombre del comando cuando se carga el archivo de la macro.

ajustar el texto de los mensajes mostrados al usuario. Haciendo que cada mensaje se
muestre en una nueva lnea de la ventana de comandos

ofrecer al usuario valores por defecto para la introduccin de datos. En este caso se
ofrecer por defecto como valor de permetro el correspondiente a la ltima circunferencia
dibujada

impedir la entrada de valores errneos, negativos o nulos por parte del usuario,
haciendo que se repita el mensaje de solicitud del permetro hasta que se indique un valor
apropiado o se pulse ESC para cancelar el comando

desactivar los modos de referencia a entidades de AutoCAD justo antes de dibujar la


circunferencia

guardar el estado inicial de las variables de sistema de AutoCAD que se van a


modificar a lo largo de la macro. Para lo cual en este ejemplo se utilizar una nueva funcin
de usuario denominada VARSAVE

restaurar el estado inicial de las variables de sistema de AutoCAD al terminar la


macro. Para lo cual en este ejemplo se utilizar una nueva funcin de usuario denominada
VARRESC que toma los valores almacenados en VARSAVE
cargar las funciones de usuario utilizadas definiendo su mbito como local

optimizar el funcionamiento del comando Deshacer o H de AutoCAD para que


deshaga todos los cambios realizados por la macro

aadir una funcin de tratamiento de errores

Veamos como queda el cdigo aplicando los cambios indicados antes:


;;;_____________________Eduardo Magdalena_____________________;;;
;;;_______________________CIRCPERI.LSP _______________________;;;
;;;________________________Versin 1.1________________________;;;
;;;________________________06/10/2012_________________________;;;
;;; Se aaden comentarios y se optimiza el funcionamiento de la rutina
;;;________________________Versin 1.0________________________;;;
;;;________________________06/10/2012_________________________;;;
;;; Comando para dibujar una circunferencia indicando su centro y la longitud de su
permetro.
(defun C:CIRCPERI ( / pto rad peri mens lstvar error0 VARSAVE VARRESC )
(CARGALISP T
(list
(list Varsave.lsp (list VARSAVE))
(list Varresc.lsp (list VARRESC))
)
)
;; Carga las rutinas VARSAVE y VARRESC.
(VARSAVE (cmdecho osmode))
;; Almacena los valores iniciales de las variables de sistemas a modificar.
(setvar cmdecho 0)
;; Desactiva el eco de mensajes.
(setq error0 *error* *error* errores)

;; Activa nuestra propia funcin de errores


(command _.undo _begin)
;; Principio para el comando desHacer
(initget 1)
(setq pto (getpoint \nCentro de la circunferencia: ))
;; Obtiene el centro de la circunferencia.
(command _.point pto)
;; Dibuja un punto en el centro.
(while (not rad)
(if (= (getvar circlerad) 0.0)
(progn
(setq mens \nPermetro: )
(initget 7)
)
(progn
(setq mens (strcat \nPermetro < (rtos (* (getvar circlerad) 2 pi) 2 2) >: ))
(initget 6)
)
)
(if (not (setq peri (getdist mens)))
(setq rad (getvar circlerad))
(setq rad (/ peri (* 2 pi)))
)
;; Si se indica una distancia como permetro, obtiene el radio correspondiente
;; Si se muestra un permetro por defecto y se pulsa Intro como respuesta
;; obtiene el radio del ultimo crculo dibujado.
)
(setvar osmode 0)
;; Desactiva los modos de referencia de AutoCAD.
(command _.erase (entlast) )
;; Borra el punto anterior.
(command _.circle pto rad)

;; Dibuja el crculo.
(command _.undo _end)
;; Final para el comando desHacer
(setq *error* error0)
;; Activa la funcin de errores por defecto de AutoCAD
(VARRESC)
;; Restablece los valores iniciales de las variables de sistema modificadas.
(princ)
)
(prompt \nNuevo comando CIRCPERI cargado)
Adems se han incluido las
funciones CARGALISP, ERRORES, VARSAVE y VARRESC cuyo cdigo se incluye a
continuacin:
;;;_____________________Eduardo Magdalena_____________________;;;
;;;_______________________CARGALISP.LSP_______________________;;;
;;;_______________________Versin 1.0_________________________;;;
;;;________________________06/10/2012_________________________;;;
;;; Recibe una lista en la que cada elemento est formado por un nombre de archivo
;;; y una lista de funciones y variables globales definidas en dicho archivo.
;;; En caso de que alguna de las funciones (o variables globales) indicadas no est
;;; definida, carga el archivo en el que se encuentran.
(defun CARGALISP (flag lst /)
(while lst
(if (not (apply and (atoms-family 1 (cadar lst))))
;; Comprueba si las funciones ya estn cargadas.
(if (not (findfile (caar lst)))
(alert (strcat No se ha encontrado el archivo (caar lst)))
;; No se encuentra el archivo.
(progn
(load (caar lst))

;; Carga el archivo.
(if (not flag)
(prompt (strcat \nCargando archivo (caar lst) ))
)
;; Si flag no es T indica que se ha cargado el archivo.
)
;; Se encuentra el archivo.
)
)
(setq lst (cdr lst))
;; Pasa al siguiente elemento de la lista.
)
(princ)
)
;;;_____________________Eduardo Magdalena_____________________;;;
;;;________________________ERRORES.LSP________________________;;;
;;;_______________________Versin 1.0_________________________;;;
;;;________________________06/10/2012_________________________;;;
;;; Funcin de tratamiento de errores que puede reemplazar a la predefinida en AutoCAD
;;; Si se cancela el comando o funcin, la salida es limpia
;;; Deshace todos los cambios realizados por el comando o funcin desde la cual se llama
;;; Restaura la funcin de errores predefinida en AutoCAD
;;; Restablece los valores iniciales de las variables de sistema modificadas.
(defun ERRORES ( mens )
(if (= mens quitar / salir abandonar)
(princ)
(princ (strcat \nError: mens ))
)
;; Si se cancela el comando o funcin la salida es limpia
(command _.undo _end)

;; Aade una marca final para el comando desHacer


(command _.undo )
;; Deshace todos los cambios del comando o funcin desde la cual se llama
(setq *error* error0)
;; Activa la funcin de errores por defecto de AutoCAD
(VARRESC)
;; Restablece los valores iniciales de las variables de sistema modificadas.
(princ)
)
;;;_____________________Eduardo Magdalena_____________________;;;
;;;_______________________VARSAVE.LSP_________________________;;;
;;;_______________________Versin 1.0_________________________;;;
;;;________________________06/10/2012_________________________;;;
;;; Recibe una lista de variables de sistema de AutoCAD y almacena en la variable
;;; global lstvar una lista de pares punteados formados por los nombres de las variables
;;: y sus valores.
;;;
;;; Se utiliza al principio de las rutinas en las que se crean nuevos comandos de AutoCAD
;;; para almacenar los valores iniciales de las variables de sistema.
;;;
;;; Para recuperar el valor inicial de una variable en medio de dicho comando se utilizar:
;;; (setvar osmode (cdr (assoc osmode lstvar)))
;;;
;;; Al final del comando se recuperaran los valores iniciales de las variables de sistema
;;; mediante la funcin VARRESC.
(defun VARSAVE ( lst / )
(while lst
(setq lstvar (cons (cons (car lst) (getvar (car lst))) lstvar))
;; Aade un par punteado formado, por el nombre de la variable y su valor, a la lista lstvar.

(setq lst (cdr lst))


)
)
;;;_____________________Eduardo Magdalena_____________________;;;
;;;_______________________VARRESC.LSP_________________________;;;
;;;_______________________Versin 1.0_________________________;;;
;;;________________________06/10/2012_________________________;;;
;;; Restituye los valores iniciales de las variables de sistema que se han almacenado en
;;; la variable global lstvar.
;;;
;;; La variable lstvar se crea con la funcin VARSAVE y en ella se almacena una lista de
;;; pares punteados, formados por el nombre de una variable de sistema y su valor inicial.
(defun VARRESC ( / )
(while lstvar
(setvar (caar lstvar) (cdar lstvar))
;; Asigna a la variable de sistema su valor inicial.
(setq lstvar (cdr lstvar))
)
)
Adems se debera hacer lo siguiente:

las macros ERRORES y CARGALISP se deberan cargar automticamente al iniciar la


sesin de AutoCAD
aadir una opcin de carga automtica para que se cargue el archivo de la macro
CIRCPERI en cuanto se ejecute el comando

aadir el comando a un men personalizado

aadir el comando a una barra de herramientas

Los dos primeros puntos de la lista anterior se realizaran aadiendo las siguientes lneas de
cdigo al archivo Acaddoc.lsp del directorio Support de AutoCAD. Dicho archivo se carga
automticamente al iniciar sesin en AutoCAD y en caso de que no exista el archivo se puede
crear:

(load ERRORES)
(load CARGALISP)
(autoload CIRCPERI (CIRCPERI))
Para aadir nuestro nuevo comando a un men tan slo deberamos aadir a un archivo de men
una lnea como la siguiente:
ID_UTcircperi

[&Circunferencia por permetro]^C^Ccircperi

Puede que creas que se ha complicado demasiado esa simple macro de 4 lneas, pero en
realidad no es para tanto. Ten en cuenta que las funciones CARGALISP, ERRORES, VARSAVE
y VARRESC se podran reutilizar en todos tus nuevos comandos.
Adems, una gran parte del cdigo de la funcin CIRCPERI ser siempre igual (o prcticamente
igual) en el resto de comandos que crees en AutoLISP, de modo que podras crear una plantilla
para tus nuevas macros similar a la siguiente:
;;;_____________________Eduardo Magdalena_____________________;;;
;;;_______________________XXXXXXXX.LSP _______________________;;;
;;;________________________Versin 1.0________________________;;;
;;;________________________xx/xx/xxxx_________________________;;;
;;; DESCRIPCIN DEL COMANDO XXXXXXXX.
(defun C:XXXXXXXX ( / lstvar error0 VARSAVE VARRESC )
(CARGALISP T
(list
(list Varsave.lsp (list VARSAVE))
(list Varresc.lsp (list VARRESC))
)
)
;; Carga las rutinas VARSAVE y VARRESC.
(VARSAVE (cmdecho osmode))
;; Almacena los valores iniciales de las variables de sistemas a modificar.
(setvar cmdecho 0)
;; Desactiva el eco de mensajes.
(setq error0 *error* *error* errores)
;; Activa nuestra propia funcin de errores

(command _.undo _begin)


;; Principio para el comando desHacer
;;
;; Aadir aqu el cdigo del nuevo comando XXXXXXXX
;;
(command _.undo _end)
;; Final para el comando desHacer
(setq *error* error0)
;; Activa la funcin de errores por defecto de AutoCAD
(VARRESC)
;; Restablece los valores iniciales de las variables de sistema modificadas.
(princ)
)
(prompt \nNuevo comando XXXXXXXX cargado)

Listado de variables de sistema de AutoCAD


This entry was posted in AutoCADCAD and tagged AutoCADAutoLISPCADProgramacin en AutoCADVisual LISP on November 15,
2012 byemagdalena.

A continuacin se incluye un listado de las variables de sistema de AutoCAD, con su


clasificacin segn los tipos que hemos visto en el artculo Las variables de sistema de
AutoCAD, sus valores iniciales y una breve descripcin. Tambin se indica la versin de
AutoCAD en la que aparece cada variable por primera vez.
Las variables de sistema sobre acotacin no se han incluido en este listado, se indican en un
listado independiente en el artculo Listado de variables de sistema de acotacin de
AutoCAD.
El listado de variables de sistema se comenzar a aadir en breve por orden alfabtico y se
ir completando poco a poco. Avisar cuando est completo.
LISTADO DE VARIABLES DE SISTEMA DE AUTOCAD
Nombre

Tipo

Guardada Versin Valor

Descripcin

inicial
Nmero de serie de la llave de hardware.
Cadena de
_linfo

Registro

Slo

Curiosamente no se puede evaluar

lectura

directamente desde el teclado, pero si

12

texto

mediante (getvar _LINFO).


Cadena de
_pkser

Registro

Slo

Devuelve el nmero de serie asignado a

lectura

AutoCAD.

200

texto

Slo
_server

Binario

Registro

11

Estado del servidor de licencias en red.


lectura

Cadena de
_vernum

Slo
Registro

13

texto

Nmero de fabricacin de AutoCAD.


lectura
Valor

Nombre

Tipo

Guardada Versin

Descripcin
inicial
Controla si se carga el archivo acad.lsp en
todos los dibujos o slo en el primer dibujo
abierto en una sesin de AutoCAD.

Activada /
Acadlspasdoc

Registro
desactivada

2000

0 Carga el archivo acad.lsp slo en


el primer dibujo abierto al iniciar una
sesin de AutoCAD.

1 Carga acad.lsp en todos los


dibujos abiertos.

Listado de variables de sistema de acotacin de


AutoCAD
This entry was posted in AutoCADCAD and tagged AutoCADAutoLISPCADProgramacin en AutoCADVisual LISP on November 15,
2012 byemagdalena.

Debido a la cantidad de variables de sistema de AutoCAD sobre acotacin, se han separado de


las que se han visto en el artculoListado de variables de sistema de AutoCAD. Todo lo
comentado en el listado anterior y en el artculo Las variables de sistema de AutoCAD se
puede aplicar a este listado de las variables de sistema de acotacin.
El listado de variables de sistema de acotacin se comenzar a aadir en breve por orden
alfabtico y se ir completando poco a poco. Avisar cuando est completo.
LISTADO DE VARIABLES DE SISTEMA DE ACOTACIN DE AUTOCAD
Valor
Nombre

Tipo

Guardada Versin

Descripcin
inicial
Controla el nmero de posiciones de precisin

Dimadec

Entero

Dibujo

14

que aparecen en cotas angulares.

08 Indica el nmero de cifras


decimales que aparecen en cotas angulares.

Controla la visualizacin de unidades


alternativas en las cotas.

Activada /
Dimalt

Dibujo

13

DES

desactivada

Des: desactiva las unidades


alternativas.
Act: activa las unidades alternativas.

Controla el nmero de cifras decimales de las


Dimaltd

Entero

Dibujo

13

3
unidades alternativas.

Dimaltf

Real

Dibujo

13

25.4

Controla el multiplicador empleado para las


cifras de cota con unidades alternativas. Si

DIMALT est activado, multiplica las cifras de


las cotas lineales por el valor asignado a
DIMALTF.
Valor de redondeo para las cifras alternativas de
Dimaltrnd Real

Dibujo

2000

0.0
las cotas.

Las variables de entorno de AutoCAD


This entry was posted in Programacin en AutoCAD and tagged AutoCADAutoLISPCADProgramacinProgramacin en AutoCADVisual
LISP onNovember 27, 2012 by emagdalena.

En artculos anteriores se explicaron las variables de sistema de AutoCAD, las cuales permiten
definir el modo en el que queremos que funcione AutoCAD. En este artculo vamos a
introducirnos en las variables de entorno, las cuales almacenan informacin acerca de otro tipo
de parmetros de funcionamiento de AutoCAD.

Diferencias entre variables de sistema y


de entorno
Veamos algunas de las diferencias entre las variables de sistema y las variables de entorno:

Los valores asociados a las variables de sistema de AutoCAD se pueden ver (y en la


mayoria de casos tambin modificar) mediante el comando MODIVAR, y tambin
escribiendo directamente su nombre en la lnea de comandos de AutoCAD.
Las variables de entorno de AutoCAD no estn disponibles mediante el comando
MODIVAR y tampoco se pueden ver (o modificar) sus valores asociados escribindolas
directamente en la lnea de comandos.
Para obtener el valor asociado a una variable de entorno se debe utilizar la funcin de
AutoLISP GETENV en lugar de GETVAR, que se emplea para las variables de sistema.

Con un pequeo ejemplo se ve mejor:


La variable de sistema ACADPREFIX almacena la ruta de directorios de soporte de AutoCAD.
Para ver el valor que tiene asociado podemos:
1.

Ejecutar el comando MODIVAR e indicarle a continuacin el nombre de la variable de


sistema que deseamos: ACADPREFIX.
2.
Escribir directamente el nombre de la variable de sistema, ACADPREFIX, en la lnea de
comandos de AutoCAD.
La variable de entorno ACAD almacena tambin la ruta de directorios de soporte de AutoCAD.
Para obtener el valor que tiene asociado debemos escribir en la lnea de comandos de AutoCAD
la siguiente expresin:
(getenv ACAD)
En este ejemplo, conviene notar que la variable de sistema ACADPREFIX es de slo lectura, de
modo que el valor que tiene asociado no se puede modificar. Si no fuera de slo lectura
podramos modificar su valor mediante cualquiera de los dos mtodos empleados anteriormente.
Sin embargo, podemos modificar la variable de entorno ACAD. Para ello debemos escribir la
siguiente expresin en la lnea de comandos indicando el nuevo valor deseado:
(setenv ACAD C:\MIS DIRECTORIOS DE SOPORTE)
Sigamos con las diferencias entre variables de sistema y variables de entorno:

Las variables de sistema NO son sensibles a las maysculas.


Las variables de entorno SI son sensibles a las maysculas.

En el ejemplo anterior, podemos escribir la variable de sistema ACADPREFIX de cualquier


modo:

ACADPREFIX
Acadprefix

acadprefix

ACADprefix

Sin embargo, la variable de entorno ACAD debe escribirse tal cual, en este caso todo en
maysculas. Ya que si escribimos Acad, acad, etc. AutoCAD no reconocer a la variable de
entorno ACAD.
(getenv Acad) devuelve nil.
Las variables de sistema y las de entorno tambin se diferencian en funcin del lugar en el cual
se almacenan:

Las variables de sistema se pueden almacenar en el dibujo actual, en el registro de


sistema de Windows, e incluso algunas variables de sistema no se almacenan.
Las variables de entorno se almacenan siempre en el registro de Windows.

Tambin podemos distinguir las variables de sistema y las de entorno en funcin de los
comandos que permiten modificar sus valores asociados:

Las variables de sistema, en general, se pueden modificar ejecutando diversos comandos


de AutoCAD.
Las variables de entorno, en general, se modifican por medio de la configuracin de las
preferencias u opciones de AutoCAD, mediante el comando OPCIONES.

Veamos por ltimo, otra diferencia entre variables de sistema y variables de entorno:

Las variables de sistema, en general, estn documentadas. Podemos encontrar


informacin sobre ellas en la ayuda de AutoCAD, aunque existen algunas variables de
sistema indocumentadas.
Las variables de entorno, en general, no estn documentadas y la informacin existente
en la ayuda de AutoCAD es muy reducida.

Las variables de entorno siempre almacenan una cadena de texto. Pero esa cadena de texto puede
a su vez representar distintos tipos de datos.

Listado de variables de entorno de AutoCAD


En el artculo Listado de variables de entorno de AutoCAD se incluye un listado de las
variables de entorno con su clasificacin segn los tipos que hemos visto anteriormente, sus
valores iniciales y una breve descripcin. Tambin se indica si existe una variable de sistema de
AutoCAD similar.

Listado de variables de entorno de


AutoCAD
This entry was posted in Programacin en AutoCAD and tagged AutoCADAutoLISPCADProgramacinProgramacin en AutoCADVisual
LISP onNovember 27, 2012 by emagdalena.

A continuacin se incluye un listado de las variables de entorno de AutoCAD, con su


clasificacin segn los tipos que hemos visto anteriormente, sus valores iniciales y una breve
descripcin. Es conveniente resaltar que los nombres de las variables de entorno son sensibles a
las maysculas, de modo que deben escribirse tal cual se indica a continuacin.
Tambin se indica si existe una variable de sistema con el mismo nombre.
El listado de variables de entorno se comenzar a aadir en breve por orden alfabtico y se
ir completando poco a poco. Avisar cuando est completo.
LISTADO DE VARIABLES DE ENTORNO DE AUTOCAD
Valor
Nombre

Valor

Variable de sistema Descripcin


inicial
Controla si se utilizan los aceleradores de teclado

AcadClassic

Act / Des 0

estndard de Windows, o si se emplean los clsicos


de AutoCAD.
Controla la ruta del archivo de registro indicada por

ACADLOGFILE Archivo
AutoCAD.
Controla si se carga el archivo Acad.lsp en todos los
ACADLspAsDoc Act / Des 0

ACADLspAsDoc

dibujos o slo en el primer dibujo abierto en una


sesin de AutoCAD.

ActiveAssistance Act / Des 0

Controla si est activada la ayuda dinmica.


Controla si AutoCAD ejecuta un sonido en caso de

AlarmOnError

Act / Des 0
error.

Cdigos de las listas de asociaciones de


las entidades de AutoCAD
This entry was posted in Programacin en AutoCAD and tagged AutoCADAutoLISPProgramacinProgramacin en AutoCADVisual
LISP on December 4, 2012 by emagdalena.

A continuacin se incluye un listado de los cdigos de las listas de asociaciones de las


entidades de AutoCAD, con su descripcin y ordenados alfabticamente por el tipo de entidad
El listado de los cdigos de las listas de asociaciones de las entidades de AutoCAD se
comenzar a aadir en breve por orden alfabtico y se ir completando poco a poco.
Avisar cuando est completo.

Cdigos de uso general


-1 Nombre de entidad. Cambia cada vez que se abre un dibujo y no se guarda.
0

Cadena de texto que indica el tipo de entidad.

Identificador de entidad expresado en hexadecimal mediante una cadena de hasta 16 dgitos.

Nombre de tipo de lnea. Aparece si no es PORCAPA.

Nombre de capa.

48 Valor de coma flotante para indicar la escala del tipo de lnea. Si se omite es 1.0.
62 Nmero de color. Aparece si no es PORCAPA. El cero se corresponde al color PORBLOQUE y el 256 a

PORCAPA. Un valor negativo indica que la capa est desactivada.


Espacio modelo o papel. Si no existe o es cero, la entidad est en el espacio modelo, mientras que 1
67
corresponde a un objeto del espacio papel.
90 Bloque de ADE.

Cdigos de la entidad 3DFACE


10

Primer vrtice

11

Segundo vrtice

12

Tercer vrtice

13

Cuarto vrtice
Indicadores de lados ocultos. Es opcional

70

1 El primer lado es invisible


2 El segundo lado es invisible

3 El tercer lado es invisible

4 El cuarto lado es invisible

Cdigos de la entidad ARC


Lista de cdigos y mensajes de error de
AutoLISP
This entry was posted in Programacin en AutoCAD and tagged AutoCADAutoLISPCADProgramacinProgramacin en AutoCADVisual
LISP onDecember 13, 2012 by emagdalena.

A continuacin se muestra una lista con los cdigos de error que puede contener la variable de
sistema ERRNO y una breve descripcin. En la variable de sistema ERRNO se almacena el
cdigo correspondiente al ltimo error que se ha producido en AutoLISP.
Los listados de cdigos y mensajes de error se comenzarn a aadir en breve y se irn
completando poco a poco. Avisar cuando estn completos.
LISTA DE CDIGOS DE ERRORES
Valor

Descripcin

El nombre de la tabla de smbolos no es vlido

El nombre de la entidad o conjunto de seleccin no es vlido

Se ha superado el nmero mximo de conjuntos de seleccin permitidos

El conjunto de seleccin no es vlido

Uso no adecuado de una definicin de un bloque

A continuacin se muestra una tabla con los mensajes de error de AutoLISP que mostrar la
funcin de tratamiento de errores *error* definida inicialmente en AutoCAD.
LISTA DE MENSAJES DE ERROR EN AUTOLISP
Mensaje

Descripcin

SolidWorks
A continuacin se recopilan diversas utilidades, macros y cursos de programacin y
personalizacin sobre el entorno de SolidWorks.

Curso Introduccin a la programacin en


SolidWorks
Con este curso no se pretende formar a expertos programadores. Ms bien, se pretende acercar la
programacin sobre el entorno de SolidWorks a sus usuarios, para que puedan crear utilidades y
pequeas aplicaciones que les ahorren tiempo y clculos en sus trabajos.

Contenido
1. Introduccin a la programacin en SolidWorks
2. Las variables en la programacin sobre SolidWorks

Introduccin a la programacin en SolidWorks


Tabla de contenidos de Introduccin a la programacin en
SolidWorks
1.
2.

Introduccin a la programacin en SolidWorks


Las variables en la programacin sobre SolidWorks

Introduccin a la programacin en SolidWorks

Objetivos del curso


Aprovechando que actualmente dispongo de algo ms de tiempo, me he decidido a recopilar la
informacin que tengo para aadir al blog un curso de introduccin a la programacin en
SolidWorks.
Con este curso no se pretende formar a expertos programadores. Ms bien, se pretende acercar la
personalizacin y programacin sobre el entorno de SolidWorks a los usuarios, para que puedan
crear utilidades y pequeas aplicaciones que les ahorren tiempo y clculos en sus
trabajos, llegando incluso a ajustarlo a aplicaciones ms especficas o verticales.

Para seguir este curso son necesarios ciertos conocimientos de programacin en Visual Basic,
C# y/o C++, as como de diseo con SolidWorks y del sistema operativo Windows.
Otro de los objetivos del curso es el de mostrar a SolidWorks no slo como un entorno de diseo
que se puede personalizar y optimizar, sino como una de las principales fuentes de definicin y
entrada de datos a lo largo de la realizacin de un proyecto.
Los departamentos de diseo en las empresas recopilan una enorme cantidad de
informacin proveniente de otros departamentos, de clientes, de proveedores y de subcontratas o
colaboradores. Por otra parte, en el proceso de diseo se genera una enorme cantidad de
informacin, que posteriormente puede necesitarse en otros departamentos, por los clientes,
proveedores y subcontratas o colaboradores. Gran parte de esa informacin se reutiliza de forma
recurrente y si no se optimiza correctamente puede dar lugar a:

consultas y bsquedas reiteradas de los datos necesarios, lo que causar importantes


prdidas de productividad
entradas mltiples de los mismos datos de modo que, adems de suponer una importante
prdida de productividad, se incrementa enormemente la posibilidad de introducir datos
errneos
etc.

A lo largo del curso veremos varios ejemplos que nos permitirn importar y exportar informacin
desde SolidWorks, as como diversas opciones para almacenar en SolidWorks
informacin relacionada con el diseo.

Entorno de programacin en VBA de SolidWorks

Merece la pena aprender a programar sobre SolidWorks

Desde luego que puede merecer la pena. Puede agilizar y facilitar enormemente el trabajo con
SolidWorks.
Gran parte del tiempo de diseo con SolidWorks, y con cualquier otra aplicacin de CAD, se dedica
a labores repetitivas que se podran automatizar. Adems, es muy posible que tu trabajo tenga
algunas particularidades especiales derivadas del sector, tipo de aplicaciones realizadas, o del
funcionamiento interno de la empresa o del departamento de diseo. De modo que la programacin
y personalizacin de SolidWorks te permitir adaptar tu entorno de diseo a tus necesidades
particulares, tal como lo hara un programa de diseo vertical (para una aplicacin o sector
concreto) o una aplicacin desarrollada a medida, y adems sin perder la potencia y versatilidad de
una aplicacin de diseo genrica como SolidWorks.
Las nociones bsicas de programacin sobre SolidWorks son muy sencillas de aprender y
se pueden crear programas interesantes y realmente tiles desde el primer momento.
Muchas veces, la mayora del tiempo empleado en crear una macro o programa se emplea
en depurar el cdigo (corregir errores). La planificacin y el anlisis previo de la macro es de suma
importancia para evitarlo. El primer paso para escribir una macro consiste en escribir en un papel
con un lenguaje simple lo que se desea que realice el programa, a esto se le
denomina pseudocdigo. Un mtodo algo ms avanzado y eficaz es utilizar diagramas de flujo.
Cuando ya empieces a programar sobre el entorno de SolidWorks por ti solo, te ser muy til reunir
todas las anotaciones sobre proyectos de aplicaciones y macros en una libreta o bloc de notas.
Tambin puedes utilizar Evernote o cualquier otro sistema que te permita almacenar de informacin
o gestionar las macros que has creado.

Interfaces de programacin
SolidWorks ofrece varios entornos y lenguajes 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:

SolidWorks VBA (Visual Basic for Applications) es un conjunto de herramientas basadas


en Microsoft Visual Basic for Applications (VBA) que estn embebidas dentro de SolidWorks
y nos permiten de forma sencilla definir macros en SolidWorks. Las macros de SolidWorks
VBA se almacenan en archivos con extensin .swp
SolidWorks VSTA (Visual Studio Tools for Applications) es un conjunto de herramientas
basadas en Microsoft VB.NET yC# que estn embebidas dentro de SolidWorks y nos permiten
definir macros en SolidWorks utilizando los lenguajes de programacin Microsoft VB.NET y C#.
o

los proyectos de las macros de SolidWorks VSTA VB se almacenan en archivos


con extensin *.vbproj en los que se crean proyectos en Visual Basic .NET. Compilando el
proyecto se crear un archivo con extensin .dll

los proyectos de las macros de SolidWorks VSTA C# se almacenan en archivos con


extensin *.csproj en los que se crean proyectos en C#. Compilando el proyecto se crear
un archivo con extensin .dll

Puedes utilizar cualquier entorno y lenguaje de programacin que


soporte COM (Component Object Model) para crear:
o

Aplicaciones independientes (SolidWorks standalone API) que se almacenan en


archivos con extensin .exe

Complementos (SolidWorks Add-in) que se almacenan en archivos con


extensin .dll
Los lenguajes de programacin ms utilizados con SolidWorks son:

Visual Basic .NET


Visual C++/CLI (Infraestructura de lenguaje comn. Consultar los siguientes
enlaces: CLI, Visual C++ y C++/CLI)

Visual C#

Visual C++ 6.0

En principio podras crear una aplicacin independiente o un complemento en cualquier lenguaje


que permita soporte COM, o utilizar una extensin de dicho lenguaje que incorpore dicha
funcionalidad. Sin embargo utilizar otros lenguajes no es muy recomendable porque (a menos que
ests dispuesto a escribir una capa de puente para toda la API de SolidWorks en dicho lenguaje) el
cdigo se acabar pareciendo mucho a cdigo escrito en VB / COM / C#.
De momento nos centraremos en la programacin utilizando el entorno de VBA (Visual Basic for
applications) de SolidWorks para pasar posteriormente a programar Aplicaciones
independientes y Complementos en Visual Basic .NET y Visual C#.

Nuestra primera macro Guardar el


archivo actual en formato PDF
No me gustara dejar esta primera parte del curso con demasiada prosa y nada de cdigo, as que
vamos a crear nuestra primera macro. Para ello utilizaremos el grabador de macros de
SolidWorks, que empezaremos a ver en profundidad a partir del siguiente artculo del curso. Haz lo
siguiente:
1.
2.

inicia SolidWorks
abre (o crea y guarda) un archivo de dibujo (aunque tambin funcionar con un archivo de
pieza o de ensamblaje)

3.

selecciona en el men Herramientas > Macro > Grabar

4.

selecciona en el men Archivo > Guardar como

5.

en la lista desplegable Tipo de archivo selecciona Adobe Portable Document Format


(*.pdf) para guardar el archivo con el mismo nombre y ubicacin pero en formato PDF

6.

selecciona en el men Herramientas > Macro > Detener

7.

asigna un nombre a la macro, por ejemplo SaveasPdf y gurdala en formato SW VBA


Macros (*.swp)

8.

la macro ya est creada, si quieres ver el cdigo selecciona en el men Herramientas >
Macro > Editar y selecciona el archivo de la macro que acabas de crear

9.

para ejecutar la macro en otro archivo:


1.

abre (o crea y guarda) otro archivo de dibujo (aunque tambin funcionar con un
archivo de pieza o de ensamblaje)

2.

selecciona en el men Herramientas > Macro > Ejecutar y selecciona el


archivo de la macro que acabas de crear

3.

la macro ha creado un archivo PDF en el mismo directrorio y con el mismo nombre


que el archivo de SolidWorks que tenas abierto cuando se cre la macro.

El cdigo de la macro ser similar al siguiente:


Option Explicit
Dim swApp As Object
Dim Part As Object
Dim longstatus As Long
Sub main()
Set swApp = Application.SldWorks
Set Part = swApp.ActiveDoc
longstatus = Part.SaveAs3(C:\RutaDelArchivo\NombreArchivo.PDF, 0, 0)
End Sub
En el prximo artculo veremos como mejorar la macro, y otras opciones sobre la programacin en
VBA de SolidWorks y el grabador de macros.

Las variables en la programacin sobre


SolidWorks
This entry was posted in Programacin en SolidWorks and tagged APICADProgramacinProgramacin en
SolidWorksSolidWorksVBA on October 15, 2012 by emagdalena.

Introduccin a la programacin en
SolidWorks
Tabla de contenidos de Introduccin a la programacin en
SolidWorks
1.
2.

Introduccin a la programacin en SolidWorks


Las variables en la programacin sobre SolidWorks

Las variables en la programacin sobre


SolidWorks

Se supone que si estas siguiendo este curso ya dispones de algunos conocimientos de


programacin en Visual Basic, pero procurar comentar algunos conceptos generales por el
camino (aunque sin profundizar demasiado). De este modo aquellos usuarios de SolidWorks
cuya experiencia en programacin sea mnima, podrn utilizar este curso como va de
introduccin a la programacin, aunque sera recomendable que siguieran tambin un curso
especfico o un libro de programacin en Visual Basic.
As que antes de continuar viendo las opciones del grabador de macros de SolidWorks, vamos a
revisar el cdigo creado en el artculo anterior. Veremos paso a paso como funciona dicho
cdigo, y lo retocaremos para optimizar su funcionamiento.
Option Explicit
Dim swApp As Object
Dim Part As Object
Dim longstatus As Long
Sub main()
Set swApp = Application.SldWorks
Set Part = swApp.ActiveDoc
longstatus = Part.SaveAs3(C:\RutaDelArchivo\NombreArchivo.PDF, 0, 0)
End Sub

Declaracin explcita de variables :


Option Explicit
Las cuatro primeras lneas del cdigo anterior se podran eliminar, y la macro seguira
funcionando perfectamente. Sin embargo, como tratar de comentar a continuacin, es muy
recomendable que se mantengan.
Al incluir Option Explicit como primera expresin del cdigo, nos vemos obligados a declarar
explcitamente todas las variablesutilizadas mediante
instrucciones Dim, Private, Public o ReDim (como las tres siguientes lneas definidas en el
cdigo).
Algunas de las ventajas de utilizar Option Explicit son:

si intentas utilizar un nombre de variable no declarada, se producir un error en tiempo de


compilacin
si te equivocas al escribir una variable, a quin no le ha ocurrido?, Visual Basic indicar
que no existe

al agrupar las declaraciones de variables nos resultar ms fcil optimizar su uso y evitar
errores al definir su mbito de aplicacin

si no se utiliza la instruccin Option Explicit, todas las variables no declaradas son de


tipo Object. De este modo, se optimizan los recursos necesarios por la aplicacin y se evitar
posibles errores al convertir los valores de las variables de un tipo de datos a otro.

En resumen, el forzar la declaracin explicita de variables utilizando Option Explicit clarifica el


cdigo y elimina potenciales errores.
Se puede establecer Option Explicit para que aparezca como primera lnea del cdigo por
defecto:

En el entorno de desarrollo integrado (IDE) de Visual Basic for Apliccations de


SolidWorks, podemos activar por defecto el uso de Option explicit: En el men
Herramientas > Opciones activamos la casilla Requerir declaracin de variables.
En el entorno de desarrollo integrado (IDE) de Visual Studio Tools for Apliccations de
SolidWorks, podemos activar por defecto el uso de Option explicit: En el men Tools >
Options en el apartado Projects and Solutions > VB Defaults seleccionamos en
Option Explicit el valor On.

Tipos de variables

Las tres lneas de cdigo que van a continuacin de Option Explicit son declaraciones de
variables. Por medio de la instruccin Dim se declara y reserva espacio en la memoria del
sistema para almacenar el valor de las variables indicadas. El espacio reservado en la memoria
para una variable depender inicialmente del tipo de dato que se asigne en su declaracin (si no
se utiliza la declaracin explicita, por defecto las variables son de tipo variant). En la tabla
siguiente se muestran los tipos de datos con los que vamos a trabajar en Visual Basic para
Aplicaciones:
TIPOS DE VARIABLES
Tipo

Valores

Espacio en memoria

Sufijo

Tue o False. A veces tambin indicado 0 como


Boolean

1 Byte
falso y 1 como verdadero

Byte

Entero de 0 a 255

1 Byte

Currency Importes monetarios con hasta 4 decimales

8 Bytes

Date

Fechas

8 Bytes

(# #)

Decimal

Decimal hasta 29 dgitos

12 Bytes

Double

Decimal hasta 16 dgitos

8 Bytes

Integer

Entero entre -32.768 y 32.767

2 Bytes

Long

Entero entre -2.147.483.648 y 2.147.483.647

4 Bytes

&

4 bytes en plataforma
de 32 bits
Object

Referencias a objetos
8 bytes en plataforma
de 64 bits

Single

Decimal simple precisin (7 dgitos)

String

Cadena de texto

Variant

Valores de todos los tipos

4 Bytes

!
$

Declaracin de variables
El mtodo ms habitual para definir o declarar una variable es por medio de la instruccin Dim
seguida del nombre de la variable y opcionalmente la partcula As y el tipo de dato que se le
desea asignar.
Dim nombreVariable [As String]
Si no se indica el tipo de variable, se le asignar por defecto el tipo Variant.
Tambin se puede utilizar un sufijo para establecer algunos tipos de variables, tal como se indica
en la tabla anterior:
Dim nombreVariable$

Notacin empleada
Los identificadores utilizados para los nombres de las variables deben verificar:

comienzan por una letra


no se diferencia entre maysculas y minsculas

no pueden incluir los carcteres siguientes: . @ # % ! & $

no puede superar los 255 caracteres

no se pueden utilizar ciertas palabras reservadas por VBA para otras funciones, por
ejemplo Dim o As

A lo largo del curso se utilizarn las siguientes reglas:


se utilizarn nombres descriptivos para las variables
se utilizar la notacin lowerCamelCase. Es decir:

sin espacios ni ningn otro carcter entre las palabras que definen el nombre de la
variable
la primera palabra estar en minsculas

o
o

en el resto de palabras que componen un identificador, la primera letra estar en


maysculas

se utilizarn los mismos nombres de variables genricas en todas las macros y programas
creados. Coinciden con los definidos por defecto por el grabador de macros, por
ejemplo: swApp, Part

algunos nombres de variables se utilizarn para determinadas tareas, por ejemplo para los
contadores de los bucles se utilizarn los nombres de variable i, j, k

Procedimientos
Los procedimientos son bloques de cdigo definidos para la realizacin de tareas concretas. La
sintaxis de un procedimiento es la siguiente:
Sub nombreProcedimiento [ ( listaArgumentos ) ]
[instrucciones]
End Sub
Por tanto, en el cdigo de nuestra macro est definido un procedimiento denominado Main que
no recibe argumentos, que contiene 3 lneas de instrucciones y la ltima lnea del cdigo
coincide con la del final del procedimiento.
Las instrucciones son lneas de cdigo y como puedes apreciar estn tabuladas de forma que
visualmente se puede apreciar que estn comprendidas dentro de una estructura superior, la del
procedimiento Main al que pertenecen. De este modo se facilitar la lectura del cdigo.
En Visual Basic, todas las instrucciones ejecutables deben incluirse en algn procedimiento.
Siendo Main el nombre por defecto para el procedimiento de entrada principal en las macros de
VBA.

mbito de las variables

Macro SaveAsPDF
En la parte izquierda de la imagen podemos ver que la macro est definida en un nico mdulo
denominado SaveAsPDF, y tal como hemos comentado antes existe un nico procedimiento
denominado Main.
La declaracin de las variables est a nivel del mdulo, fuera del procedimiento Main. De este
modo, las variables estarn disponibles a lo largo de todo el mdulo
SaveAsPDF. Podramos acceder a los valores de las variables en cualquiera de los
procedimientos del mdulo.
Sin embargo, si las declaraciones de las variables estuvieran incluidas en el procedimiento Main,
se trataran como variables locales a dicho procedimiento. De modo que desde otro
procedimiento no podramos acceder a sus valores.
Cuando se habla del mbito de las variables, nos referimos a dnde estn disponibles dichas
variables.

Paradigmas bsicos de
programacin
Antes de continuar explicando lnea a lnea el cdigo incluido dentro del procedimiento Main,
vamos a repasar algunos conceptos generales de programacin.
Podramos considerar los Paradigmas de programacin como los diferentes puntos de vista
que podemos considerar para resolver un problema de programacin. Los ms habituales son los
siguientes:

Programacin imperativa. Conjunto de instrucciones que le indican al computador cmo


realizar una tarea
o
Programacin estructurada:
estructura secuencial. Las instrucciones se ejecutan sucesivamente una tras

otra

estructuras selectivas o de seleccin. Diversas partes del programa se


ejecutan o no dependiendo de que se cumpla alguna condicin

estructuras iteradas. Diversas instrucciones (los bucles) deben ejecutarse


varias veces, ya sea en nmero fijo o hasta que se cumpla una condicin determinada

Programacin declarativa. Especifica o declara un conjunto de condiciones,


proposiciones, afirmaciones, restricciones, ecuaciones o transformaciones que describen el
problema y detallan su solucin
o

Funcional

Lgico

Programacin modular. Consiste en dividir un programa en mdulos o subprogramas con


el fin de hacerlo ms legible y manejable.

Programacin dirigida por eventos. Tanto la estructura como la ejecucin de los


programas van determinados por los sucesos que ocurran en el sistema, definidos por el
usuario o que ellos mismos provoquen

Programacin orientada a objetos. Usa objetos en sus interacciones, y est basado en


varias tcnicas, incluyendo herencia, cohesin, abstraccin, polimorfismo, acoplamiento y
encapsulamiento

El caso de nuestra macro es un sencillo ejemplo de Programacin imperativa y estructurada en la


que adems no existen ni estructuras selectivas ni iteradas.
A medida que avancemos en el curso veremos ejemplos de programacin modular, dirigida por
eventos y orientada a objetos.

Aadir comentarios
Utilizar comentarios en el cdigo es una de las mejores prcticas que debes adoptar desde que te
inicias en el mundo de la programacin.
Los comentarios en Visual Basic se indican con una comilla simple, de modo que todo lo que se
escriba en una lnea despus del caracter es considerado un comentario y se mostrar en el
editor de Visual Basic de color verde.
Los comentario no se tendrn en cuenta al ejecutar el programa, sino que sern solo visibles al
editar el cdigo de modo que te facilitaran mucho el trabajo cuando tengas que modificar el
cdigo. Adems, si otra persona tiene que revisar o hacer modificaciones en el cdigo le sern de
gran ayuda los comentarios que has agregado.

El modelo de objetos de
SolidWorks
Las instrucciones de cdigo contenidas en la funcin Main acceden al modelo de objetos de
SolidWorks. Podemos considerar un modelo de objetos como: Una coleccin de objetos o
clases por las cuales un programa puede examinar y manipular algunas partes especficas de su
entorno. No nos vamos a parar ahora a explicar el modelo de objetos de SolidWorks,

simplemente aadiremos unos comentarios para describir lo que hace cada lnea y retomaremos
la explicacin del modelo de objetos de SolidWorks ms adelante.
Establece la variable swApp como el objeto de la aplicacin SolidWorks
conecta con la instancia actual de SolidWorks en ejecucin
Set swApp = Application.SldWorks
Establece la variable Part como el objeto del documento activo en SolidWorks
Set Part = swApp.ActiveDoc
Ejecuta el mtodo SaveAs3 para guardar el documento activo con el nuevo nombre
indicado
longstatus = Part.SaveAs3(C:\RutaDelArchivo\NombreArchivo.PDF, 0, 0)

Editar el cdigo
La macro actualmente guarda siempre un archivo PDF en la ruta C:\RutaDelArchivo\ y con
el nombre de archivoNombreArchivo.PDF. Vamos a modificar el cdigo para que obtenga la
ruta y nombre del archivo actual, y lo guarde en esa ruta con el mismo nombre pero con
extensin PDF.
En primer lugar vamos a definir una variable para almacenar una cadena de texto con la ruta y
nombre del archivo
Dim FilePath As String
Necesitamos la ruta completa del archivo actual de SolidWorks, para lo cual utilizaremos el
mtodo GetPathName.
FilePath = Part.GetPathName
Por ltimo, la extensin del archivo actual de SolidWorks ser slddrw, sldprt o sldasm. De
modo que GetPathName devolver algo parecido
a C:\RutaDelArchivo\NombreArchivo.SLDDRW. Como las tres extensiones anteriores
tienen 6 caracteres, podemos obtener la longitud de FilePath, restarle los ltimos 6 caracteres y
aadirle la cadena de texto PDF
FilePath = Left (FilePath, Len (FilePath) -6) & PDF
De este modo ya tendremos el nombre del archivo que queremos crear, con la extensin PDF.
Estas dos ltimas lneas se podran agrupar en una, quedando el cdigo de la macro as:
Option Explicit
Declaracin de variables
Dim swApp As Object
Dim Part As Object
Dim longstatus As Long
La funcin principal Main

Sub main()
Declaracin de variables locales de la funcin Main
Dim FilePath As String
Establece la variable swApp como el objeto de la aplicacin SolidWorks
conecta con la instancia actual de SolidWorks en ejecucin
Set swApp = Application.SldWorks
Establece la variable Part como el objeto del documento activo en SolidWorks
Set Part = swApp.ActiveDoc
Obtiene la ruta y nombre del archivo actual y le cambia la extensin por PDF
FilePath = Left (Part.GetPathName, Len (Part.GetPathName) -6) & PDF
Ejecuta el mtodo SaveAs3 para guardar el documento activo con el nuevo nombre
indicado
longstatus = Part.SaveAs3(FilePath, 0, 0)
End Sub

Programacin a medida, consultora,


formacin y presentaciones

Programacin a medida
Si utilizas un sistema de CAD/CAM y quieres que se ajuste an ms a tus necesidades y al tipo de
trabajo que realizas, es posible optimizarlo o personalizarlo para mejorar considerablemente
tuproductividad.
Tampoco dudes en consultar si precisas de una formacin a medida, ayuda con el diseo, soporte
tcnico o si buscas un ponente para realizar una presentacin.
Una consultora te permitir optimizar tus procesos, estandarizar procedimientos as como detectar
las oportunidades de mejora y destacar los puntos dbiles y los cuellos de botella existentes en el
proceso de diseo.
A continuacin puedes ver una lista de los tipos de trabajos realizados:


o
o

programacin a medida
utilidades genricas y utilidades especficas
mdulos especficos completos para verticalizar o adaptar una aplicacin de CAD a
tus necesidades
modificacin de programas a medida ya existentes

consultora

optimizacin de procesos de diseo in situ

formacin

diseo 2D y 3D. Trabajando con proyectos reales

optimizacin del diseo. Parametrizacin y personalizacin del entorno de diseo

programacin sobre aplicaciones de CAD


presentaciones y ponencias

aplicaciones de CAD 3D paramtricas

aplicaciones de CAD en software libre

programacin y personalizacin de entornos de diseo


diseo

libreras de elementos

creacin de catlogos

parametrizacin del diseo

representacin fotorrealstica

animaciones fotorrealsticas
soporte tcnico

Si estas interesado en la programacin a medida, la personalizacin y la optimizacin de entornos


CAD, no dudes en consultarme.

Contacta conmigo por email en emagdalena@ingenierosvigo.com


Puedes seguirme en Twitter pulsando en este icono

Consulta mi perfil de LinkedIn en el siguiente enlace

Estos son algunos ejemplos de los trabajos sobre entornos CAD que he realizado:

Desarrollo de un mdulo de construccin naval sobre SolidWorks

Parametrizacin y programacin de la estructura de autobuses

Creacin de libreras de elementos personalizadas

Automatizacin de Propiedades e informacin vinculada al diseo

Automatizacin de fachadas de piedra y generacin de gamas de produccin


Otros trabajos:

Programacin y automatizacin de la creacin de esquemas elctricos, neumticos e


hidrulicos
Programacin para disear y calcular instalaciones de calefaccin y fontanera

Programacin a medida para la creacin de patrones en la industria textil

Generacin automatizada de cdigo CNC para contorneado de piezas

Generacin automatizada de cdigo CNC para taladrado de piezas

Creacin de diversas libreras de componentes

Captulo 27. OpenDCL


El lenguaje DCL tiene caractersticas muy interesantes. El procedimiento que se utiliza para controlar la
estructura de dilogo utilizando los contenedores de columna y fila es comparable a los contenedores y
Controladores de Distribucin en Java , lo que sin duda es mucho mejor que la manera formas de Visual
Basic se programan. Para muchas aplicaciones, su rendimiento es ms que suficiente. Esto se puede
comprobar con slo comprobar los muchos archivos de DCL en una instalacin tpica de AutoCAD. Pero
DCL se limita a los cuadros de dilogo modal y slo se puede utilizar algunas de la amplia gama de
widgets disponibles en la interfaz grfica de usuario de Windows.Tener un ambiente verdaderamente
"visual" por su diseo que permite en pantalla tambin se pierde la colocacin.Este segundo aspecto,
dada la extrema simplicidad de la lengua DCL, no es tan problemtica.
En este captulo se dedicar a examinar OpenDCL , una alternativa que, incluso si no cumple con todos
los requisitos que desearamos encontrar en una herramienta como esta, es actualmente la solucin ms
prctica para el programador de Visual LISP que deseen enriquecer la grfica de usuario de interfaz .
all de lo que las ofertas de DCLOpenDCL se justifica en los casos en que:

Un no-dilogo modal es necesaria, es decir, un cuadro de dilogo que permite trabajar en


AutoCAD a pesar del cuadro de dilogo est abierto.

El uso de controles (widgets) no est disponible en DCL.

En este captulo se analizar el funcionamiento de OpenDCL desarrollo de una aplicacin de estas


caractersticas.
OpenDCL no forma parte de AutoCAD. Se basa en ObjectDCL , una aplicacin comercial por tercera
jornada softwareque fue liberado como cdigo abierto bajo la GNU General Public License en 2006 por
el propietario Chad Wanless.OpenDCL se ha enriquecido con la aportacin de un gran grupo de
desarrolladores liderado por Owen Wengerd y David Robison en un proyecto de cdigo abierto alojado
en SourceForge, desde donde la ltima versin de la aplicacin se puede descargar. La URL para
OpenDCL es http://www.sourceforge.net/projects/opendcl . Este captulo ha sido preparado con la
versin
ENU.7.0.0.4. La
ayuda
OpenDCL
est
disponible
en
lnea
enhttp://www.opendcl.com/HelpFiles/index.php .
El paquete descargado incluye un instalador que crea carpetas de la aplicacin y se instala los archivos
necesarios.El mdulo de tiempo de ejecucin OpenDCL se registra automticamente para todas las
versiones de AutoCAD instalado en el anfitrin ordenador. Una vez instalado, el entorno de desarrollo
OpenDCL puede iniciarse como un programa independiente, haga doble clic en el icono creado en el
escritorio o en el men Inicio.

Podemos incluir la interfaz de usuario creada con OpenDCL en nuestro archivo de cdigo fuente de
LSP. Pero para que esta aplicacin funcione en un equipo que no tiene instalado OpenDCL debemos
incluir en nuestra aplicacin de su mdulo de tiempo de ejecucin. Asegurar la correcta instalacin de los
archivos necesarios de forma automtica requiere la creacin de un instalador, para los que no son
ampliamente usadas aplicaciones, pero este tema est ms all del alcance de este libro. Una aplicacin
gratuita excelente que se puede utilizar para crear instalador de nuestra aplicacin, incluyendo el mdulo
de tiempo de ejecucin, es de Jordan Russell InnoSetup . La pgina web OpenDCL incluye un tutorial
paso a paso escrito por Lance Gordon que muestra cmo crear un instalador de aplicaciones utilizando
InnoSetup. En el caso de una aplicacin que utiliza los cuadros de dilogo modales, como el creado en
este captulo hay que tener en cuenta la necesidad de incluir en un archivo acaddoc.lsp la expresin
necesaria
para
cargar
la
aplicacin
para
cada
dibujo.
Una aplicacin OpenDCL consiste en un cdigo de AutoLISP y datos del proyecto OpenDCL. El proyecto
OpenDCL es creado y editado en OpenDCL Studio y se puede almacenar en un archivo ODCL o
incrustado en el archivo de cdigo fuente de AutoLISP. OpenDCL sigue el paradigma de la programacin
orientada a eventos, por lo que lo que ocurre en la interfaz de usuario inicia la accin especificada por la
funcin de devolucin de llamada de ese evento en particular.Una aplicacin tpica OpenDCL incluye en
un archivo LSP asociados:

El cdigo necesario para cargar y mostrar un formulario.

Los controladores de eventos, es decir, funciones que reaccionan a eventos tales como la
seleccin de un elemento de botn o lista.
Para simplificar la estructura de un archivo de proyecto LSP debe ser creado para cada forma, con el
cdigo organizada de tal manera que la funcin principal se coloca primero, seguido de las funciones
auxiliares y finalmente las funciones de eventos de devolucin de llamada.

Tutorial de este captulo: Una aplicacin desarrollada con OpenDCL.


Para mostrar cmo crear y utilizar un dilogo OpenDCL vinculada a una aplicacin Visual LISP, vamos a
discutir la aplicacin que hemos llamado XREF Explorador . Esta aplicacin muestra las capas en una
vista de rbol jerrquica en relacin con el dibujo al que pertenecen, ya sea el dibujo principal o una

referencia externa conectada. Todos los dibujos, tanto en el activo y sus referencias externas adjuntos
aparecen como ramas que dependen de un nodo raz identificado como Todos .
Junto al nombre de cada dibujo se muestra un icono para distinguir entre el dibujo actual y las
referencias externas conectadas. Este icono cambia de color para indicar si se selecciona o no el nodo
correspondiente. De los nodos de dibujo nuevas ramas se originan en representacin de sus
capas. Estas ramas son identificados como Capas por un icono diferente, que tambin cambia de color
para
indicar
que
la
capa
que
representa
est
seleccionada.
La aplicacin se puede utilizar para llevar a cabo algunas operaciones de capa como convirtindolas en y
fuera, aislando las capas seleccionadas al apagar el otros y cambiar los colores de capa. Ms
operaciones no se incluyen para mantener el cdigo lo ms simple posible, pero mediante la creacin de
ms botones y sus acciones de devolucin de llamada de la funcionalidad del comando de capa nativa
de
AutoCAD
se
pueden
reproducir.
Para este proyecto se utilizar un formulario Palette no modal. Este formulario se puede acoplar a un
lado de la ventana de AutoCAD y tambin se puede mostrar u ocultar de forma automtica de acuerdo a
la posicin del cursor.Ser un formulario no modal se ser necesario:

Para cargar el cdigo de AutoLISP para cada dibujo abierto, lo que podra hacerse con una
expresin incluida en el acaddoc.lsp archivo.

Para prever los posibles cambios en el entorno, tales como la apertura de nuevos archivos o
cambiar el foco entre diferentes dibujos abiertos con el fin de actualizar la vista de Dibujos y Capas Tree.

Considerar la posibilidad de que todos los dibujos estn cerradas, entrando en un nodocumento estatal. En este caso, el formulario debe ser cerrado.
Adems de esto, el cambio de tamao se activar mostrando cmo mantener una disposicin coherente
de los controles en el formulario cambia de tamao.

Figura 27.7. Paleta XREF Explorador en uso.

Este captulo incluye las siguientes secciones:


27.1. El
27.2. El
27.3. Tipos
27.4. Asistente
27.5. Tutorial:
27.6. Sumando
27.7. La
27.8. Resumen

proyecto
de
desarrollo
de
para
la
propiedad
Una
aplicacin
desarrollada
los
controles
distribucin
de
la
entorno

de
con

OpenDCL.
OpenDCL.
formulario.
control.
OpenDCL.
necesarios.
aplicacin.

Cdigo Depuracin con el IDE de Visual LISP

Alguna vez ha pasado un par de horas a escribir un fantstico programa slo para
encontrar que se bloquea la primera vez que se ejecuta?
Pues donde podra ese error haber venido de ...?
Si alguna vez ha profundizado en el mundo de AutoLISP, (o cualquier lenguaje de
programacin para el caso) Casi puedo garantizar que va a tener, en algn
momento, encontr un error al escribir y ejecutar un programa - es casi inevitable:
Tan pronto como empezamos la programacin, nos enteramos con sorpresa que no era tan
fcil de conseguir programas de derecho como lo habamos pensado. Depuracin tuvo que
ser descubierto. Puedo recordar el instante exacto en que me di cuenta de que una gran parte de
mi vida a partir de entonces iba a ser gastado en la bsqueda de errores en mis propios
programas.
- Sir Maurice Wilkes
En este punto, la mayora de los usuarios se encontrarn recorriendo el cdigo para
los errores tipogrficos y otros errores tan - un proceso que podra tomar el mismo
tiempo que la escritura del programa en s.
Este tutorial tiene el objetivo de ensear a usar las instalaciones de depuracin que
ofrece el IDE Visual LISP (VLIDE) para detectar de inmediato el punto en que un
programa se ha estrellado y adems le mostrar los pasos que puede tomar para
determinar por qu el cdigo se ha estrellado en ese punto en particular.
Este tutorial asume que el usuario tiene un conocimiento bsico de cmo usar el IDE
de Visual LISP. Si usted no es uno de estos usuarios, me permito sugerir que usted
da a esto una lectura: Una introduccin a la IDE de Visual LISP .

Contenido

Introduccin
Un ejemplo de programa
Dnde est el cdigo de fallo?
Por qu el Cdigo de Falla?
Adicin de puntos de ruptura
Observacin de variables
Animacin del Cdigo
Restablecimiento del Medio Ambiente
Fijacin del Cdigo
Ms informacin

Un ejemplo de programa
A lo largo de este tutorial voy a mostrar diversos mtodos de depuracin mediante la
siguiente prueba de cdigo que simplemente pide al usuario una seleccin de las
entidades de lnea y procede a imprimir la longitud total combinada de las lneas a la
lnea de comandos de AutoCAD.

SELECCIONE TODOS

( defun c: linelen ( / ent enx idx tot ssl sel )


( si ( setq sel ( ssget ' (( 0 . "LINE" ))))
( progn
( setq ssl ( sslength sel )
tot 0.0
idx 0
)
( mientras que ( <= idx ssl )
( setq ent ( ssname sel longitud de las lneas: " (
RTOS tot ))) ) ) ( princ )
( defun c: linelen ( / ent enx idx tot ssl sel )
( si ( setq sel ( ssget ' (( 0 . "LINE" ))))
( progn
( setq ssl ( sslength sel )
tot 0.0
idx 0
)
( mientras que ( <= idx ssl )
( setq ent ( ssname sel longitud de las lneas: " ( RTOS tot ))) ) ) ( princ ) )
RTOS tot ))) ) ) ( princ )
Puedes ver el error en el cdigo ya?)
Comience abriendo AutoCAD y escribiendo VLIDE en la lnea de comandos para
abrir el IDE de Visual LISP. Abra un archivo nuevo ( Archivo Nuevo archivo o Ctrl +
N ) y, o bien escriba o copie el cdigo anterior en la ventana del editor.
En primer lugar, veamos cul es el mensaje de error que estamos recibiendo.
Dibuja unas pocas lneas en AutoCAD con el que probar el programa. Ahora carga el
cdigo en la ventana del editor ( Herramientas Load Texto en Editor o Ctrl + Alt +
E ), y ejecutarlo en AutoCAD escribiendo la sintaxis del comando ' linelen 'en la lnea
de comandos.
Despus de seleccionar unas pocas lneas, recibir este mensaje de error en la lnea
de comandos:
; error: mal tipo de argumento: lentityp nil

Dnde est el cdigo de fallo?


Si se hace de forma manual , este es probablemente el elemento que consume
ms tedioso y del proceso de depuracin: encontrar el lugar exacto en el cdigo del
programa hafallado . Por suerte, el VLIDE ofrece una manera fcil de determinar de
inmediato el punto en que un programa falle.
Para responder esta pregunta, navegar de vuelta a la VLIDE e ir a la depuracin
Abrete Error . Asegrese de que esta opcin est marcada.

Al establecer esta opcin, el VLIDE establecer un punto de quiebre en el


AutoLISP expresin a la que el cdigo falla. Un punto de quiebre es similar a un
'marcador' en el cdigo y har que el programa para hacer una pausa en la
evaluacin de la expresin marcada por el punto de ruptura. Al instruir el VLIDE para
establecer automticamente un punto de quiebre cuando el programa encuentra un
error, que ms tarde puede volver a este punto de quiebre y rpidamente identificar
el origen del error.
Tenga en cuenta que la asignacin de puntos de quiebre en el IDE de Visual LISP no
modifica el archivo de AutoLISP en modo alguno, y tales puntos de quiebre no se
almacenan despus del archivo de AutoLISP se cierra.
Ahora, en AutoCAD, ejecute el programa de nuevo. Cuando los errores de cdigo, a
navegar de nuevo a la ventana VLIDE y van a la depuracin ltima Pausa
Fuente ( Ctrl + F9 ).

La expresin en la que el cdigo ha encontrado un error debe ser resaltado en la


ventana VLIDE Editor:

Por ltimo, reinicie el punto de ruptura por ir a depuracin Restablecer a nivel


superior ( Ctrl + R ); esto elimina el punto de rotura y restablece el intrprete de
pausa (el objeto que evala el cdigo de AutoLISP) hasta el comienzo del programa.
As que, ahora que sabemos dnde falla el cdigo, pero por qu lo hace fracasamos
en ese punto?

Por qu el Cdigo de Falla?

Para ayudar a responder esta pregunta la VLIDE tiene algunas otras herramientas
que podemos utilizar.
Como sabemos que el error se produce en el tiempo de bucle, nos vamos a centrar
nuestros esfuerzos de depuracin en esa seccin del cdigo.

Adicin de puntos de ruptura


Como se seal anteriormente, romper puntos pausa evaluacin del cdigo de
AutoLISP, esto puede ser considerado como similar a presionar el botn de pausa en
un reproductor de casete - el cabezal de lectura ya no es 'evaluar' la cinta magntica
en el cassette y convertirla en electricidad pulsos enviados a los altavoces.
Por pausar el intrprete AutoLISP, podemos tomar el control del flujo de la
evaluacin, comenzando y parando el cdigo cuando y donde queramos.
Para ello, en la ventana VLIDE Editor, coloque el cursor en la parte frontal del
soporte de apertura de la mientras que la expresin, haga clic en, y vaya a Depurar
Toggle Break Point ( F9 ). El corchete de apertura del tiempo de expresin debe ser
resaltado en rojo.
Ahora coloque el cursor detrs del corchete de cierre del tiempo de expresin y
aadir otro punto de quiebre siguiendo el mismo mtodo que el anterior.

Observacin de variables
El IDE de Visual LISP tambin nos permite 'ver' las variables utilizadas en el cdigo,
mostrando sus valores como se evala el cdigo. Con esto en mente, vamos a
agregar un reloj a la variable ndice idx y la variable que contiene cada lnea de la
entidad: ent .
Para ello, haga doble clic en cualquier instancia de la idx variable para resaltarlo y
abra la ventana de visualizacin, vaya a Ver Ventana de vigilancia ( Ctrl + Shift +
W ).

La variable idx ahora debera aparecer en la lista de la ventana de vigilancia, con un


valor de cero (ya que es local para el programa y no se mantiene un valor hasta que
el correspondiente setq se evala la expresin en el cdigo).
Con la ventana de visualizacin sigue abierto, haga doble clic en cualquier instancia
en el ent variable y haga clic en el Agregar inspeccin botn en la ventana de
visualizacin (el botn con el smbolo de gafas):

Esta variable tambin debe aparecer ahora en la lista, tambin con un valor de cero .

Animacin del Cdigo


Con nuestros puntos de quiebre y establecer las variables miraban, ahora estamos
pusimos a animar la evaluacin cdigo.
Cambie a la ventana de AutoCAD, y ejecutar el programa de nuevo por volver a
escribir linelen en la lnea de comandos.
Cuando la evaluacin cdigo llega a nuestro primer punto de quiebre, evaluacin
cdigo se detuvo y aparecer la ventana VLIDE Editor, destacando el cdigo entre los
dos puntos de quiebre. A partir de aqu, tenemos un control completo sobre la
evaluacin de cdigo. Podemos entrar en y salir de expresiones y evaluarlos como
nos plazca.
Por ahora, ir a la depuracin Animate y garantizar esta opcin est marcada.

Ahora vaya a Depurar Continuar (alternativamente haga clic en la flecha verde en la


barra de herramientas de depuracin, o pulse Ctrl + F8 ).
El cdigo debe comenzar a evalute, expresin por expresin a partir del punto de
interrupcin establecido anteriormente:

Observe cmo las variables en la ventana Inspeccin cambiarn sus valores como los
diversos setq expresiones dentro del tiempo se evalan bucle.
Los valores que se muestran en la ventana Inspeccin revelan la causa de un error
nuestro: el valor de la ent variables se convierte en nula cuando nuestra variable
ndice conjunto de seleccin entero idx alcanza 2.
Esto indica que ninguna entidad se encuentra en el conjunto de seleccin SEL en el
ndice 2, lo que significa que la condicin de prueba para el mientras bucle est
permitiendo que el contador sea demasiado alta antes de la condicin de prueba
devuelve nil y por lo tanto deja de evaluacin del tiempo de bucle.

Restablecimiento del Medio Ambiente

Ahora que hemos identificado la causa de un error nuestro, podemos restablecer el


entorno VLIDE.
Restablecer el intrprete AutoLISP yendo a depurar Restablecer a nivel
superior ( Ctrl + R ) - esto es anlogo a pulsar el botn de "Stop" en nuestro
reproductor de cassette.
Borrar todos los puntos de quiebre por ir a depuracin Borrar todos los puntos de
ruptura ( Ctrl + Shift + F9 ), aceptar la solicitud.
Borrar la ventana de visualizacin haciendo clic en la ventana clara botn en la
ventana de visualizacin.

Por ltimo, vaya a Depurar Animate y depuracin Descanso en error y desactive


estas opciones.

Fijacin del Cdigo


Ahora que hemos identificado dnde y por qu el cdigo est fallando, podemos mirar
para implementar un cambio en el tiempo la condicin de prueba y espero corregir el
error.
En mi demostracin que he seleccionado 2 objetos de lnea, y, puesto que el ndice
conjunto de seleccin est basado en cero (es decir, la primera entidad reside en el
ndice 0), la variable de ndice idx debe tomar valores enteros en el rango de 0 a 1.
Con este conocimiento, podemos arreglar el cdigo de la siguiente manera:
SELECCIONE TODOS

( defun c: linelen ( / ent enx idx tot ssl sel )


( si ( setq sel ( ssget ' (( 0 . "LINE" ))))
( progn
( setq ssl ( sslength sel )
tot 0.0
idx 0
)
( mientras que ( < idx ssl ) ;; Cambiado <= a <
( setq ent ( ssname sel longitud de las lneas: " (
RTOS tot ))) ) ) ( princ ) )

Ms informacin
Para obtener ms informacin acerca de las capacidades de depuracin del IDE
Visual LISP (VLIDE), consulte la documentacin VLIDE Ayuda:

AutoLISP y Visual LISP Tutoriales

Cmo ejecutar un programa AutoLISP

Carga de programas Automticamente

Una introduccin a la escritura de guiones

La localizacin de las variables

Provocando con una opcin por defecto

Control de errores

Mapcar y Lambda

Set Processing Seleccin

El apstrofe y la funcin Quote

Solucionador de problemas de mensajes de error

Visual LISP IDE Tutoriales

Una introduccin a la IDE de Visual LISP

Recuperacin de informacin acerca de una funcin

Cdigo Depuracin con el IDE de Visual LISP

Un atajo para la localizacin de variables

DCL Tutoriales

Cuadro de lista de sincronizacin

Recordando Posicin de dilogo

CAD y Programacin Foros

TheSwamp.org

CADTutor.net

AUGI.com

Autodesk Grupos de discusin

Referencias a la programacin

ssget Referencia de funciones

AutoCAD DXF Referencia

AutoLISP Referencia de funciones

Funcin DIESEL Referencia

Visual LISP Biblia Desarrolladores

Visual LISP Tabla de referencia

Cmo ejecutar un programa AutoLISP


Guardar el archivo de AutoLISP
Antes de que podamos ejecutar ningn programa hay que asegurarse de que
el archivo de programa ( .lsp archivo en este caso) reside en el sistema.
Si va a descargar programas desde mi sitio, el mtodo para guardar el archivo de
AutoLISP puede depender del navegador que est utilizando. Por ejemplo, IE8 puede
pedirle que guarde el archivo directamente a su ordenador, pero creo que Firefox te
permite ver el contenido del archivo en el navegador en s, en cuyo caso, puede ir
a Archivo Guardar pgina como asegurndose de que el Guardar como tipo panel
se ajusta a todos los archivos ; O bien, puede simplemente copiar el contenido en un
archivo de Bloc de notas abierto y guardarlo como ' nombre de archivo .lsp '(de
nuevo, asegurando tipo de archivo se establece en' Todos los archivos ').

Tenga en cuenta que el nombre de archivo utilizado para guardar el cdigo


fuente es arbitraria y no afectar el programa de ninguna manera - sin embargo, la
mayora de los usuarios utilizan la sintaxis de la funcin (y tal vez incluya la versin
del programa) para mayor comodidad.

Carga del Programa

Mtodo 1: Utilizar APPLOAD


En la lnea de comandos de AutoCAD, tipo APPLOAD (alternativamente ir
a Herramientas aplicacin de la carga ).

Seleccione el archivo de programa como previamente guardado y haga clic


en Cargar para cargar el programa en la sesin de dibujo actual. Haga clic
en Cerrar para cerrar el cuadro de dilogo APPLOAD.

La lnea de comandos debe mostrar si el programa efectivamente se ha cargado


correctamente, y los mensajes de carga de la autora pudo haber decidido incluir.

Mtodo 2: Utilizar el acaddoc.lsp


Otra forma de cargar un programa AutoLISP es incluir una llamada de carga en el
acaddoc.lsp.
Cada vez que un nuevo dibujo se abre, AutoCAD buscar las rutas de soporte para
los archivos acaddoc.lsp, y proceder a cargar el primero que descubre.
Primero debemos comprobar que existe un archivo acaddoc.lsp - para hacer este
tipo en la lnea de comandos de AutoCAD:
( findfile "acaddoc.lsp" )
Si esto devuelve una ruta de archivo, vaya al archivo acaddoc.lsp existente y en los
pasos que siguen, modificar su contenido.
Si no, puede crear un nuevo archivo acaddoc.lsp abriendo un nuevo documento de
Bloc de notas (u otro editor de texto plano) y guardarlo como acaddoc.lsp en una
ruta de AutoCAD Apoyo (asegurando el Guardar como tipo panel se ajusta una vez
ms a todos los archivos ).
En el acaddoc.lsp, aada una lnea similar a esta:
( carga de "C: \\ MiCarpeta \\ MyLISP.lsp"
)

"MyLISP no se pudo cargar"

Si el archivo LISP no reside en el Camino AutoCAD apoyo, se necesita una ruta de


archivo completa para que el archivo LISP puede estar ubicada; en este caso,
asegrese de utilizar dobles barras invertidas al especificar la ruta.
Cuando haya terminado, abra un nuevo dibujo y los archivos LISP deben cargar.
Nota: si se utiliza este mtodo para cargar muchos archivos LISP en el arranque est
causando dibujos para abrir ms lento, se refieren a mi tutorial sobre el uso
de carga automtica para exigir archivos LISP carga.

Mtodo 3: Utilizar el LISP Entorno de desarrollo


integrado Visual (VLIDE)
Este mtodo est dirigido principalmente a los desarrolladores, ya que
el VLIDE ofrece muchas utilidades de depuracin al escribir y cdigo de carga.
Para cargar un programa con este mtodo, el tipo VLIDE en la lnea de comandos de
AutoCAD. En la ventana que aparece posteriormente, ir a File Open
File (alternativamente,Ctrl + O ), y seleccione el archivo guardado previamente.
Ahora ve a Herramientas Cargue Texto en Editor (alternativamente, Ctrl + Alt + E )

Ejecucin del programa

Si el programa se ha cargado correctamente, ahora puede proceder a ejecutar el


programa en la sesin de dibujo actual.
La sintaxis (nombre del comando) para llamar al programa se puede mostrar en los
mensajes de carga de la autora, o tal vez se seala en la cabecera del programa. Si
no se puede encontrar en cualquiera de estos lugares, puede inspeccionar el propio
cdigo fuente para determinar el comando a utilizar.
La sintaxis se encuentra despus de la c: en una defun funcin de llamada, por
ejemplo:
( defun c: MyCommand (
...

En el ejemplo anterior, el comando sera MyCommand .


Si el c: no aparece despus de la defun funcin, esto indica que la funcin es una
funcin parcial y est diseado para ser llamado desde otro programa.
Cuando se conoce la sintaxis de comandos, puede ser escrito en la lnea de
comandos de AutoCAD para invocar al programa.

Carga de programas Automticamente


Ver mi tutorial sobre cargar programas al iniciar

Carga de programas Automticamente


Este tutorial pretende guiarle a travs de los diversos mtodos que se pueden
utilizar para cargar un programa automticamente en el arranque.
Si usted tiene una caja de herramientas de los programas LISP que utiliza con
regularidad, sera tedioso tener que cargar cada programa cada vez que se abre un

dibujo. Por suerte, voy a presentar dos mtodos para realizar esta tarea, cada uno
con sus propias ventajas en diferentes situaciones.caja de herramientas de los
programas LISP que utiliza con regularidad, sera tedioso tener que cargar cada
programa cada vez que se abre un dibujo. Por suerte, voy a presentar dos mtodos
para realizar esta tarea, cada uno con sus propias ventajas en diferentes situaciones.

Mtodo 1: Utilizar la suite de inicio


Este es quizs el mtodo ms fcil de usar para cargar automticamente un
programa en el inicio, ya que el usuario no necesita tener ninguna experiencia en
absoluto LISP.LISPexperiencia alguna.
En primer lugar, el tipo APPLOAD en la lnea de comandos de AutoCAD (como
alternativa, vaya a Herramientas aplicacin de la carga ).
En el dilogo que aparece posteriormente, haga clic en el Contenido botn debajo de
la Cargar al inicio rubro:

Un dilogo secundario en consecuencia aparecer, en que los programas que se


cargan al inicio del sistema se pueden aadir. Para ello, haga clic en Agregar y
navegue hasta el programa deseado.programas pueden ser aadidos a ser
cargados en el arranque. Para ello, haga clic en

Todos los programas que aparecen en el panel de arriba se cargarn cada vez que se
abre un dibujo.
El mtodo de uso de la suite de inicio para cargar programas automticamente tiene
algunas desventajas, sin embargo: si el usuario desea migrar sus programas a otro
equipo, tendr que ser aadido a la Suite de inicio en el equipo nuevo todos los
programas.
Tambin ha habido algunos errores conocidos que rodean la suite de inicio en
versiones anteriores de AutoCAD. Por estas razones, voy a introducir otro mtodo
que, aunque requiere que el usuario tenga un conocimiento bsico de AutoLISP,
supera estas dificultades.

Mtodo 2: Utilizar el acaddoc.lsp


Al abrir un dibujo o iniciar un nuevo dibujo, AutoCAD buscar todos los caminos de
ayuda enumerados incluyendo el directorio de trabajo para un archivo con el nombre
de archivo:acaddoc.lsp . Si se encuentran uno o ms de dichos archivos, AutoCAD
proceder a cargar el primer archivo encontrado.mas este tipo de archivos se
encuentran, AutoCAD se proceder a cargar el primer archivo encontrado.
Con este conocimiento se puede editar o crear un acaddoc.lsp para incluir cualquier
expresin AutoLISP para ser evaluados en el arranque.
Las cosas se ponen un poco complicado caso de que existan ms de un archivo
acaddoc.lsp, por lo que, para comprobar si ya existe un archivo de este tipo, escriba
o copie la siguiente lnea a la lnea de comandos de AutoCAD:
( findfile "acaddoc.lsp" )
En caso de ser devuelto una ruta de archivo, en los pasos que siguen, vaya a este
archivo y modifique su contenido. De lo contrario, si la lnea anterior devuelve nil ,
usted puede crear su propia acaddoc.lsp en el Bloc de notas o el VLIDE y guardarlo
en una ruta de AutoCAD Apoyo.guardar en una ruta de AutoCAD Apoyo.
Una clara ventaja de utilizar el acaddoc.lsp para cargar automticamente los
programas es que, despus de la migracin, que puede ser fcilmente copiada de un

ordenador a otro, o incluso residir en una red para cargar programas en varios
equipos simultneamente.de hecho residir en una red para cargar programas en
varios equipos simultneamente.

La funcin de carga
La carga de la funcin evaluar todas las expresiones de AutoLISP se encuentran
dentro de un archivo con un nombre de archivo suministrado (si se encuentra), la
carga efectivamente un archivo de programa (.lsp / .fas / .vlx) en la sesin de dibujo
actual.
La carga funcin toma dos argumentos:
( carga <nombre de archivo> [el fallo] )
Cuando el nombre de archivo es el nombre del archivo de un archivo de programa
para cargar, y en caso de fallo es un argumento opcional a devolver si el programa
no se cargar (esto suele ser una cadena o nulo).
Si el archivo del programa reside en una ruta de AutoCAD Apoyo, el nombre del
archivo slo debe ser el nombre del fichero a cargar; ms se requiere una ruta de
archivo completa para localizar el archivo, por ejemplo:
Archivo que reside en Camino AutoCAD Soporte:
( carga "MyProgram" "MyProgram no se pudo cargar." )
( carga "MyLISP.lsp" "MyLISP no se pudo cargar." )
Archivo residentes en otros pases:
( carga de "C: \\ Mi carpeta \\ MyProgram.vlx"
cargar". )

"MyProgram no se pudo

Tenga en cuenta que se debe omitir la extensin del archivo, la carga de la funcin
agregar .vlx, .fas, .lsp (en ese orden) de parada cuando se encuentra un archivo.
Aunque el fallo en el argumento es opcional, yo recomendara a incluirlo en la
declaracin de carga, de lo contrario la funcin devuelve un error si el archivo no se
cargar.
El uso de este conocimiento podemos llenar nuestro archivo acaddoc.lsp con
instrucciones de carga para ser evaluados cuando el archivo acaddoc.lsp se carga en
el inicio.
De esta manera, el acaddoc.lsp puede ser algo como esto:
( carga de "C: \\ MyLISP.lsp MyPrograms \\" "MyLISP no se pudo
cargar." )
( carga "F: \\ Mi Carpeta \\ MyApp.fas" "MyApp no se pudo cargar." )
( carga "MyProgram" "MyProgram no se pudo cargar." )
Para ayudar en la construccin de un acaddoc.lsp utilizando la carga de la funcin
que he construido un acaddoc.lsp Creador del Programa que puede escribir
declaraciones a la acaddoc.lsp para cargar todos los programas en un directorio (y
subdirectorios) - que le ahorra todo el mecanografiar aburrido .
Una desventaja del uso de la carga de la funcin surge cuando el usuario desea
cargar un gran nmero de programas. Este mtodo va a cargar cada programa en la
memoria cada vez que se abre un dibujo, por lo tanto, si un gran nmero de

programas requieren de carga, puede haber un notable aumento en el tiempo


necesario para abrir un dibujo.aumentaren el tiempo necesario para abrir un dibujo.
Para evitar este retraso de tiempo, los programas pueden ser "demanda-carga ', es
decir, cargado como y cuando un usuario los necesita; para este introduzco la carga
automticade funciones.

La funcin de carga automtica


La carga automtica funcin permite al usuario cargar un archivo de AutoLISP
cuando se introduce un comando especfico en la lnea de comandos. Esto puede
reducir en gran medida el tiempo necesario para abrir un dibujo y la memoria
utilizada si el usuario desea cargar muchos programas automticamente como
programas slo se cargan en la sesin de dibujo cuando sea requerido por el
usuario.
La carga automtica funcin toma el siguiente formato:
( carga automtica <filename> <cmdlist> )
Cuando el nombre de archivo es el nombre de un archivo de AutoLISP y sigue mucho
las mismas reglas que con la carga de la funcin: si el archivo de AutoLISP residir en
una ruta de AutoCAD Apoyo, slo se necesita el nombre del archivo, ms se requiere
una ruta de archivo completa.
El cmdlist es una lista de comandos que, al usuario escribir un comando en la lista,
el nombre de archivo suministrado ser cargado en la sesin de dibujo actual.
Este mtodo se demuestra mejor con un ejemplo. Considere el siguiente programa
LISP:
( defun c: DrawLine (
( si

/ pq )

( y

( setq p ( GetPoint "\ nEspecifique Primer Punto:" ))


( setq q ( GetPoint "\ nEspecifique Punto siguiente:" p )))

( entmake ( lista
0 )) ( contras 11

( cons 0 "lnea" )
( trans q 1 0 ))))

( contras

10

( trans p

)
( princ )
)
El anterior programa simplemente construir una lnea entre dos puntos
seleccionados; pero, lo ms importante de este ejemplo, puede ser llamado con la
sintaxis: DrawLine .
Asumamos que el cdigo de seguridad se guarda en un archivo LISP en una ruta de
AutoCAD Apoyo llamada: LineProgram.lsp .
Exigir a cargar este programa automticamente podramos incluir esta lnea en el
acaddoc.lsp:
( carga automtica

"LineProgram"

' ( "DrawLine" ))

Ahora, al abrir un dibujo o crear un nuevo dibujo, si el tipo de usuario DrawLine en


la lnea de comando, el LineProgram.lsp archivo se cargar en la sesin de dibujo y
el programa comenzar.

En caso de que el archivo de programa contener ms de un comando, los comandos


adicionales pueden ser aadidos a la lista suministrada a la carga
automtica funcin, por lo tanto, la activacin de la carga del archivo suministrado
sobre el usuario escribir cualquier comando en la lista.

Ms informacin
Para ms informacin acerca de las funciones que he demostrado en este tutorial se
puede encontrar en la documentacin VLIDE Ayuda. Luchando para acceder a la
ayuda? Ver mi tutorial aqu .VLIDE Ayuda Documentacin. Luchando para acceder a
la ayuda? Ver mi tutorial

Das könnte Ihnen auch gefallen