Está en la página 1de 103

Ayuda de AutoCAD Página 1 de 103

Aprendizaje de AutoLISP
Información general
Aprendizaje de AutoLISP proporciona lecciones paso a paso en
las que se enseña cómo utilizar Visual LISP™ para desarrollar
una aplicación de AutoLISP®. En Aprendizaje de AutoLISP se Archivos de ayuda
incluyen los siguientes temas:
Manual de personalización
z Introducción AutoLISP Reference
AutoLISP Developer’s Guide
z Diseño e inicio del programa
Aprendizaje de AutoLISP
z Uso de las herramientas de depuración de Visual LISP Manual de referencia de DXF
Manual del desarrollador de ActiveX y
z Dibujo del contorno del camino VBA
z Creación de un proyecto y adición del interface ActiveX and VBA Reference
Sheet Set Objects Reference
z Dibujo de las baldosas Connectivity Automation Reference
z Funcionamiento de los reactivos ObjectARX
Mi Ayuda
z Integración de todos los elementos
Recursos en la Web

Este manual de aprendizaje está diseñado para mostrar las diversas ventajas del entorno de
programación AutoLISP® para AutoCAD® y presentar las funciones del lenguaje AutoLISP con las que
el usuario puede que no esté familiarizado.

El objetivo de este manual de aprendizaje consiste en dibujar un camino de jardín con ayuda de una
herramienta de dibujo automatizada que reduce al mínimo el tiempo de dibujo y muestra las ventajas de
la programación paramétrica. Aprenderá a crear una rutina de dibujo que automatiza la generación de
formas complejas, con el fin de no tener que repetir el mismo diseño una y otra vez.

Temas de esta sección:

z Trabajar con Visual LISP

z Presentación general del aprendizaje

¿Comentarios?

Introducción

Este manual de aprendizaje está diseñado para usuarios con experiencia en AutoCAD y que estén
familiarizados con LISP o AutoLISP. Asimismo, se presupone un conocimiento de las tareas básicas de
administración de archivos de Windows® , como crear carpetas, copiar archivos y desplazarse por el

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 2 de 103

sistema de archivos del disco duro o la red.

En esta guía de aprendizaje encontrará

z Introducción del entorno Visual LISP® (VLISP) Este entorno proporciona herramientas de edición,
depuración, etc. diseñadas para crear aplicaciones de AutoLISP.
z Se presentan las funciones de ActiveX® y Reactor de AutoLISP, así como otras ampliaciones del
lenguaje AutoLISP que se incluyen con VLISP.

Existen dos posibles contextos de ejecución en este aprendizaje.

z Esta aplicación se puede ejecutar como LISP interpretado en archivos independientes y en funciones
cargadas en un solo documento.
z De manera alternativa, el código del programa se puede compilar en una aplicación VLX, que genera
un archivo ejecutable con extensión *.vlx. Los ejecutables VLX funcionan desde un espacio de
nombre autónomo que interactúa con el documento que carga la aplicación

¿Comentarios?

Introducción

El objetivo de este manual de aprendizaje consiste en desarrollar un comando nuevo para AutoCAD
que dibuje un camino de jardín y lo rellene con baldosas circulares. El aprendizaje se divide en siete
ejercicios. A medida que se avanza, las instrucciones sobre cómo efectuar tareas individuales se
ofrecen de forma menos detallada. Si tiene alguna duda, puede encontrar ayuda en la documentación
de VLISP.

Los ejercicios 4 y 5 son de nivel intermedio y exigen el conocimiento de los conceptos básicos de
AutoLISP. Los ejercicios 6 y 7 contienen tareas de programación avanzadas y de considerable
complejidad, y están diseñados para desarrolladores de AutoLISP con experiencia.

Si ha seleccionado la instalación completa al instalar AutoCAD, los archivos de código fuente estarán
en el siguiente directorio:

Directorio de <AutoCAD>\Tutorial\VisualLISP\

Si no ha instalado los ejemplos durante la instalación AutoCAD, vuelva a ejecutar la instalación, elija
Personalizada y, a continuación, seleccione el elemento Aprendizaje.

No es recomendable modificar los archivos de código fuente de ejemplo suministrados con AutoCAD. Si
el programa que está desarrollando no funciona correctamente, puede resultarle útil copiar el código
fuente de ejemplo en el directorio de trabajo. En este manual de aprendizaje, el directorio de trabajo se
denomina:

Directorio de <AutoCAD>\Tutorial\VisualLISP\Micamino

Si elige una ruta distinta para el directorio de trabajo, sustituya este directorio cuando sea necesario.

¿Comentarios?

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 3 de 103

En este primer ejercicio empezará definiendo qué debe hacer la aplicación. En el entorno de desarrollo
Visual LISP® (VLISP) creará un archivo LISP y empezará a escribir el código de AutoLISP® necesario
para la aplicación. Mientras tanto, descubrirá cómo VLISP facilita el desarrollo de las aplicaciones.

Temas de esta sección:

z Definición de los objetos generales del programa

z Para empezar con Visual LISP

z Formato del código de Visual LISP

z Análisis del código

z Últimos retoques del programa

z Comprobación del código por parte de Visual LISP

z Ejecución del programa con Visual LISP

z Repaso de la lección 1

¿Comentarios?

Diseño e inicio del programa

El desarrollo de un programa AutoLISP comienza por la idea de automatizar algún aspecto de


AutoCAD®. Puede que necesite acelerar una función de dibujo repetitiva o simplificar una serie
compleja de operaciones. En el aprendizaje, el camino de jardín que debe dibujar el programa es una
forma compleja con un número de componentes variable, basada en los datos introducidos por el
usuario. Tendrá el siguiente aspecto:

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 4 de 103

El programa debe hacer lo siguiente para dibujar el camino de jardín:

z Trazar un contorno rectilíneo a partir de un punto inicial, un punto final y una anchura. El contorno
puede situarse en cualquier orientación 2D. No debe especificarse un límite de tamaño mínimo ni
máximo.
z Solicitar al usuario valores para el tamaño de las baldosas y el espacio entre las mismas. Las
baldosas son sencillos círculos, que rellenan el contorno sin sobrepasarlo ni solaparse con él.
z Colocar las baldosas en filas alternas.

Si desea ver cómo funciona en la práctica, puede ejecutar una versión completa de la aplicación que se
facilita con AutoCAD.

Para ejecutar el ejemplo proporcionado


1. En el menú Herramientas de AutoCAD, seleccione Cargar aplicación.
2. Seleccione gardenpath.vlx en el directorio Tutorial\VisualLISP y elija Cargar.
3. Seleccione Cerrar.
4. En la solicitud de comando, escriba gpath.
5. Responda a las dos primeras solicitudes eligiendo un punto inicial y un punto final en el área de
dibujo de AutoCAD.
6. Escriba 2 en la solicitud Half Width of Path.
7. Pulse OK cuando lo solicite el cuadro de diálogo Garden Path Tile Specifications.

¿Comentarios?

Diseño e inicio del programa

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 5 de 103

Ahora que ha visto cómo debe funcionar la aplicación, puede empezar a desarrollarla con VLISP. Pero
antes es conveniente comprobar lo que puede ocurrir cuando VLISP espera la devolución del control de
AutoCAD. Es posible que ya haya experimentado esta situación.

Para comprobar cómo Visual LISP espera la devolución del control de AutoCAD
1. En el menú Herramientas de AutoCAD, seleccione Cargar aplicación.
2. Seleccione gardenpath.vlx en el directorio Tutorial\VisualLISP y elija Cargar.
3. Seleccione Cerrar.
4. En la solicitud de comando de AutoCAD, escriba vlisp para iniciar Visual LISP.
5. Vuelva a la ventana de AutoCAD (seleccione AutoCAD en la barra de tareas o pulse ALT + TAB y
seleccione AutoCAD) y, a continuación, escriba gpath en la solicitud de comando de AutoCAD.
6. Antes de responder a las solicitudes de gpath, vuelva a la ventana de VLISP.
En la ventana de VLISP el puntero del ratón tiene el aspecto de un símbolo de VLISP y no
es posible elegir ningún comando ni introducir texto en ninguna parte de esta ventana. El
símbolo del puntero sirve para recordar que, antes de reanudar el trabajo con VLISP, es
necesario terminar una actividad en AutoCAD. Recuerde esto siempre que vea el puntero
de VLISP.
7. Vuelva a la ventana de AutoCAD y responda a todas las solicitudes de gpath.

Ahora puede empezar a crear la aplicación Camino de jardín.

Para iniciar el desarrollo de la aplicación con Visual LISP

1. En el menú Archivo de VLISP, seleccione Nuevo archivo.


2. Introduzca el código siguiente en la ventana de edición de texto (la ventana llamada “<Sin título-
0>”); si lo desea, puede omitir los comentarios:
;;; Function C:GPath is the main program function and defines the
;;; AutoCAD GPATH command.
(defun C:GPath ()
;; Ask the user for input: first for path location and
;; direction, then for path parameters. Continue only if you have
;; valid input.
(if (gp:getPointInput) ;
(if (gp:getDialogInput)
(progn
;; At this point, you have valid input from the user.
;; Draw the outline, storing the resulting polyline
;; "pointer" in the variable called PolylineName.
(setq PolylineName (gp:drawOutline))
(princ "\nThe gp:drawOutline function returned <")
(princ PolylineName)
(princ ">")
(Alert "Congratulations - your program is complete!
)
(princ "\nFunction cancelled.")
)
(princ "\nIncomplete information to draw a boundary.")
)
(princ); exit quietly
)
;;; Display a message to let the user know the command name.
(princ "\nType gpath to draw a garden path.")
(princ)

3. En el menú Archivo , seleccione Guardar como y guarde el código del nuevo archivo en el

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 6 de 103

directorio de <AutoCAD\Tutorial\VisualLISP\Micamino\gpmain.lsp.
4. Revise el trabajo realizado.

¿Comentarios?

Diseño e inicio del programa

VLISP reconoce los diversos tipos de caracteres y palabras que constituyen un archivo de programa de
AutoLISP y resalta los caracteres en distintos colores. Esto facilita una rápida identificación de los
errores. Por ejemplo, si faltan las comillas finales después de una cadena de texto, todo lo que se
escribe a continuación sigue mostrándose en magenta, el color que identifica las cadenas. Cuando se
introducen las comillas cerradas, VLISP aplica el color correcto al texto siguiente a la cadena, según el
elemento del lenguaje que represente.

A medida que se introduce el texto, VLISP le aplica el formato adecuado, agregando espacios y
sangrías. Para que VLISP asigne formato al código copiado en su editor de texto desde otro archivo, en
el menú VLISP seleccione Herramientas Formatear código en editor.

¿Comentarios?

Diseño e inicio del programa

La secuencia de función defun define la nueva función. Observe que la función principal se llama
C:GPath. El prefijo C: establece que es posible llamar a esta función desde la línea de comando de
AutoCAD. GPath es el nombre que introduce el usuario para iniciar la aplicación desde la solicitud de
comando de AutoCAD. Las funciones que obtienen entradas de los usuarios se llaman gp:getPointInput
y gp:getDialogInput. La función que dibuja el contorno del camino de jardín es gp:drawOutline. Estos
nombres van precedidos de gp: para indicar que son específicos de la aplicación del camino de jardín.
No es obligatorio, pero se recomienda utilizar este prefijo para distinguir las funciones específicas de
una aplicación de las funciones de utilidad general que se emplean con frecuencia.

En la función principal, las expresiones princ, muestran el resultado del programa si se ejecuta
adecuadamente o un mensaje de advertencia si surge un imprevisto. Por ejemplo, como se verá en el
Ejercicio 2, si el usuario pulsa INTRO en vez de designar un punto de la pantalla, la llamada a
gp:getPointInput finaliza de forma prematura y devuelve un valor nil a la función principal. Como
consecuencia, el programa emitirá un mensajeprinc que indicará "Incomplete information to draw a
boundary".

La llamada a princ cerca del final del programa hace las veces de solicitud. Cuando se carga la
aplicación, la solicitud comunica al usuario lo que debe escribir para dar comienzo al dibujo de un
camino de jardín. El último princ sin argumento de cadena obliga al programa a finalizar sin respuesta,
esto es, sin devolver el valor de la última expresión de la función principal. Si se omitiera este último
princ inhibidor, la solicitud aparecería dos veces.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 7 de 103

¿Comentarios?

Diseño e inicio del programa

Para que el código de este archivo nuevo funcione correctamente, debe escribir otras tres definiciones
de función. El código principal del camino de jardín contiene llamadas a tres funciones personalizadas:

z gp:getPointInput
z gp:getUserInput
z gp:drawOutline

Por ahora sólo vamos a escribir definiciones de funciones vacías. Las funciones vacías sirven de
marcadores para las funciones completas que se escribirán posteriormente. Permiten experimentar con
fragmentos de código antes de agregar todos los detalles necesarios para completar la aplicación.

Definición de funciones vacías para la aplicación


1. Coloque el cursor en la parte superior del código de programa, en la ventana de edición de texto,
y pulse INTRO un par de veces para agregar líneas en blanco.
2. Introduzca el código siguiente, empezando por el lugar en que se han insertado las líneas en
blanco:
;;; Function gp:getPointInput will get path location and size
(defun gp:getPointInput()
(alert
"Function gp:getPointInput will get user drawing input"
)
;; For now, return T, as if the function worked correctly.
T
)
;;; Function gp:getDialogInput will get path parameters
(defun gp:getDialogInput ()
(alert
"Function gp:getDialogInput will get user choices via a dialog"
)
;; For now, return T, as if the function worked correctly.
T
)
;;; Function gp:drawOutline will draw the path boundary
(defun gp:drawOutline ()
(alert
(strcat "This function will draw the outline of the polyline "
"\nand return a polyline entity name/pointer."
)
)
;; For now, simply return a quoted symbol. Eventually, this
;; function will return an entity name or pointer.
'SomeEname
)

Antes del final de cada función de entrada hay una línea de código que contiene sólo una T. Se utiliza
como valor de devolución para la función que la llama. Todas las funciones de AutoLISP devuelven un
valor a la función que las llama. La letra T simboliza "true" (verdadero) en AutoLISP y cuando se agrega

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 8 de 103

esta letra, la función devuelve un valor verdadero. Tal y como se ha estructurado gpmain.lsp, cada
función de entrada a la que llama debe devolver un valor distinto de nil (que equivale a "ningún valor")
para que el programa continúe con el paso siguiente.

Por defecto, las funciones de AutoLISP devuelven el valor de la última expresión que hayan evaluado.
En las funciones vacías, la única expresión es una llamada a la función alert Pero alert siempre
devuelve nil. Si se deja como última expresión de gp:getPointInput, siempre devolverá nil, y nunca
pasará a la función if para llegar a gp:getDialogInput.

Por un motivo parecido, el final de la función gp:DrawOutline devuelve un símbolo precedido de una
comilla ('SomeEname) como marcador. Un símbolo entre comillas es una construcción LISP que no se
ha evaluado. (Si siente curiosidad por saber cómo funciona el lenguaje LISP; existe un gran número de
libros, mecionados al final de este tutorial.

¿Comentarios?

Diseño e inicio del programa

VLISP cuenta con una útil herramienta para buscar errores de sintaxis en el código. Utilícela antes de
intentar ejecutar el programa. Permite identificar errores mecanográficos frecuentes, como la falta de
paréntesis o comillas y otros problemas sintácticos.

Para comprobar la sintaxis del código


1. Asegúrese de que la ventana de edición de texto que contiene gpmain.lsp es la ventana . (haga
clic en la barra de título de la ventana para activarla.)

2. En el menú de VLISP, elija Herramientas Comprobar texto en editor.


Aparece la ventana Salida de generación mostrando el resultado del análisis sintáctico. Si
VLISP no detecta ningún error, la ventana contiene un texto parecido al siguiente:
[CHECKING TEXT GPMAIN.LSP loading...]
......
; Check done.

Si necesita ayuda, consulte la sección “Introducción del entorno Visual LISP” de AutoLISP Developer’s
Guide. Intente averiguar dónde se encuentra el problema. Si tarda demasiado tiempo en localizar el
problema, utilice el archivo de muestra gpmain.lsp, que se encuentra en el directorio lesson1, para
continuar con el aprendizaje.

Para utilizar el programa suministrado gpmain.lsp (en caso necesario)


1. Cierre la ventana de edición de texto que contiene el código de gpmain.lsp que ha introducido.
2. En el menú de VLISP, elija Archivo Abrir archivo y abra el archivo gpmain.lsp del directorio
\Tutorial\VisualLISP\lesson1
3. Seleccione el menú Archivo Guardar como y guarde el archivo en el directorio \Tutorial\
VisualLISP\Miruta con el nombre gpmain.lsp, sustituyendo la copia que había creado.

¿Comentarios?

Diseño e inicio del programa

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 9 de 103

La ejecución de programas de AutoLISP en VLISP permite utilizar las múltiples funciones de depuración
de VLISP para investigar los problemas que pueden surgir en la aplicación.

Para cargar y ejecutar el programa


1. Con la ventana de edición de texto activa, elija en el menú Herramientas para cargar texto en
editor en el menú VLISP.
2. En la solicitud _$ de la ventana Consola de VLISP, escriba (C:GPath).
La ventana Consola espera que los comandos se introduzcan en sintaxis de AutoLISP, por
lo que todos los nombres de funciones deben encontrarse entre paréntesis.
3. Pulse INTRO o el botón Aceptar en respuesta a las ventanas de mensaje. El último mensaje que
aparece es "Congratulations your program is complete!”

Nota Si AutoCAD se encuentra minimizado al ejecutar gpath, no se podrán ver las solicitudes hasta que
se restablezca la ventana de AutoCAD (por medio de la barra de tareas o ALT + TAB).

¿Comentarios?

Diseño e inicio del programa

En esta lección:

z Ha definido los objetivos del programa.


z Ha aprendido el valor de las funciones vacías.
z Ha aprendido a asignar nombres a las funciones para indicar si pertenecen a una aplicación o si son
funciones generales que pueden utilizarse varias veces.
z Ha aprendido a utilizar VLISP para comprobar el código.
z Ha aprendido a cargar y ejecutar programas en VLISP.

Este ejercicio ha terminado. Vuelva a guardar el archivo del programa para asegurarse de que contiene
las últimas modificaciones.

¿Comentarios?

En este capítulo aprenderá a utilizar las distintas herramientas de depuración de Visual LISP® para
hacer más rápido el desarrollo de los programas AutoLISP®. También aprenderá la diferencia entre las

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 10 de 103

variables locales y globales, y cuándo utilizarlas. El programa se comportará de forma más activa y
pedirá a los usuarios que introduzcan información. La información se almacenará en una lista y
empezará a entender la utilidad de las listas dentro de los programas de AutoLISP. A fin de cuentas,
LISP recibe este nombre por ser un lenguaje que procesa listas

Temas de esta sección:

z Diferencia entre variables locales y globales

z Utilización de listas de asociaciones para agrupar datos

z Examen de las variables del programa

z Revisión del código del programa

z Comentarios en el código del programa

z Establecimiento de puntos de interrupción y uso de varias ventanas de inspección

z Repaso de la Lección 2

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

En este ejercicio se trata el uso de las variables locales comparadas con las variables de documento
globales. Puede acceder a las variables globales desde todas las funciones cargadas en un documento
(un dibujo de AutoCAD®). Estas variables pueden conservar su valor después de que finalice el
programa que las ha definido. En ocasiones, esto es lo deseable. Más adelante, en este ejercicio, se
presenta un ejemplo.

Las variables locales sólo conservan su valor mientras se ejecuta la función que las ha definido.
Cuando la función termina de ejecutarse, los valores de la variable local se desechan automáticamente,
y el sistema vuelve a tener a su disposición la memoria que utilizaba la variable. Esto se conoce como
recuperación automática de la memoria no usada y es una función de la mayoría de los entornos de
desarrollo LISP, como VLISP. Las variables locales utilizan la memoria con más eficacia que las
globales.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 11 de 103

Otra importante ventaja consiste en que las variables locales facilitan la depuración y el mantenimiento
de las aplicaciones. Con las variables globales no se sabe nunca cuándo ni en qué función se puede
modificar su valor; mientras que en las variables locales la detección de errores es más fácil.
Normalmente se producen menos efectos secundarios (es decir, cuando una parte del programa afecta
a una variable de otra parte del programa).

A causa de las ventajas mencionadas, en este aprendizaje se utilizan casi exclusivamente variables
locales.

Nota Si ha utilizado AutoLISP concierta frecuencia, probablemente estará acostumbrado a utilizar las
variables globales para examinar el programa que está desarrollando. Esto ya no es necesario, gracias
a las completas herramientas de depuración de VLISP.

Temas de esta sección:

z Uso de variables locales en el programa

z Examen de la función gp:getPointInput

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

Volvamos a la función gp:getPointInput creada en el Ejercicio 1:

(defun gp:getPointInput()
(alert
"Function gp:getPointInput will get user drawing input"
)
;; For now, return T, as if the function worked correctly.
T
)

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 12 de 103

Por el momento, no sirve para gran cosa. Ahora empezaremos a construirla, agregándole funciones
para pedir datos al usuario, que definirá el punto inicial, el punto final y la anchura del camino.

Es un método recomendado al crear programas AutoLISP para emular el comportamiento de AutoCAD.


Por tanto, en vez de pedir al usuario que indique la anchura designando un punto en el dibujo relativo a
la línea central de una forma lineal, el programa pedirá que se designe la mitad de la anchura.

Cuando la función gp:getPointInput está completa, las variables y los valores que tienen asignados
dejan de existir. Por tanto, los valores introducidos por el usuario se almacenan en variables locales.
Éste es el aspecto que puede presentar la función:

(defun gp:getPointInput(/ StartPt EndPt HalfWidth)


(if (setq StartPt (getpoint "\nStart point of path: "))
(if (setq EndPt (getpoint StartPt "\nEndpoint of path: "))
(if (setq HalfWidth (getdist EndPt "\nhalf-width of path: "))
T
)
)
)
)

Las variables locales se declaran a continuación de la barra oblicua, en la secuencia defun que da
comienzo a la función. La primera llamada a getpoint solicita al usuario que indique un punto inicial. A
continuación, el punto final se calcula en relación con el punto inicial elegido. Mientras selecciona el
punto final, el usuario observará una línea elástica que se extiende desde el punto inicial. Del mismo
modo, al establecer el valor de la mitad de la anchura, el usuario podrá ver otra línea elástica, esta vez
representando la distancia, que surge del punto final.

Para ver cómo funciona gp:getPointInput


1. Escriba el código de gp:getPointInput en la ventana de consola de VLISP.
2. Con el cursor de la ventana de consola después del último paréntesis del bloque de código (o en
la línea siguiente), pulse INTRO para sustituir cualquier versión de la función gp:getPointInput que
haya cargado anteriormente.
3. Ejecute la función desde la ventana de consola escribiendo(gp:getPointInput)en la solicitud de la
consola.
4. Designe los puntos que se le piden y escriba elvalor de la mitad de la anchura.

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

Al ejecutar la función gp:getPointInput, el control se pasó automáticamente de VLISP a AutoCAD.


Respondió a tres solicitudes, tras lo cual, el control se volvió a pasar de AutoCAD a VLISP y se mostró
el símbolo T en la ventana Consola.

Esto es lo que ha ocurrido dentro del programa:

1. VLISP espera a que se designe el primer punto.


2. Al designar el primer punto, el programa almacena el valor de la selección (una lista que contiene
tres valores de coordenadas: X, Y y Z) en la variable StartPt.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 13 de 103

3. La primera funciónif examina el resultado para averiguar si se ha introducido un valor válido o no


se ha introducido ningún valor. Cuando se designa un punto inicial, el control pasa a la siguiente
función getpoint.
4. Cuando se designa un punto final, su valor se almacena en la variable Endpt .
5. El resultado de esta secuencia se examina en la siguiente secuencia if y el control pasa a la
función getdist.
6. La función getdist actúa de forma parecida cuando se designa un punto en la pantalla o se
introduce un valor numérico. El resultado de la función getdist se almacena en la variable
HalfWidth.
7. El flujo del programa alcanza la T que se encuentra anidada dentro de la función. Como no existe
ninguna función más, la función termina y se devuelve el valor T. Ésta es la T que se ve en la
ventana de consola.

Se necesita una forma de transmitir los valores de una función a otra. Una manera de conseguirlo
consiste en crear una lista de los valores recuperados de gp:getPointInput, como se indica en el código
siguiente:

(defun gp:getPointInput(/ StartPt EndPt HalfWidth)


(if (setq StartPt (getpoint "\nStart point of path: "))
(if (setq EndPt (getpoint StartPt "\nEndpoint of path: "))
(if (setq HalfWidth (getdist EndPt "\nhalf-width of path: "))
(list StartPt EndPt HalfWidth)
)
)
)
)

Copie esta versión de gp:getPointInput en la ventana de consola y pulse INTRO. Ahora dispone de la
oportunidad de utilizar otra característica de la ventana de consola.

Para utilizar la función de historial de la ventana de consola con el fin de ejecutar


gp:getPointInput
1. Pulse TAB.
Esta acción llama al comando Historial de consola, que recorre los comandos introducidos
anteriormente en la consola. Si pasa de largo, pulse MAYÚS + TAB para desplazarse en
sentido contrario.
2. Cuando vea (gp:getPointInput) en la solicitud de la consola, pulse INTRO para volver a ejecutar la
función.
3. Responda a las solicitudes como antes.

La función devuelve una lista que contiene dos listas anidadas y un valor real (de coma flotante). Los
valores devueltos son parecidos a los siguientes:

((4.46207 4.62318 0.0) (7.66688 4.62318 0.0) 0.509124)

Estos valores corresponden a las variables StartPt,EndPt y HalfWidth.

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 14 de 103

El ejemplo anterior funciona, pero se puede mejorar. En el siguiente ejercicio se va a crear una lista de
asociaciones o lista assoc (llamada así por la función de LISP que gestiona las listas de asociaciones).
En las listas de asociaciones los valores que nos interesan se asocian a valores clave. He aquí un
ejemplo:

((10 4.46207 4.62318 0.0) (11 7.66688 4.62318 0.0) (40 . 1.018248))

En la lista de asociaciones de ejemplo, los valores clave son los números 10, 11 y 40. Estos valores
clave son el índice unívoco de la lista. Es el mecanismo que utiliza AutoCAD para devolver datos de
entidades a AutoLISP cuando accede a una entidad desde su programa. El valor clave 10 indica un
punto inicial, y el 11 se utiliza normalmente para el punto final.

Tal vez se pregunte cuáles son las ventajas de las listas de asociaciones. Para empezar, a diferencia
de las listas normales, el orden de los valores devueltos no tiene importancia. Observe de nuevo la
primera lista:

((4.46207 4.62318 0.0) (7.66688 4.62318 0.0) 0.509124)

Los valores devueltos no indican qué sublista es el punto inicial ni cuál es el punto final. Además, si la
función se modifica posteriormente, cualquier otra función que dependa de los datos devueltos en un
orden determinado puede verse afectada negativamente.

Si se utiliza una lista de asociaciones, el orden de los valores no tiene importancia. Si cambia el orden
de una lista de asociaciones se puede saber de todas formas qué define cada valor. Por ejemplo, un
valor 11 sigue siendo un punto final, independientemente del lugar que ocupe en la lista general.

((11 7.66688 4.62318 0.0) ; order of list


(40 . 1.018248) ; has been
(10 4.46207 4.62318 0.0)) ; modified

Temas de esta sección:

z Utilización de las listas de asociaciones

z Almacenamiento del valor devuelto por gp:getPointInput en una variable

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

Cuando se utilizan listas de asociaciones se debe documentar qué representan los valores clave. En el
Camino de jardín, los valores clave 10, 11, 40, 41 y 50 significan lo siguiente:

z 10 indica la coordenada 3D del punto inicial del camino.


z 11 indica la coordenada 3D del punto final del camino.
z 40 indica la anchura del camino (no la mitad de la anchura).
z 41 indica la longitud del camino, del principio al final.
z 50 indica el vector (o el ángulo) primario del camino.

A continuación se muestra una versión actualizada de la función gp:getPointInput. En ella, una función
de AutoLISP llamada cons (abreviatura de "construir lista") crea las sublistas con claves que pertenecen
a la lista de asociaciones. Copie esta versión en la ventana de consola, pulse INTRO y ejecute

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 15 de 103

(gp:getPointInput) de nuevo:

(defun gp:getPointInput(/ StartPt EndPt HalfWidth)


(if (setq StartPt (getpoint "\nStart point of path: "))
(if (setq EndPt (getpoint StartPt "\nEndpoint of path: "))
(if (setq HalfWidth (getdist EndPt "\nhalf-width of path: "))
;; if you've made it this far, build the association list
;; as documented above. This will be the return value
;; from the function.
(list
(cons 10 StartPt)
(cons 11 EndPt)
(cons 40 (* HalfWidth 2.0))
(cons 50 (angle StartPt EndPt))
(cons 41 (distance StartPt EndPt))
)
)
)
)
)

Recuerde que al construir la lista, el programa convierte la mitad de la anchura especificada por el
usuario en la anchura total multiplicando el valor por 2.

La ventana de consola muestra una salida parecida a la siguiente:

_$ (gp:getPointInput)
((10 2.16098 1.60116 0.0) (11 12.7126 7.11963 0.0) (40 . 0.592604) (50 . 0.4818
_$

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

Ahora vamos a intentar otra cosa. Vuelva a llamar a la función, pero esta vez, almacenará el valor
devuelto en una variable llamada gp_PathData. Para ello, escriba lo siguiente en la solicitud de la
ventana de consola:

(setq gp_PathData (gp:getPointInput))

Para ver el valor de la variable que acaba de definir, escriba su nombre en la solicitud de la ventana de
consola:

_$ gp_PathData

VLISP devuelve unos datos como los siguientes:

((10 2.17742 1.15771 0.0) (11 13.2057 7.00466 0.0) (40 . 1.12747) (50 . 0.48749

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 16 de 103

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

VLISP proporciona un conjunto completo de herramientas de programación y depuración. Una de las


herramientas más útiles es Inspección, que permite observar las variables con mayor detalle que en la
ventana de consola de VLISP. También es posible observar las variables locales de las funciones que
se están ejecutando.

Para observar el valor de una variable


1. En el menú de VLISP, elija Depurar . VLISP muestra el cuadro de diálogo “ Añadir inspección”.

Escriba el nombre de la variable que desea examinar. En este ejemplo, escriba


gp_PathData,, la variable que acaba de establecer en la ventana de consola. VLISP
muestra una ventana Inspección:

VLISP presenta el valor de la variable en una sola línea de la ventana Inspección (la
ventana básica mostrada en la ilustración). En este caso, el valor de la variable es una lista
muy larga, que no se puede ver entera. Se puede cambiar de tamaño la ventana
Inspección arrastrando su marco, pero hay una alternativa mejor.
2. En la ventana Inspección, haga doble clic en el nombre de la variable. Se abre una ventana
Inspeccionar:

La ventana Inspeccionar indica el tipo de datos de la variable que se está inspeccionando


(en este caso, una lista) y el valor de la variable. Cuando se trata de listas, Inspeccionar
muestra cada elemento en una línea.
3. Haga doble clic en la línea con la clave de lista de asociación 11. VLISP abre otra ventana
Inspeccionar:

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 17 de 103

4. Cuando termine de inspeccionar las variables, cierre todas las ventanas Inspeccionar, pero deje
abierta la ventana Inspección.

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

Ahora que ha visto cómo utilizar las listas de asociaciones en código AutoLISP, puede utilizar este
método para escribir la versión completa de la función gp:getPointInput. Utilice el código siguiente para
sustituir o modificar la versión de gp:getPointInput que guardó anteriormente en gpmain.lsp.

Nota Si necesita o desea escribir el código en gpmain.lsp, en vez de copiarlo de otro archivo, puede
ahorrar tiempo si omite los comentarios (todas las líneas que empiezan con un punto y coma). No
obstante, no es aconsejable acostumbrarse a escribir código sin comentarios.
;;;--------------------------------------------------------------;
;;; Function: gp:getPointInput ;
;;;--------------------------------------------------------------;
;;; Description: This function asks the user to select three ;
;;; points in a drawing, which will determine the ;
;;; path location, direction, and size. ;
;;;--------------------------------------------------------------;
;;; If the user responds to the get functions with valid data, ;
;;; use startPt and endPt to determine the position, length, ;
;;; and angle at which the path is drawn. ;
;;;--------------------------------------------------------------;
;;; The return value of this function is a list consisting of: ;
;;; (10 . Starting Point) ;; List of 3 reals (a point) denoting ;
;;; ;; starting point of garden path. ;
;;; (11 . Ending Point) ;; List of 3 reals (a point) denoting ;
;;; ;; ending point of garden path. ;
;;; (40 . Width) ;; Real number denoting boundary ;
;;; ;; width. ;
;;; (41 . Length) ;; Real number denoting boundary ;
;;; ;; length. ;
;;; (50 . Path Angle) ;; Real number denoting the angle ;
;;; ;; of the path, in radians. ;
;;;--------------------------------------------------------------;
(defun gp:getPointInput(/ StartPt EndPt HalfWidth)
(if (setq StartPt (getpoint "\nStart point of path: "))

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 18 de 103

(if (setq EndPt (getpoint StartPt "\nEndpoint of path: "))


(if (setq HalfWidth (getdist EndPt "\nhalf-width of path: "))
;; if you've made it this far, build the association list
;; as documented above. This will be the return value
;; from the function.
(list
(cons 10 StartPt)
(cons 11 EndPt)
(cons 40 (* HalfWidth 2.0))
(cons 50 (angle StartPt EndPt))
(cons 41 (distance StartPt EndPt))
) ) ) ) )

A continuación es necesario actualizar la función principal, C:GPath, en gpmain.lsp. Modifíquela de


acuerdo con el código siguiente:

(defun C:GPath (/ gp_PathData)


;; Ask the user for input: first for path location and
;; direction, then for path parameters. Continue only if you
;; have valid input. Store the data in gp_PathData.
(if (setq gp_PathData (gp:getPointInput))
(if (gp:getDialogInput)
(progn
;; At this point, you have valid input from the user.
;; Draw the outline, storing the resulting polyline
;; pointer in the variable called PolylineName.
(setq PolylineName (gp:drawOutline))
(princ "\nThe gp:drawOutline function returned <")
(princ PolylineName)
(princ ">")
(Alert "Congratulations - your program is complete!
) ;_ end of progn
(princ "\nFunction cancelled.")
) ;_ end of if
(princ "\nIncomplete information to draw a boundary.")
) ;_ end of if
(princ); exit quietly
) ;_ end of defun

Si está copiando y pegando el código, agregue los siguientes comentarios como cabecera, antes de
C:GPath:

;;;**************************************************************;
;;; Function: C:GPath The Main Garden Path Function ;
;;;--------------------------------------------------------------;
;;; Description: This is the main garden path function. It is a ;
;;; C: function, meaning that it is turned into an ;
;;; AutoCAD command called GPATH. This function ;
;;; determines the overall flow of the garden path ;
;;; program. ;
;;;**************************************************************;
;;; The gp_PathData variable is an association list of the form: ;
;;; (10 . Starting Point) - List of 3 reals (a point) denoting ;
;;; starting point of the garden path. ;
;;; (11 . Ending Point) - List of 3 reals (a point) denoting ;
;;; endpoint of the garden path. ;
;;; (40 . Width) - Real number denoting boundary ;
;;; width. ;
;;; (41 . Length) - Real number denoting boundary ;

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 19 de 103

;;; length. ;
;;; (50 . Path Angle) - Real number denoting the angle of ;
;;; the path, in radians. ;
;;; (42 . Tile Size) - Real number denoting the size ;
;;; (radius) of the garden path tiles. ;
;;; (43 . Tile Offset) - Spacing of tiles, border to border. ;
;;; ( 3 . Object Creation Style) ;
;;; - Object creation style indicates how ;
;;; the tiles are to be drawn. The ;
;;; expected value is a string and one ;
;;; one of three values (string case ;
;;; is unimportant): ;
;;; "ActiveX" ;
;;; "Entmake" ;
;;; "Command" ;
;;; ( 4 . Polyline Border Style) ;
;;; - Polyline border style determines ;
;;; the polyline type to be used for ;
;;; path boundary. The expected value ;
;;; one of the following (string case is;
;;; unimportant): ;
;;; "Pline" ;
;;; "Light" ;
;;;**************************************************************;

Para comprobar las revisiones de código:


1. Guarde el archivo actualizado.
2. Busque errores de sintaxis con la herramienta Comprobar.
3. Dé formato al código para hacerlo más legible.
4. Cargue el código para que VLISP redefina las versiones anteriores de las funciones.
5. Para ejecutar el programa, escriba (c:gpath) en la solicitud de la consola.

Si el programa no se ejecuta correctamente, intente arreglarlo y ejecútelo de nuevo. Repita el proceso


hasta que no se sienta capaz de continuar. Si todo lo demás falla, puede copiar el código correcto del
directorio Tutorial\VisualLISP\lesson2.

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

VLISP considera comentarios todas las declaraciones de AutoLISP que empiezan por punto y coma.
Los dos últimos ejemplos de código contenían muchos comentarios. Los comentarios del código de
AutoLISP se escriben como aclaración para el desarrollador, y no influyen en la ejecución del programa.
Es conveniente incluir siempre comentarios en el código. Tal vez se pregunte por qué.

z Suponga que dentro de nueve meses tiene que modificar el programa para añadirle funciones que
los usuarios echan en falta. Es posible que no recuerde exactamente lo que ha hecho, y la secuencia
de funciones que ahora le parece más clara le puede parecer en el futuro una serie de paréntesis
irreconocible.
z Además, los comentarios también sirven para explicar el código a otras personas encargadas de
actualizar el programa. Leer el código de otra persona puede resultar muy frustrante, sobre todo si

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 20 de 103

contiene pocos comentarios.

VLISP contiene varias utilidades que pueden ayudar a comentar el código. Observe que algunos de los
comentarios del ejemplo empiezan con tres puntos y coma (;;;), otros con dos (;;) y otros sólo con uno
(;). Para ver cómo VLISP gestiona los distintos comentarios, consulte “Applying Visual LISP Comment
Styles” en el AutoLISP Developer’s Guide.

Para ahorrar espacio y no malgastar papel, los siguientes ejemplos de código de este aprendizaje no
incluyen todos los comentarios que contienen los archivos de código fuente de muestra. Se presupone
que ya ha adquirido la conveniente costumbre de añadir comentarios y lo hará sin que se lo
recordemos.

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

Los puntos de interrupción son símbolos (puntos) que se colocan en el código fuente para indicar dónde
se desea que se deje de ejecutar temporalmente un programa. Cuando se ejecuta el código, VLISP
continúa con normalidad hasta llegar a un punto de interrupción. En ese punto, VLISP suspende la
ejecución y espera a que el usuario le diga lo que tiene que hacer. No se detiene el programa
definitivamente, únicamente se mantiene en un estado de animación suspendida.

Mientras el programa está detenido, se puede:

z Repasar el código, función por función o expresión por expresión.


z Reanudar la ejecución normal del programa en cualquier parte,
z Modificar el valor de las variables de forma dinámica y cambiar el resultado del programa que se
ejecuta.
z Agregar variables a la ventana Inspección.

Temas de esta sección:

z Uso de la barra de herramientas de depuración

z Revisión del código

z Inspección de variables mientras se avanza por el programa

z Salida de la función gp:getPointInput y entrada en C:Gpmain

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 21 de 103

La barra de herramientas de depuración contiene distintas herramientas que se utilizarán a lo largo de


esta sección. Esta barra de herramientas está enlazada por defecto a las barras de herramientas Ver y
Herramientas, y aparece como barra de herramientas de VLISP independiente.

La barra de herramientas de depuración está compuesta por el conjunto de iconos de la izquierda. La


mayoría de los elementos de la barra se encuentran inactivos hasta que se ejecuta un programa en
modo depuración (esto es, con uno o varios puntos de interrupción definidos).

Si no lo ha hecho aún, quite la barra de herramientas de depuración de la parte superior de la pantalla.


Para ello, arrástrela por los dos pinzamientos verticales que tiene a la izquierda. Todas las barras de
herramientas de VLISP se pueden colocar en la parte de la pantalla en la que resulten más cómodas.

La barra de herramientas de depuración se divide en tres grupos, cada uno de los cuales tiene tres
botones. Cuando se ejecuta un programa en modo depuración la barra de herramientas presenta este
aspecto:

z Los tres primeros botones permiten avanzar por el código del programa.
z Los tres botones siguientes permiten determinar la forma en que VLISP debe continuar la ejecución
después de detenerse en un punto de interrupción o en un error.
z Los tres botones siguientes sirven para colocar o eliminar un punto de interrupción, agregar un
Inspección y saltar a la posición del código fuente en la que se produjo la última interrupción

El último botón de la barra de herramientas de depuración es un indicador de pasos. No ejecuta


ninguna función, sino que proporciona una indicación visual del lugar donde se encuentra el cursor a
medida que revisa el código. Cuando no se efectúa la ejecución en modo depuración, este botón
aparece en blanco.

Para establecer un punto de interrupción


1. En la ventana de edición de VLISP que contiene gpmain.lsp, coloque el cursor justo delante del
paréntesis de apertura de la función setq de la siguiente línea de código, dentro de la función
gp:getPointInput:
(setq HalfWidth (getdist EndPt "\nhalf-width of path: "))

2. Haga clic una vez. Esta posición se muestra en la siguiente instantánea de pantalla:

3. Con el punto de inserción definido, pulse el botón Act/Des punto interrupción en la barra de
herramientas Depurar.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 22 de 103

El botón Act/Des punto interrupción es un conmutador que alterna entre los estados de
activado y desactivado. Si no hay un punto de interrupción en la posición del cursor, lo
añade; si ya hay uno, lo elimina.
4. Pulse el botón Cargar ventana de edición activa en la barra Herramientas para cargar el archivo.

5. Ejecute la función (C:GPath) desde la solicitud de la consola de VLISP.


VLISP ejecuta el programa normalmente hasta llegar al punto de interrupción. En este
caso, solicita los puntos inicial y final del camino.
6. Designe los puntos inicial y final cuando se solicite.
Después de establecer los puntos, VLISP suspende la ejecución del programa y devuelve
el foco a la ventana de edición de texto, resaltando la línea de código en la que se
encuentra el punto de ruptura:

Se deben observar un par de aspectos:

z El cursor se encuentra justo en el punto de interrupción. Esto puede ser difícil de ver, por lo que
VLISP proporciona otra pista.
z En la barra de herramientas de depuración, el icono indicador de pasos presenta un cursor en I rojo
delante de unos paréntesis. Esto indica que el depurador de VLISP está detenido antes de la
expresión.

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

Hay tres botones que se pueden utilizar para revisar el código. Se trata de los tres iconos que se
encuentran en la parte izquierda de la barra de herramientas de depuración. Representan, por orden,

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 23 de 103

las siguientes acciones:

z Entrar en la expresión resaltada.


z Pasar al final de la expresión resaltada.
z Salir de la función en la que el programa se encuentra detenido.

Antes de pulsar uno de estos botones, observe de nuevo el estado del código resaltado, la posición del
cursor y el botón indicador de pasos. En resumen: se resalta un expresión, que consiste en anidar una
función getdist en una función setq y colocar el cursor justo al principio del bloque resaltado.

Para avanzar por el código a partir del punto de interrupción

1. Pulse el botón Pasar al siguiente.


Después de pulsar este botón, el control pasa a AutoCAD y se le pide que especifique la
mitad de la anchura.
2. Responda a la solicitud.
Después de establecer la anchura el control vuelve a VLISP. Observe dónde se encuentra
el cursor y qué muestra el botón indicador de pasos.
VLISP evalúa toda la expresión resaltada y se detiene al final.
3. Pulse de nuevo el botón Pasar al siguiente. VLISP salta al principio del siguiente bloque de código
y lo resalta entero.

4. Pulse el botón Entrar (no Pasar al siguiente).

Nota Durante este ejercicio, si se pulsa el botón incorrecto y se salta un paso o dos es muy fácil volver
a empezar. En primer lugar, pulse el botón Restablecer de la barra de herramientas de depuración. Esto
pone fin a la ejecución del código de VLISP y restablece el sistema VLISP al nivel superior. A
continuación, vuelva a empezar por el primer paso.

Ahora está resaltada la primera función cons, y VLISP se detiene justo antes de la función (observe el
botón indicador de pasos).

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

Mientras se avanza por un programa es posible agregar variables a la ventana Inspección y cambiar su
valor.

Si no se ve la ventana Inspección, pulse el botón de la ventana Inspección en la barra de herramientas


para volver a mostrarla.

Si la ventana Inspección contiene aún la variable gp_PathData, pulse el botón Borrar ventana que se
encuentra en la parte superior de la ventana.

Para agregar variables a la ventana Inspección


1. Haga doble clic en cualquier lugar en que aparezca StartPt, en la ventana de edición de texto de
VLISP. Éste es el nombre de la variable cuyo valor desea rastrear.
2. Pulse el botón Añadir inspección de la ventana Inspección, o haga clic con el botón derecho del

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 24 de 103

ratón y elija Añadir inspección.


3. Repita este proceso con las variables EndPt y HalfWidth. La ventana Inspección debe tener un
aspecto parecido al siguiente:

Si está depurando un programa que no funciona correctamente, utilice puntos de interrupción en


combinación con Inspecciones para comprobar si las variables contienen los valores esperados.

Si una variable no contiene el valor que considera que le corresponde, puede cambiarlo y ver cómo
influye sobre el programa. Por ejemplo, supongamos que espera que el valor halfwidth sea un número
entero. Sin embargo, como no fue preciso al designar los puntos durante la selección de entradas
acabó con un valor de 1,94818.

Para cambiar el valor de una variable mientras se ejecuta el programa


1. Escriba lo siguiente en la solicitud de la consola:
(setq halfwidth 2.0)

Observe que el valor de la ventana Inspección cambia. Sin embargo, esto no garantiza que
se vaya a utilizar el valor nuevo en la creación de la sublista de anchura (40 . width) en la
lista de asociaciones. Agregue otra expresión a la ventana Inspección para comprobarlo.
2. En el menú de VLISP elija Depurar Inspeccionar última evaluación.
Esto agrega una variable llamada *Last-Value* a la ventana Inspección. <:imk 127)
*Last‑Value* es una variable global en la que VLISP guarda automáticamente el valor de
la última expresión evaluada.
3. Avance por el programa (pulsando Entrar o Pasar al siguiente) hasta que se evalúe la expresión
encargada de crear la sublista width. El código de esta acción es:
(cons 40 (* HalfWidth 2.0))

Si se ha sustituido el valor de HalfWidth de la forma indicada, la evaluación de esta


expresión debe devolver (40 . 4.0) en la ventana Inspección.

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

Queda por explicar otro punto: ¿qué ocurre con el valor de las variables locales de gp:getPointInput al
salir de la función?.

Para salir de gp:getPointInput y devolver el control a c:gpath

1. Pulse el botón Ir al final


VLISP pasa al final de la función gp:getPointInput y se detiene justo

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 25 de 103

2. Pulse el botón Entrar.

El control vuelve a c:gpmain, la función que ha llamado a gp:getPointInput.

Examine los valores de las variables de la ventana Inspección. Dado que son variables locales de la
función gp:getPointInput, el valor de endpt y StartPt es nil. VLISP ha vuelto a ocupar automáticamente
la memoria que ocupaban estas variables. Normalmente, HalfWidth, la tercera variable local de la
función, también tiene como valor nil, pero a causa de la actividad de depuración, se ha sustituido
globalmente en la ventana de consola y sigue teniendo un valor 2.0 en la ventana Inspección. También
la variable global *Last-Value* presenta la lista de asociaciones creada por gp:getPointInput.

Acaba de finalizar su primera sesión de depuración. Pero no olvide que el programa sigue en animación
suspendida.

Para completar este ejercicio


1. Pulse el botón Continuar de la barra de herramientas de depuración. Responda a las solicitudes.
Se ejecuta el programa hasta el final.
2. En el menú de VLISP, elija Depurar Borrar todos puntos interrupción. Responda "sí" a la
solicitud. Así, se eliminan todos los puntos de interrupción del código.
Recuerde: para suprimir puntos de interrupción individuales, coloque el cursor en el punto y
pulse el botón Act/Des punto interrupción.

¿Comentarios?

Uso de las herramientas de depuración de Visual LISP

En esta lección:

z Ha aprendido la diferencia entre las variables locales y globales.


z Ha colocado y ha quitado puntos de interrupción en un programa.
z Ha revisado un programa durante su ejecución.
z Ha observado y ha modificado de forma dinámica el valor de las variables del programa durante su
ejecución.
z Ha visto cómo las variables locales se restablecen a nil después de ejecutarse la función que las
define.

Las herramientas que ha aprendido a utilizar en este ejercicio formarán parte de su trabajo cotidiano si
pretende desarrollar aplicaciones de AutoLISP con LISP.

¿Comentarios?

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 26 de 103

En este ejercicio va a ampliar el programa para poder dibujar algo en AutoCAD: el contorno de la
polilínea del camino de jardín. Para dibujar el borde es necesario crear funciones de utilidades que no
pertenecen a una sola aplicación, sino que son de índole general y se podrán reutilizar más adelante.
También va a aprender a escribir funciones que aceptan argumentos (datos que se transmiten a la
función desde fuera) y por qué el uso de argumentos es muy importante en programación. Cuando
termine con este ejercicio, dibujará una figura de AutoCAD de forma paramétrica, esto decir, dibujará de
forma dinámica una figura basada en los parámetros facilitados exclusivamente por el usuario.

Temas de esta sección:

z Planificación de las funciones de utilidades reutilizables

z Dibujo de entidades de AutoCAD

z Activación de la función de dibujo del contorno

z Repaso de la lección 3

¿Comentarios?

Dibujo del contorno del camino

Las funciones de utilidades llevan a cabo tareas comunes a muchas de las aplicaciones que escribirá.
Estas funciones constituyen un conjunto de herramientas que se podrá utilizar una y otra vez.

Cuando se crea una función como parte de un conjunto de herramientas es conveniente invertir cierto
tiempo en su documentación detallada. También es aconsejable incluir en los comentarios las
características que se desea agregar a la función en el futuro.

Temas de esta sección:

z Conversión de grados a radianes

z Conversión de puntos 3D en puntos 2D

¿Comentarios?

Dibujo del contorno del camino

Ahora va a crear una función que evita tener que escribir de forma repetitiva una ecuación. Tiene el
siguiente aspecto:

(defun Degrees->Radians (numberOfDegrees)


(* pi (/ numberOfDegrees 180.0)))

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 27 de 103

Esta función se llama Degrees->Radians. El nombre de la función indica su finalidad.

Tal vez se pregunte para qué necesita una función que convierte medidas angulares. Internamente,
AutoCAD® utiliza radianes para medir los ángulos, aunque es más habitual pensar en grados. Esta
función del conjunto de herramientas permite pensar en grados y hace que AutoLISP ® los convierta a
radianes.

Para probar la función de utilidades


1. Escriba lo siguiente en la solicitud de la consola de VLISP:
(defun Degrees->Radians (numberOfDegrees)
(* pi (/ numberOfDegrees 180.0)))

2. Escriba lo siguiente en la solicitud de la consola de VLISP:


(degrees->radians 180)

La función devuelve el número 3.14159. Según el funcionamiento de la función, 180 grados


equivalen a 3.14159 radianes.

Para utilizar esta función dentro del programa basta con copiar su definición de la ventana de consola
en el archivo gpmain.lsp. Se puede pegar en cualquier lugar del archivo, siempre y cuando no se sitúe
dentro de otra función.

Para limpiar el trabajo, seleccione el texto que acaba de pegar y pulse el botón Formatear selección;
VLISP aplicará al código las sangrías y el formato adecuados.

A continuación, agregue algunos comentarios descriptivos a la función. Cuando haya documentado


completamente la función, el código debe presentar un aspecto parecido a éste.

;;;--------------------------------------------------------------;
;;; Function: Degrees->Radians ;
;;;--------------------------------------------------------------;
;;; Description: This function converts a number representing an ;
;;; angular measurement in degrees, into its radian ;
;;; equivalent. There is no error checking on the ;
;;; numberOfDegrees parameter -- it is always ;
;;; expected to be a valid number. ;
;;;--------------------------------------------------------------;
(defun Degrees->Radians (numberOfDegrees)
(* pi (/ numberOfDegrees 180.0))
)

¿Comentarios?

Dibujo del contorno del camino

Otra función muy útil del programa de camino de jardín convierte los puntos 3D en puntos 2D.
Normalmente, AutoCAD trabaja con coordenadas 3D, pero algunas entidades, como las polilíneas
ligeras, son siempre 2D. Los puntos que devuelve la función getpoint son 3D, por lo que es necesario
crear una función que los convierta.

Para convertir puntos 3D en puntos 2D

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 28 de 103

1. Escriba lo siguiente en la solicitud de la ventana de consola:


(defun 3dPoint->2dPoint (3dpt)(list (car 3dpt) (cadr 3dpt)))

2. Compruebe la función escribiendo lo siguiente en la solicitud de la consola:


(3dpoint->2dpoint (list 10 20 0))

Esto funciona, pero hay que tener en cuenta otra cosa para la aplicación de camino de
jardín. Aunque a menudo es indiferente que los números sean enteros o reales en las
funciones de LISP, no ocurre lo mismo con las funciones de ActiveX, que se utilizan más
adelante en este ejercicio. Las funciones de ActiveX requieren números reales. Es fácil
modificar la función para que devuelva números reales en lugar de enteros.
3. Escriba el código siguiente en la solicitud de la consola:
(defun 3dPoint->2dPoint (3dpt)(list (float(car 3dpt))
(float(cadr 3dpt))))

4. Vuelva a ejecutar la función:


(3dpoint->2dpoint (list 10 20 0))

Observe que los valores devueltos ahora son reales (como indican los valores decimales).
5. Vuelva a comprobar la función, utilizando esta vez la función getpoint. Escriba lo siguiente en la
solicitud de la consola:
(setq myPoint(getpoint))

6. Designe un punto en el área de dibujo de AutoCAD.


La función getpoint devuelve un punto 3D.
7. Escriba lo siguiente en la solicitud de la consola:
(3dPoint->2Dpoint myPoint)

Observe el punto 2D devuelto.


Ahora, agregue la función al archivo gpmain.lsp, como hizo con Degrees‑>Radians. El
nuevo código debe ser parecido al siguiente:
;;;--------------------------------------------------------------;
;;; Function: 3dPoint->2dPoint ;
;;;--------------------------------------------------------------;
;;; Description: This function takes one parameter representing a;
;;; 3D point (list of three integers or reals), and ;
;;; converts it into a 2D point (list of two reals).;
;;; There is no error checking on the 3D point ;
;;; parameter -- it is assumed to be a valid point. ;
;;;--------------------------------------------------------------;
;;; To do: Add some kind of parameter checking so that this ;
;;; function won’t crash a program if it is passed a ;
;;; null value, or some other kind of data type than a ;
;;; 3D point. ;
;;;--------------------------------------------------------------;
(defun 3dPoint->2dPoint (3dpt)
(list (float(car 3dpt)) (float(cadr 3dpt)))
)

Tenga en cuenta que el encabezamiento de la función incluye un comentario sobre algo


que se debe hacer en esta función en el futuro. Si desea aumentar su rendimiento, piense
en cómo asegurar esta función para que no falle si se introducen datos no válidos.
Sugerencia: funciones numberp y listp…
(listp '(1 1 0)) => T
(numberp 3.4) => T

¿Comentarios?

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 29 de 103

Dibujo del contorno del camino

La mayoría de los programas AutoLISP dibujan las entidades por medio de uno de estos métodos:

z Funciones ActiveX
z La función entmake
z La función command

Este ejercicio se centra en la creación de entidades por medio de ActiveX®. En el Ejercicio 5 se


implementarán las alternativas: entmake y command de AutoCAD.

Temas de esta sección:

z Creación de entidades por medio de las funciones ActiveX

z Utilización de entmake para crear entidades

z Utilización de la línea de comandos de AutoCAD

¿Comentarios?

Dibujo del contorno del camino

La forma más avanzada de crear entidades consiste en utilizar las funciones de ActiveX dentro de
VLISP. ActiveX tiene varias ventajas sobre entmake y command.

z Las funciones de ActiveX son más rápidas.


z Los nombres de las funciones ActiveX indican la acción que llevan a cabo, lo que mejora la
legibilidad, el mantenimiento y la depuración.

Más adelante, en este ejercicio, encontrará un ejemplo de una función ActiveX.

¿Comentarios?

Dibujo del contorno del camino

La función entmake permite crear entidades recopilando valores tales como la posición y la orientación
de coordenadas, la capa y el color en una lista de asociaciones, y solicitando posteriormente a
AutoCAD que genere la entidad. La lista de asociaciones que se crea para la función entmake es muy

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 30 de 103

parecida a la lista de asociaciones que se obtiene cuando se llama a la función entget. La diferencia es
que entget devuelve la información sobre una entidad, pero entmake crea una entidad nueva a partir de
los datos introducidos.

¿Comentarios?

Dibujo del contorno del camino

Cuando AutoLISP apareció en AutoCAD, sólo era posible crear entidades por medio de la función
command. Esta función permite a los programadores de AutoLISP incluir en el código prácticamente
cualquiera de los comandos que es posible ejecutar desde la línea de comandos de AutoCAD. Es un
método fiable, pero no es tan rápido como los métodos de ActiveX, y no cuenta con la flexibilidad de
entmake.

¿Comentarios?

Dibujo del contorno del camino

Después del último ejercicio, la función gp:drawOutline tenía el siguiente aspecto:

;;;--------------------------------------------------------------;
;;; Function: gp:drawOutline ;
;;;--------------------------------------------------------------;
;;; Description: This function draws the outline of the ;
;;; garden path. ;
;;;--------------------------------------------------------------;
(defun gp:drawOutline ()
(alert
(strcat "This function will draw the outline of the polyline "
"\nand return a polyline entity name/pointer."
)
)
;; For now, simply return a quoted symbol. Eventually, this
;; function will return an entity name or pointer.
'SomeEname
)

Tal y como está, el código no hace gran cosa. Sin embargo, la lista de asociaciones guardada en la
variable gp_PathData proporciona suficiente información para calcular los puntos del contorno del
camino. Ahora debe averiguar la forma de transmitir la información de esta variable a gp:drawOutline.

Recuerde que gp_PathData es una variable local definida dentro de la función C:GPath. En AutoLISP,
las variables locales declaradas en una función son visibles desde cualquier función a la que se llame
desde ésta (si desea más explicaciones, consulte Diferencia entre variables locales y globales). Se llama
a la función gp:drawOutline desde dentro de C:GPath. Puede consultar la variable gp-PathData de

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 31 de 103

gp:drawOutline, pero no es un hábito de programación aconsejable.

Tal vez se pregunte por qué. Cuando dos funciones que utilizan la misma variable se definen en el
mismo archivo, como en los ejemplos mostrados hasta ahora, no es difícil saber dónde se define la
variable y para qué sirve. Sin embargo, si las funciones se definen en archivos distintos, como ocurre a
menudo, sería necesario realizar búsquedas en los dos archivos para averiguar qué representa
gp_PathData.

Temas de esta sección:

z de parámetros a funciones

z Trabajo con listas de asociaciones

z Utilización de ángulos y definición de puntos

z Explicación del código de ActiveX de gp:drawOutline

z Comprobación de que ActiveX está cargado

z Obtención de un puntero al espacio modelo

z Construcción de matrices de puntos de polilínea

z Creación de una variante a partir de una lista de puntos

z Integración de todos los elementos

¿Comentarios?

Dibujo del contorno del camino

Una forma mejor de transferir información de una función a otra consiste en transmitir parámetros a la
función llamada. La función se debe diseñar de forma que pueda recibir varios valores. ¿Recuerda la
función Degrees->Radians? A esta función se le transmite un parámetro llamado numberOfDegrees:

(defun Degrees->Radians (numberOfDegrees)


(* pi (/ numberOfDegrees 180.0)))

Cuando se llama a la función, espera que se introduzca un número. El número que se encuentra junto a
Degrees->Radians se declara como el parámetro llamado numberOfDegrees. Por ejemplo:

_$ (degrees->radians 90)
1.5708

En este caso, se asigna el número 90 al parámetro numberOfDegrees.

También es posible transmitir una variable a una función. Por ejemplo, tenemos una variable llamada
aDegreeValue que contiene el número 90. Los siguientes comandos establecen aDegreeValue y
transmiten la variable a Degrees->Radians:

_$ (setq aDegreeValue 90)


90
_$ (degrees->radians aDegreeValue)

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 32 de 103

1.5708

¿Comentarios?

Dibujo del contorno del camino

La lista de asociaciones de la variable gp_PathData se puede transmitir a la función gp:drawOutline


llamándola como sigue:

(gp:drawOutline gp_PathData)

Es bastante sencillo, pero también debe averiguar la forma de procesar la información almacenada en
la lista de asociaciones. La función Inspección de VLISP puede resultar útil para dar el siguiente paso.

Utilización de la función Inspección de VLISP para analizar la lista de asociaciones


1. Cargue el código que aparece en la ventana de edición de texto.
2. Escriba la siguiente expresión en la solicitud de la consola:
(setq BoundaryData (gp:getPointInput))

VLISP guarda la información facilitada en una variable llamada BoundaryData.


3. Responda a las solicitudes de punto inicial, punto final y media anchura.
4. Seleccione el nombre de la variable BoundaryData en la ventana de consola, haciendo doble clic
en él.

5. En el menú de VLISP seleccione Ver Inspección.


VLISP muestra una ventana como la siguiente:

La ventana Inspección muestra todas las sublistas de la variable BoundaryData.


6. Escriba lo siguiente en la solicitud de la consola de VLISP:
(assoc 50 BoundaryData)

La función assoc devuelve el elemento de la lista de asociaciones que se identifica con la


clave especificada. En este ejemplo, la clave especificada es 50; está asociada al ángulo
del camino de jardín (si desea ver una lista de los pares clave-valor definidos para esta
aplicación, consulte Utilización de las listas de asociaciones).
7. Escriba lo siguiente en la solicitud de la consola de VLISP:
(cdr(assoc 50 BoundaryData))

La función cdr devuelve el segundo elemento de la lista y todos los siguientes. En este
ejemplo, cdr recupera el valor del ángulo, que es el segundo y último elemento de la
entrada devuelta por la función assoc.
Después de ver lo anterior debe interpretar sin problemas el siguiente fragmento de código:
(setq PathAngle (cdr (assoc 50 BoundaryData))

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 33 de 103

Width (cdr (assoc 40 BoundaryData))


HalfWidth (/ Width 2.00)
StartPt (cdr (assoc 10 BoundaryData))
PathLength (cdr (assoc 41 BoundaryData))

¿Comentarios?

Dibujo del contorno del camino

Todavía quedan un par de asuntos por tratar. En primer lugar hay que averiguar cómo dibujar el camino
con el ángulo especificado por el usuario. La función gp:getPointInput permite establecer fácilmente el
ángulo primario del camino. Para dibujarlo son necesarios un par de vectores adicionales
perpendiculares al ángulo primario.

Es ahora cuando resulta útil la funciónDegrees->Radians. El siguiente fragmento de código muestra la


forma de definir dos vectores perpendiculares transmitiendo la variable PathAngle como argumento a la
función Degrees‑>Radians:

(setq angp90 (+ PathAngle (Degrees->Radians 90))


angm90 (- PathAngle (Degrees->Radians 90)))

Con los datos disponibles actualmente es posible determinar los puntos de las cuatro esquinas del
camino, por medio de la función polar:

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 34 de 103

(setq p1 (polar StartPt angm90 HalfWidth)


p2 (polar p1 PathAngle PathLength)
p3 (polar p2 angp90 Width)
p4 (polar p3 (+ PathAngle (Degrees->Radians 180))

La función polar devuelve un punto 3D a un ángulo y una distancia especificados respecto a un punto.
Por ejemplo, polar emplaza p2 proyectando p1 una distancia de PathLength a lo largo de un vector
orientado a un ángulo de PathAngle, en el sentido contrario a las agujas del reloj desde el eje x.

¿Comentarios?

Dibujo del contorno del camino

La función gp:drawOutline efectúa llamadas de ActiveX para mostrar el marco de polilínea en AutoCAD.
El siguiente fragmento de código utiliza ActiveX para dibujar el marco:

;; Add polyline to the model space using ActiveX automation.


(setq pline (vla-addLightweightPolyline
*ModelSpace*; Global Definition for Model Space
VLADataPts; vertices of path boundary
) ;_ end of vla-addLightweightPolyline
) ;_ end of setq
(vla-put-closed pline T)

Interpretemos este código: El ActiveX and VBA Reference, es un recurso esencial que describe los
métodos y propiedades, como esta aplicación de camino de jardín, a los que tienen acceso los clientes
de ActiveX. La sección “Trabajo con ActiveX” de AutoLISP Developer’s Guide explica cómo traducir la
sintaxis de VBA™ de ActiveX and VBA Reference en llamadas de ActiveX con sintaxis de AutoLISP.

No obstante, por el momento puede entenderlo provisionalmente examinando la estructura de las dos
llamadas a vla- del ejemplo anterior. El nombre de todas las funciones ActiveX de AutoLISP que
funcionan en los objetos de AutoCAD está precedido de vla-. Por ejemplo, addLightweightPolyline es el
nombre de un método de ActiveX, y vla-addLightweightPolyline es la función de AutoLISP que llama a
este método. La llamada a vla-put-closed actualiza la propiedad cerrada del objeto pline, la polilínea que
dibuja vla‑addLightweightPolyline.

Los objetos de automatización que influyen en las llamadas a ActiveX de AutoLISP se rigen por una
serie de normas:

z El primer argumento de una llamada a los métodos vla-put, vla-get, o vla- es el objeto que se

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 35 de 103

modifica o consulta, por ejemplo,*ModelSpace* en la primera llamada de función y pline en la


segunda llamada.
z El valor devuelto por una llamada a un método vla- es un objeto VLA, que se puede utilizar en
llamadas subsiguientes. Por ejemplo, vla-addLightweightPolyline devuelve un objeto, pline, que se
modifica en la siguiente llamada a ActiveX.
z El modelo de objeto ActiveX tiene estructura jerárquica. Los objetos recorren desde el objeto de la
aplicación de nivel superior hacia abajo, hasta las primitivas de dibujo, como los objetos de polilínea
y círculo. Por tanto, la función gp:drawOutline no está aún completa, porque es necesario acceder al
objeto de automatización *ModelSpace* en primer lugar a través del objeto raíz de la aplicación.

¿Comentarios?

Dibujo del contorno del camino

Las funciones de ActiveX no se activan automáticamente al iniciar AutoCAD o VLISP, por lo que hay
que asegurarse de que los programas tengan cargado ActiveX. Esto se consigue con la siguiente
llamada de función:

(vl-load-com)

Si aún no está disponible ActiveX, la ejecución de vl-load-com inicia el entorno ActiveX de AutoLISP. Si
ActiveX ya se ha cargado, vl-load-com no tiene ningún efecto.

¿Comentarios?

Dibujo del contorno del camino

Al añadir entidades mediante funciones ActiveX, tendrá que identificar el espacio modelo o el espacio
papel en que se debe insertar la entidad. (En la terminología ActiveX las entidades son objetos, pero en
este tutorial seguiremos utilizando el término entidad. Para comunicar a AutoCAD qué espacio deben
ocupar las entidades nuevas hay que conseguir un puntero a ese espacio. El problema es que la
obtención de un puntero al espacio modelo no es una tarea fácil. El siguiente fragmento de código
muestra la forma en que hay que configurar la operación:

(vla-get-ModelSpace (vla-get-ActiveDocument
(vlax‑get‑Acad‑Object)))

Desde el interior, la función vlax-get-Acad-Object recupera un puntero al AutoCAD. Este puntero se


transmite a la función vla‑get‑ActiveDocument, que recupera un puntero al dibujo (documento)
activo en AutoCAD. Después, el puntero del documento activo se transmite a la función
vla‑get‑ModelSpace, que recupera un puntero al espacio modelo del dibujo actual.

Ésta no es una expresión que se pueda escribir una y otra vez cómodamente. Por ejemplo, observe lo
complicado que es el código de adición de una polilínea por medio de ActiveX cuando se utiliza toda la
extensión del espacio modelo:

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 36 de 103

(setq pline (vla-addLightweightPolyline


(vla-get-ModelSpace
(vla-get-ActiveDocument
(vlax-get-Acad-Object)
)
)
VLADataPts)
)
(vla-put-closed pline T)

Sin duda, esta función es menos comprensible. Además, dentro de cada expresión del programa en la
que se crea una entidad se repite el mismo conjunto de funciones anidadas. Esto demuestra uno de los
pocos usos idóneos de las variables globales. La aplicación de Camino de jardín puede agregar
muchas entidades al espacio modelo (piense en todas las baldosas del camino), por lo que es
conveniente establecer una variable global que guarde el puntero al espacio modelo, como en el código
siguiente:

(setq *ModelSpace* (vla-get-ModelSpace (vla-get-ActiveDocument


(vlax-get-Acad-Object))))

La variable *ModelSpace* se puede utilizar cada vez que se llame a una función de creación de
entidades de ActiveX. El único problema es que la variable *ModelSpace* debe estar preparada antes
de dar comienzo al dibujo. Por ello, es necesario llamar a la función setq que establece esta variable
cuando se cargar la aplicación, inmediatamente después de la llamada a vl-load-com. Estas llamadas
se colocarán delante de cualquier defun en el archivo del programa. Como consecuencia, se ejecutan
en cuanto se carga

¿Comentarios?

Dibujo del contorno del camino

El último asunto que se va a tratar es la manera de convertir las variables de punto individuales (p1, p2,
p3, y p4) al formato necesario para la función vla‑addLightweightpolyline. En primer lugar, busque
ayuda sobre el tema.

Para obtener información sobre una función

1. En la barra de herramientas de VLISP, pulse el botón Ayuda.


2. Escriba vla‑addLightweightpolyline en el cuadro de diálogo Indicar nombre de elemento y pulse
Aceptar (el sistema de ayuda no distingue entre mayúsculas y minúsculas, por lo que no es
necesario poner la mayúscula del nombre de la función.)

En la Ayuda en pantalla se explica que AddLightWeightPolyline requiere que se especifiquen los


vértices de polilínea de una matriz de coordenadas en forma de variante. Así es como la ayuda describe
este parámetro:

The array of 2D WCS coordinates specifying the vertices of the polyline. At lea

Las variantes son construcciones de ActiveX que sirven de contenedores para varios tipos de datos.
Las cadenas, los enteros y las matrices se pueden representar por medio de variantes. Las variantes
almacenan datos junto con la información que los identifica.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 37 de 103

Hasta ahora tenemos cuatro puntos, todos ellos en formato (x, y, z). Lo que tenemos que hacer es
convertir estos cuatro puntos en una lista con la siguiente estructura:

(x1 y1 x2 y2 x3 y3 x4 y4)

La función append toma varias listas y las concatena. Para crear una lista de los cuatro puntos en el
formato adecuado para la función de ActiveX se puede utilizar la expresión siguiente:

(setq polypoints (append (3dPoint->2dPoint p1)


(3dPoint->2dPoint p2)
(3dPoint->2dPoint p3)
(3dPoint->2dPoint p4)))

Escribir cuatro veces la función 3dPoint‑>2dPoint resulta un poco trabajoso. Puede reducir más el
código por medio de las funciones mapcar y apply. Una vez seleccionada, mapcar ejecuta una función
en elementos individuales de una o más listas y apply transfiere una lista de argumentos a la función
especificada. El código resultante tiene este aspecto:

(setq polypoints (apply 'append (mapcar '3dPoint->2dPoint


(list p1 p2 p3 p4))))

Antes de la llamada a mapcar, la lista de puntos tiene esta estructura:

((x1 y1 z1) (x2 y2 z2) (x3 y3 z3) (x4 y4 z4))

Después de mapcar la lista de puntos tiene esta estructura:

((x1 y1) (x2 y2) (x3 y3) (x4 y4))

Por último, después de aplicar la función append a la lista devuelta por mapcar, se obtiene lo siguiente:

(x1 y1 x2 y2 x3 y3 x4 y4)

¿Comentarios?

Dibujo del contorno del camino

Hasta ahora, los datos de la variable de polipuntos se encuentran en un formato de lista adecuado para
muchas llamadas de AutoLISP. Sin embargo, estos datos se deben proporcionar como parámetro de
entrada a una llamada de ActiveX que espera una matriz de coordenadas de variante. Se puede usar
otra función de utilidades para efectuar la conversión necesaria, de lista a variante:

(defun gp:list->variantArray (ptsList / arraySpace sArray)


; allocate space for an array of 2d points stored as doubles
(setq arraySpace (vlax-make-safearray
vlax-vbdouble ; element type
(cons 0
(- (length ptsList) 1)
) ; array dimension
)
)

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 38 de 103

(setq sArray (vlax-safearray-fill arraySpace ptsList))


; return array variant
(vlax-make-variant sArray)
)

Las siguientes acciones tienen lugar en gp:list->variantArray:

z Se llama a la función vlax‑make-safearray para asignar una matriz de coordenadas (vlax-


vbdouble). La función vlax‑make‑safearray también requiere que se especifiquen los límites
inferior y superior de la matriz. En gp:list->variantArray, la llamada a vlax‑make‑safearray
especifica un índice inicial de 0 y establece el límite superior en el número de elementos que se le
han transmitido menos uno (ptsList).
z Se llama a la función vlax-safearray-fill para llenar la matriz con los elementos de la lista de puntos.
z Se llama a vlax-make-variant para convertir la matriz segura en una variante. Como en la última
llamada de función de gp:list->variantArray, el valor devuelto se transmite a la función que efectúa la
llamada.

A continuación puede ver un ejemplo de una llamada a gp:list‑>variantArray para convertir una lista
en una matriz de coordenadas de variante:

; data conversion from list to variant


(setq VLADataPts (gp:list->variantArray polypoints))

¿Comentarios?

Dibujo del contorno del camino

Ya tiene todo el código necesario para dibujar el contorno del camino

Para actualizar el código


1. Sustituya el código antiguo de la función gp:drawOutline por el siguiente:
;;;---------------------------------------------------------------
;;; Function: gp:drawOutline
;;;---------------------------------------------------------------
;;; Description: This function will draw the outline of the garden
;;; path.
;;;---------------------------------------------------------------
;;; Note: No error checking or validation is performed on the
;;; BoundaryData parameter. The sequence of items within this
;;; parameter does not matter, but it is assumed that all sublists
;;; are present and contain valid data.
;;; --------------------------------------------------------------
(defun gp:drawOutline (BoundaryData / VLADataPts PathAngle
Width HalfWidth StartPt PathLength
angm90 angp90 p1 p2
p3 p4 polypoints pline
)
;; extract the values from the list BoundaryData
(setq PathAngle (cdr (assoc 50 BoundaryData))
Width (cdr (assoc 40 BoundaryData))
HalfWidth (/ Width 2.00)

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 39 de 103

StartPt (cdr (assoc 10 BoundaryData))


PathLength (cdr (assoc 41 BoundaryData))
angp90 (+ PathAngle (Degrees->Radians 90))
angm90 (- PathAngle (Degrees->Radians 90))
p1 (polar StartPt angm90 HalfWidth)
p2 (polar p1 PathAngle PathLength)
p3 (polar p2 angp90 Width)
p4 (polar p3 (+ PathAngle (Degrees->Radians 180)) PathLength)
polypoints (apply 'append
(mapcar '3dPoint->2dPoint (list p1 p2 p3 p4))
)
)
;; ***** data conversion *****
;; Notice, polypoints is in AutoLISP format, consisting of a list
;; of the 4 corner points for the garden path.
;; The variable needs to be converted to a form of input parameter
;; acceptable to ActiveX calls.
(setq VLADataPts (gp:list->variantArray polypoints))
;; Add polyline to the model space using ActiveX automation.
(setq pline (vla-addLightweightPolyline
*ModelSpace* ; Global Definition for Model Space
VLADataPts
) ;_ end of vla-addLightweightPolyline
) ;_ end of setq
(vla-put-closed pline T)
;; Return the ActiveX object name for the outline polyline
;; The return value should look something like this:
;; #<VLA-OBJECT IAcadLWPolyline 02351a34>
pline
) ;_ end of defun

Observe que gp:drawOutline devuelve ahora la variable pline, no el símbolo precedido de


un comilla simple 'SomeEname que se utilizó en la versión vacía de la función.
2. Dé formato al código que acaba de introducir seleccionándolo y pulsando el botón Formatear
selección de la barra de herramientas de VLISP.
3. Active ahora ActiveX y agregue la asignación de variable global para el puntero del espacio
modelo, de la forma antes descrita. Vaya a la parte superior de la ventana de edición de texto y
agregue el siguiente código antes del primer defun:
;;;--------------------------------------------------------------
;;; First step is to load ActiveX functionality. If ActiveX support
;;; already exists in document (can occur when Bonus tools have been
;;; loaded into AutoCAD), nothing happens. Otherwise, ActiveX
;;; support is loaded.
;;;---------------------------------------------------------------
(vl-load-com)
;;; In Lesson 4, the following comment and code is moved to utils.lsp
;;;---------------------------------------------------------------
;;; For ActiveX functions, we need to define a global variable that
;;; "points" to the Model Space portion of the active drawing. This
;;; variable, named *ModelSpace* will be created at load time.
;;;---------------------------------------------------------------
(setq *ModelSpace*
(vla-get-ModelSpace
(vla-get-ActiveDocument (vlax-get-acad-object))
) ;_ end of vla-get-ModelSpace
) ;_ end of setq

Tenga en cuenta que el código anterior se encuentra fuera de los grupos defun. Por ello,
VLISP ejecuta el código automáticamente cuando se carga el archivo.
4. Observe la siguiente línea de la función C:GPath:

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 40 de 103

(setq PolylineName (gp:drawOutline))

Cámbiela por lo siguiente:


(setq PolylineName (gp:drawOutline gp_PathData))

Ahora, la función gp:drawOutline espera un parámetro (la lista que contiene los datos del
contorno de la polilínea) y este cambio cumple dicho requisito.
5. Agregue la función gp:list->variantArray que se muestra en Creación de una variante a partir de una
lista de puntos al final de gpmain.lsp.
Intente cargar y ejecutar el programa revisado. VLISP quita el control a AutoCAD antes de
que se vea el resultado final, por lo que se debe volver a la ventana de AutoCAD después
de que el control vuelva a VLISP. Si el programa se ha ejecutado correctamente, debe
aparecer un marco del camino de jardín. Si encuentra algún error, depure el código y
vuelva a intentarlo.

¿Comentarios?

Dibujo del contorno del camino

En esta lección:

z Ha escrito funciones de utilidades que se pueden reutilizar en otras aplicaciones.


z Ha agregado la lógica de creación de entidades al programa.
z Ha aprendido a utilizar las funciones de ActiveX.
z Ha aprendido a trabajar con listas de asociaciones.
z Ha hecho que el programa dibuje el marco del camino de jardín.

Si no ha comprendido del todo este ejercicio, es aconsejable que lo repase antes de empezar con el
Ejercicio 4 (si decide hacerlo, copie el código completo del directorio Lesson2 para comenzar al
ejercicio desde el lugar adecuado). Si todo lo demás falla, puede copiar el código correcto del directorio
Tutorial\VisualLISP\Lesson3.

¿Comentarios?

En este ejercicio se realizarán dos tareas principales: la creación de un proyecto Visual LISP® y la
adición de una interfaz de cuadro de diálogo a la aplicación. Para ello, dividirá el único archivo de
AutoLISP® con el que ha trabajado hasta ahora ( gpmain.lsp) en varios archivos más pequeños, en
aplicación del concepto de modularidad del código.

A partir de este ejercicio, el aprendizaje proporciona descripciones más generales de las tareas que
deben realizarse, excepto cuando se traten temas nuevos. Asimismo, los fragmentos de código se
comentan al mínimo para ahorrar espacio.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 41 de 103

Temas de esta sección:

z Modularización del código

z Utilización de los proyectos de Visual LISP

z Adición de la interfaz de cuadros de diálogo

z Interacción con el cuadro de diálogo desde el código de AutoLISP

z Elección del tipo de línea del contorno

z Limpieza

z Ejecución de la aplicación

z Repaso de la Lección 4

¿Comentarios?

Creación de un proyecto y adición de la interfaz

Como resultado del trabajo efectuado en el ejercicio 3, el archivo gpmain.lsp tiene un tamaño
considerable. Esto no es un problema para VLISP, pero el mantenimiento del código resulta más fácil si
se divide en archivos que contengan funciones relacionadas de forma lógica. También facilita la
depuración del código. Por ejemplo, si tiene un solo archivo con 150 funciones, puede resultar muy
difícil encontrar un paréntesis que falta.

En el aprendizaje, los archivos se organizan como sigue:

Organización del archivo de aprendizaje


Nombre de Contenido
archivo
gp-io.lsp Incluye todas las funciones de entrada y salida (E/S), como la obtención de datos del usuario.
También contiene el código de AutoLISP necesario para la interfaz de cuadro de diálogo que
se va a agregar.
utils.lsp Incluye todas las funciones genéricas que se pueden volver a utilizar en otros proyectos.
También contiene inicializaciones para el momento de la carga.
gpdraw.lsp Todas las rutinas de dibujo: el código que crea en realidad las entidades de AutoCAD.
gpmain.lsp La función básica C:GPath.

Para dividir gpmain.lsp en cuatro archivos


1. Cree un archivo nuevo y corte y pegue en él las siguientes funciones de gpmain.lsp:
z gp:getPointInput
z gp:getDialogInput

Guarde el archivo nuevo en el directorio de trabajo con el nombre gp-io.lsp.


2. Cree un archivo nuevo y corte y pegue en él las siguientes funciones de gpmain.lsp:
z Degrees->Radians
z 3Dpoint->2Dpoint
z gp:list->variantArray

Asimismo, al principio del archivo, inserte las líneas de código que activan la funcionalidad

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 42 de 103

de ActiveX (vl-load-com) y realizan la asignación de variables globales (*ModelSpace*).


Guarde el archivo con el nombre utils.lsp.
3. Cree un archivo nuevo y corte y pegue en él la siguient función de gpmain.lsp:
z gp:drawOutline

Guarde este archivo con el nombre gpdraw.lsp.


4. Después de extraer el código de gpmain.lsp, guarde y verifique el archivo. Sólo debe quedar en
él C:GPath, la función original.

El escritorio de VLISP empieza a llenarse mucho. Puede minimizar cualquier ventana de VLISP sin que
deje de ser accesible. En la barra de herramientas, pulse el botón Seleccionar ventana para elegir una
ventana de la lista o bien elija Ventana en el menú de VLISP y seleccione la ventana que desee
presentar.

¿Comentarios?

Creación de un proyecto y adición de la interfaz

La función de proyectos de VLISP facilita la gestión de los archivos que constituyen la aplicación. Con
esta función es posible abrir a la vez todos los archivos de un proyecto, en vez de abrir uno a uno todos
los archivos LISP de la aplicación. Una vez abierto el proyecto, los archivos que lo constituyen están a
un doble clic de distancia

Para crear un proyecto de VLISP:


1. En el menú de VLISP seleccione Proyecto Nuevo proyecto.
2. Guarde el archivo en el directorio Lesson4 con el nombre gpath.prj.
Una vez guardado el archivo, VLISP muestra el cuadro de diálogo de propiedades del
proyecto.
3. Pulse el botón (De)Seleccionar todo del cuadro de diálogo de propiedades del proyecto
4. Pulse el botón que representa una flecha que apunta a la derecha. De esta forma se agregan al
proyecto los archivos seleccionados.
En el cuadro de diálogo de propiedades del proyecto, el cuadro de lista de la izquierda
muestra todos los archivos LISP que se encuentran en el mismo directorio que el archivo
del proyecto y no están incluidos en el proyecto. El cuadro de lista de la derecha muestra
todos los archivos que están incluidos en el proyecto. Cuando se agregaron al proyecto los
archivos seleccionados, sus nombres de archivo se desplazaron del cuadro de la izquierda
al de la derecha
5. Seleccione gpmain en el cuadro de lista de la derecha y pulse el botón Final. Esto desplaza el
archivo al final de la lista.
VLISP carga los archivos de los proyectos por el orden en que aparecen en la lista. Dado
que la solicitud que da a los usuarios el nombre del comando se encuentra al final del
archivo gpmain.lsp, es necesario desplazar este archivo a la parte inferior de la lista.
Cuando se carga este archivo en último lugar sale la solicitud que se muestra a todos los
usuarios. El archivo utils.lsp se debe cargar en primer lugar porque contiene el código de
inicio de la aplicación. Por tanto, seleccione utils en el cuadro de lista del cuadro de
diálogo y pulse el botón Inicio.
6. Pulse Aceptar.

VLISP agrega una pequeña ventana de proyecto al escritorio de VLISP. En la ventana se muestra una

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 43 de 103

lista de los archivos del proyecto. Haga doble clic en cualquiera de ellos para abrirlo en el editor de texto
de VLISP (si no está abierto ya) y convertir el editor en la ventana activa

¿Comentarios?

Creación de un proyecto y adición de la interfaz

La siguiente parte de este ejercicio trata sobre la forma de agregar una interfaz de cuadros de diálogo a
la aplicación de camino de jardín. Para esto hay que trabajar con otro lenguaje, llamado DCL ( Dialog
Control Language, Lenguaje de control de cuadros de diálogo).

En la actualidad, la función gpath sólo acepta entradas en la línea de comando. Hemos incluido una
función vacía (gp:getDialogInput) con intención de agregar una interfaz de cuadros de diálogo. Éste es
el momento de agregar la interfaz.

Para crear una interfaz funcional de cuadros de diálogo hay que dar dos pasos:

z Definir el aspecto y el contenido de los cuadros de diálogo.


z Agregar código de programación para controlar el comportamiento de los cuadros de diálogo.

La descripción y el formato de los cuadros de diálogo se definen en un archivo . dcl. En AutoLISP


Developer’s Guide, DCL se describe en los Capítulos 11, “Designing Dialog Boxes”, 12 “Managing
Dialog Boxes” y 13, “Programmable Dialog Box Reference”.

El código de programa que inicia la configuración por defecto y responde a la interacción del usuario se
agrega a gp:getDialogInput.

Temas de esta sección:

z Definición del cuadro de diálogo con DCL

z Guardado de un archivo DCL

z Presentación preliminar del cuadro de diálogo

¿Comentarios?

Creación de un proyecto y adición de la interfaz

Empecemos por observar el cuadro de diálogo que se va a crear.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 44 de 103

Este cuadro de diálogo contiene los siguientes elementos:

z Dos conjuntos de botones de opción.


Uno de ellos determina el estilo de polilínea del contorno, y el otro especifica el método de
creación de entidades (ActiveX, entmake o command). No es posible seleccionar más de un
botón de opción del mismo grupo a la vez.
z Casillas de edición para establecer el radio de las baldosas y la separación entre éstas.
z Un conjunto estándar de botones Aceptar y Cancelar.

Los elementos que constituyen un cuadro de diálogo se denominan componentes en DCL. Puede
parecer que escribir todo el contenido de un cuadro de diálogo en un archivo DCL supone mucho
trabajo. El truco consiste en esbozar lo que se desea, dividirlo en secciones y escribir las secciones una
a una.

Para definir el cuadro de diálogo


1. Abra un archivo nuevo en la ventana de edición de texto de VLISP.
2. Introduzca la siguiente declaración en el archivo nuevo:
label = "Garden Path Tile Specifications";

Esta declaración de DCL define el título de la ventana del cuadro de diálogo.


3. Defina los botones de opción para especificar el tipo de polilínea añadiendo el siguiente código:
: boxed_radio_column { // defines the radio button areas
label = "Outline Polyline Type";
: radio_button { // defines the lightweight radio button
label = "&Lightweight";
key = "gp_lw";
value = "1";
}
: radio_button { // defines the old-style polyline radio button
label = "&Old-style";
key = "gp_hw";
}
}

La directriz boxed_radio_column de DCL define un contorno de cuadro y permite colocar


una etiqueta al grupo de botones. Dentro del cuadro se especifican los botones de opción
agregando directrices radio_button. Cada botón de opción debe tener una etiqueta y una
clave. La clave es el nombre mediante el cual el código de AutoLISP hace referencia al
botón.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 45 de 103

Observe que se ha dado al botón de opción que lleva la etiqueta "optimizada" un valor de
1. El valor de 1 (como cadena; no como entero) asignado a un botón lo convierte en la
opción por defecto de su grupo. En otras palabras, cuando se abra el cuadro de diálogo
éste es el botón que se encontrará seleccionado. Observe también que, en los archivos
DCL, los comentarios seidentifican con dos barras oblicuas, y no con punto y coma como
en AutoLISP.
4. Defina la columna de selecciones para especificar el estilo de creación de entidades añadiendo el
siguiente código:
: boxed_radio_column { // defines the radio button areas
label = "Tile Creation Method";
: radio_button { // defines the ActiveX radio button
label = "&ActiveX Automation";
key = "gp_actx";
value = "1";
}
: radio_button { // defines the (entmake) radio button
label = "&Entmake";
key = "gp_emake";
}
: radio_button { // defines the (command) radio button
label = "&Command";
key = "gp_cmd";
}
}

5. Agregue el código siguiente para definir los componentes de la casilla de edición, que permiten a
los usuarios introducir los números que definen el tamaño y el intervalo de las baldosas:
: edit_box { // defines the Radius of Tile edit box
label = "&Radius of tile";
key = "gp_trad";
edit_width = 6;
}
: edit_box { // defines the Spacing Between Tiles edit box
label = "S&pacing between tiles";
key = "gp_spac";
edit_width = 6;
}

Observe que esta definición no establece ningún valor inicial para las casillas de edición.
Los valores por defecto de las casillas de edición se definen en el programa AutoLISP.
6. Agregue el código siguiente para los botones Aceptar y Cancelar:
: row { // defines the OK/Cancel button row
: spacer { width = 1; }
: button { // defines the OK button
label = "OK";
is_default = true;
key = "accept";
width = 8;
fixed_width = true;
}
: button { // defines the Cancel button
label = "Cancel";
is_cancel = true;
key = "cancel";
width = 8;
fixed_width = true;
}
: spacer { width = 1;}
}

Los dos botones están definidos en una fila, por lo que tienen alineación horizontal.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 46 de 103

7. Vaya a la parte superior de la ventana de edición de texto y agregue la siguiente declaración


como primera línea del DCL:
gp_mainDialog : dialog {

8. La directriz dialog requiere una llave de cierre, por lo que se debe ir al final del archivo y colocar
esta llave como última línea del código DCL:
}

¿Comentarios?

Creación de un proyecto y adición de la interfaz

Antes de guardar el archivo que contiene el DCL se debe tener en cuenta que AutoCAD® debe ser
capaz de localizar este archivo durante la ejecución. Por este motivo, el archivo debe estar colocado en
una de las ubicaciones Ruta de búsqueda de archivo de soporte de AutoCAD. (Si no está seguro de
estas ubicaciones, en AutoCAD seleccione Herramientas Opciones y examine Ruta de búsqueda de
archivo de soporte en la ficha Archivos).

Por ahora, el archivo se puede guardar en el directorio Support de AutoCAD.

Para guardar el archivo DCL


1. En el menú de VLISP seleccione Archivo Guardar como.
2. En el cuadro de diálogo Guardar como, en la sección Guardar como tipo, elija Archivos fuente
DCL en el menú desplegable.
3. Cambie la ruta de Guardar en por el directorio de <AutoCAD\Support.
4. Escriba el nombre de archivo gpdialog.dcl.
5. Pulse Guardar.

Observe que VLISP cambia el modelo de coloreado de la sintaxis después de guardar el archivo. VLISP
está diseñado para reconocer los archivos DCL y resaltar distintos tipos de elementos sintácticos.

¿Comentarios?

Creación de un proyecto y adición de la interfaz

VLISP incluye una función de presentación preliminar que permite controlar el resultado del código
DCL.

Para abrir la presentación preliminar de un cuadro de diálogo definido con DCL


1. En el menú de VLISP, seleccione Herramientas Herramientas de la interfaz Vista preliminar
DCL en editor.
2. Pulse Aceptar cuando se le pida que elija el nombre de un cuadro de diálogo.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 47 de 103

En este caso, el archivo DCL sólo define un cuadro de diálogo, por lo que no es necesario
elegir. No obstante, cuando se crean aplicaciones mayores y más sólidas es normal que
los archivos DCL contengan varios cuadros de diálogo. Aquí es donde se elige el que se
desea ver.
3. Si el cuadro de diálogo se presenta correctamente, pulse cualquier botón para salir.

VLISP transmite el control a AutoCAD para presentar el cuadro de diálogo. Si AutoCAD encuentra
errores de sintaxis, muestra una o varias ventanas de mensaje en las que los identifica.

Si AutoCAD encuentra errores de DCL y no sabe cómo arreglarlos, copie el archivo gpdialog.dcl del
directorio Tutorial\VisualLISP\Lesson4 y guárdelo en el directorio Support.

¿Comentarios?

Creación de un proyecto y adición de la interfaz

Ahora es necesario programar la función de AutoLISP de modo que interactúe con el cuadro de diálogo.
La actividad tendrá lugar en la función vacía gp:getDialogInput, es donde tendrá lugar la actividad. Esta
función se encuentra ahora en el archivo gp-io.lsp, ya que antes de extrajo de gpmain.lsp.

El desarrollo de una interfaz de cuadros de diálogo puede resultar muy complicado las primeras veces.
Para hacerlo es necesario planificar las tareas de antemano y plantearse preguntas como:

z ¿Es necesario establecer valores por defecto en el cuadro de diálogo?


z ¿Qué ocurre cuando el usuario pulsa un botón o introduce un valor?
z ¿Qué ocurre si el usuario pulsa Cancelar?
z ¿Qué debe ocurrir si falta el archivo de cuadro de diálogo (. dcl)?

Temas de esta sección:

z Definición de los valores de cuadros de diálogo

z Carga del archivo de cuadro de diálogo

z Carga de un cuadro de diálogo en la memoria

z Inicialización de los valores por defecto del cuadro de diálogo

z Asignación de acciones a los componentes

z Apertura del cuadro de diálogo

z Cierre del cuadro de diálogo

z Qué hacer a continuación

z Integración del código

z Actualización de funciones vacías

¿Comentarios?

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 48 de 103

Creación de un proyecto y adición de la interfaz

Cuando se ejecuta la aplicación de camino de jardín completa, el cuadro de diálogo empieza siempre
con ActiveX como método por defecto de creación de objetos, y Optimizada como estilo de polilínea.
Con el tamaño de baldosa por defecto ocurre algo más interesante: los valores cambian según la
anchura del camino. El siguiente fragmento de código muestra la forma en que hay que configurar los
valores por defecto que se muestran en el cuadro de diálogo:

(setq objectCreateMethod "ACTIVEX"


plineStyle "LIGHT"
tilerad (/ pathWidth 15.0)
tilespace (/ tilerad 5.0)
dialogLoaded T
dialogShow T
) ;_ end of setq

De momento, no se preocupe por la finalidad de las variables dialogLoaded y dialogShow. Esto se verá
en las dos secciones siguientes.

¿Comentarios?

Creación de un proyecto y adición de la interfaz

El programa debe empezar por cargar el archivo DCL mediante la función load_dialog. Esta función
busca archivos de cuadro de diálogo atendiendo a la ruta de búsqueda de archivo de soporte de
AutoCAD, excepto si se especifica una ruta completa.

Cada vez que se coloque en el código una función load_dialog se debe poner más adelante la función
unload_dialog correspondiente. Ahora mismo veremos esto. Por ahora, observe cómo se carga el
cuadro de diálogo:

;; Load the dialog box. Set up error checking to make sure


;; the dialog file is loaded before continuing
(if (= -1 (setq dcl_id (load_dialog "gpdialog.dcl")))
(progn
;; There's a problem - display a message and set the
;; dialogLoaded flag to nil
(princ "\nCannot load gpdialog.dcl")
(setq dialogLoaded nil)
) ;_ end of progn
) ;_ end of if

La variable dialogLoaded indica si el cuadro de diálogo se ha cargado correctamente. En el código en el


que se establecen los valores iniciales del cuadro de diálogo se define para dialogLoaded un valor
inicial de T. Como puede ver en el fragmento de código anterior, el valor de dialogLoaded es nil si surge
algún problema durante la carga.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 49 de 103

¿Comentarios?

Creación de un proyecto y adición de la interfaz

Antes se ha comentado que un archivo DCL puede contener la definición de varios cuadros de diálogo.
El siguiente paso, pues, consiste en especificar cuál de las definiciones de cuadro de diálogo se debe
mostrar. Esto se muestra en el código siguiente:

(if (and dialogLoaded


(not (new_dialog "gp_mainDialog" dcl_id))
) ;_ end of and
(progn
;; There's a problem...
(princ "\nCannot show dialog gp_mainDialog")
(setq dialogShow nil)
) ;_ end of progn
) ;_ end of if

Observe que la función and se utiliza para comprobar si se ha cargado el cuadro de diálogo, y si la
llamada a new_dialog se ha efectuado correctamente. Si hay varias expresiones evaluadas dentro de
una llamada de función and, la evaluación de las expresiones subsiguientes finaliza con la primera
expresión cuya evaluación arroje un valor de nil. En este caso, si el indicador de dialogLoaded es nil (lo
que significa que ha fallado la función de carga de la sección anterior), VLISP no intenta llevar a cabo la
función new_dialog.

Observe que el código también prevé la posibilidad de que algo no funcione correctamente en el archivo
DCL, y establece la variable dialogShow en nil si esto ocurre.

La función new_dialog sólo carga el cuadro de diálogo en la memoria, pero no lo muestra. La función
start_dialog muestra el cuadro de diálogo. Todas las tareas de inicialización del cuadro de diálogo,
como la definición de valores del componente, la creación de imágenes o listas para cuadros de lista y
la asociación de acciones a componentes específicos deben tener lugar después de la llamada a
new_dialog y antes de la llamada a start_dialog.

¿Comentarios?

Creación de un proyecto y adición de la interfaz

Si la carga del cuadro de diálogo se ha efectuado correctamente, ya es posible empezar a establecer


los valores que se presentarán al usuario. La carga se ha efectuado correctamente si las variables de
indicador dialogLoadedy dialogShowtienen el valor T (verdadero).

Ahora hay que establecer los valores iniciales del radio de la baldosa y el intervalo entre baldosas. La
función set_tile asigna valores a los componentes. Las casillas de edición utilizan cadenas en lugar de
números, por lo que se debe emplear la función rtos (convertir número real en cadena) para convertir

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 50 de 103

los valores de las variables de tamaño de la baldosa en cadenas de formato decimal, con una precisión
de dos cifras. El código siguiente lleva a cabo esta conversión:

(if (and dialogLoaded dialogShow)


(progn
;; Set the initial state of the tiles
(set_tile "gp_trad" (rtos tileRad 2 2))
(set_tile "gp_spac" (rtos tileSpace 2 2))

¿Comentarios?

Creación de un proyecto y adición de la interfaz

Las definiciones de ACL se limitan a crear un cuadro de diálogo "sin vida". Este cuadro de diálogo se
conecta al código dinámico de AutoLISP con la función action_tile, de la forma expuesta en el código
siguiente:

;; Assign actions (the functions to be invoked) to dialog buttons


(action_tile
"gp_lw"
"(setq plineStyle \"Light\")"
)
(action_tile
"gp_hw"
"(setq plineStyle \"Pline\")"
)
(action_tile
"gp_actx"
"(setq objectCreateMethod \"ActiveX\")"
)
(action_tile
"gp_emake"
"(setq objectCreateMethod \"Entmake\")"
)
(action_tile
"gp_cmd"
"(setq objectCreateMethod \"Command\")"
)
(action_tile "cancel" "(done_dialog) (setq UserClick nil)")
(action_tile
"accept"
(strcat "(progn (setq tileRad (atof (get_tile \"gp_trad\")))"
"(setq tileSpace (atof (get_tile \"gp_spac\")))"
"(done_dialog) (setq UserClick T))"
)
)

Observe todas las comillas que rodean el código de AutoLISP. Cuando se escribe una función
action_tile de AutoLISP, el código da instrucciones al componente para que recuerde la cadena y se la
devuelva cuando el usuario elija el componente. La cadena (cualquier serie de caracteres entre comillas
dobles) permanecerá inactiva hasta que el usuario seleccione el componente. En ese momento, el
componente transmite la cadena a AutoCAD, que la convierte en código funcional de AutoLISP y

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 51 de 103

ejecuta el código.

Por ejemplo, consideremos la siguiente expresión action_tile, que está conectada al botón de opción de
la polilínea optimizada:

(action_tile
"gp_lw"
"(setq plineStyle \"Light\")"
)

El código asigna la cadena "(setq plineStyle \"Light\")" al botón de opción. Cuando un usuario elige este
botón, la cadena se devuelve a AutoCAD y se transforma directamente en la siguiente expresión de
AutoLISP:

(setq plineStyle "Light")

Observe otro fragmento de código. Ésta es la expresión action_tile asignada al botón Aceptar:

(action_tile
"accept"
(strcat "(progn (setq tileRad (atof (get_tile \"gp_trad\")))"
"(setq tileSpace (atof (get_tile \"gp_spac\")))"
"(done_dialog) (setq UserClick T))"
)

Cuando un usuario pulsa el botón Aceptar, la cadena que tiene asignada se transmite a AutoCAD y se
transforma en el siguiente código de AutoLISP:

(progn
(setq tileRad (atof (get_tile "gp_trad")))
(setq tileSpace (atof (get_tile "gp_spac")))
(done_dialog)
(setq UserClick T)
)

Este código realiza varias acciones: recupera los valores actuales de los componentes cuyos valores
clave son gp_trad (el radio de la baldosa) y gp_spac (el valor del espacio entre baldosas). Después, atof
convierte la cadena numérica en un número real. El cuadro de diálogo se cierra con la función
done_dialog, y se asigna el valor T a la variable UserClick.

Ya ha terminado de asignar acciones a los botones. El siguiente paso consiste en poner esto en
marcha.

¿Comentarios?

Creación de un proyecto y adición de la interfaz

La función start_dialog presenta un cuadro de diálogo y acepta los datos introducidos por el usuario. La
función start_dialog no requiere argumentos.

(start_dialog)

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 52 de 103

El control se transmite al usuario cuando se emite start_dialog. Los usuarios pueden efectuar
selecciones dentro del cuadro de diálogo hasta que pulsen Aceptar o Cancelar.

¿Comentarios?

Creación de un proyecto y adición de la interfaz

Cuando un usuario pulse Aceptar o Cancelar, deberá descargar el cuadro de diálogo. Igual que
start_dialog, unload_dialog es una función muy sencilla.

(unload_dialog dcl_id)

¿Comentarios?

Creación de un proyecto y adición de la interfaz

Cuando el usuario pulsa Aceptar, hay que crear una lista que contenga los valores establecidos por el
usuario en el cuadro de diálogo. Esta lista es lo que gp:getDialogInput devuelve a la función que la
llama. Si el usuario pulsa Cancelar, la función devuelve nil:

(if UserClick ; User clicked Ok


;; Build the resulting data
(progn
(setq Result (list
(cons 42 tileRad)
(cons 43 TileSpace)
(cons 3 objectCreateMethod)
(cons 4 plineStyle)
)
)
)
)

¿Comentarios?

Creación de un proyecto y adición de la interfaz

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 53 de 103

Con los ejemplos anteriores y unas cuantas líneas adicionales tiene el código necesario para completar
la función gp:getDialogInput.

Integración de gp:getDialogInput
1. Abra su copia de gp-io.lsp en una ventana de edición de texto de VLISP.
2. Borre el código de gp:getDialogInput (la declaración defun gp:getDialogInput y todo lo que hay a
continuación).
3. Introduzca la siguiente declaración defun como primera línea de código de la función
gp:getDialogInput:
(defun gp:getDialogInput (pathWidth / dcl_id objectCreateMethod
plineStyle tilerad tilespace result UserClick
dialogLoaded dialogShow)

La función espera un solo argumento (pathwidth), y establece una serie de variables


locales.
4. Introduzca después del código agregado en el paso 3, el código de muestra de las siguientes
secciones de este capítulo:
z Definición de los valores de cuadros de diálogo
z Carga del archivo de cuadro de diálogo
z Carga de un cuadro de diálogo en la memoria
z Inicialización de los valores por defecto del cuadro de diálogo
z Asignación de acciones a los componentes

Nota Introduzca sólo el primer ejemplo de código de Asignación de acciones a los componentes no
los fragmentos de las explicaciones que se encuentran a continuación. Estos fragmentos sólo
repiten partes del ejemplo.
z Apertura del cuadro de diálogo
z Cierre del cuadro de diálogo
z Qué hacer a continuación

5. Después de la última línea de código, añada lo siguiente:


)
)
Result;
) ;_ end of defun

6. Dé formato al código introducido eligiendo en el menú de VLISP Herramientas Formatear


código en editor.

¿Comentarios?

Creación de un proyecto y adición de la interfaz

Ya ha revisado la función gp:getDialogInput. Cuando se modifica una función vacía es necesario


comprobar un par de cosas:

z ¿Ha cambiado la declaración defun? Es decir, ¿aún toma la función el mismo número de
argumentos?
z ¿Devuelve la función algo diferente?

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 54 de 103

En el caso de gp:getDialogInput, la respuesta a las dos preguntas es sí. Ahora, la función acepta el
parámetro de la anchura del camino (para establecer el tamaño de baldosa y el intervalo entre baldosas
por defecto). En vez de devolver T, que es el valor que devolvía la versión vacía de la función,
gp:getDialogInput devuelve ahora una lista de asociaciones que contiene cuatro valores nuevos.

Los dos cambios influyen sobre el código que llama a la función y sobre el código que gestiona los
valores devueltos por las funciones. Sustituya la versión anterior de la función C:Gpath de gpmain.lsp
por el siguiente código:

(defun C:GPath (/ gp_PathData gp_dialogResults)


;; Ask the user for input: first for path location and
;; direction, then for path parameters. Continue only if you
;; have valid input. Store the data in gp_PathData.
(if (setq gp_PathData (gp:getPointInput))
(if (setq gp_dialogResults (gp:getDialogInput (cdr(assoc 40
gp_PathData))))
(progn
;; Now take the results of gp:getPointInput and append this
;; to the added information supplied by gp:getDialogInput.
(setq gp_PathData (append gp_PathData gp_DialogResults))
;; At this point, you have all the input from the user.
;; Draw the outline, storing the resulting polyline
;; "pointer" in the variable called PolylineName.
(setq PolylineName (gp:drawOutline gp_PathData))
) ;_ end of progn
(princ "\nFunction cancelled.")
) ;_ end of if
(princ "\nIncomplete information to draw a boundary.")
) ;_ end of if
(princ); exit quietly
) ;_ end of defun

Eche un vistazo a las líneas que aparecen en negrita en la revisión de la función C:GPath principal. Hay
dos cambios esenciales que hacen que el programa funcione correctamente:

z Cuando se llama a la función gp:getDialogInput se le transmite la anchura del camino. Esto se hace
extrayendo el valor asociado al índice de la clave 40 de la lista de asociaciones gp_PathData.
z La lista de asociaciones devuelta por gp:getPointInput se asigna a una variable llamada
gp_dialogResults. Si esta variable tiene un valor, su contenido debe agregarse al final de los valores
de la lista de asociaciones que ya se encuentran almacenados en gp_PathData.

En el código hay más cambios, que se deben a la sustitución de marcadores en la versión vacía de la
función. Lo más fácil es copiar este código del aprendizaje en pantalla y pegarlo en el archivo.

¿Comentarios?

Creación de un proyecto y adición de la interfaz

Uno de los requisitos de la aplicación de camino de jardín era que los usuarios pudieran dibujar el
contorno como polilínea optimizada o polilínea al estilo antiguo. La primera versión de gp:drawOutline
que se escribió utilizaba siempre una polilínea optimizada para dibujar el contorno. Ahora que la interfaz
del cuadro de diálogo está preparada, es posible integrar la opción de dibujar también una polilínea de
estilo antiguo. Para ello, gp:drawOutline debe averiguar qué tipo de polilínea debe dibujar y, a

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 55 de 103

continuación, dibujarla.

Los cambios que se deben efectuar en gp:drawOutline se incluyen en el siguiente fragmento de código.
Efectúe la modificación desde el archivo gpdraw.lsp indicado en negrita:

(setq PathAngle (cdr (assoc 50 BoundaryData))


Width (cdr (assoc 40 BoundaryData))
HalfWidth (/ Width 2.00)
StartPt (cdr (assoc 10 BoundaryData))
PathLength (cdr (assoc 41 BoundaryData))
angp90 (+ PathAngle (Degrees->Radians 90))
angm90 (- PathAngle (Degrees->Radians 90))
p1 (polar StartPt angm90 HalfWidth)
p2 (polar p1 PathAngle PathLength)
p3 (polar p2 angp90 Width)
p4 (polar p3 (+ PathAngle (Degrees->Radians 180))
PathLength)
poly2Dpoints (apply 'append
(mapcar '3dPoint->2dPoint (list p1 p2 p3 p4))
)
poly3Dpoints (mapcar 'float (append p1 p2 p3 p4))
;; get the polyline style
plineStyle (strcase (cdr (assoc 4 BoundaryData)))
) ;_ end of setq
;; Add polyline to the model space using ActiveX automation
(setq pline (if (= plineStyle "LIGHT")
;; create a lightweight polyline
(vla-addLightweightPolyline
*ModelSpace* ; Global Definition for Model Space
(gp:list->variantArray poly2Dpoints) ;data conversion
) ;_ end of vla-addLightweightPolyline
;; or create an old-style polyline
(vla-addPolyline
*ModelSpace*
(gp:list->variantArray poly3Dpoints) ;data conversion
) ;_ end of vla-addPolyline
) ;_ end of if
) ;_ end of setq

Puede ser bastante complicado incorporar estos cambios al código, porque no sólo se deben agregar
partes, sino que es necesario borrar algunas líneas y reestructurar otras. Es recomendable copiar toda
la declaración setq del aprendizaje en pantalla y copiarla en el código.

¿Comentarios?

Creación de un proyecto y adición de la interfaz

Si no lo ha hecho ya, borre el siguiente fragmento de código de la función C:GPath de gpmain.lsp:

(princ "\nThe gp:drawOutline function returned <")


(princ PolylineName)
(princ ">")

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 56 de 103

(Alert "Congratulations - your program is complete!

Ha estado utilizando este código como marcador, pero ahora que gp:drawOutline funciona, ya no es
necesario.

¿Comentarios?

Creación de un proyecto y adición de la interfaz

Antes de ejecutar el programa, guarde todos los archivos modificados, si no lo ha hecho ya. Puede
elegir, en el menú de VLISP Archivo Guardar todo, o utilizar el método abreviado ALT+MAYÚS+s
para guardar todos los archivos abiertos.

El siguiente paso consiste en volver a cargar todos los archivos en VLISP.

Para cargar y ejecutar todos los archivos de la aplicación


1. Si el archivo de proyecto creado antes todavía no está abierto, elija Proyecto Abrir proyecto
en el menú de VLISP y, a continuación, introduzca el nombre de archivo del proyecto gpath; no
incluya la extensión .prj. Si VLISP no encuentra el archivo del proyecto, pulse Examinar y elija el
archivo en el cuadro de diálogo Abrir proyecto. Pulse Abrir.

2. En la ventana del proyecto pulse el botón Cargar archivos de origen.


3. Escriba el comando (C:GPath) en la solicitud de la consola de VLISP para ejecutar el programa.
Si tiene que depurar el código, intente utilizar las herramientas que se vieron en los ejercicios 2 y
3, y recuerde que, si todo lo demás falla, siempre puede copiar el código del directorio
Tutorial\VisualLISP\Lesson4.

Intente también dibujar el camino con polilíneas optimizadas y del estilo antiguo. Después de dibujar los
caminos, utilice el comando list de AutoCAD para comprobar si el programa está dibujando los tipos
correctos de entidades.

¿Comentarios?

Creación de un proyecto y adición de la interfaz

En esta lección:

z Ha modularizado el código dividiéndolo en cuatro archivos.


z Ha organizado el código en módulos en un proyecto de VLISP.
z Ha aprendido a definir un cuadro de diálogo con DCL (Dialog Control Language, Lenguaje de control
de cuadros de diálogo).
z Ha agregado código de AutoLISP para establecer y gestionar la entrada del cuadro de diálogo.
z Ha modificado el código para permitir a los usuarios la elección del tipo de línea de contorno.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 57 de 103

Ahora tiene un programa que dibuja un contorno de camino de jardín. En la próxima lección va a
agregar las baldosas al camino de jardín. En el proceso conocerá más herramientas de desarrollo de
programas de VLISP.

¿Comentarios?

Cuando termine con este ejercicio, la aplicación cumplirá los requisitos básicos establecidos en el
Ejercicio 1. Agregará la función de rellenar el camino con baldosas dentro del contorno y utilizará para
ello varios métodos diferentes de creación de entidades. También aprenderá el uso de varios métodos
abreviados y nuevas herramientas de edición.

Temas de esta sección:

z Presentación de otras herramientas de edición de Visual LISP

z Añadir baldosas al camino de jardin

z Comprobación del código

z Repaso de la Lección 5

¿Comentarios?

Dibujo de las baldosas

Si no hay ninguna abierta, abra una copia de gpdraw.lsp en la ventana del editor de texto de Visual
LISP®. Este código tiene algunos aspectos que se repiten en gran parte del código que va a desarrollar
en VLISP. En primer lugar, encontrará varios paréntesis y otros que a su vez se encuentran entre
paréntesis. También existen muchas llamadas a funciones, algunas de ellas con nombres muy largos
(por ejemplo, vla‑addLightweightPolyline. En VLISP puede utilizar algunas herramientas que le
ayudarán a trabajar con estas funciones comunes del código AutoLISP®.

Temas de esta sección:

z Coincidencia de paréntesis

z Completar palabras automáticamente

z Completar palabra por aproximación

z Obtención de ayuda sobre una función

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 58 de 103

¿Comentarios?

Dibujo de las baldosas

VLISP cuenta con una función de comprobación de coincidencia de paréntesis que le ayudará a buscar
los paréntesis de cierre correspondientes a los de apertura.

Para emparejar un paréntesis de apertura con el correspondiente de cierre


1. Coloque el cursor delante del paréntesis de apertura que precede a la llamada a la función setq.
2. Pulse CTRL + SHIFT + ]. (También puede hacer doble clic).

VLISP busca el paréntesis de cierre correspondiente al que ha indicado y selecciona el código completo
entre los dos paréntesis. De este modo, además de asegurarse de haber incluido la cantidad correcta
de paréntesis, puede cortar o copiar el texto seleccionado más fácilmente. Estos consejos le habrán
sido de utilidad al actualizar esta llamada al final del Ejercicio 4.

¿Qué otras utilidades tiene? Puede copiar parte del código en la ventana Consola de VLISP, pegarlo y
hacer una prueba. También puede servir para reemplazar 50 líneas de código por otras tres mucho más
completas que acaba de crear. Con la herramienta de comprobación de coincidencia de paréntesis
puede seleccionar rápidamente el código antiguo y, a continuación, eliminarlo con sólo pulsar una tecla.
Es mucho más rápido dejar que VLISP busque el bloque completo que buscar todos los paréntesis de
cierre.

También dispone de un comando de combinación de teclas para buscar paréntesis de apertura y


realizar la búsqueda hacia atrás. Coloque el cursor detrás del paréntesis de cierre y haga doble clic o
pulse CTRL +SHIFT +[. VLISP busca el paréntesis de apertura correspondiente y lo selecciona con el
código completo entre los dos paréntesis.

Ambos comandos pueden seleccionarse también en el menú VLISP, Edición Coincidencia en


paréntesis.

¿Comentarios?

Dibujo de las baldosas

Suponga que necesita añadir nuevas funciones a un programa mediante el código siguiente:

ObjectCreationStyle (strcase (cdr (assoc 3 BoundaryData)))


(if (equal ObjectCreationStyle "COMMAND")
(progn
(setq firstCenterPt(polar rowCenterPt (Degrees->Radians 45) distanceOnPath))
(gp:Create_activeX_Circle)
)
)

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 59 de 103

(No se preocupe por lo que pueda hacer este código, si es que hace algo. Es sólo un ejemplo que
incluye diversas variables largas y nombres de funciones.)

VLISP puede completar las palabras y ahorrarle varias pulsaciones de teclas.

Para usar la función Completar palabra repetida de Visual LISP


1. Escriba el código siguiente al final del archivo gpdraw.lsp:
ObjectCreationStyle (strcase (cdr (assoc 3 BoundaryData)))
(if (equal Ob

2. Pulse CTRL + BARRA ESPACIADORA.


VLISP le ha ahorrado diecisiete pulsaciones de tecla buscando en el archivo abierto, donde
ha encontrado las palabras que más se parecen a las dos últimas que ha escrito.
3. Complete la línea de código tal y como se muestra a continuación:
(if (equal ObjectCreationStyle "COMMAND")

4. Añada las líneas siguientes:


(progn
(setq firstCenterPt(p

5. Pulse CTRL + BARRA ESPACIADORA.


VLISP encuentra la palabra “p” más reciente, que en este caso es progn. Sin embargo, la
palabra que está buscando es polar. Si continúa pulsando CTRL + BARRA
ESPACIADORA, VLISP muestra en orden todas las posibles coincidencias del código.
Finalmente, encontrará la palabra polar.
6. Borre el código que ha escrito, ya que sólo sirve para esta demostración.
También puede seleccionar la función Completar palabra repetida en el menú Buscar de
VLISP.

¿Comentarios?

Dibujo de las baldosas

Si ya ha trabajado con AutoLISP, posiblemente habrá tenido que escribir alguna expresión como la
siguiente:

(setq myEnt (ssname mySelectionSet ssIndex))

A menudo, es complicado hacer un seguimiento de todas las funciones de selección definidas: ssname,
ssget, sslength, etc. La función Completar palabra por aproximación de VLISP puede ayudarle.

Para usar la función Completar palabra por aproximación de VLISP


1. Escriba el código siguiente en una línea nueva al final del archivo gpdraw.lsp:
(setq myEnt (ent

2. Pulse CTRL + MAYÚS + BARRA ESPACIADORA.


VLISP muestra una lista con todos los símbolos de AutoLISP que empiezan con las letras
ent.
Utilice las teclas de flecha arriba y abajo para desplazarse por la lista. Elija ENTGET y
pulse INTRO.
VLISP cambia la palabra ent que ha escrito por ENTGET.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 60 de 103

3. Borre el código.

¿Comentarios?

Dibujo de las baldosas

El código que añade una polilínea ligera al dibujo invoca una función denominada vla-
addLightweightPolyline. Además de ser una palabra muy larga para escribirla, existen muchas otras
funciones para crear entidades que también empiezan por vla-add. Si no desea consultar en el manual
el nombre de las funciones cada vez que va a crear un programa, puede dejar que lo haga VLISP.

Para obtener ayuda sobre el uso de una función


1. Escriba el código siguiente en una línea nueva
(vla-add

2. Pulse CTRL + MAYÚS + BARRA ESPACIADORA.


3. Busque vla‑addLightweightPolyline en la lista.
4. Haga doble clic en vla‑addLightweightPolyline.
VLISP muestra el cuadro de diálogo Servicio de símbolos correspondiente a la función
seleccionada.
5. Haga clic en el botón Ayuda del cuadro de diálogo Servicio de símbolos. (Si son funciones de
ActiveX®, pasará automáticamente al ActiveX and VBA Reference).

6. Borre los cambios que ha hecho en el archivo gpdraw.lsp, ya que sólo sirven para esta
demostración. Cierre también los cuadros de diálogo Servicio de símbolos y Completar palabra
por aproximación.

¿Comentarios?

Dibujo de las baldosas

Ya tiene un contorno del camino y está listo para rellenarlo con baldosas. Necesitará aplicar algunos
datos lógicos y modificar una pequeña sección de la geometría.

Temas de esta sección:

z Aplicación de datos lógicos

z Aplicación de alguna geometría

z Para dibujar las baldosas

z Dibujo de las baldosas en una fila

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 61 de 103

z Comprobación del código

¿Comentarios?

Dibujo de las baldosas

Una de las tareas que debe realizar es determinar el espacio entre las baldosas y dibujarlas. Si se trata
de un trazado sencillo de baldosas rectilíneas, puede uilizar el comando MATRIZ de AutoCAD® para
rellenar las baldosas. Sin embargo, para el camino de jardín necesitará desfasar cada fila de baldosas
de la fila anterior.

Este patrón de desfase de filas es un programa repetitivo. Imagne cómo sería la distribución de las
baldosas en la generación del camino real. Seguramente, trataría de empezar en un extremo para
seguir colocando las baldosas hasta que no quede más espacio libre.

El pseudo código lógico es el siguiente:

En el punto inicial del camino


Elija el desfase de la fila inicial desde el centro (centrado en
el camino o desfasado por un "espacio de baldosa")
Mientras que el espacio del contorno relleno sea menor que el espacio que se va
rellenar,
Dibuje una fila de baldosas.
Restablezca el siguiente punto inicial (incrementado por un "espacio de baldo
Añada la distancia ocupada por la nueva fila al total del espacio
relleno.
Active o desactive el desfase (si está centrado, elija descentrado y
viceversa).
Vuelva al principio del bucle.

¿Comentarios?

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 62 de 103

Dibujo de las baldosas

Para dibujar el camino de jardín sólo necesita conocer algunas cotas. La media anchura es fácil: es
exactamente la mitad de la anchura del camino. Ya ha definido el código para que los usuarios puedan
obtener esta anchura y lo ha guardado en una lista de asociación.

El espaciado de las baldosas también es sencillo: es el doble del radio, es decir, el diámetro, más el
espacio entre las baldosas. Las cotas también las eligen los usuarios.

El espaciado de las filas es algo más complejo, a menos que domine la trigonometría. Vea la fórmula a
continuación:

Row Spacing = (Diámetro de baldosa + Espacio entre baldosas) * (el seno


de 60 grados)

¿Comentarios?

Dibujo de las baldosas

Compruebe si la siguiente función tiene algún sentido. Compárela con el pseudo código e intente seguir
los cálculo geométricos descritos. Quizá encuentre algunas funciones de AutoLISP que desconoce. Si
necesita ayuda sobre alguna de las funciones, consulte la AutoLISP Reference. De momento, sólo
tiene que leer el código sin escribir nada.

(defun gp:Calculate-and-Draw-Tiles (BoundaryData / PathLength


TileSpace TileRadius SpaceFilled SpaceToFill
RowSpacing offsetFromCenter
rowStartPoint pathWidth pathAngle
ObjectCreationStyle TileList)
(setq PathLength (cdr (assoc 41 BoundaryData))
TileSpace (cdr (assoc 43 BoundaryData))
TileRadius (cdr (assoc 42 BoundaryData))
SpaceToFill (- PathLength TileRadius)
RowSpacing (* (+ TileSpace (* TileRadius 2.0))
(sin (Degrees->Radians 60))
) ;_ end of *
SpaceFilled RowSpacing
offsetFromCenter 0.0
offsetDistance (/ (+ (* TileRadius 2.0) TileSpace) 2.0)
rowStartPoint (cdr (assoc 10 BoundaryData))
pathWidth (cdr (assoc 40 BoundaryData))
pathAngle (cdr (assoc 50 BoundaryData))
ObjectCreationStyle (strcase (cdr (assoc 3 BoundaryData)))
) ;_ end of setq
;; Compensate for the first call to gp:calculate-Draw-tile Row
;; in the loop below.
(setq rowStartPoint

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 63 de 103

(polar rowStartPoint
(setq rowStartPoint
(/ TileRadius 2.0)
) ;_ end of polar
) ;_ end of setq
;; Draw each row of tiles.
(while (<= SpaceFilled SpaceToFill)
;; Get the list of tiles created, adding them to our list.
(setq tileList (append tileList
(gp:calculate-Draw-TileRow
(setq rowStartPoint
(polar rowStartPoint
pathAngle
RowSpacing
) ;_ end of polar
) ;_ end of setq
TileRadius
TileSpace
pathWidth
pathAngle
offsetFromCenter
ObjectCreationStyle
) ;_ end of gp:calculate-Draw-TileRow
) ;_ end of append
;; Calculate the distance along the path for the next row.
RowSpacing)
SpaceFilled (+ SpaceFilled RowSpacing)
;; (causes alternate rows to be indented).
offsetFromCenter
(if (= offsetFromCenter 0.0)
offsetDistance
0.0
) ;_ end of if
) ;_ end of setq
) ;_ end of while
;; Return the list of tiles created.
tileList
) ;_ end of defun

Es necesario ampliar la información sobre algunas líneas de código.

El fragmeto de código siguiente se produce justo antes de iniciar el bucle while:

;; Compensate for the very first start point!!


(setq rowStartPoint(polar rowStartPoint
(+ pathAngle pi)(/ TileRadius 2.0)))

Hay que resolver tres piezas siguiendo la lógica de este algoritmo:

z La variable rowStartPoint empieza a cargarse en la función gp:Calculate‑and‑Draw-Tiles cuando


se asigna el punto que el usuario ha seleccionado como punto inicial del camino.
z El primer argumento pasado a la función gp:calculate-Draw-TileRow hace lo siguiente:
(setq rowStartPoint(polar rowStartPoint pathAngle RowSpacing))
Otra forma de empezar: al llamar a la función gp:calculate‑Draw‑TileRow, se define la
variable rowStartPoint como una distancia RowSpacing pasado el rowStartPoint actual.
z El argumento rowStartPoint se utiliza en gp:calculate-Draw-TileRow como punto inicial de los centros
de los circulos de la fila.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 64 de 103

Para compensar el desplazamiento hacia adelante inicial de rowStartPoint al dibujar la primera fila (es
decir, el primer ciclo durante el bucle while), necesita desplazar ligeramente rowStartPoint en la
dirección opuesta. Se trata de evitar un aspecto de un margen grande de espacio vacío entre el
contorno del camino y la primera fila. La mitad de TileRadius es una cantidad suficiente para desplazar
el punto. Para hacerlo, puede utilizar polar para proyectar rowStartPoint sobre un vector orientado a 180
grados desde PathAngle. Observe que el punto se coloca de forma provisional fuera del contorno del
camino.

El siguiente fragmento (modificado para hacerlo más comprensible) es quizá algo más complicado:

(setq tileList (append tileList


(gp:calculate-Draw-TileRow
(setq rowStartPoint
(polar rowStartPoint pathAngle RowSpacing)
) ;_ end of setq
TileRadius TileSpace pathWidth pathAngle
offsetFromCenter ObjectCreationStyle
)))

Esencialmente, se trata de setq desdoblado alrededor de append y la llamada a gp:calculate-Draw-


TileRow.

La función gp:calculate-Draw-TileRow devuelve el ID de objeto de cada baldosa dibujada. (El ID de


objeto apunta al objeto de baldosa en el dibujo.) Como está dibujando las baldosas fila a fila, la función
devuelve el ID de objeto de cada fila por separado. La función append añade los nuevos ID de objeto a
los demás ID de objeto almacenados en tileList.

Cerca del final de la función puede encontrar el siguiente fragmento de código:


(setq offsetFromCenter
(if (= offsetFromCenter 0.0)
offsetDistance
0.0
)
)

Es el conmutador de desplazamiento, que determina si la fila que se está dibujando debe empezar con
un círculo centrado en el camino o con un desfase de éste. El pseudo código de este algoritmo es el
siguiente:

Defina la distancia de desfase como sigue:


Si el desfase es cero, defínalo en la distancia de desfase;
Si no, vuelva a ponerlo a cero.

¿Comentarios?

Dibujo de las baldosas

Ahora que ya dispone del código lógico para dibujar el camino, debe decidir cómo dibujar las baldosas
en cada fila. El siguiente diagrama muestra dos supuestos: una fila en la que el desfase desde el centro
del camino es igual a 0.0 y otra en la que es distinto Examine el diagrama y lea el pseudo código que
sigue.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 65 de 103

Defina las variables de StartPoint, angp90, angm90, etc.


Defina la variable FirstCenterPoint en StartPoint + distancia de desfase
(puede ser 0.0).
Defina el valor inicial de TileCenterPt en FirstCenterPoint.
(Nota: empiece a dibujar los círculos en la dirección angp90.)
Mientras la distancia desde StartPoint a TileCenterPt sea menor que HalfWidth:
Dibuje un círculo y añádalo a la lista acumulada de círculos.
Defina TileCenterPt en el siguiente incremento de espacio de baldosa en la
angp90.
End While
Restablezca TileCenterPoint a FirstCenterPoint + el incremento de espacio de ba
Mientras la distancia desde StartPoint a TileCenterPt sea menor que HalfWidth:
Dibuje un círculo y añádalo a la lista acumulada de círculos.
Defina TileCenterPt al siguiente incremento de espacio de baldosa en la dir
angp90.
End While
Vuelva a la lista de círculos.

¿Comentarios?

Dibujo de las baldosas

A continuación se muestra el código de la función gp:calculate-Draw-TileRow:

(defun gp:calculate-Draw-TileRow (startPoint TileRadius


TileSpace pathWidth pathAngle offsetFromCenter
ObjectCreationStyle / HalfWidth TileDiameter
ObjectCreationFunction angp90 angm90
firstCenterPt TileCenterPt TileList)
(setq HalfWidth (- (/ pathWidth 2.00) TileRadius)
Tilespacing (+ (* TileRadius 2.0) TileSpace)
TileDiameter (* TileRadius 2.0)
angp90 (+ PathAngle (Degrees->Radians 90))
angm90 (- PathAngle (Degrees->Radians 90))
firstCenterPt (polar startPoint angp90 offsetFromCenter)
tileCenterPt firstCenterPt
ObjectCreationStyle(strcase ObjectCreationStyle)
ObjectCreationFunction
(cond

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 66 de 103

((equal ObjectCreationStyle "ACTIVEX")


gp:Create_activeX_Circle
)
((equal ObjectCreationStyle "ENTMAKE")
gp:Create_entmake_Circle
)
((equal ObjectCreationStyle "COMMAND")
gp:Create_command_Circle
)
(T
(alert (strcat "ObjectCreationStyle in function
gp:calculate‑Draw‑TileRow"
"\nis invalid. Contact developer for assistance."
"\n ObjectCreationStyle set to ACTIVEX"
)
)
setq ObjectCreationStyle "ACTIVEX")
)
)
)
;; Draw the circles to the left of the center.
(while (< (distance startPoint tileCenterPt) HalfWidth)
;; Add each tile to the list to return.
(setq tileList
(cons
(ObjectCreationFunction tileCenterPt TileRadius)
tileList
)
)
;; Calculate the center point for the next tile.
(setq tileCenterPt
(polar tileCenterPt angp90 TileSpacing)
)
);_ end of while
;; Draw the circles to the left of the center.
(setq tileCenterPt
(polar firstCenterPt angm90 TileSpacing))
(while (< (distance startPoint tileCenterPt) HalfWidth)
;; Add each tile to the list to return.
(setq tileList
(cons
(ObjectCreationFunction tileCenterPt TileRadius)
tileList
)
)
;; Calculate the center point for the next tile.
(setq tileCenterPt (polar tileCenterPt angm90 TileSpacing))
);_ end of while
;; Return the list of tiles.
tileList
) ;_ end of defun

El código lógico de AutoLISP sigue el pseudo código y añade lo siguiente:

(setq ObjectCreationFunction
(cond
((equal ObjectCreationStyle "ACTIVEX")
gp:Create_activeX_Circle
)
((equal ObjectCreationStyle "ENTMAKE")

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 67 de 103

gp:Create_entmake_Circle
)
((equal ObjectCreationStyle "COMMAND")
gp:Create_command_Circle
)
(T
(alert
(strcat
"ObjectCreationStyle in function gp:calculate-Draw-TileRow"
"\nis invalid. Contact developer for assistance."
"\n ObjectCreationStyle set to ACTIVEX"
) ;_ end of strcat
) ;_ end of alert
(setq ObjectCreationStyle "ACTIVEX")
)
) ;_ end of cond
) ;_ end of setq

¿Recuerda la especificación que permite dibujar las baldosas (círculos) en ActiveX, con la función
entmake o con la función command? La variable ObjectCreationFunction tiene asignada una función de
tres posibles, dependiendo del parámetro ObjectCreationStyle (pasado desde C:GPath y mediante
gp:Calculate-and-Draw-Tiles). A continuación se muestran las tres funciones como se van a definir en
gpdraw.lsp:

(defun gp:Create_activeX_Circle (center radius)


(vla-addCircle *ModelSpace*
(vlax-3d-point center) ; convert to ActiveX-compatible 3D point
radio
)
) ;_ end of defun
(defun gp:Create_entmake_Circle (center radius)
(entmake
(list (cons 0 "CIRCLE") (cons 10 center) (cons 40 radius))
)
(vlax-ename->vla-object (entlast))
)
(defun gp:Create_command_Circle (center radius)
(command "_CIRCLE" center radius)
(vlax-ename->vla-object (entlast))
)

La primera función dibuja un círculo utilizando una función ActiveX y devuelve un objeto ActiveX.

La segunda función dibuja un círculo utilizando entmake. Devuelve un nombre de entidad convertido en
un objeto ActiveX.

La tercera función dibuja un círculo utilizando command. También devuelve un nombre de entidad
convertido en un objeto ActiveX.

¿Comentarios?

Dibujo de las baldosas

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 68 de 103

Si ha llegado hasta aquí, se ha ganado un atajo.

Para comprobar el código


1. Cierre todas las ventanas activas de VLISP, incluidas las de proyecto.
2. Copie el contenido completo del directorio Tutorial\VisualLISP\Lesson5 en el directorio de
aprendizaje Micamino.
3. Abra el archivo de proyecto gpath5.prj: en la barra de menús de VLISP, elija Seleccionar
proyecto Abrir proyecto.
4. Cargue los archivos de origen del proyecto.
5. Active (cambie a) la ventana de AutoCAD® y ejecute el comando gpath para ejecutar el programa.
6. Ejecute gpath para dibujar el camino de jardín tres veces, cada una con un método de creación
distinto. ¿Puede ver alguna diferencia de velocidad al dibujar el camino con cada método?

¿Comentarios?

Dibujo de las baldosas

Ha empezado este ejercicio aprendiendo las funciones de edición de VLISP que pueden ayudarle a

z Comprobar la coincidencia de paréntesis en el código.


z Buscar y completar un nombre de función.
z Obtener información en la ayuda sobre una función.

Al completar el ejercicio, ha generado el código que dibuja las baldosas del camino de jardín. Ahora
tiene un programa que cumple los requisitos establecidos al principio del aprendizaje.

Alcanzado este punto, probablemente ha adquirido la experiencia necesaria en VLISP para continuar
por sus propios medios. No obstante, si lo desea, puede continuar con los dos ejercicios de aprendizaje
restantes, donde se explica cómo utilizar las funciones de reactor y otras funciones avanzadas del
entorno VLISP.

¿Comentarios?

En este ejercicio va a aprender qué son los reactivos y cómo utilizarlos para dibujar eventos y
entidades. Los reactivos permiten que AutoCAD® informe a la aplicación siempre que tengan lugar un
determinados eventos. Por ejemplo, si un usuario desplaza una entidad a la que la aplicación ha
enlazado un reactivo, la aplicación recibirá la notificación del desplazamiento de la entidad. Esto se
puede programar para desencadenar operaciones adicionales, como mover otras entidades asociadas
a la que ha desplazado el usuario, o para actualizar una etiqueta de texto que registra la información de
versión de la función de dibujo alterada. Es como dotar a la aplicación de un buscapersonas y decir a
AutoCAD que avise a la aplicación cuando ocurra algo.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 69 de 103

Temas de esta sección:

z Conceptos básicos de los reactivos

z Diseño de reactivos para el camino de jardín

z Prueba de los reactivos

z Repaso de la Lección 6

¿Comentarios?

Funcionamiento de los reactivos

Los reactivos son objetos que se enlazan al editor del dibujo o a determinadas entidades de un dibujo.
El objeto reactivo es como una alarma automática que sabe cómo llamar a su buscapersonas cuando
ocurre algo importante. El aviso lo envía una función de AutoLISP® a la que llama el reactivo, función
denominada retorno de llamada.

Nota La complejidad del código de la aplicación y el nivel de conocimientos necesarios para estos dos
últimos ejercicios son muy superiores a los de los ejercicios 1 a 5. Se facilita mucha información, pero
no se explica con tanto detalle como en los ejercicios anteriores. Si es principiante, no se preocupe si
no lo entiende la primera vez. Considérelo un vistazo a algunas de las útiles pero técnicamente difíciles
características de Visual VLISP®.

Temas de esta sección:

z Tipos de reactivos

¿Comentarios?

Funcionamiento de los reactivos

Existen varios tipos de reactivos de AutoCAD®. Cada tipo de reactivo responde a uno o más eventos de
AutoCAD. Los reactivos se agrupan en las siguientes categorías:

Reactivos de editor
Notifican a la aplicación cada vez que se llama a un comando de AutoCAD.
Reactivos de vinculador
Notifican a la aplicación cada vez que se carga o se descarga una aplicación ObjectARX®
Reactivos de base de datos
Corresponden a entidades u objetos determinados de una base de datos de dibujo.
Reactivos de documento
Notifican a la aplicación en modo MDI de los cambios en el documento de dibujo actual, como la

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 70 de 103

apertura de un nuevo documento de dibujo, la activación de una ventana de documento distinto o


el cambio del estado de bloqueo de un documento.
Reactivos de objeto
Notifican cada vez que se modifica, se copia o se borra un objeto determinado.

Con la excepción de los reactivos de editor, sólo hay un tipo de reactivo por categoría. Los reactivos de
editor incluyen una amplia gama de tipos: por ejemplo, los reactivos DXF™ (que notifican a una
aplicación acerca de cuándo se importa o se exporta un archivo DXF) y los reactivos de ratón (que
notifican sobre eventos de ratón como el doble clic).

Dentro de las categorías de reactivos hay muchos eventos distintos a los que se puede enlazar un
reactivo. AutoCAD permite realizar muchos tipos de acciones distintas, no obstante, el usuario deberá
elegir las acciones que más le convengan. Cuando termine, puede añadir el reactivo “auto-dialer” al
evento y, a continuación, escribir la función callback que se activa cuando se produce el evento.

¿Comentarios?

Funcionamiento de los reactivos

Para implementar las funciones de los reactivos en la aplicación camino de jardín, empiece por
gestionar unos pocos eventos, en vez de intentar abarcar todas las acciones que puede efectuar el
usuario.

Temas de esta sección:

z Selección de eventos de reactivo para el camino de jardín

z Planificación de las funciones de retorno de llamada

z Planificación de reactivos múltiples

z Enlace de los reactivos

z Guardado de datos con un reactivo

z Actualización de la función C:GPath

z Adición de funciones de retorno de llamada de reactivo

z Limpieza después de los reactivos

¿Comentarios?

Funcionamiento de los reactivos

Para el aprendizaje, fíjese los siguientes objetivos:

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 71 de 103

z Cuando se cambia la posición de una esquina (vértice) del contorno del camino de jardín, el camino
se debe dibujar de nuevo para que el contorno siga siendo rectilíneo. Además hay que volver a
dibujar las baldosas de acuerdo con el tamaño y la forma nuevos.
z Cuando se borra el contorno del camino de jardín se deben borrar también las baldosas.

¿Comentarios?

Funcionamiento de los reactivos

Para cada evento de reactivo se debe planificar la función a la que se llama cuando ocurre este. El
siguiente pseudocódigo esboza la secuencia lógica de eventos que debe tener lugar cuando el usuario
arrastra uno de los vértices de la polilínea a una posición nueva:

Defun gp:outline-changed
Erase the tiles.
Determine how the boundary changed.
Straighten up the boundary.
Redraw new tiles.
End function

Aquí hay un pequeño problema. Cuando el usuario empieza a arrastrar el contorno de un vértice de
polilínea, AutoCAD notifica a la aplicación emitiendo un evento :vlr‑modified. No obstante, el usuario
acaba de empezar a arrastrar uno de los vértices de la polilínea. Si se llama inmediatamente a la
función gp:outline‑changed, se interrumpe la acción que está efectuando el usuario. No se puede
conocer la nueva posición del vértice, porque el usuario no la ha seleccionado aún. Además, AutoCAD
no permite a la función modificar el objeto de polilínea mientras el usuario lo está arrastrando. AutoCAD
tiene el objeto de polilínea abierto para su modificación y lo deja abierto hasta que el usuario termina de
cambiar su posición.

Es necesario cambiar el enfoque. Ésta es la lógica actualizada:

When the user begins repositioning a polyline vertex,


Invoke the gp:outline-changed function
Defun gp:outline-changed
Set a global variable that stores a pointer to the polyline
being modified by the user
End function
When the command completes,
Invoke the gp:command-ended function
Defun gp:command-ended
Erase the tiles
Get information on the previous polyline vertex locations
Get information on the new polyline vertex locations
Redefine the polyline (straighten it up)
Redraw the tiles
End function

Cuando un usuario termina de modificar un contorno de camino, Defun gp:command-ended notifica a la


aplicación emitiendo un evento :vlr‑commandEnded, si se ha establecido un reactivo de editor.

Es necesario utilizar una variable global para identificar la polilínea que ha modificado el usuario, porque
no hay continuidad entre las funciones gp:outline-changed y gp:command-ended. En la aplicación,

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 72 de 103

estas dos funciones son llamadas y ejecutadas por separado. La variable global almacena información
importante que se establece en una función y a la que la otra debe tener acceso

Considere ahora qué hacer si el usuario borra el contorno del camino de jardín. El objetivo, en definitiva,
consiste en borrar todas las baldosas. El pseudocódigo siguiente esboza la lógica:

When the user begins to erase the boundary,


Invoke the gp:outline-erased function
Defun gp:outline-erased
Set a global variable that stores a pointer to the reactor
attached to the polyline currently being erased
End function
When the erase is completed,
Invoke the gp:command-ended function
Defun gp:command-ended
Erase the tiles that belonged to the now-deleted polyline
End function

¿Comentarios?

Funcionamiento de los reactivos

Los usuarios pueden tener varios caminos de jardín en la pantalla y borrar más de uno. Es necesario
prever esta posibilidad

El reactivo asociado a una entidad es un reactivo de objeto. Si hay varias entidades en el dibujo,
también puede haber varios reactivos de objeto, uno para cada entidad. Un evento de edición
determinado, como el comando borra puede desencadenar muchos retornos de llamada, según cuántas
de las entidades seleccionadas tengan enlazado un reactivo. Los reactivos de editor, sin embargo, son
únicos. La aplicación sólo debe enlazar un reactivo de evento :vlr-commandEnded.

La secuencia de eventos para las dos modificaciones (el cambio de la posición del vértice y el borrado
de la polilínea) terminan con acciones que se deben efectuar dentro de la función gp:command-ended.
Determine qué conjunto de acciones se debe efectuar para cada condición. El pseudocódigo siguiente
esboza la lógica:

Defun gp:command-ended (2nd version)


Retrieve the pointer to the polyline (from a global variable)
Conditional:
If the polyline has been modified then:
Erase the tiles
Get information on the previous polyline vertex locations
Get information on the new polyline vertex locations
Redefine the polyline (straighten it up)
Redraw the tiles
End conditional expression
If the polyline has been erased then:
Erase the tiles
End conditional expression
End Conditional
End function

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 73 de 103

¿Comentarios?

Funcionamiento de los reactivos

El siguiente paso en la planificación de una aplicación con reactivos consiste en averiguar cómo y
cuándo se deben enlazar. Es necesario enlazar dos reactivos de objeto para el marco de la polilínea de
todos los caminos de jardín (uno para responder a los eventos de modificación y el otro para responder
al borrado), y un reactivo de editor para notificar a la aplicación cuando el usuario termina de modificar
la polilínea. Los reactivos de objeto están enlazados a entidades, mientras que los reactivos de editor
están registrados en AutoCAD.

Se debe tener en cuenta otra cosa. Para calcular de nuevo el contorno de la polilínea y devolverle la
forma rectilínea después de que el usuario lo haya modificado es necesario saber cuál era la
configuración del vértice antes de la modificación. Esta información no se puede determinar después de
modificar la polilínea. En ese momento sólo se puede obtener información sobre la configuración nueva.
¿Cómo resolver este problema? Podría mantener esta información en una variable global, pero esto
tiene un inconveniente. Los usuarios pueden dibujar todos los caminos de jardín que quieran, y todos
los caminos nuevos requerirían una nueva variable global.

¿Comentarios?

Funcionamiento de los reactivos

El problema de guardar la configuración original se puede resolver aprovechando otra característica de


los reactivos VLISP: la capacidad de almacenar datos dentro de un reactivo. Cuando el usuario dibuja
por primera vez un contorno de camino, se enlaza un reactivo al camino, junto con los datos que se
desea guardar. Para ello hay que modificar la función principal del programa, C:GPath, como sigue:

Defun C:GPath
Do everything that is already done in the garden path
(and don't break anything)
Attach an object reactor to the polyline using these parameters:
A pointer to the polyline just drawn,
A list of data that you want the reactor to record,
A list of the specific polyline object events to be tracked,
along with the LISP callback functions to be invoked
End of the object reactor setup
Attach editor reactor to the drawing editor using the
following parameters:
Any data you want attached to the reactor (in this case, none)
A list of the specific editor reactor events to be tracked,
along with the LISP callback functions to be invoked
End of the editor reactor setup
End function

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 74 de 103

¿Comentarios?

Funcionamiento de los reactivos

Actualice la función C:GPath agregándole lógica de creación de reactivos.

Para agregar lógica de creación de reactivos a C:GPath


1. Sustituya la versión que tiene de gpmain.lsp por la versión actualizada que se muestra a
continuación. Copie este código del directorio <AutoCAD>\Tutorial\VisualLISP\lesson6:
(defun C:GPath (/
gp_PathData
gp_dialogResults
PolylineName
tileList
)
(setvar "OSMODE" 0) ;; Turn off object snaps
;|
;; Lesson 6 adds a stubbed-out command reactor to AutoCAD
;; However, it would be undesirable to react to every
;; drawing of a circle should the COMMAND tile creation
;; method be chosen by the user. So, disable the
;; *commandReactor* in case it exists.
|;
(if *commandReactor*
(progn
(setq *commandReactor* nil)
(vlr-remove-all :VLR-Command-Reactor)
)
)
;; Ask the user for input: first for path location and
;; direction, then for path parameters. Continue only if you
;; have valid input. Store the data in gp_PathData.
(if (setq gp_PathData (gp:getPointInput))
(if (setq gp_dialogResults
(gp:getDialogInput
(cdr (assoc 40 gp_PathData))
) ;_ end of gp:getDialogInput
) ;_ end of setq
(progn
;; Now take the results of gp:getPointInput and append this to
;; the added information supplied by gp:getDialogInput
(setq gp_PathData (append gp_PathData gp_DialogResults))
;; At this point, you have all the input from the user
;; Draw the outline, storing the resulting polyline "pointer"
;; in the variable called PolylineName
(setq PolylineName (gp:drawOutline gp_PathData))
;; Next, it is time to draw the tiles within the boundary.
;; The gp_tileList contains a list of the object pointers for
;; the tiles. By counting up the number of points (using the
;; length function), we can print out the results of how many
;; tiles were drawn.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 75 de 103

(princ "\nThe path required ")


(princ
(length
(setq tileList (gp:Calculate-and-Draw-Tiles gp_PathData))
) ;_ end of length
) ;_ end of princ
(princ " tiles.")
;; Add the list of pointers to the tiles (returned by
;; gp:Calculate-and-Draw-Tiles) to gp_PathData. This will
;; be stored in the reactor data for the reactor attached
;; to the boundary polyline. With this data, the polyline
;; "knows" what tiles (circles) belong to it.
(setq gp_PathData
(append (list (cons 100 tileList))
; all the tiles
gp_PathData
) ;_ end of append
) ;_ end of setq
;; Before we attach reactor data to an object, let's look at
;; the function vlr-object-reactor
;; vlr-object-reactor has the following arguments:
;; (vlr-object-reactor owner’s data callbacks)
;; The callbacks Argument is a list comprised
;; '(event_name . callback_function)
;;
;; For this exercise we will use all arguments
;; associated with vlr-object-reactor
;; These reactor functions will execute only if
;; the polyline in PolylineName is modified or erased
(vlr-object-reactor
;; The first argument for vlr-object-reactor is
;; the "Owner’s List" argument. This is where to
;; place the object to be associated with the
;; reactor. In this case, it is the vlaObject
;; stored in PolylineName.
(list PolylineName)
;; The second argument contains the data for the path
gp_PathData
;; The third argument is the list of specific reactor
;; types that we are interested in using
'
(
;; reactor that is called upon modification of the object
(:vlr-modified . gp:outline-changed)
;; reactor that is called upon erasure of the object
(:vlr-erased . gp:outline-erased)
)
) ;_ end of vlr-object-reactor
;; Next, register a command reactor to adjust the polyline
;; when the changing command is finished
(if (not *commandReactor*)
(setq *commandReactor*
(VLR-Command-Reactor
nil ; No data is associated with the command reactor
'(
(:vlr-commandWillStart . gp:command-will-start)
(:vlr-commandEnded . gp:command-ended)
)
) ;_ end of vlr-command-reactor
)

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 76 de 103

)
;; The following code removes all reactors when the drawing is
;; closed. This is extremely important!!!!!!!!!
;; Without this notification, AutoCAD may crash upon exiting!
(if (not *DrawingReactor*)
(setq *DrawingReactor*
(VLR-DWG-Reactor
nil ; No data is associated with the drawing reactor
'((:vlr-beginClose . gp:clean-all-reactors)
)
) ;_ end of vlr-DWG-reactor
)
)
) ;_ end of progn
(princ "\nFunction cancelled.")
) ;_ end of if
(princ "\nIncomplete information to draw a boundary.")
) ;_ end of if
(princ); exit quietly
) ;_ end of defun
;;; Display a message to let the user know the command name.
(princ "\nType GPATH to draw a garden path.")
(princ)

2. Repase las modificaciones del código y los comentarios que describen qué hace cada declaración
nueva. Este manual de aprendizaje muestra todo el código modificado en negrita.

¿Comentarios?

Funcionamiento de los reactivos

Las funciones de retorno de llamada de reactivo añaden bastante código a la aplicación. Puede
encontrar este código en el directorio Lesson6.

Para agregar las funciones de retorno de llamada de reactivo al programa


1. Copie el archivo gpreact.lsp del directorio Tutorial\VisualLISP\Lesson6 al directorio de trabajo
micamino.
2. Abra el proyecto GPath (si no está abierto ya) y pulse el botón Propiedades del proyecto de la
ventana del proyecto gpath.
3. Añada el archivo gpreact.lsp al proyecto.
4. El archivo gpreact.lsp se puede colocar en cualquier lugar, entre utils.lsp, que debe permanecer
al principio, y gpmain.lsp, que debe permanecer al final. Mueva los archivos necesarios y pulse
Aceptar.
5. Abra el archivo gpreact.lsp haciendo doble clic en su nombre dentro de la ventana del proyecto
gpath.

Lea los comentarios del archivo para entender lo que está haciendo. Observe que todas las funciones
de retorno de llamada son funciones vacías; lo único que hacen cuando se desencadenan es mostrar
una advertencia.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 77 de 103

La última función del archivo es tan importante que merece un apartado propio.

¿Comentarios?

Funcionamiento de los reactivos

Los reactivos son muy activos. Cuando se diseña una aplicación que los utiliza es muy fácil que el
programa tenga errores, y a veces, que se produzcan también en AutoCAD. Es útil tener una
herramienta que elimine todos los reactivos agregados en caso necesario.

El archivo gpreact.lsp contiene una función llamada gp:clean-all-reactors que no hace gran cosa por sí
misma. Sin embargo, llama a la función CleanReactors. Añada esta función al archivo utils.lsp copiando
el siguiente código al final:

;;;--------------------------------------------------------------;
;;; Function: CleanReactors ;
;;;--------------------------------------------------------------;
;;; Description: General utility function used for cleaning up ;
;;; reactors. It can be used during debugging, as ;
;;; well as cleaning up any open reactors before ;
;;; a drawing is closed. ;
;;;--------------------------------------------------------------;
(defun CleanReactors ()
(mapcar 'vlr-remove-all
'(:VLR-AcDb-reactor
:VLR-Editor-reactor
:VLR-Linker-reactor
:VLR-Object-reactor
)
)
)

¿Comentarios?

Funcionamiento de los reactivos

Ahora ya debe tener en su sitio todas las piezas necesarias para experimentar en vivo con los reactivos.

Para probar el código de los reactivos


1. Cargue todos el código fuente del proyecto. En la ventana del proyecto gpath pulse el botón
Cargar archivos de origen.
2. Active la función C:GPath.
El programa dibuja un camino de jardín, como ocurría en el Ejercicio 5. Al principio no se

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 78 de 103

ve nada interesante.
3. Intente hacer lo siguiente después de dibujar el camino:
z Mueva un vértice de la polilínea. Seleccione la polilínea para activar sus pinzamientos y
arrastre un vértice a otra posición.
z Estire la polilínea.
z Desplace la polilínea.
z Borre la polilínea.

Examine los mensajes que aparecen. Está observando las acciones que tienen lugar entre bastidores.

(Si la aplicación no funciona correctamente y no quiere tomarse la molestia de depurarla ahora, puede
ejecutar el código de ejemplo que se encuentra en el directorio Tutorial\VisualLISP\Lesson6. Utilice el
proyecto Gpath6 de ese directorio.)

Nota A causa del comportamiento del reactivo, puede observar que después de probar una secuencia
de reactivos en AutoCAD no es posible volver a VLISP pulsando ALT + TAB, ni haciendo clic para
activar la ventana de VLISP. Si esto ocurre, basta con que escriba vlisp en la solicitud de comando de
AutoCAD para volver a VLISP.

Temas de esta sección:

z Examen detallado del comportamiento de los reactivos

¿Comentarios?

Funcionamiento de los reactivos

Tome unos papeles y empiece a apuntar en ellos los eventos de reactivo que ocurren dentro de la
aplicación. Éste es un ejemplo de las cosas que debe buscar:

Dibuje diez caminos de jardín y después efectúe un seguimiento de las siguientes combinaciones
comando / objeto, seleccionando las polilíneas de forma sucesiva:

z Borrar/marco de polilínea (camino 1)


z Borrar/círculo dentro de una polilínea (camino 2)
z Borrar/dos polilíneas (caminos 3 y 4)

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 79 de 103

z Mover/marco de polilínea (camino 5)


z Mover/círculo dentro de una polilínea (camino 6)
z Mover/dos polilíneas y varios círculos (caminos 7 y 8)
z Mover vértice (con pinzamientos)/marco de polilínea (camino 9)
z Estirar/marco de polilínea (camino 10)

Este ejercicio le permitirá comprender qué es lo que ocurre entre bastidores. Si en algún momento del
Ejercicio 7 se desorienta con las funciones de los reactivos, consulte las notas de seguimiento que ha
tomado en papel.

¿Comentarios?

Funcionamiento de los reactivos

En esta lección se han presentado los reactivos de AutoCAD y ha aprendido a implementarlos con
VLISP. Ha diseñado un plan para agregar reactivos a la aplicación de camino de jardín y ha añadido
parte del código que el programa necesita para llevar a cabo el plan.

Los reactivos pueden añadir muchas funciones a las aplicaciones, pero recuerde: cuanto más complejo
sea un programa, más fácil será que tenga un fallo.

Otra cosa que se debe tener en cuenta es que, tal y como está diseñada la aplicación, las funciones de
los reactivos no se conservan de una sesión de dibujo a la siguiente. Si se guarda un dibujo que
contiene un camino de jardín enlazado a reactivos, éstos no estarán la próxima vez que se abra el
dibujo. Puede aprender a añadir reactivos permanentes consultando el tema “Transient versus
Persistent Reactors” del Visual LISP Developer’s Guide, y después leyendo sobre las funciones
mencionadas en la AutoLISP Reference.

¿Comentarios?

En el Ejercicio 6 aprendió el funcionamiento básico de las aplicaciones con reactivos. En el ejercicio 7


va a añadir funcionalidad a este conocimiento y a crear un camino de jardín que sabe cómo y cuándo
modificarse. Después de probar la aplicación y comprobar que funciona correctamente creará una
aplicación Visual LISP® desde el proyecto de VLISP.

Deberá considerar esta parte del manual de aprendizaje como la sección de temas avanzados. Si es
principiante, es posible que no entienda todo el código de AutoLISP® que se presenta aquí. Al final de
este ejercicio se facilita una lista de libros sobre AutoLISP que proporcionan información más completa
sobre algunos de los conceptos avanzados de AutoLISP utilizados aquí.

Temas de esta sección:

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 80 de 103

z Planificación del proceso general de los reactivos

z Adición de una nueva funcionalidad de los reactivos

z Redefinición del contorno de la polilínea

z Repaso del código

z Crear una aplicación

z Repaso del aprendizaje

z Bibliografía sobre LISP y AutoLISP

¿Comentarios?

Integración de todos los elementos

En este ejercicio deberá definir varias funciones nuevas. En vez de facilitarle detalles sobre todos los
aspectos del código nuevo, este ejercicio proporciona una visión general y señala los conceptos que
hay detrás del código. Al final del ejercicio tendrá todo el código fuente necesario para crear una
aplicación de camino de jardín idéntica al programa de muestra que ejecutó en el ejercicio 1.

Nota Cuando se desarrollan y se depuran aplicaciones con reactivos siempre existe la posibilidad de
desestabilizar AutoCAD®. Esto puede ocurrir, por ejemplo, si no se elimina un reactivo de las entidades
borradas. Por este motivo se recomienda cerrar VLISP guardando todos los archivos abiertos y salir de
AutoCAD para volver a abrir las dos aplicaciones antes de empezar con el Ejercicio.

Empiece por cargar el proyecto tal y como estaba al final del Ejercicio 6.

En la aplicación del camino de jardín quedan por hacer dos cosas fundamentales:

z Escribir los retornos de llamada del reactivo de objeto.


z Escribir los retornos de llamada del reactivo de editor.

También debe considerar la forma de gestionar las variables globales del programa. A menudo es
conveniente que las variables globales retengan un valor a lo largo de toda la sesión de dibujo de
AutoCAD. Sin embargo, en el caso de los reactivos no es así. Para entenderlo, imagine que un usuario
de la aplicación Camino de jardín ha dibujado varios caminos en un solo dibujo. Después los borra,
primero uno a uno, después dos a dos, etc., hasta que sólo queda uno.

En el ejercicio 5 se presentaba una variable global, *reactorsToRemove*, responsable de guardar los


punteros a los reactivos de las polilíneas que se iban a borrar. Cuando se
*reactorsToRemove*gp:outline-erasedel evento comunica que la polilínea está a punto de borrarse. La
polilínea no se borra realmente hasta que se desencadena el evento gp:command-ended.

La primera vez que el usuario borra una polilínea todo funciona de la forma esperada. En gp:outline-
erased se guarda un puntero al reactor. Cuando se desencadena gp:command-ended se eliminan
también las baldosas asociadas a la polilínea a la que está enlazado el reactor, y todo marcha bien.
Entonces, el usuario decide borrar dos caminos. Como resultado, la aplicación recibe dos llamadas a to
gp:outline‑erased, na para cada polilínea que se va a borrar. Hay que prever dos posibles problemas:

z Cuando se establece con setq la variable *reactorsToRemove* se debe añadir a la variable global un
puntero a un reactivo, con cuidado de no sustituir los valores que se encuentran almacenados. Esto
significa que *reactorsToRemove* debe tener estructura de lista para que se pueda agregar punteros

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 81 de 103

de reactivo. Después se pueden acumular varios punteros de reactivo, correspondientes al número


de caminos que borra el usuario con de un solo comando de borrado.
z Cada vez que se desencadena gp:command-will-start , indicando que comienza una nueva
secuencia de comandos, se debe reinicializar la variable *reactorsToRemove* a nil.Esto es necesario
para que la variable global no guarde punteros a reactivos del comando de borrado anterior.
Si no se reinicializa la variable global, o si no se utiliza la estructura de datos correcta (en este
caso, una lista) se puede obtener un resultado inesperado. En el caso de los reactivos, los
comportamientos imprevistos pueden hacer que falle la sesión de AutoCAD.

Ésta es la secuencia de eventos que debe suceder para que los usuarios borren dos caminos de jardín
con un solo comando de borrado. Observe cómo se gestionan las variables globales:

z Inicie el comando borra. Con ello se desencadena la función gp:command-will-start. Asigne a


*reactorsToRemove* el valor nil.
z Seleccione dos polilíneas; aún no se ha notificado a la aplicación.
z Pulse INTRO para borrar las dos polilíneas seleccionadas.
La aplicación recibe un retorno de llamada a gp:outline-erased para una de las polilíneas.
Añade su puntero de reactivo a la variable global vacía *reactorsToRemove*.
La aplicación tiene una función de retorno de llamada a gp:outline-erased para la segunda de
las polilíneas. Añade el puntero de reactivo a la variable global *reactorsToRemove* que ya
contiene el primer puntero al reactivo.
z AutoCAD suprime las polilíneas.
z La función de retorno de llamada gp:command-ended se ejecuta. Con lo que se elimina cualquier
baldosa asociada a los punteros de reactivo almacenados en *reactorsToRemove*.

Además de la variable global *reactorsToRemove*, la aplicación también incluye una variable global
*polyToChange* que almacena un puntero a cada polilínea que se va a modificar. Más adelante, en
esta lección, se introducirán dos variables globales adicionales para la aplicación.

Temas de esta sección:

z Reacting Comportamiento ante más comandos llamados por el usuario

z Almacenamiento de la información en los objetos de reactivo

¿Comentarios?

Integración de todos los elementos

Cuando se escribe una aplicación con reactivos, es necesario gestionar cualquiera de los comandos
que afecten de forma significativa a los objetos. Una de las actividades de diseño del programa debería
ser la de revisar todos los posibles comandos de edición de AutoCAD y determinar cómo la aplicación
deberá responder ante cada uno de ellos. El formato de la hoja de seguimiento de reactivos que se
muestra casi al final de la lección 6 es un buen ejemplo. Llame a aquellos comandos que crea que el
usuario va a utilizar y anote el tipo de comportamiento con el que debería responder la aplicación.
También deberá planificar las siguientes acciones:

z Determinar qué hacer cuando los usuarios activen los comandos DESHACER y REHACER
z Determinar qué hacer cuando los usuarios activen un comando UY después de borrar entidades
vinculadas a reactivos.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 82 de 103

Para evitar que un tema complicado pueda convertirse en un tema muy muy complicado, este
aprendizaje no pretende cubrir todas las posibilidades que debería, y esta lección se ocupa de una
parte mínima de esta funcionalidad.

Aunque no vaya a desarrollar toda la funcionalidad de estos comandos adicionales, compruebe lo que
unas cuantas funciones de edición adicionales supondrían:

z Si los usuarios estiran el contorno de una polilínea (mediante el comando ESTIRA), pueden ocurrir
varias cosas. Se puede estirar en cualquier dirección, no sólo en la dirección del eje mayor o del eje
menor, de manera que el contorno podría adquirir una forma muy extraña. Además, es necesario
tener en cuenta el número de vértices que se han estirado. Si sólo se estira un vértice el resultado
será una polilínea muy diferente a la que resultaría si se desplazan dos vértices. En cualquier caso,
una vez decididos los ajustes necesarios para el contorno, las baldosas deben borrarse y las nuevas
posiciones deben volver a calcularse.
z Si se desplaza el contorno de la polilínea, todas las baldosas deberán borrarse y, a continuación,
volverse a dibujar en la nueva ubicación. Esta operación es bastante sencilla ya que el contorno de la
polilínea no ha cambiado de tamaño ni forma.
z Si los usuarios amplían o reducen el contorno de la polilínea, es necesario tomar una decisión.
¿Deben ampliarse o reducirse también las baldosas, de manera que el camino contenga el mismo
número de baldosas que antes? ¿O bien debe mantenerse el tamaño de la baldosa y hacer que la
aplicación añada o suprima baldosas, según se amplíe o reduzca la polilínea?
z Si los usuarios hacen girar el contorno de la polilínea, todas las baldosas deberían borrarse y, a
continuación, volverse a dibujar con la nueva orientación.

No obstante, para empezar haga simplemente lo que se indica a continuación:

z Advierta al usuario antes de iniciar un comando, que el comando de edición que ha seleccionado
(como estirar, desplazar o girar) tendrá efectos negativos en el camino de jardín.
z Si el usuario continúa, borre las baldosas y no las vuelva a dibujar.
z Suprima los reactivos del contorno del camino.

Nota Además de los comandos de AutoCAD invocados por el usuario, las entidades también pueden
modificarse o suprimirse a través de aplicaciones AutoLISP u ObjectARX®. El ejemplo que se
proporciona en el Aprendizaje del Camino de jardín no trata ninguna manipulación programada sobre el
contorno de la polilínea del camino de jardín, como a través (entdel < polyline entity>). En este caso, los
eventos de reactivos de :vlr-commandWillStart y :vlr-commandEnded no se ejecutarán.

¿Comentarios?

Integración de todos los elementos

Otro aspecto importante de la aplicación que es necesario tener en cuenta es el tipo de información que
se va a enlazar al reactivo de objeto que se crea para cada entidad de polilínea. En la lección 6, añadió
un código que enlazó el contenido de gp_PathData (la lista de asociaciones) con el reactivo. Al añadir
un nuevo campo con clave (100) a la lista de asociaciones, ha ampliado los datos de gp_PathData. Esta
nueva sublista es una lista con los punteros de todas las entidades circulares asignadas al contorno de
la polilínea.

Debido al trabajo que se necesita realizar para volver a calcular el contorno de la polilínea, es necesario
añadir a gp_pathData cuatro valores clave adicionales:

;;; StartingPoint ;
;;; (12 . BottomStartingPoint) 15------------------------14 ;

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 83 de 103

;;; (15 . TopStartingPoint) | | ;


;;; EndingPoint 10 ----pathAngle---> 11 ;
;;; (13 . BottomEndingPoint) | | ;
;;; (14 . TopEndingPoint) 12------------------------13 ;
;;; ;

Estos puntos ordenados son necesarios para volver a calcular el contorno de las polilíneas siempre que
el usuario arrastre el pinzamiento de una esquina a una nueva ubicación. Esta información ya existe
dentro de la función gp:drawOutline del archivo gpdraw.lsp. Pero compruebe el valor devuelto de la
función. En la actualidad, sólo se devuelve el puntero al objeto de polilínea. Por lo tanto, es necesario
realizar tres cosas:

z Una los puntos del perímetro en el formato adecuado.


z Modifique la función de manera que devuelva la lista de puntos de perímetro y el puntero a la
polilínea.
z Modifique la función C:GPath para que trate de forma correcta el nuevo formato de los valores
devueltos por gp:drawOutline.

La unión de las listas de puntos del perímetro es sencillo. Mire el código de gp:drawOutline. La variable
local p1 corresponde al valor clave 12, p2 corresponde al 13, p3 al 14 y p4 al 15. Para unir esta
información, puede añadir la siguiente llamada de función:

(setq polyPoints(list
(cons 12 p1)
(cons 13 p2)
(cons 14 p3)
(cons 15 p4)
))

También es fácil modificar la función para que devuelva los puntos del perímetro de la polilínea y el
puntero a la polilínea. Como indica la última expresión dentro de gp:drawOutline, una en una lista los
dos elementos de información que desee devolver.

(list pline polyPoints)

Para añadir al programa la lógica para guardar los puntos del perímetro de la polilínea
1. Modifique gp:drawOutline; para ello, realice los cambios que se muestran en negrita en el código
siguiente (no olvide añadir la variable local polyPoints a la secuencia defun):
(defun gp:drawOutline (BoundaryData / PathAngle
Width HalfWidth StartPt PathLength
angm90 angp90 p1 p2
p3 p4 poly2Dpoints
poly3Dpoints plineStyle pline
polyPoints
)
;; extract the values from the list BoundaryData.
(setq PathAngle (cdr (assoc 50 BoundaryData))
Width (cdr (assoc 40 BoundaryData))
HalfWidth (/ Width 2.00)
StartPt (cdr (assoc 10 BoundaryData))
PathLength (cdr (assoc 41 BoundaryData))
angp90 (+ PathAngle (Degrees->Radians 90))
angm90 (- PathAngle (Degrees->Radians 90))
p1 (polar StartPt angm90 HalfWidth)
p2 (polar p1 PathAngle PathLength)
p3 (polar p2 angp90 Width)
p4 (polar p3 (+ PathAngle
(Degrees->Radians 180)) PathLength)
poly2Dpoints (apply 'append
(mapcar '3dPoint->2dPoint (list p1 p2 p3 p4))

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 84 de 103

)
poly3Dpoints (mapcar 'float (append p1 p2 p3 p4))
;; get the polyline style.
plineStyle (strcase (cdr (assoc 4 BoundaryData)))
;; Add polyline to the model space using ActiveX automation.
pline (if (= plineStyle "LIGHT")
;; create a lightweight polyline.
(vla-addLightweightPolyline
*ModelSpace* ; Global Definition for Model Space
(gp:list->variantArray poly2Dpoints)
;data conversion
) ;_ end of vla-addLightweightPolyline
;; or create a regular polyline.
(vla-addPolyline
*ModelSpace*
(gp:list->variantArray poly3Dpoints)
;data conversion
) ;_ end of vla-addPolyline
) ;_ end of if
polyPoints (list
(cons 12 p1)
(cons 13 p2)
(cons 14 p3)
(cons 15 p4)
)
) ;_ end of setq
(vla-put-closed pline T)
(list pline polyPoints)
) ;_ end of defun

2. Modifique la función C:GPath de gpmain.lsp. Busque la línea de código que, en este momento,
es:
(setq PolylineName (gp:drawOutline gp_PathData))

Cámbiela para que aparezca como se muestra a continuación:


(setq PolylineList (gp:drawOutline gp_PathData)
PolylineName (car PolylineList)
gp_pathData (append gp_pathData (cadr PolylineList))
) ;_ end of setq

La variable gp_PathData tiene en estos momentos toda la información que la función de


reactivos necesita.
3. Añada PolylineList a la sección de variables locales de la definición de la función C:GPath.

¿Comentarios?

Integración de todos los elementos

En la lección 6, conectó la función de retorno de llamada gp:command-will-start al evento del reactivo


event :vlr-commandWillStart Como ya existe, la función muestra algunos mensajes e inicializa dos
variables globales, *polyToChange* y *reactorsToRemove*, a nil.

Para añadir funcionalidad a la función de retorno de llamada

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 85 de 103

1. Abra el archivo gpreact.lsp.


2. En la función gp:command‑will‑start, añada dos variables a la llamada de función setq; para
ello, realice la siguiente modificación:
;; Reset all four reactor globals to nil.
(setq *lostAssociativity* nil
*polyToChange* nil
*reactorsToChange* nil
*reactorsToRemove* nil)

3. Sustituya el código restante de gp:command‑will‑start, hasta la última llamada de función


princ, por el siguiente código:
(if (member (setq currentCommandName (car command-list))
'( "U" "UNDO" "STRETCH" "MOVE"
"ROTATE" "SCALE" "BREAK" "GRIP_MOVE"
"GRIP_ROTATE" "GRIP_SCALE" "GRIP_MIRROR")
) ;_ end of member
(progn
(setq *lostAssociativity* T)
(princ "\nNOTE: The ")
(princ currentCommandName)
(princ " command will break a path's associativity .")
) ;_ end of progn
) ;_ end of if

Este código comprueba si el usuario ha activado un comando que rompe la asociación


entre las baldosas y el camino. Si el usuario ha activado uno de esos comandos, el
programa establece la variable global *lostAssociativity* y advierte de ello al usuario.
Mientras experimenta con la aplicación camino de jardín, puede descubrir otros comandos
de edición que pueden modificar el camino del jardín y suponer la pérdida de la asociación.
Añada estos comandos a la lista precedida de una comilla simple, de manera que el
usuario sepa lo que va a ocurrir. Cuando esta función se ejecuta, el usuario ha iniciado un
comando pero no ha seleccionado la entidad que desea modificar. El usuario aún podría
cancelar el comando y dejarlo todo como estaba.

Temas de esta sección:

z Añadir actividad a las funciones de retorno de llamada de reactivos de objetos

z Diseño de la función de retorno de llamada gp:command-ended

z Gestión de diversos tipos de entidades

z Utilización de métodos ActiveX en funciones de reactivo

z Identificación de las secuencias de reactivos no lineales

z Codificación de la función command-ended

z Actualización de gp:Calculate-and-Draw-Tiles

z Modificación de otras llamadas a gp:Calculate-and-Draw-Tiles

¿Comentarios?

Integración de todos los elementos

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 86 de 103

En la lección 6, registró dos funciones de retorno de llamada con eventos La función gp:outline-erased
se asoció al evento de reactivos :vlr-erased y gp:outline-changed se asoció al evento :vlr‑modified Es
necesario hacer que estas funciones realicen aquello para lo que fueron creadas.

Para que las funciones de retorno de llamada de reactivos de objetos realicen aquello para lo
que fueron creadas
1. En gpreact.lsp, cambie gp:outline-erased de manera que aparezca como se muestra a
continuación
(defun gp:outline-erased (outlinePoly reactor parameterList)
(setq *reactorsToRemove*
(cons reactor *reactorsToRemove*))
(princ)
) ;_ end of defun

Sólo se ha realizado una operación. El reactivo enlazado a la polilínea se guarda en una


lista de todos los reactivos que es necesario suprimir. (Recuerde que aunque los reactivos
se enlazan a entidades, son objetos completamente diferenciados y su relación con
entidades necesita gestionarse con el mismo cuidado que las entidades regulares de
AutoCAD).
2. Cambie gp:outline-changed de manera que refleje el siguiente código:
(defun gp:outline-changed (outlinePoly reactor parameterList)
(if *lostAssociativity*
(setq *reactorsToRemove*
(cons reactor *reactorsToRemove*))
(setq *polytochange* outlinePoly
*reactorsToChange* (cons reactor *reactorsToChange*))
)
(princ)
)

Existen dos categorías de funciones que pueden modificar el contorno de las polilíneas. La
primera categoría contiene aquellos comandos que rompen la asociación del camino con
sus baldosas. Ya ha comprobado esta condición en gp:command‑will‑start y, en
consecuencia, ha establecido la variable global *lostAssociativity*. En este caso, es
necesario borrar las baldosas y el camino queda en manos del usuario. La otra categoría
es el modo de pinzamiento del comando ESTIRA, en el que la asociación se mantiene y es
necesario enderezar el contorno después de que el usuario haya acabado de arrastrar un
vértice a una nueva ubicación.
La variable *polyToChange* almacena un puntero de objetos de VLA a la propia polilínea.
Esto se utilizará en la función gp:command-ended cuando llegue la hora de calcular de
nuevo el marco de la polilínea.

¿Comentarios?

Integración de todos los elementos

La función de retorno de llamada de gp:command-ended editor es donde la mayoría de las acciones


tienen lugar. Hasta que no se llame a esta función, las polilíneas del marco del camino del jardín se
encuentran "abiertas a posibles modificaciones," es decir, los usuarios pueden aún manipular los
marcos en AutoCAD. En la secuencia de reactivos, antes de poder realizar lo que desee es necesario
esperar a que AutoCAD haga su parte del trabajo.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 87 de 103

El siguiente pseudocódigo muestra la lógica de la función gp:command-ended:

Determine the condition of the polyline.


CONDITION 1 - POLYLINE ERASED (Erase command)
Erase the tiles.
CONDITION 2 - LOST ASSOCIATIVITY (Move, Rotate, etc.)
Erase the tiles.
CONDITION 3 - GRIP_STRETCH - REDRAW AND RE-TILE
Erase the tiles.
Get the current boundary data from the polyline.
If it is a lightweight polyline,
Process boundary data as 2D
Else
Process boundary data as 3D
End if
Redefine the polyline border (pass in parameters of the current
boundary configuration, as well as the old).
Get the new boundary information and put it into the format
required for setting back into the polyline entity.
Regenerate the polyline.
Redraw the tiles (force ActiveX drawing).
Put the revised boundary information back into the reactor
named in *reactorsToChange*.
End function

El pseudocódigo es relativamente sencillo, pero hay varios detalles importantes en él que, por el
momento, no es necesario que conozca..

¿Comentarios?

Integración de todos los elementos

El primer detalle es el hecho de que la aplicación puede dibujar dos clases de polilíneas: de estilo
antiguo y ligeras. Estos tipos diferentes de polilíneas devuelven sus datos de entidad en distintos
formatos. La polilínea de estilo antiguo devuelve una lista de doce reales: cuatro juegos de puntos X, Y
y Z. Sin embargo, la polilínea ligera devuelve una lista de ocho reales: cuantro juegos de puntos X e Y.

Es necesario realizar algunos cálculos para determinar el contorno de la polilínea revisado después de
que algún usuario haya desplazado uno de los vértices. Sería mucho más fácil realizar los cálculos si
los datos de la polilínea tienen un formato consistente.

El Ejercicio 7 del archivo utils.lsp contiene funciones que realizan las conversiones de formato
necesarias: xyzList->ListOfPoints extrae y cambia el formato de las listas de puntos 3D por listas de
listas, mientras que xyList->ListOfPoints hace lo mismo con las listas de puntos 2D.

Para añadir el código para convertir los datos de la polilínea a un formato consistente, siga los
siguientes pasos
1. Si tiene una copia de utils.lsp abierta en una ventana de edición de texto VLISP, ciérrela.
2. Copie la versión de utils.lsp del directorio Tutorial\VisualLISP\Lesson7 en su directorio de trabajo.
Además de las dos funciones que vuelven a dar formato a los datos de la polilínea, utils.lsp
contiene otras funciones de utilidad necesarias para identificar las modificaciones que los

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 88 de 103

usuarios realicen en el camino de jardín.


3. Abra utils.lsp en una ventana de edición de texto VLISP y revise el nuevo código.

¿Comentarios?

Integración de todos los elementos

El segundo detalle que aparece en el pseudocódigo se encuentra casi al final, en el paso en el que se
vuelven a dibujar las baldosas. Esta es la secuencia del pseudocódigo:

Redraw the tiles (force ActiveX drawing)

The parenthetical phrase says it all: force ActiveX drawing. ¿Por qué es esto necesario? ¿Por qué la
aplicación no puede utilizar la preferencia de creación de objetos que se encuentra almacenada en la
sublista de asociaciones?

La respuesta es que no se puede utilizar la función command para la creación de entidades dentro de
una función de retorno de llamada de un reactivo. Porque está relacionada con algunos procesos
internos de AutoCAD. Es necesario hacer que la rutina de dibujar baldosas utilice ActiveX. Este tema se
volverá a tratar con más detenimiento más adelante en esta misma lección.

¿Comentarios?

Integración de todos los elementos

El último detalle importante hace referencia a una peculiaridad en la secuencia de comando/reactivo en


AutoCAD cuando los usuarios modifican una polilínea mediante los comandos GRIP especializados.
Estos comandos, como por ejemplo GRIP_MOVE y GRIP_ROTATE, se encuentran disponibles en un
menú contextual tras seleccionar el pinzamiento de un objeto y hacer clic con el botón derecho del
ratón. La secuencia de reactivos no es tan lineal como un simple comando DESPLAZA o BORRA. De
hecho, el usuario cambia a un comando diferente mientras se encuentra en medio de otro. Para
comprobar esta situación cargue el código de la lección 6 en el que se rastrea la secuencia de eventos
de reactivos. O bien, revise simplemente la siguiente salida de la ventana de consola de VLISP para ver
lo que sucede:

;; To start, select the polyline and some of the circles by using a


;; crossing selection box. The items in the selection set--
;; the chosen circles and the polyline--are now shown with grips on.
;; To initiate the sequence, click on one of the polyline grips:
(GP:COMMAND-WILL-START #<VLR-Command-reactor> (GRIP_STRETCH))
;; Now change the command to a move by right-clicking and choosing
;; MOVE from the pop-up menu. Notice that the command-ended
;; reactor fires in order to close out the GRIP_STRETCH command
;; without having fired an object reactor event:
(GP:COMMAND-ENDED #<VLR-Command-reactor> (GRIP_STRETCH))

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 89 de 103

(GP:COMMAND-WILL-START #<VLR-Command-reactor> (GRIP_MOVE))


;; Now drag the outline (and the selected circles) to a new location.
(GP:OUTLINE-CHANGED #<VLA-OBJECT IAcadLWPolyline 028f3188>
#<VLR-Object-reactor> nil)
(GP:COMMAND-ENDED #<VLR-Command-reactor> (GRIP_MOVE))

De esta forma se demuestra que no es posible tener la certeza de que en todos los casos se llamen a
los retornos de llamadas de reactivos de objetos.

Esta secuencia tiene asociada una peculiaridad. Incluso durante la llamada de retorno command ended
final, los círculos que aún forman parte del conjunto de selección de pinzamiento no se pueden borrar.
Estos círculos aún se encuentran abiertos en AutoCAD. Si intenta borrarlos durante la llamada de
retorno command-ended, puede provocar un fallo de AutoCAD. Para que esto no ocurra, puede utilizar
otra variable global para almacenar una lista de punteros a los objetos de baldosas hasta que puedan
borrarse.

Para procesar secuencias no lineales de reactivos


1. Añada al archivo gpreact.lsp la siguiente función:
(defun gp:erase-tiles (reactor / reactorData tiles tile)
(if (setq reactorData (vlr-data reactor))
(progn
;; Tiles in the path are stored as data in the reactor.
(setq tiles (cdr (assoc 100 reactorData)))
;; Erase all the existing tiles in the path.
(foreach tile tiles
(if (and (null (member tile *Safe-to-Delete*))
(not (vlax-erased-p tile))
)
(progn
(vla-put-visible tile 0)
(setq *Safe-to-Delete* (cons tile *Safe-to-Delete*))
)
)
)
(vlr-data-set reactor nil)
)
)
)

Esta nueva función se utilizará en la primera fase de borrado de las baldosas. Observe que
las baldosas no se han borrado realmente: se han hecho invisibes y se han añadido a una
variable global denominada *Safe-to-Delete*.
2. Añada al archivo gpreact.lsp la siguiente función:
(defun Gp:Safe-Delete (activeCommand)
(if (not (equal
(strcase (substr activeCommand 1 5))
"GRIP_"
)
)
(progn
(if *Safe-to-Delete*
(foreach Item *Safe-to-Delete*
(if (not (vlax-erased-p Item))
(vla-erase item)
)
)
)
(setq *Safe-to-Delete* nil)
)
)

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 90 de 103

Esta función puede invocarse en un momento en el que no se estén ejecutando los


comandos GRIP_MOVE o GRIP_STRETCH .

¿Comentarios?

Integración de todos los elementos

Ahora, que ya ha visto el pseudocódigo y algunos de los detalles importantes, sustituya el código vacío
del retorno de llamada de reactivo gp:command-ended por lo siguiente:

(defun gp:command-ended (reactor command-list


/ objReactor
reactorToChange reactorData
coordinateValues currentPoints
newReactorData newPts
tileList
)
(cond
;; CONDITION 1 - POLYLINE ERASED (Erase command)
;; If one or more polyline borders are being erased (indicated
;; by the presence of *reactorsToRemove*), erase the tiles
;; within the border, then remove the reactor.
(*reactorsToRemove*
(foreach objReactor *reactorsToRemove*
(gp:erase-tiles objReactor)
)
(setq *reactorsToRemove* nil)
)
;; CONDITION 2 - LOST ASSOCIATIVITY (Move, Rotate, etc.)
;; If associativity has been lost (undo, move, etc.), then
;; erase the tiles within each border
;;
((and *lostassociativity* *reactorsToChange*)
(foreach reactorToChange *reactorsToChange*
(gp:erase-tiles reactorToChange)
)
(setq *reactorsToChange* nil)
)
;; CONDITION 3 - GRIP_STRETCH
;; In this case, the associativity of the tiles to the path is
;; kept, but the path and the tiles will need to be
;; recalculated and redrawn. A GRIP_STRETCH can only be
;; performed on a single POLYLINE at a time.
((and (not *lostassociativity*)
*polytochange*
*reactorsToChange*
(member "GRIP_STRETCH" command-list)
;; for a GRIP_STRETCH, there will be only one reactor in
;; the global *reactorsToChange*.
(setq reactorData
(vlr-data (setq reactorToChange

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 91 de 103

(car *reactorsToChange*)
)
)
)
)
;; First, erase the tiles within the polyline border.
(gp:erase-tiles reactorToChange)
;; Next, get the current coordinate values of the polyline
;; vertices.
(setq coordinateValues
(vlax-safearray->list
(vlax-variant-value
(vla-get-coordinates *polyToChange*)
)
)
)
;; If the outline is a lightweight polyline, you have
;; 2d points, so use utility function xyList->ListOfPoints
;; to convert the coordinate data into lists of
;; ((x y) (x y) ...) points. Otherwise, use the
;; xyzList->ListOfPoints function that deals
;; with 3d points, and converts the coordinate data into
;; lists of ((x y z) (x y z) ... ) points.
(setq CurrentPoints
(if (= (vla-get-ObjectName *polytochange*) "AcDbPolyline")
(xyList->ListOfPoints coordinateValues)
(xyzList->ListOfPoints coordinateValues)
)
)
;; Send this new information to RedefinePolyBorder -- this
;; will return the new Polyline Border
(setq NewReactorData
(gp:RedefinePolyBorder CurrentPoints reactorData)
)
;; Get all the border Points and ...
(setq newpts (list (cdr (assoc 12 NewReactorData))
(cdr (assoc 13 NewReactorData))
(cdr (assoc 14 NewReactorData))
(cdr (assoc 15 NewReactorData))
)
)
;; ...update the outline of the polyline with the new points
;; calculated above. If dealing with a lightweight polyline,
;; convert these points to 2D (since all the points in
;; newpts are 3D), otherwise leave them alone.
(if (= (cdr (assoc 4 NewReactorData)) "LIGHT")
(setq newpts (mapcar '(lambda (point)
(3dPoint->2dPoint Point)
)
newpts
)
)
)
;; Now update the polyline with the correct points.
(vla-put-coordinates
*polytochange*
;; For description of the list->variantArray see utils.lsp.
(gp:list->variantArray (apply 'append newpts))
)
;; Now use the current definition of the NewReactorData,

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 92 de 103

;; which is really the same as the garden path data


;; structure. The only exception is that the field (100)
;; containing the list of tiles is nil. This is OK since
;; gp:Calculate-and-Draw-Tiles does not require this field
;; to draw the tiles. In fact this function creates the tiles
;; and returns a list of drawn tiles.
(setq tileList (gp:Calculate-and-Draw-Tiles
;; path data list without correct tile list
NewReactorData
;; Object creation function
;; Within a reactor this *MUST* be ActiveX
"ActiveX"
)
)
;; Now that you have received all the tiles drawn, rebuild
;; the data structure with the correct tileList value and
;; reset the data property in the reactor.
;; Update the tiles associated with the polyline border.
(setq NewReactorData
(subst (cons 100 tileList)
(assoc 100 NewReactorData)
NewReactorData
)
)
;; By now you have the new data associated with the polyline.
;; All there is left to do is associate it with the reactor
;; using vlr-data-set.
(vlr-data-set (car *reactorsToChange*) NewReactorData)
;; Remove all references to the temporary
;; variables *polytochange* and *reactorsToChange*.
(setq *polytochange* nil
*reactorsToChange* nil
)
)
)
;; Delete any items in the *Safe-to-Delete* global if you can!!!
(Gp:Safe-Delete (car command-list))
(princ)
)

¿Comentarios?

Integración de todos los elementos

Con anterioridad, en esta lección se ha observado la necesidad de hacer que gp:Calculate‑y‑Draw-


Tiles utilice ActiveX para crear objetos cuando se activa desde una llamada de retorno de reactivos.
Esto significa ignorar, si es necesario, el estilo de creación de objetos (ActiveX, entmake o command)
que el usuario ha seleccionado. El código que acaba de actualizar, en la función gp:command-ended,
contiene la siguiente llamada a la rutina de dibujo de baldosas:

(setq tileList (gp:Calculate-and-Draw-Tiles


;; path data list without correct tile list.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 93 de 103

NewReactorData
;; Object creation function.
;; Within a reactor this *MUST* be ActiveX.
"ActiveX"
)
)

Se pasan dos parámetros a gp:Calculate-and-Draw-Tiles: NewReactorData (que es una lista con la


misma forma que la lista de asociaciones original gp_PathData) y la cadena "ActiveX" (que establece el
estilo de creación de objetos). No obstante, consulte la definición actual de
gp:Calculate‑and‑Draw‑Tiles. (que se encuentra definida en gpdraw.lsp). Esta es la parte de la
función en la que se declaran los parámetros y las variables locales:

(defun gp:Calculate-and-Draw-Tiles (BoundaryData /


PathLength TileSpace
TileRadius SpaceFilled
SpaceToFill RowSpacing
offsetFromCenter rowStartPoint
pathWidth pathAngle
ObjectCreationStyle TileList)

Observe que se especifica un solo parámetro y que ObjectCreationStyle se define como una variable
local. Revise cómo se establece la variable ObjectCreationStyle, que se encuentra un poco más
adelante en la función:

(setq ObjectCreationStyle (strcase (cdr (assoc 3 BoundaryData))))

ElObjectCreationStyle se establece en este momento de forma interna dentro la función mediante la


recuperación del valor escondido en la variable BoundaryData (lista de asociaciones). Pero no necesita
poder ignorar ese valor.

Para modificar gp:Calculate-and-Draw-Tiles de manera que acepte un argumento de estilo de


creación de objetos
1. Añada la variable ObjectCreationStyle al argumento de la función.
2. Suprima ObjectCreationStyle de las variables locales.
La secuencia defun de la función debe ser como se muestra a continuación:
(defun gp:Calculate-and-Draw-Tiles (BoundaryData
ObjectCreationStyle
PathLength TileSpace
TileRadius SpaceFilled
SpaceToFile RowSpacing
offsetFromCenter rowStartPoint
pathWidth pathAngle
TileList) ; remove ObjectCreationStyle from locals

Observe que si declara una variable como un parámetro (antes de la barra oblicua) y como
una variable local (después de la barra oblicua), VLISP se lo señalará. Por ejemplo, si
declara ObjectCreationStyle como un parámetro y también como una variable y, a
continuación, utiliza la herramienta de comprobación de sintaxis de VLISP en la función
gp:Calculate‑and‑Draw‑Tiles, en la ventana Generar salida aparecerá el siguiente
mensaje:
; *** WARNING: same symbol before and after / in arguments list: OBJECTCREA

3. Modifique la primera expresión setq dentro de gp:Calculate-and-Draw-Tiles de manera que sea


como se muestra a continuación:
(setq
PathLength (cdr (assoc 41 BoundaryData))
TileSpace (cdr (assoc 43 BoundaryData))
TileRadius (cdr (assoc 42 BoundaryData))

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 94 de 103

SpaceToFill (- PathLength TileRadius)


RowSpacing (* (+ TileSpace (* TileRadius 2.0))
(sin (Degrees->Radians 60))
)
SpaceFilled RowSpacing
offsetFromCenter 0.0
offsetDistance /(+(* TileRadius 2.0)TileSpace)2.0)
rowStartPoint cdr (assoc 10 BoundaryData))
pathWidth cdr (assoc 40 BoundaryData))
pathAngle cdr (assoc 50 BoundaryData))
) ;_ end of setq
(if (not ObjectCreationStyle)
(setq ObjectCreationStyle (strcase (cdr (assoc 3 BoundaryData))))
)

Se ha suprimido la declaración de asignación original de ObjectCreationStyle. El código


ahora comprueba si se ha proporcionado algún valor para ObjectCreationStyle. Si no se
establece ObjectCreationStyle, es decir, su valor es nil, la función le asigna un valor de la
variable BoundaryData.
Existe otra serie de cambios que es necesario realizar en gp:Calculate‑and‑Draw-Tiles.

¿Comentarios?

Integración de todos los elementos

En la llamada de retorno de reactivos, se transmite una cadena codificada "ActiveX" a gp:Calculate-and-


Draw-Tiles como argumento de ObjectCreationStyle. Pero, ¿qué ocurre en las demás ocasiones en las
que se llama a gp:Calculate-and-Draw-Tiles?

Recuerde que en la lección 4 se señalaba que siempre que cambie una función vacía, es necesario
hacerse la siguiente pregunta:

z ¿Ha cambiado la llamada a la función? Es decir, ¿aún toma la función el mismo número de
argumentos?
z ¿Devuelve la función algo diferente?

Estas mismas preguntas hay que hacerlas siempre que se realice un cambio significativo en una
función de trabajo mientras se integran, afinan y actualizan las aplicaciones. En este caso, es necesario
encontrar cualquier otra función en el proyecto que llame a gp:Calculate-and-Draw-Tiles. VLISP tiene
una función para ayudarle en esta tarea.

Para encontrar todas las llamadas a gp:Calculate-and-Draw-Tiles de su proyecto


1. En la ventana de edición de texto de VLISP, haga doble clic en la palabra gp:Calculate‑and-
Draw-Tiles del archivo gpdraw.lsp.

2. Seleccione Buscar del menú VLISP.


Como ha seleccionado previamente el nombre de la función, éste ya se encuentra definido
como la cadena que hay que buscar.
3. Seleccione el botón Proyecto que aparece relacionado en Buscar del cuadro de diálogo Buscar.
Cuando selecciona esta opción, el cuadro de diálogo Buscar se expande por la parte
inferior y puede seleccionar el proyecto que desea buscar.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 95 de 103

4. Seleccione el nombre del proyecto actual y, a continuación, pulse el botón Buscar.


VLISP visualiza los resultados en la ventana Buscar salida:
5. Observe los resultados en la ventana Buscar salida y determine si hay otras ubicaciones en el
código en las que realice llamadas a gp:Calculate‑and‑Draw-Tiles. Sólo puede haber una:
una ubicación dentro de gpmain.lsp.
6. En la ventana Buscar salida, haga doble clic en la línea de código que llama a
gp:Calculate‑and‑Draw-Tiles.
VLISP activa una ventana de edición de texto y le muestra justo en esa línea del código de
gpmain.lsp. El código aparece como se muestra a continuación:
(setq tilelist (gp:Calculate-and-Draw-Tiles gp_PathData))

7. Sustituya la línea de código por lo siguiente:


(setq tilelist (gp:Calculate-and-Draw-Tiles gp_PathData nil))

¿Por qué nil? Vuelva a observar el pseudocódigo:


If ObjectCreationStyle is nil, assign it from the BoundaryData.

Transmitir nil como parámetro a gp:Calculate-and-Draw-Tiles hace que esa función


compruebe la selección del usuario sobre cómo dibujar las baldosas (como se determinó
en la selección del cuadro de diálogo y la almacenó en gp_PathData). No obstante,
llamadas posteriores desde el retorno de llamada de reactivos command-ended ignorarán
este comportamiento mediante el uso forzoso de ActiveX.

¡Enhorabuena! Ya dispone de la funcionalidad básica del reactivo. Si lo prefiere, desde


Tutorial\VisualLISP\Lesson7 copie los archivos gpmain.lsp y gpdraw.lsp en su directorio de trabajo y
examine el código completo y depurado.

No obstante, aún queda mucho trabajo por realizar y todo tiene que ver con este fragmento de código
de la función gp:Command-ended:

(setq NewReactorData
(gp:RedefinePolyBorder CurrentPoints reactorData)
) ;_ end of setq

¿Comentarios?

Integración de todos los elementos

Ha realizado un gran trabajo hasta llegar a este punto y probablemente haya aprendido muchos
conceptos, términos, comandos y órdenes nuevos, suficientes por el momento. Teniendo todo esto en
cuenta, se recomienda copiar el código de ejemplo que se suministra en el aprendizaje en vez de tener
que teclearlo.

Para copiar el código usado para redefinir el contorno de la polilínea


1. Copie el archivo gppoly.lsp del directorio Tutorial\VisualLISP\Lesson7 en su directorio de trabajo.
2. En la ventana de proyecto para su proyecto, pulse el botón Propiedades del proyecto.
3. Añada el archivo gppoly.lsp al proyecto.
4. Pulse Aceptar para aceptar el proyecto con el archivo adicional.
5. En la ventana de proyecto, haga doble clic en el archivo gppoly.lsp para abrirlo.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 96 de 103

Temas de esta sección:

z Interpretación de las funciones de gppoly.lsp

z Explicación de la función gp:RedefinePolyBorder

z Explicación de la función gp:FindMovedPoint

z Explicación de la función gp:FindPointInList

z Explicación de la función gp:RedefinePolyBorder

z Explicación de las funciones gp:pointEqual, gp:rtos2 y gp:zeroSmallNum

¿Comentarios?

Integración de todos los elementos

El archivo gppoly.lsp contiene un número de funciones que son necesarias para enderezar una
polilínea cuando se ha estirado un único pinzamiento. En este aprendizaje se explicarán con detalle
sólo algunas de estas funciones.

Nota Esta sección del Aprendizaje de Camino de jardín contiene algunos de los códigos y conceptos
más complejos de toda la lección. Si es un principiante, puede saltar hasta la sección Crear una
aplicación.

Las funciones del archivo gppoly.lsp se organizan del mismo modo que ha podido observar en los
archivos de código fuente de AutoLISP. La función de más alto nivel, normalmente la función principal o
C: (en este caso, gp:Redefine-PolyBorder) se encuentra al final del archivo. Las funciones llamadas
desde la función principal se definen encima de ésta dentro del archivo fuente. Esta convención nos
lleva al pasado de la programación cuando en algunos entornos era necesario organizar los archivos de
esta manera. En VLISP, es una cuestión de estilo personal ya que no es necesario organizar las
funciones siguiendo ninguna secuencia específica.

Antes de profundizar en los detalles, retroceda y vea lo que es necesario hacer para calcular de nuevo y
dibujar el contorno del camino de jardín. En la siguiente ilustración se muestra un ejemplo de camino de
jardín, junto con los puntos clave de la lista de asociaciones almacenados en los datos del reactivo:

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 97 de 103

En este ejemplo, el punto clave 12 es la esquina inferior izquierda, el 13 es la esquina inferior derecha,
etc. Si el usuario desplaza el punto superior derecho (el punto clave 14 ), el programa necesitará volver
a calcular dos puntos ya existentes, el inferior derecho (13) y el superior izquierdo (15).

¿Comentarios?

Integración de todos los elementos

El siguiente pseudocódigo muestra la lógica que hay detrás de la función principal,


gp:RedefinePolyBorder:

Function gp:RedefinePolyBorder
Extract the previous polyline corner points (12, 13, 14, and 15
key values).
Find the moved corner point by comparing the previous
polyline corner points with the current corner points.
(The one "misfit" point will be the point that moved.)
Set the new corner points by recalculating the two points
adjacent to the moved point.
Update the new corner points in the reactor data (that will
be stored back in the reactor for the modified polyline).
Update other information in the reactor data. (Start point,
endpoint, width, and length of path need to be recalculated.)

¿Comentarios?

Integración de todos los elementos

La función gp:FindMovedPoint contiene varias expresiones LISP muy útilies para la manipulación de
listas. Principalmente, lo que hace esta función es comparar la lista de los puntos actuales de la
polilínea (después de que el usuario arrastrara uno a una nueva ubicación) con los puntos anteriores y
devolver la lista con claves (13 <xvalue> <yvalue>) del punto desplazado.

La mejor manera de ver cómo trabaja esta función es revisar el código y observar los valores que
manipula. Establezca un punto de interrupción justo en la primera expresión (setq result . . .) y observe
las siguientes variables mientras revisa la función:

z KeyListToLookFor
z PresentPoints
z KeyedList
z Result
z KeyListStatus
z MissingKey
z MovedPoint

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 98 de 103

Las funciones mapcar y lambda se examinarán en la siguiente sección. Por el momento, siga los
comentarios del código para ver si puede entender lo que sucede en las funciones.

¿Comentarios?

Integración de todos los elementos

En el encabezamiento de la función en el código fuente se explica cómo gp:FindPointInList transforma


la información con la que trabaja. Al igual que la función anterior, Gp:FindMovedPoint, esta función
utiliza las capacidades de manipulación de listas de LISP para realizar el trabajo. Cuando se opera con
listas, a menudo se ven las funciones mapcar y lambda utilizadas juntas como están aquí. A primera
vista, éstas son funciones extrañas y confusas, con nombres que no indican lo que realizan.No
obstante, una vez que se aprende a utilizarlas, las considerará como dos de las funciones más potentes
del repertorio de AutoLISP. Lo que viene a continuación es una presentación general de mapcar y
lambda.

La función mapcar aplica (mapea) una expresión a cada elemento de una lista. Por ejemplo, en una
lista de enteros 1, 2, 3 y 4, puede utilizar mapcar para aplicar la función1+ y añadir 1 a cada número de
la lista:

_$ (mapcar '1+ '(1 2 3 4))


(2 3 4 5)

Una primera definición de mapcar podría ser que aplica la función dada en el primer parámetro a los
sucesivos elementos del segundo parámetro, la lista. El valor que resulta de una operación de mapcar
es la lista transformada por la función o expresión que se le aplica. En realidad, mapcar puede hacer
aún más, pero esta definición será suficiente por el momento.

En el ejemplo que se proporciona, todos los valores de la lista '(1 2 3 4) han pasado por la función 1+.
Principalmente, mapcar ha realizado las siguientes operaciones y ha unido los valores obtenidos en una
lista:

(1+ 1) -> 2
(1+ 2) -> 3
(1+ 3) -> 4
(1+ 4) -> 5

Este es otro ejemplo de mapcar, esta vez se utiliza la función null para probar si los valores de una lista
son o no valores nulos (no verdaderos):

_$ (mapcar 'null (list 1 (= 3 "3") nil "Steve"))


(nil T T nil)

Lo que ha sucedido en este código es fundamentalmente lo siguiente:

(null 1) -> nil


(null (= 3 "3") -> T
(null nil) -> T
(null "Steve") -> nil

Puede utilizar muchas funciones de AutoLISP ya existentes dentro de un mapcar. También puede
utilizar sus propias funciones. Por ejemplo, imagine que acaba de crear una función muy potente

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 99 de 103

denominada equals2:

_$ (defun equals2(num)(= num 2))


EQUALS2
_$ (mapcar 'equals2 '(1 2 3 4))
(nil T nil nil)

Parece que equals2 no es tan potente. Es en casos como este en los que lambda nos viene bien.
Puede utilizar lambda en casos en los que no desea o no necesita definir una función. En ocasiones
encontrará lambda definida como una función anónima. Por ejemplo, en vez de definir una función
denominada equals2, podría escribir una expresión lambda para realizar la misma operación sin la
sobrecarga de definir la función:

_$ (mapcar '(lambda (num) (= num 2)) '(1 2 3 4))


(nil T nil nil)

Lo que ha sucedido en el código es lo siguiente:

(= 1 2) -> nil
(= 2 2) -> T
(= 3 2) -> nil
(= 4 2) -> nil

Con toda esta información, compruebe si la función gp:FindPointInList tiene sentido. Revise de nuevo
los comentarios del código fuente.

¿Comentarios?

Integración de todos los elementos

La clave para entender cómo funciona gp:recalcPolyCorners está en volver a consultar el diagrama que
muestra lo que representan los valores del 12 al 15:

En el diagrama, el usuario ha desplazado el punto de la esquina asociado al valor clave 14. Lo que
supone volver a calcular los puntos de esquina asociados al 13 y al 15.

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 100 de 103

Es necesario desplazar el punto 15 a lo largo del vector definido por el punto 12 al punto 15 hasta que
se alinee con el nuevo punto 14. Los vectores del 12 al 15 y del 14 al 15 deben ser perpendiculares los
unos con los otros. La misma operación se debe aplicar para volver a calcular la nueva ubicación del
punto 13.

Vuelva a ver el código para comprobar si tiene sentido.

¿Comentarios?

Integración de todos los elementos

Estas tres funciones son necesarias para estudiar al fin una de las peculiaridades de la programación
en un sistema AutoCAD que, como sabe, permite obtener datos de gran precisión. No obstante, en
ocasiones los números no son todo lo precisos que debieran por el redondeo hacia arriba o hacia abajo
de los valores de coma flotante que definen posiciones geométricas. Debe saber comparar un conjunto
de puntos con otros ya que deberá tratar estos casos.

Ha observado en alguna ocasión que algunas veces cuando enumera la información asociada a una
entidad de AutoCAD, ve un valor como 1.0e-017? Este número es casi cero, aunque cuando lo
compara con cero en un programa LISP, casi no se tiene cuenta.

En el camino de jardín, debe saber comparar los números sin necesidad de preocuparse por el hecho
de que 1.0e-017 no sea igual a cero. Las funciones gp:pointEqual, gp:rtos2 y gp:zeroSmallNum
permiten identificar cualquier discrepancia en el redondeo cuando compara listas de puntos.

Con esto se completa la revisión de las funciones de gppoly.lsp.

¿Comentarios?

Integración de todos los elementos

Hasta el momento, en este ejercicio ha realizado lo siguiente:

z Ha modificado la función gp:drawOutline de manera que devuelva los puntos del perímetro de la
polilínea además del puntero a la polilínea. Ha añadido esta información a la variable gp_PathData.
Esta variable se almacena con los datos del reactivo en el reactivo de objetos adjunto a cada camino
de jardín.
z Ha actualizado las funciones de reactivos en gpreact.lsp.
z Ha añadido funciones xyzList->ListOfPoints, xyList‑>ListOfPointsy otras funciones de utilidades al
archivo utils.lsp .
z Ha actualizado la función gp:Calculate-and-Draw-Tiles de manera que ObjectCreationStyle es ahora
un parámetro para la función y no una variable local.
z Ha modificado la llamada a gp:Calculate-and-Draw-Tiles en la función C:GPath dentro del archivo

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 101 de 103

gpmain.lsp.
z Ha añadido gppoly.lsp a su proyecto y examinado las funciones que en él se encuentran.

Conceda una oportunidad a la aplicación finalizada. Guarde su trabajo y, a continuación, cargue las
fuentes del proyecto; ejecute la función Gpath e intente estirar y desplazar el contorno del camino del
jardín. Recuerde: si algo no funciona y no consigue resolver el problema satisfactoriamente, puede
cargar el código completo desde el directorio Tutorial\VisualLISP\Lesson7.

¿Comentarios?

Integración de todos los elementos

La última tarea dentro de este aprendizaje es coger su código del camino de jardín y convertirlo en una
aplicación independiente. De esta manera, se puede distribuir como un único ejecutable para cualquier
usuario o cliente. Afortunadamente, este último conjunto de tareas es probablemente el más fácil de
todo el aprendizaje ya que VLISP hace prácticamente todo el trabajo.

Nota Se recomienda que proceda a integrar una aplicación sólo en el caso de que su código esté
funcionando perfectamente. Asegúrese que ha probado la aplicación con los archivos fuente originales
y que está conforme con los resultados.

Temas de esta sección:

z Inicio del asistente Crear aplicación

¿Comentarios?

Integración de todos los elementos

Para ayudarle a crear aplicaciones independientes, VLISP proporciona el asistente Crear aplicación.

Para ejecutar el asistente Crear aplicación


1. Para iniciar el asistente, en el menú de VLISP seleccione Archivo Crear aplicación
Aplicación nueva Asistente para nueva aplicación.
2. Seleccione Modo Expert y pulse Siguiente.
El asistente le pide que precise el directorio en el que desea almacenar los archivos
creados por Crear aplicación y que le asigne un nombre a la aplicación. Crear aplicación
genera dos archivos de salida: a . vlx que contiene el ejecutable del programa y un
archivo . prv que contiene las opciones elegidas para Crear aplicación. El archivo . prv
también se conoce como archivo de creación. Puede utilizar el archivo de creación para,
en caso de ser necesario, integrar de nuevo la aplicación.
3. Introduzca el directorio Tutorial\VisualLISP\micamino como la dirección de la aplicación y llame a
la aplicación gardenpath. VLISP utiliza el nombre de aplicación en los nombres de los archivos de
salida (en este ejemplo, gardenpath.vlx y gardenpath.prv).

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 102 de 103

Seleccione Siguiente para continuar.


4. Las opciones de la aplicación no se tratan en este aprendizaje. Acepte los valores por defecto y
pulse Siguiente. (Para más información sobre aplicaciones de espacio de nombre individuales,
véase “Running an Application in Its Own Namespace” en el AutoLISP Developer’s Guide.)
5. En este paso, el asistente solicita que se identifiquen todos los archivos de códigos fuente de
AutoLISP que forman la aplicación. Podría seleccionar de forma individual los archivos fuente de
LISP, pero existe un camino más fácil. Cambie el cuadro de selección del tipo de archivo
desplegable de manera que se muestre "Archivos de proyecto de Visual LISP" y, a continuación,
pulse el botón Añadir. Seleccione el archivo de proyecto Gpath y pulse Abrir.
Nota Aparecerán varios archivos de proyecto Gpath según lo que haya realizado a lo largo del
aprendizaje. Seleccione el archivo más reciente. Si copió el código fuente completo de la lección
7, el nombre de proyecto que debe seleccionar debe ser Gpath7.prj.
Después de seleccionar el archivo de proyecto, pulse Siguiente para continuar.
Una ventaja de las aplicaciones VLX compiladas es que puede compilar los archivos de
control de diálogo (. dcl) en la aplicación completa. De esta manera se reduce el número de
archivos fuente individuales con los que el usuario final tiene que tratar y elimina cualquiera
de los problemas de la ruta de búsqueda cuando se carga un archivo DCL.
6. Cambie el cuadro de selección del tipo de archivo desplegable de manera que se muestre
"archivos DCL" y, a continuación, pulse el botón Añadir. Seleccione el archivo gpdialog.dcl y
pulse Abrir.
Pulse Siguiente para continuar con la integración de la aplicación.
7. Las opciones de compilación no se tratan en este aprendizaje. Acepte los valores por defecto y
pulse Siguiente. (Para más información sobre las opciones de compilación, véase “Optimizing
Application Code” en el Visual LISP Developer’s Guide.)
8. El último paso se utiliza para revisar las selecciones que ha realizado. En este momento, ya
puede seleccionar Finalizar. VLISP iniciará el proceso de integración mostrando los resultados en
la ventana Generar salida. Se producen varios archivos intermedios mientras sus archivos de
código fuente individuales se compilan en un formato que se puede vincular a la aplicación VLX.

Cuando todo haya acabado, tendrá un archivo ejecutable denominado gardenpath.vlx. Para probarlo,
realice lo siguiente:

z En el menú Herramientas de AutoCAD, seleccione Cargar aplicación.


z Cargue la aplicación gardenpath.vlx que se acaba de crear y que se encuentra en el directorio
Tutorial\VisualLISP\ MyPath.
z Ejecute el comando gpath.

¿Comentarios?

Integración de todos los elementos

¡Ya ha llegado al final del camino! Como ha podido comprobar, en este aprendizaje se han cubierto
muchos temas. Se han introducido conceptos de AutoLISP así como operaciones de VLISP. El "Repaso
del camino de jardín" se ha diseñado como ejemplo para muchos de los temas y conceptos. Quizá esté
interesado en obtener más información. A continuación encontrará una breve bibliografía de algunos de
los libros LISP y AutoLISP.

¿Comentarios?

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007


Ayuda de AutoCAD Página 103 de 103

Integración de todos los elementos

Understanding AutoLISP: Programming for Productivity, William Kramer, Autodesk Press, ISBN 0-8273-
5832-6.

AutoLISP in Plain English: A Practical Guide for Non-Programmers, George O. Head, Ventana Press,
ISBN: 1566041406.

LISP, 3rd Edition, Patrick Henry Winston and Berthold Klaus Paul Horn, Addison-Wesley Publishing
Company, ISBN 0-201-08319-1.

ANSI Common Lisp, Paul Graham, Prentice Hall, ISBN 0-13-370875-6.

Common LISP, The Language, Second Edition, Guy L. Steele, Jr., Digital Press, ISBN 1-55558-041-6.

¿Comentarios?

file://C:\Documents and Settings\JuanmaRS\Configuración local\Temp\~hh3AE9.htm 20/10/2007

También podría gustarte