Anda di halaman 1dari 168

NDICE DE CONTENIDOS

AGRADECIMIENTOS INTRODUCCIN

LISP: PARADIGMA DEL ESTILO DE PROGRAMACIN FUNCIONAL

PRIMERA PARTE: EL ENTORNO DE DESARROLLO VISUAL LISP Esta seccin se encuentra en preparacin. 1. VISUAL LISP 2. EL ENTORNO DE DESARROLLO VISUAL LISP o El Trabajo con Visual LISP y AutoCAD o Barra de Mens o Las Barras de Herramientas o La Consola Visual LISP o El Editor Visual LISP Barras de Herramientas Men Contextual Teclas Rpidas SEGUNDA PARTE: TCNICAS FUNDAMENTALES DE LA PROGRAMACIN LISP 1. TIPOS DE DATOS o TOMOS o TOMOS SIMBLICOS (S-ATOMS) o CONSTANTES NMEROS CADENAS DE TEXTO o LISTAS Y CONSES LISTAS DE UN NIVEL LISTAS ANIDADAS LISTAS DE ASOCIACIN (A-LIST) LA LISTA VACA (NIL) o FUNCIN TYPE: EXAMEN DEL TIPO DE DATO TIPOS DE DATOS LISP TIPOS DE DATOS AUTOCAD TIPOS DE DATOS ACTIVE-X 2. FUNCIONES o FUNCIONES PRIMITIVAS OPERADORES ARITMTICOS FUNCIONES DE ACCESO A LISTAS

CONSTRUCCIN DE LISTAS PROCESAMIENTO DE LISTAS TRATAMIENTO DE CADENAS TRATAMIENTO DE CADENAS CON VLISP o FORMAS ESPECIALES o FUNCIONES DEFINIDAS POR EL USUARIO DEFUN: NUEVAS FUNCIONES PARA LA EXTENSIN DE LISP REALES A ENTEROS: TRUCAMIENTO O REDONDEO FUNCIONES TRIGONOMTRICAS LAMBDA FUNCTION LOAD 3. ESTRUCTURAS DE CONTROL o PREDICADOS GENERALES o PREDICADOS ARITMTICOS o OPERADORES LGICOS o OPERADORES LGICOS BINARIOS Nmeros Binarios Funcin LSH Funcin ~ (NOT lgico binario) Funcin LOGAND CONVERSIN ENTRE BINARIOS Y DECIMALES (I) CONVERSIN ENTRE BINARIOS Y DECIMALES (II) Funcin LOGIOR Funcin BOOLE o PREDICADOS DEFINIDOS POR EL USUARIO o ESTRUCTURAS CONDICIONALES 4. FUNCIONES RECURSIVAS E ITERATIVAS o FUNCIONES RECURSIVAS EXTRACCIN DE LOS VRTICES DE UNA POLILNEA o FUNCIONES ITERATIVAS REPETICIN UN NMERO DETERMINADO DE VECES ITERACIONES SOBRE ELEMENTOS DE UNA SECUENCIA CICLOS DEPENDIENTES DE UNA CONDICIONAL o FUNCIONES DE MAPEADO SOBRE SECUENCIAS EXTRACCIN DE LOS VRTICES DE UNA POLILNEA Una solucin ms eficaz. o CUNDO RECURSIN Y CUNDO ITERACIN?

TERCERA PARTE: ACCESO A LA BASE DE DATOS GEOMTRICA Esta seccin se encuentra en preparacin.

ACCESO A LA LISTA DE DATOS DE OBJETO

EXTRACCIN DE LISTAS DE DATOS DE OBJETO TRANSFORMACIN DE LOS DATOS DE OBJETO: CONVERSIN DE POLILNEAS EN SPLINES PROGRAMA PL2SP.LSP EJEMPLOS DE LA UTILIZACIN DE ENTMAKE o DEFINICIN DE BLOQUES o DEFINICIN DE CAPAS SISTEMAS DE COORDENADAS o EJEMPLO DE TRANSFORMACIN ENTRE SISTEMAS DE COORDENADAS: CONVERSIN DE POLILNEAS 3D EN 2D
o o

ANEXO A
TABLA DE FUNCIONES VISUAL LISP

NOTA: Esta tabla est en formato PDF. Para verla es necesario el Acrobat READER. Para descargar el Acrobat Reader 4.0 pulse aqu ANEXO B
ARCHIVOS LISP Y DCL SUMINISTRADOS CON AUTOCAD:

Versin 2.5 Versin 10 Versin 11 Versin 12 Versin 13 Versin 14 Versin 2000

ANEXO C
EJEMPLO DE MEN PERSONALIZADO (R14):

Mens AutoCAD y Bonus Personalizados Descarga de ambos en formato ZIP ANEXO D

UTILIDADES VARIAS:

3DTHD.LSP - Programa para dibujar roscas mediante slidos 3D

ANEXO E Enlaces conocidos a este sitio WEB

Inicio | Continuar... 1999, Reinaldo Togores. El cdigo publicado es nuestro, salvo en los casos en que as se expresa. Todos los derechos sobre los programas que citamos son de la exclusiva propiedad de sus autores. En los casos en que as lo requiere el autor hemos incluido las respectivas informaciones sobre el copyright. El cdigo que publicamos bajo nuestro nombre slo puede ser utilizado con fines no comerciales, mencionando siempre al autor y a la obra de donde se ha tomado. /hide script from old browsers document.write( " Actualizado "+ document.lastModified ); //end hiding contents --->
FastCounter by bCentral

INTRODUCCIN:

LISP se encuentra entre los ms antiguos lenguajes de programacin de alto nivel an en uso generalizado. Fue desarrollado alrededor de 1958 por John McCarthy. La idea de LISP surgi a partir de un sistema lgico llamado "lambda calculus'' desarrollado por Alonzo Church. Existen diversas variantes (o dialectos) de LISP, entre las cuales se encuentran Scheme, T, etc. LISP lleg a ser fundamental como lenguaje de programacin para las investigaciones de Inteligencia Artificial, y sigue an hoy siendo uno de los ms utilizados en este campo. En la dcada de los '80 se intent estandardizar el lenguaje. Como resultado surgi el Common LISP cyas especificaciones se recogen en Common LISP: The Language, 2nd Edition (CLTL2). Common LISP es actualmente el dialecto ms difundido y la base para el desarrollo de numerosas implementaciones. Las razones para ello se encuentran en el hecho de poseer una de las formas de sintaxis menos restrictivas entre los lenguajes de alto nivel. Esto facilita su aprendizaje, al ser muy corto el nmero de estructuras y funciones que el estudiante debe conocer para llegar a dominar las tcnicas de programacin en este lenguaje. De hecho, este curso se propone la utilizacin de un subconjunto de las muchas funciones disponibles para con ellas examinar las tcnicas que hacen de LISP un lenguaje tan especial. LISP: PARADIGMA DEL ESTILO DE PROGRAMACIN FUNCIONAL Una de Las caractersticas de LISP es la posibilidad de tratar las propias funciones como datos. En LISP, funciones e incluso programas enteros pueden ser utilizados directamente como entrada a otros programas o subrutinas. En esto el prototipo para la concepcin del lenguaje ha sido la estructura de las funciones matemticas. Todos sabemos cmo resolver una expresin del tipo (8 * ((17 + 3) / 4)). Primero hallaramos el resultado de 17 + 3, que entonces dividiramos entre 4, para el resultado multiplicarlo por 8. Es decir, que iramos resolviendo los parntesis ms interiores y pasando los resultados a las operaciones descritas en los parntesis que los contienen. (* 8 (/ (+ 3 17) 4)) sera la funcin LISP equivalente. *, / y + son nombres de funciones LISP. Los nmeros en (+ 3 17) son los argumentos que se pasan a la funcin '+'. Pero en (/ (+ 3 17) 4) a la funcin '/' se le est pasando un argumento numrico 4, pero tambin (+ 3 17), otra funcin con dos argumentos numricos. Esta es la esencia de un lenguaje de programacin funcional y por eso decimos que LISP lo es. "Programacin funcional significa, seg Graham (On Lisp, pg. 28), escribir programas que operan a base de devolver valores en lugar de producir efectos colaterales. Estos efectos colaterales incluyen cambios destructivos en los objetos y la asignacin de variables (con setq, por ejemplo)." Sigue explicando Graham (pg. 31) que "una funcin destructiva es una que puede alterar los argumentos que se le pasan. Slo unos pocos operadores LISP estn pensados para producir efectos colaterales. En general, los operadores propios del lenguaje estn pensados de manera tal que se invoquen para obtener los valores que devuelven. Nombres como sort (vl-sort), remove (vl-remove) o substitute (subst) no deben

llamarnos a engao. Si usted quiere efectos colaterales, utilice setq sobre el valor devuelto. Esta misma regla sugiere" -sigue explicando Graham- "que algunos efectos colaterales son inevitables. Tener la programacin funcional como ideal no implica que los programas nunca debieran tener efectos colaterales. Slo quiere decir que no deben tener ms de los necesarios." Esta caracterstica de la programacin funcional no es arbitraria. Citando de nuevo a Graham: Los programadores LISP no adoptaron el estilo funcional por razones meramente estticas. Lo usan porque facilita su trabajo. En el entorno dinmico de LISP, los programas funcionales pueden ser escritos a una velocidad poco usual, y a la vez, pueden ser inusualmente confiables. En LISP es comparativamente fcil el depurar los programas. Una gran cantidad de informacin se encuentra disponible en tiempo de ejecucin, lo que ayuda en el rastreo de los errores. Pero an ms importante es la facilidad con la que pueden probarse los programas. No es necesario el compilar el programa para probar su funcionamiento como un todo. Podemos probar las funciones individualmente, llamndolas desde el nivel superior del evaluador. Esta comprobacin de carcter incremental es tan valiosa que el estilo de programacin LISP ha evolucionado para aprovecharla. Los programas escritos en un estilo funcional pueden ser comprendidos una funcin a la vez, y desde el punto de vista del lector, esta es su principal ventaja. Sin embargo, el estilo funcional se adapta perfectamente a la comprobacin incremental: los programas escritos en este estilo pueden ser tambin probados una funcin a la vez. Cuando una funcin ni examina ni altera el estado exterior, los errores se harn aparentes de inmediato. Una funcin as diseada slo puede afectar el mundo exterior a travs de los valores que devuelve. En la medida que estos valores sean los esperados, podemos confiar en el cdigo que los produjo. Los programadores LISP experimentados de hecho disean sus programas de manera que puedan ser fcilmente probados: 1. Tratan de aislar los efectos colaterales en unas pocas funciones, de manera que la mayor parte del programa pueda ser escrito en un estilo puramente funcional. 2. Si una funcin debe producir efectos colaterales, tratan de que al menos posea una interfaz funcional. 3. Le dan a cada funcin un propsito nico y bien definido Cuando acaba de escribirse una funcin, pueden probarla sobre una seleccin de casos representativos, y una vez hecho esto pasar a la prxima funcin. En LISP, como en cualquier otro lenguaje, el desarrollo se lleva a cabo en ciclos de escritura y comprobacin. Pero en LISP el ciclo es muy corto: funciones aisladas, e incluso partes de funciones. Y si comprobamos todo a medida que lo escribimos, sabremos dnde buscar cuando se produzca un error: en lo ltimo que se escribi.

Graham, On Lisp, pg. 37 y 38. Lisp mas all de AutoCAD Hay implementaciones de LISP para uso en el desarrollo de aplicaciones de todo tipo. El lenguaje se ha normalizado con el nombre de Common LISP (norma ANSI). Existen entornos de desarrollo disponibles muchas veces como software gratuito a travs de internet. Para ms informacin se recomienda acceder a los siguientes sitios WEB*: Compiladores y entornos de desarrollo Common LISP para WINDOWS:

Xanalys LispWorks Allegro CL Corman Common Lisp CLISP

Los primeros tres son productos comerciales, pero todos ofrecen versiones gratuitas de evaluacin perfectamente adecuadas para el aprendizaje del lenguaje. CLISP es totalmente gratis (GPL). LispWorks es especialmente recomendable por su claro entorno de desarrollo (IDE), la capacidad de construir fcilmente aplicaciones con una interfaz grfica de usuario (GUI) y la licencia de evaluacin que permite el utilizar el producto por tanto tiempo como se desee, con slo unas limitaciones de menor entidad. Le acompaa una muy completa referencia en formato HTML y PDF. Allegro CL posee herramientas para el desarrollo de interfaces grficas mucho ms completas, pero la licencia de evaluacin debe ser renovada cada mes. Corman LISP slo brinda la posibilidad de utilizar el IDE como evaluacin durante un mes, aunque el compilador en s es gratuito y posee una consola LISP tambin gratuita. Para Corman Common Lisp el profesor Reini Urban ha implementado la posibilidad de su ejecucin desde el entorno AutoCAD lo que que pudiera sealar un camino de desarrollo interesante para el futuro. Tutoriales en la Red: El libro de David Touretzky "Common Lisp: A Gentle Introduction to Symbolic Computation", que est disponible en formato PDF. El libro de David Lamkins "Successful Lisp: How to Understand and Use Common Lisp" en formato html. La Common LISP HyperSpec, de Kent Pitman, que no es un tutorial, sino la referencia definitiva del lenguaje. Cortesa de la casa que comercializa LispWorks. El libro de Guy Steele "Common LISP, the language. 2nd Edition", ms conocido como CLTL2, aunque anterior a la norma ANSI, an merece ser ledo.

Si se trata de comprar un libro, lo recomendable sera comenzar, ya sea con el de Paul Graham "ANSI Common Lisp" o con el de Stephen Slade "Object-Oriented Common LISP". Despus, el PAIP ("Paradigms of Artificial Intelligence Programming") de Peter Norvig es una lectura obligada. En la Web sera necesario visitar el CLiki y la pgina de ALU (Association of LISP Users) para ms enlaces de inters. Un caso particular es el del Corman Common Lisp, para el que Reini Urban ha implementado la posibilidad de su ejecucin desde el entorno AutoCAD y que pudiera sealar un camino de desarrollo interesante para el futuro. Tambin existen utilidades para la transferencia de programas AutoLISP-XLISP desarrolladas por Tony Tanzillo. * Fuente: Dr. Edmund Weitz (edi@agharta.de) posting al newsgroup comp.lang.lisp Fecha: 2001-09-28 03:38:20 PST PARA MUESTRA... Como una muestra de la capacidad de sntesis y abstraccin a la que podemos acceder con LISP (y una buena cuota de ingenio) reproducimos este pequeo problema planteado a manera de acertijo hace unos das por Vladimir Nesterovski en el grupo de noticias autodesk.autocad.customization, y la solucin propuesta otro maestro, Tony Tanzillo:
Hola todos, os propongo algo: crear una funcin que para una lista de puntos devuelva un par de puntos con los valores mnimos y mximos (una suerte de "caja de abarque"), que funcione para puntos n-dimensionales y que no emplee LAMBDA o SETQ. Debe ser simple tambin. :) Por ejemplo, para '( (1 2 2) (2 5 4) (3 1 2) ) devolvera '( (1 1 2) (3 5 4) ). Pasadlo bien, :-) -Vlad

Y la respuesta de Tony Tanzillo:


(defun extents (plist) (list (apply 'mapcar (cons 'min plist)) (apply 'mapcar (cons 'max plist))))

En dos lneas de cdigo resuelta una funcin que explicada en trminos de programacin ms convencionales, recibir dos matrices de dimensiones variables n x m y devolver una matriz conteniendo los mximos y mnimos para cada uno de los trminos de las matrices recibidas. La funcin EXTENTS recibe como argumento una lista de listas y devuelve otra, sin recurrir en ningn momento a la creacin de variables como almacenaje intermedio. Por

otra parte el argumento original permanece inalterado, es decir que se trata de una funcin no destructiva. Esto a manera de muestra de lo que trataremos de exponer de aqu en adelante.

Visual LISP

LISP fu inicialmente fue desarrollado como un lenguaje interpretado, aunque las modernas versiones cuentan siempre con un compilador que transforma el cdigo fuente en lenguaje de mquina optimizado. Esta compilacin puede ejecutarse de manera inmediata al cargar en el entorno de desarrollo el cdigo fuente del programa, lo que facilita el desarrollo al disponer de una evaluacin de manera inmediata. Para acceder a este entorno, en el caso del Visual LISP, se teclea desde la lnea de comando de AutoCAD las instrucciones VLISP VLIDE (esta ltima para compatibilidad con el Visual LISP de la versin 14). Las instrucciones LISP se introducen para su evaluacin en una ventana especial conocida como la Consola Visual LISP. Si no est a la vista, se puede abrir esta ventana pulsando el botn de la barra de herramientas.

El cursor que aparece junto al smbolo _$ indica que le sistema est listo para recibir las expresiones LISP del usuario. La imagen anterior muestra el resultado de evaluar una expresin usando funciones aritmticas. La evaluacin se produce al pulsar <INTRO>. Una vez impreso el resultado aparece de nuevo el smbolo _$ indicando que el sistema est listo para recibir una nueva expresin. Este ciclo que se desarrolla en el intrprete se conoce como bucle de lectura-evaluacin-impresin (read-eval-print loop). Esto significa que el intrprete lee lo que se ha tecleado, lo evala y entonces imprime el resultado antes de quedar listo para la nueva expresin. Al uso de la consola dedicaremos una seccin especfica de este curso. El entorno de desarrollo (IDE) Visual LISP cuenta adems con un Editor especializado y una serie de medios para la depuracin de los programas muy superiores a los que estaban disponibles en el viejo AutoLISP. No obstante, estas lecciones podrn ser seguidas utilizando cualquier versin de AutoLISP. Se ha tratado de sealar cuando se est hablando de funciones o modos de operacin propios del Visual LISP que noi estn disponibles en el entorno AutoLISP.

Hay otras implementaciones de LISP para uso general disponibles muchas veces como software gratuito a travs de internet. Para ms informacin se recomienda acceder a los siguientes sitios WEB: AutoCAD-AutoLISP info+tools Pgina AutoCAD/AutoLISP de Reini Urban. The Association of Lisp Users Pgina WEB de la Asociacin de Usuarios de LISP. Un caso particular es el del Corman Common Lisp, para el que Reini Urban ha implementado la posibilidad de su ejecucin desde el entorno AutoCAD y que pudiera sealar un camino de desarrollo interesante para el futuro. Tambin existen utilidades para la transferencia de programas AutoLISP-XLISP desarrolladas por Tony Tanzillo.

EL ENTORNO DE DESARROLLO VISUAL LISP

Visual LISP (VLISP) representa una renovacin de LISP para AutoCAD, actualizndolo para incluir prestaciones que ya son normales en los modernos dialectos de LISP que se ajustan a la normativa COMMON LISP. An sin llegar a ser totalmente compatible con esta normativa, es significativo el incremento de su potencia como lenguaje de programacin. Es particularmente til la posibilidad que se incorpora para la interaccin con la jerarqua de objetos de la aplicacin mediante la interfaz ActiveX Automation de Microsoft, y la posibilidad de responder a eventos mediante la implementacin de funciones diseadas como reactores. Como herramienta de desarrollo se aporta un Entorno de Desarrollo Integrado (IDE) que incluye un compilador y varias utilidades para la depuracin. El IDE Visual LISP incluye:

Comprobador de Sintaxis que reconoce secuencias AutoLISP errneas y el uso incorrecto de los argumentos en llamadas a las funciones primitivas del lenguaje. Compilador de Ficheros que incrementa la velocidad de ejecucin y constituye una plataforma de distribucin que brinda seguridad al cdigo fuente. Depurador de Fuentes, diseado especficamente para AutoLISP, que permite la ejecucin paso a paso del cdigo fuente en una ventana mientras se observan simultneamente los resultados obtenidos en la pantalla grfica de AutoCAD. Editor de Programacin que emplea la codificacin por color para LISP y DCL, as como otras caractersticas de apoyo sintctico. Formateo LISP automtico que redistribuye las lneas de cdigo y las identa para facilitar la lectura de los programas. Amplias caractersticas de Inspeccin y Vigilancia (Watch) que permiten el acceso en tiempo real a los valores de las expresiones y las variables, y que pueden ser empleadas tanto para datos LISP como para objetos grficos de AutoCAD. Ayuda sensible al contexto sobre las funciones AutoLISP y una ventana Apropos para bsqueda de nombres de smbolos. Sistema de Administracin de Proyectos que facilitan el mantenimiento de aplicaciones con mltiples ficheros fuente. Empaquetado de los ficheros AutoLISP compilados en un nico mdulo de programa. Capacidad para guardar y recuperar la configuracin del Escritorio para reutilizar la distribucin de ventanas de cualquier sesin anterior de VLISP. Consola Visual LISP Inteligente que permite un nuevo nivel de interaccin del usuario, con funciones que amplan las de la ventana de texto habitual de AutoCAD.

El Trabajo con Visual LISP y AutoCAD

VLISP posee su propia ventana de aplicacin distinta de la de AutoCAD, pero no puede ejecutarse de manera independiente. Para acceder al IDE Visiual LISP, antes deber haberse iniciado una sesin de AutoCAD.
Iniciar Visual LISP

Como se dijo antes, Debe haberse iniciado una sesin de AutoCAD. Esta sesin puede contener slo un dibujo vaco, o pueden estar abiertos dibujos cuyo contenido se desee procesar. Para activar el IDE VLISP tenemos tres opciones:

Seleccionar del men Herramientas>AutoLISP>Editor Visual LISP Teclear en la lnea de comandos: VLISP Nota: Hemos encontrado al menos en una versin localizada espaola que el comando VLIDE no es reconocido por el sistema. La Ayuda de esa misma versin aeala como alternativa el comando VISUALLISPIDE, que tampoco es reconocido. En estos casos siempre se puede recurrir al comando VLIDE, descrito en el punto siguiente. La versin anterior de Visual LISP utilizaba con los mismos fines el comando VLIDE, que sigue siendo reconocido por la versin 2000. De hecho, internamente la llamada de AutoCAD al IDE Visual LISP se realiza mediante este comando, que veremos aparecer en la lnea de comandos cada vez que se cambie a ese entorno.

La Ventana de la Aplicacin

Al iniciarse Visual LISP pasa a primer plano la siguiente ventana de aplicacin:

Puede seleccionar cada parte de la ventana para una breve descripcin. Barra de Mens

Asumimos que el lector est familiarizado con el uso de mens desplegables en AutoCAD u otras aplicaciones. Slo cabra destacar que stos mens son sensibles al contexto en que se utilizan. Es decir, que algunas opciones que pueden estar activas si se abre la ventana del Editor pueden no estarlas si el foco se encuentra en la Consola o en la ventana de TRACE. Las funciones de la aplicacin se distribuyen entre los mens desplegables de la siguiente manera FILE Creacin de nuevos ficheros de programas abiertos para su edicin Apertura de ficheros existentes Guardar los cambios efectuados Compilar aplicaciones Visual LISP Imprimir los ficheros de programas EDIT Copiar y Pegar texto Deshacer el ltimo cambio en el Editor o la ltima funcin ejecutada desde la Consola Seleccionar texto en el Editor o la Consola

Comprobar el cierre de parntesis Recuperar funciones ejecutadas desde la Consola SEARCH Buscar y Reemplazar texto Colocar marcadores de referencia (bookmarks) y navegar en el texto utilizando estos marcadores. VIEW Buscar y mostrar el valor de variables y smbolos en su cdigo AutoLISP. PROJECT Trabaja con los proyectos y la compilacin de programas DEBUG Establecer y quitar puntos de ruptura en los programas Ejecutar programas paso a paso comprobando el estado de las variables y el valor devuelto por las expresiones. TOOLS Establecer las opciones para el formateado del texto y varias otras opciones del entorno, tales como la ubicacin de ventanas y barras de herramientas. WINDOW Organiza, abre y cierra ventanas en el IDE. HELP Pues eso, la Ayuda en lnea.

Las Barras de Herramientas

Visual LISP dispone de cinco Barras de Herramientas que pueden activarse/desactivarse desde el men View>Toolbars... que abre el siguiente dilogo:

Estas cinco Barras de Herramientas contienen las opciones u comandos esenciales del IDE, facilitando el acceso a los mismos.

Contiene las herramientas usuales de Crear Nuevo, Abrir, Guardar, Imprimir, Cortar, Copiar, Pegar, Deshacer, Rehacer y por ltimo un acceso a la fucin Apropos que sirve para completar el texto buscando una correlacin de una subcadena con nombres de funciones, etc. Incluye las funciones de Buscar, Buscar y Reemplazar. Adems una casilla de lista desplegable donde se guardan los trminos anteriormente buscados durante la sesin de trabajo, lo que permite repetir una busqueda con ms facilidad, cosa que se hace con la herramienta situada a la derecha de la casilla. Por ltimo incluye una serie de herramientas para navegar dentro del texto mediante marcadores, que se introducen con la herramienta de la izquierda, se avanza o retrocede con las dos siguientes y se eliminan con la ltima. La barra Tools (Herramientas) opera slo con la ventana del Editor activa. Sus funciones son, de izquierda a derecha: cargar el cdigo del Editor para su ejecucin desde la Consola, cargar slo el cdigo seleccionado, comprobar la sintaxis de todo el contenido de la ventana del Editor, o con la siguiente, comprobar slo lo seleccionado. Para formatear el texto se utilizan los prximos dos botones, el primero para todo el editor y el segundo slo para el textoseleccionado. Los dos siguientes botones sirven para marcar como coimentario el texto seleccionado o para desmarcarlo. Y por supuesto, el ltimo se trata de la Ayuda en lnea. Los tres primeros botones de esta barra determinan la accin al encontrar un punto de ruptura durante la evaluacin. El primero entra en las expresiones anidadas posteriores al punto de ruptura, evalundolas desde la ms interior. El segundo evala esta expresin y se detiene antes de la siguiente para de nuevo decidir si se quiere entrar a evaluar las expresiones anidadas. El tercer botn contina hasta el final de la funcin en curso y entonces cuando se detiene de nuevo la evaluacin. El segundo tro de botones tene que ver con las acciones a tomar cuando se produce una ruptura del flujo de ejecucin a causa de un error, o de que se alcance un punto de ruptura prefijado dentro del programa. Aunque es un tema que se explicar ms adelante, cabe decir ahora que estos estados de suspensin en la ejecucin del programa se utilizan para examinar los valores asumidos por las variables, cambiarlos si es preciso, etc. El primer botn (Continue) permite terminar con esta pausa y continuar la ejecucin normal del programa. El segundo botn (Quit) permite abandonar el nivel de evaluacin actual (pueden superponerse varios ciclos de evaluacin si se producen varios errores durante la depuracin) y pasar al nivel de ms arriba. Y el tercer botn (Reset) pasa el control de la ejecucin directamente al nivel superior (Top Level). El tercer grupo de botones incluye otras tiles herramientas de depuracin. El botn Toggle Breakpoint permite aadir un nuevo punto de ruptura en el programa, situado en la posicin actual del cursor. El segundo botn (Add Watch) da acceso al dilogo que permite seleccionar un nombre de variable para observar sus resultados durante la ejecucin. Estos resultados se exhiben en una ventana especial, la ventana

Watch. El botn Last Break resalta en la ventana del editor la expresin que dio origen a la ltima ruptura. En caso de error, de esta manera se detecta de inmediato dnde se produjo ste. El ltimo botn no es realmente un botn de comando. Sirve simplemente para indicar si la interrupcin actual se encuentra antes o despus de la expresin. El primer botn sirve para poner en primer plano la ventana de aplicacin de AutoCAD. El segundo botn abre un men donde podemos seleccionar la ventana del IDE Visual LISP que deseamos poner en primer plano. Esto se hace necesario pues podemos tener abiertas de manera simultnea un gran nmero de programas y puede no der fcil localizar aqulo que queremos. El tercer botn traslada el foco a la Consola de Visual LISP. El siguiente permite activar la caracterstica de Inspeccin (Inspect). Inspect permite examinar y modificar objetos AutoLISP as como AutoCAD. La herramienta Inspect crea una ventana separada para cada objeto sometido a inspeccin. La siguiente herramienta (Trace Stack) necesita explicaciones que se salen del marco de esta introduccin. Baste decir que nos permite acceder a la memoria de pila donde se guardan las llamadas a funcin. Puede invocarse en un momento de suspensin en la ejecucin de un programa y permite mediante un men contextual acceder a datos relacionados con la operacin del programa. El botn que le sigue (Symbol Service) est diseado para simplificar el acceso a las distintas utilidades de depuracin relacionadas con smbolos. Podemos resaltar cualquier nombre de smbolo en el Editor y al pulsar sobre este botn se abrir la ventana Symbol Service donde se muestra el valor vinculado. Este valor se puede cambiar directamente en esta ventana. Adems tiene una barra de herramientas que permiten otros procesos con el smbolo seleccionado. El siguiente botn permite abrir la ventana Apropos que describimos en detalle ms adelante Y por ltimo un botn que permite acceder a la ventana Watch. La Consola Visual LISP

Aunque parecida a la ventana de texto de AutoCAD en el hecho de que se puden introducir funciones para evaluarlas y obtener el resultado en pantalla, la Consola es una herramienta de mucha mayor potencia y existen varias diferencias en su manera de operar que es importante tener en cuenta. Por ejemplo, para conocer el valor asociado a un smbolo no es necesario, como en AutoCAD, precederlo de un signo de admiracin <!>. Basta teclear el nombre de la variable y pulsar <INTRO>. En la Consola se emiten una serie de mensajes de diagnstico durante la ejecucin de las funciones y si se encuentra un error interrumpe la ejecucin y habilita un nuevo nivel de evaluacin donde podemos ensayar cambios en valores de variables y realizar pruebas para detectar los problemas existentes. De producirse un nuevo error, se habilita un nuevo nivel y as sucesivamente, hasta que decidamos regresar al nivel superior. Las baras de desplazamiento de la consola nos permiten revisar los resultados anteriores. Las prestaciones ms importantes de la Consola se resumen a continuacin:

Evaluar expresiones AutoLISP y mostrar el resultado devuelto por dichas expresiones. Introducir expresiones AutoLISP en lneas mltiples pulsando para el cambio de lne la combinacin <CTRL> + <INTRO>. Pulsar slo <INTRO> provocara la evaluacin de la expresin tecleada hasta entonces. Evaluar mltiples expresiones a la misma vez. Copiar y transferir texto entre las ventanas de la Consola y el Editor. La mayor parte de los comandos de texto estn disponibles tambin en la Consola. Recuperar expresiones tecleadas anteriormente en la Consola, pulsando la tecla <TAB>. Pulsando esta tecla varias veces se van recuperando las expresiones anteriores. Para realizar el ciclo en sentido inverso puede utilizarse la combinacin <SHIFT> + <TAB>. La tecla <TAB> tambin permite realizar una bsqueda de carcter asociativo a travs del conjunto de expresiones anteriores. Si se quiere buscar anteriores expresiones de creacin de variables bastara teclear (SETQ y entonces pulsar <TAB>, con lo que se ira directamente a la ltima expresin tecleada que comenzaba as. Para realizar el ciclo en sentido inverso aqu tambin puede utilizarse la combinacin <SHIFT> + <TAB>.

Pulsando <ESC> se elimina cualquier texto a continuacin del smbolo (prompt) del evaluador. Pulsando <SHIFT> + <ESC> abre una nueva Consola, dejando el texto escrito en la ventana de Consola anterior sin evaluar. Al pulsar el botn derecho del ratn en cualquier punto de la Consola o tecleando <SHIFT> + <F10> abre un men contextual de funciones y opviones VLISP. Esto facilita, por ejemplo, copiar y pegar texto en la lnea de comandos de la consola, buscar texto e iniciar las utilidades de depuracin VLISP.

La Consola Visual LISP en Entorno Multidocumento (MDI)

AutoCAD 2000 es capaz de abrir varios dibujos a la vez. Esto se conoce como Interfaz Multidocumento (Multiple Document Interface - MDI) en contraposicin con la interfaz de documento nico de versiones anteriores*. Hay una nica ventana de Consola para todos los dibujos AutoCAD abiertos. Cuando se utilizan las barras de desplazamiento para revisar las expresiones y mensajes de la consola, los veremos todos, aunque se hayan emitido para distintos dibujos. Esta es otra diferencia en relacin con la ventana de texto de AutoCAD, que slo es capaz de mostrar los comandosque corresponden al dibujo activo. Dicho de otra manera, cada dibujo tiene su propia ventana de texto, pero comparten una sla Consola VLISP. El cambio de contexto es automtico al cambiar de dibujo en AutoCAD. El dibujo activo en AutoCAD es siempre el dibujo activo en VLISP. El nombre del dibujo activo aparece en la barra de ttulo de la aplicacin.
El men Contextual en la Consola

El pulsar el botn derecho del ratn sobre cualquier lugar de la ventana de la Consola abre un men contextual donde, segn est o no seleccionado algn texto, se habilitarn algunas de las siguientes opciones: Cut Borra el texto seleccionado de la Consola y lo transfiere al Portapapeles de Windows**. Copy Copia el texto seleccionado al Portapapeles de Windows**.

Paste Pega el contenido del Portapapeles de Windows en la posicin indicada por el cursor**. Clear Console window Vaca la Ventana de la Consola. Find Busca el texto especificado en la Consola. Inspect Abre el dilogo de la utilidad Inspect. Add Watch Abre la ventana de la utilidad Watch. Apropos Abre la ventana del Apropos. Symbol Service Abre el dilogo de la utilidad Symbol Service. Undo Deshace la ltima operacin. Redo Anula el efecto del ltimo Deshacer (Undo). AutoCAD Mode Transfiere toda las entradas a la lnea de comandos de AutoCAD para su evaluacin. Toggle Console Log Copia la salida de la Consola a un archivo de registro (log file).

Cmo utilizar la Consola para seguir este Curso:

La consola es la herramienta fundamental que utilizaremos para seguir este curso. Encontraremos fragmentos de cdigo como ste (que fue ya citado en la Introduccin):
(defun extents (plist) (list (apply 'mapcar (cons 'min plist)) (apply 'mapcar (cons 'max plist))))

Podemos seleccionar dicho fragmento en nuestro browser utilizando el ratn y copiarlo (<CTRL> + <V>), para despus pegarlo en la consola.

Hecho esto, pulsamos <INTRO> para que se evale el contenido de la consola, con lo que ya estar definida la funcin EXTENTS. Esta funcin requiere como argumento una lista de puntos (entendindose por puntos una lista de tres nmeros reales representando las coordenadas X, Y, Z. Supongamos que queremos utilizar la lista:
'((162.75 35.76 145.99) (127.77 25.37 91.72)(139.355 1.40 0.088) (242.12 59.34 121.08)(260.897 64.92 30.33) (299.29 76.33 -55.96)(187.13 -9.28 235.85) (313.10 -37.47 96.17))

Para ello la introducirmos en la consola (tambin podemos copiar y pegar) una nueva expresin con el nombre de la funcin y la lista como nico argumento:

Y entonces, pulsando <INTRO> obtendremos el resultado devuelto:

Obsrvese cmo los colores identifican los componentes de las expresiones, rojo para los parntesis, azul para las funciones, verdeazul para los nmeros reales. Una vez evaluada los colores del texto cambian a negro, con lo que se identifica fcilmente qu formas son las que est en condiciones de ser evaluadas.

* AutoCAD 2000 puede configurarse para trabajar en modo de documento nico. Para ello se activa la variable de sistema SDI. El valor por defecto de SDI es 0, cambindolo a 1 se pasa a trabajar en modo de documento nico. Trabajando en este modo, la ventana de texto de AutoCAD contendr los comandos emitidos para los sucesivos dibujos abiertos. ** Es posible realizar operaciones de cortar, copiar y pegar entre la consola de VLISP y la ventana de texto de AutoCAD. El Editor Visual LISP

Es ms que un simple editor de texto. Ser, en realidad, nuestro lugar de trabajo habitual para la programacin LISP dentro de AutoCAD. Cada fichero de programa abierto tendr su propia ventana del Editor Un programa en el editor tendr ms o menos este aspecto:

Codificacin sintctica por color

Lo que primero llama la atencin la ventana del editor es el color que adoptan los diferentes componentes del programa. El editor identifica las distintas partes de un programa LISP y le asigna distintos colores. Esto permite detectar a primera vista elementos tales como nombres de funcin, nmeros enteros o reales y cadenas, distinguindolos de los nombres de funciones y variables asignados por el usuario. Los errores mecanogrficos saltan as a la vista de manera inmediata. Estos colores pueden personalizarse a gusto del usuario.
Controles de la Ventana del Editor

La ventana del Editor no posee Barras de Mens ni de Herramientas. Al estar el foco situado en una ventana del Editor se activarn las opciones de Men y las Herramientas de la ventana de la Aplicacin que pueden usarse para operaciones del Editor. Muchas de las opciones pueden tambin ser ejecutadas desde el men contextual que se abre al pusar el

botn derecho del ratn. Existe la posibilidad de utilizar tambin las combinaciones de teclas rpidas usuales en los editores de texto y adems algunas combinaciones que se utilizan para funciones exclusivas de este editor. En trminos generales, adems de la codificacin por color el editor ofrece otras ayudas que facilitan grandemente el desarrollo de programas. Algunas de estas utildades son:

Comprobacin del cierre de parntesis Formateo del Texto Comentarios automticos en los cierres de Expresiones Comentado y Descomentado automtico de las lneas seleccionadas Bsqueda y Sustitucin de Texto Comprobacin de la Sintaxis Carga de expresiones LISP para ser probadas.

En los prximos apartados pasaremos a exponer estas funcionalidades:


Barras de Herramientas Men Contextual Teclas Rpidas Copias de Seguridad

El Editor VLISP viene configurado para hacer siempre copias de seguridad de los ficheros. Estas copias de seguridad se sitan en el mismo directorio de la fuente del programa usando el mismo nombre y la extensin _ls. De esta manera la copia de seguridad del fichero caras.lsp se llamar caras._ls. Para recuperar la ltima versin guardada de un fichero se emplea la opcin Revert del men Files.

Barras de Herramientas

Casi todas las funcionalidades del programa pueden accederse desde iconos de las Barras de Herramientas. Los iconos que aparecen agrisados cuando se activa la ventana del Editor

no son utilizables en este contexto. Las Herramientas utilizables para operaciones en el Editor son:
Herramientas de Edicin Bsqueda y Marcadores Revisin y Formateo Acceso a otras Ventanas de la Aplicacin Utilidades de Depuracin

Herramientas de Edicin

Esta barra incluye las herramientas de edicin acostumbradas en todo programa Windows, adems de una propia para completar nombres de smbolos:

Crear nuevo archivo. Abrir un archivo existente. Guardar el contenido de la ventana del editor. Imprimir Cortar Texto copindolo al Portapapeles. * Copiar Texto al Portapapeles.* Pegar Texto desde el Portapapeles.* Deshacer la ltima operacin. Rehacer lo deshecho en la operacin anterior. Completar el nombre de un smbolo.

Completar Nombres de Smbolos

La Barra de Herramientas de Edicin incluye una herramienta para completar nombres de Smbolos. Este Icono realiza una bsqueda inteligente de nombres de smbolos definidos en el sistema. Al teclear algunas letras del nombre, el pulsar este icono inicia la bsqueda. Segn la cantidad de smbolos que pudieran corresponder a los caracteres tecleados, puede abrir un men contextual en la posicin del cursor, abrir la ventana de resultados de Apropos o abrir la ventana de inicio de bsqueda de Apropos si fuera demasiado extensas las opciones posibles (por ejemplo, teclear una sla letra inicial). A esta funcin puede accederse desde el Men Search>Complete Word by Apropos... y tambin con la combinacin de teclas rpidas <CTRL> + <SHIFT> + <BARRA ESPACIADORA>
Herramientas de Bsqueda de Texto Bsqueda de texto en mltiples ficheros La bsqueda de una expresin puede realizarse tanto en el fichero que se edita como en los ficheros del proyecto u otros grupos de ficheros seleccionados. Desde el Men se accede mediante Search>Find o mediante las teclas rpidas <CTRL> + <F>.

La caracterstica ms interesante de la herramienta de bsqueda del Editor VLISP es su capacidad de buscar en un grupo de ficheros seleccionados y mejor an, en los ficheros que configuran un proyecto. El resultado de la bsqueda se muestra en una ventana de salida, llamada <Find Output>, donde aparecen completas las expresiones donde se emplea el trmino buscado. Se puede configurar la herramienta de bsqueda para que inserte marcadores (bookmarks) cada vez que encuentre el trmino buscado, de manera automtica. Para ello se deber marcar la casilla Mark Instances (Marcar Instancias)

Buscar y Reemplazar Permite buscar y reemplazar texto en la ventana activa del Editor. Se accede a esta opcin desde el men Search>Replace... (Teclas <CTRL> + <H>). Memorizacin de bsquedas anteriores Los trminos utilizados en bsquedas anteriores se guardan en una lista desplegable para su reutilizacin. Insercin de Marcadores Los marcadores permiten desplazarse dentro del texto de marcador en marcador. Disponible en el men Search>Bookmarks>Toggle Bookmark. Hay problemas con los marcadores al usar la opcin de formateo automtico del texto. (ver nota ms abajo).

Herramientas de Revisin y Formateo Carga de Expresiones LISP Seleccionadas A medida que se escriben, las expresiones seleccionadas pueden cargarse para ser evaluadas. Al ejecutarse la carga el foco pasa a la ventana de la Consola VLISP. Disponible en el Men como Tools>Load Selection (<CTRL> + <SHIFT> + <E>) Carga de la Ventana del Editor Puede cargarse tambin para su ejecucin el contenido total actual de la ventana del Editor y no slo las expresiones seleccionadas. En ambos casos se informar de los errores que impidan la carga del programa, aunque no de los errores sintcticos que pudieran existir. Desde el men Tools>Load Text in Editor (<CTRL> + <ALT> + <E>) Comprobacin del Cdigo Seleccionado Comprueba automticamente la correccin del cdigo tecleado. Puede comprobar todo el contenido de la ventana o slo de las expresiones seleccionadas. Los resultados de la comprobacin pasan a la ventana Build Output. En el ejemplo siguiente se ha suprimido intencionalmente uno de los argumentos necesarios para ls funcin CONS, lo que es detectado al ejecutar la comprobacin. Esta opcin est disponible desde el men Tools>Check Selection o con la combinacin de teclas <CTRL> + <SHIFT> + <C>.

Comprobacin de la Sintaxis del Programa El Editor posee una herramienta para comprobar la sintaxis del cdigo tecleado. El resultado pasa a una ventana llamada Build Output, donde se sealan no slo los errores evidentes sino determinadas situaciones que deben ser manejadas con cierto cuidado. Aplicada la comprobacin de Sintaxis al cdigo anterior obtendramos la siguiente advertencia:

Esto no impide la ejecucin del programa y corresponde a una tcnica de programacin perfectamente vlida en LISP, donde una funcin puede siempre ser empleada como dato. Esta opcin se encuentra tambin en el men Tools>Check Text in Editor (<CTRL> + <SHIFT> + <C>). Formateo del Texto El editor tiene opciones para formateo del texto, haciendo identaciones de manera automtica. El estilo de formateo puede ser personalizado en cierta medida. Puede formatearse todo el contenido de la ventana o slo las lneas seleccionadas. Nota: Aunque no lo hemos encontrado descrito en la documentacin del programa, cuando se formatea un texto que contiene marcadores, stos se trasladan al inicio del bloque seleccionado para su formateo. De manera que si tenemos varios marcadores establecidos y formateamos todo el contenido de la ventana del editor, perderemos los marcadores quedando slo uno en la primera lnea de la ventana del editor, lo que obviamente quita toda utilidad que pudiera tener esta funcin de insercin de marcadores.Comentarios automticos de

cierre de Expresin Entre las opciones de formateo del texto, adems de la identacin se incluye la posibilidad de incluir comentarios al cierre de los parntesis que indican a que funcin corresponden cuando dicha funcin abarca varias lneas. Comentado y Descomentado automtico de las lneas seleccionadas Los comentarios se destacan mediante el esquema de colores elegido con fondo gris, pero adems de ello, la inclusin de los caracteres <;;;> al inicio de la lnea se realiza mediante una opcin del men Edit>Extra Commands>Comment Block y se quitan mediante Edit>Extra Commands>Uncomment Block. Si se estuvieran editando archivos DCL, los caracteres introducidos como seal de comentario sern dos barras inclinadas <//>. Ayuda Esta barra de Herramientas incluye tambin el Icono para el Acceso a la Ayuda en-lnea. Acceso a Otras Ventanas de la Aplicacin

Estas Herramientas permiten Acceder a las ventanas de:


Autocad Otras Ventanasde Visual LISP, incluyendo las de otros ficheros abiertos para su edicin. La Consola Visual LISP La ventana de Inspeccin de objetos LISP y AutoCAD. El Trace Stack, que guarda la memoria de pila de errores. El Symbol Service para la gestin de Smbolos. La Utilidad de Apropos. La Utilidad de Watch.

Utilidades de Depuracin

Slo tres de las herramientas se encuentran disponibles cuando est activa la ventana del Editor:

Insertar Punto de Ruptura. Aadir el smbolo seleccionado a la ventana de Watch. Resaltar en el editor el cdigo que provoc la ltima interrupcin en la ejecucin del programa.

* Es posible realizar operaciones de cortar, copiar y pegar entre el Editor VLISP y la ventana de texto de AutoCAD.

Men Contextual del Editor

El pulsar el botn derecho del ratn sobre cualquier lugar de la ventana del Editor abre un men contextual donde, segn est o no seleccionado algn texto, se habilitarn algunas de las siguientes opciones: Cut Borra el texto seleccionado de la Consola y lo transfiere al Portapapeles de Windows*. Copy Copia el texto seleccionado al Portapapeles de Windows*. Paste Pega el contenido del Portapapeles de Windows en la posicin indicada por el cursor*. Find Busca el texto especificado en una o ms ventanas del Editor. Go to Last Edited Desplaza el cursor hacia la ltima posicin editada. Toggle Breakpoint Coloca un punto de ruptura en la posicin del cursor, o lo elimina en caso de que ya existiera uno en dicha posicin. Inspect Abre el dilogo de la utilidad Inspect. Add Watch Abre la ventana de la utilidad Watch. Apropos Abre la ventana del Apropos. Symbol Service Abre el dilogo de la utilidad Symbol Service. Undo Deshace la ltima operacin. Redo Anula el efecto del ltimo Deshacer (Undo). AutoCAD Mode Transfiere toda las entradas a la lnea de comandos de AutoCAD para su evaluacin. Toggle Console Log Copia la salida de la Consola a un archivo de registro (log file). Teclas Rpidas

Las siguientes combinaciones de teclas rpidas son caractersticas especficas de este editor:
Comandos de ARCHIVO: <CTRL> + <S> Guarda el contenido de la ventana activa del Editor. <CTRL> + <ALT> + <S> Guarda el contenido de la ventana activa del Editor con otro nombre de archivo. <CTRL> + <SHIFT> + <S> Guarda el contenido de todas las ventanas de Editor abiertas. <CTRL> + <F4> Cierra la ventana de Editor activa. <CTRL> + <P> Imprime el contenido de la ventana de Editor activa. Comandos de Edicin: <CTRL> + <Z> Deshacer la ltima operacin en el Editor. Soporta ilimitadas operaciones de Deshacer, hasta la ltima ocasin en que se guard el contenido del Editor a disco. Una vez guardado es imposible deshacer. En ese caso, si fuera necesario, habra que recuperar la copia de seguridad mediante la opcin Files>Revert. <CTRL> + <V> Pegar el contenido del Portapapeles en el lugar sealado por el cursor. <SUPR> Borrar el Texto sealado o el carcter a la derecha del cursor. <CTRL> + <A> Seleccionar todo el contenido de la ventana del Editor.

<CTRL> + <M> Abre un men desplegable con las opciones de bsqueda del cierre de parntesis. <CTRL> + <)> Desplaza el cursor hasta el parntesis de cierre correspondiente. <CTRL> + <(> Desplaza el cursor hasta el parntesis de apertura correspondiente. <CTRL> + <SHIFT> + <)> Selecciona la expresin hasta el parntesis de cierre corresondiente, resaltndola en vdeo inverso. <CTRL> + <SHIFT> + <(> Selecciona la expresin hasta el parntesis de apertura corresondiente, resaltndola en vdeo inverso. <CTRL> + <E> Abre un men desplegable con una serie de comandos adicionales:

Identar Bloque de Texto. Suprimir la Identacin de un bloque de Texto. Identar hasta el nivel actual Aadir un prefijo a cada lnea de texto seleccionada. Aadir texto al final de cada lnea seleccionada. Marcar el bloque seleccionado

como comentario. Desmarcar como comentario el bloque seleccionado. Guardar bloque de texto seleccionado a un archivo. Convertir el texto seleccionado a maysculas. Convertir el texto seleccionado a minsculas. Cambiar a maysculas la primera letra de cada palabra. Insertar Fecha. Insertar Hora. Definir el formato de fecha y hora. Ordenar alfabticamen te las lneas seleccionadas. Insertar el contenido de un archivo de texto en el lugar indicado por el cursor Borrar desde

la posicin del cursor hasta el final de la lnea. Borrar espacios en torno a la posicin actual del cursor.

Comandos de Bsqueda: <CTRL> + <F> Buscar texto. <CTRL> + <H> Buscar y sustituir texto. <CTRL> + <BARRA ESPACIADORA> Completar una palabra por similitud a otras existentes en la ventana actual del Editor. Cuando ya se ha tecleado un nombre anteriormente, El editor VLISP facilita el incorporarlo de nuevo al documento con slo teclear los caracteres iniciales. Si en el ejemplo de arriba quisiramos teclear de nuevo el nombre de la funcin PosVert bastara teclear Po y despus pulsar <CTRL> + <BARRA ESPACIADORA>. Si en lugar de encontrar PosVert encontrara el nombre de variable pos, bastara con volver a pulsar <CTRL> + <BARRA ESPACIADORA> cuantas veces fuera necesaro para llegar al texto deseado. <CTRL> + <SHIFT> + <BARRA ESPACIADORA> Completar una palabra mediante APROPOS (buscando en todo el conjunto de smbolos AutoLISP. <ALT> + <.> Poner o quitar marcador. <CTRL> + <.> Desplazarse al prximo marcador. <CTRL> + <,>

Desplazarse al marcador anterior. <CTRL> + <SHIFT> + <.> Seleccionar hasta el prximo marcador. <CTRL> + <SHIFT> + <,> Seleccionar hasta el marcador anterior. Comandos de Vistas: <CTRL> + <SHIFT> + <I> Abre una ventana de Inspeccin para introducir una expresin. <CTRL> + <SHIFT> + <T> Abre la ventana de Inspeccin de Trace. <CTRL> + <SHIFT> + <R> Abre la ventana de Inspeccin para la ltima pila de error. <CTRL> + <SHIFT> + <S> Abre una ventana de Inspeccin para un smbolo. <CTRL> + <SHIFT> + <W> Abre la ventana de Vigilancia (WATCH). <CTRL> + <SHIFT> + <A> Abre la ventana APROPOS para ayuda con expresiones LISP. <CTRL> + <SHIFT> + <B> Muestra los puntos de interrupcin actuales (en todos los programas abiertos, no slo la ventana activa). <F6> Abre la Consola Visual LISP y/o la pone en primer plano.

Comandos del Proyecto: <CTRL> + <SHIFT> + <P> Abre un proyecto existente. Comandos de Depuracin: <CTRL> + <W> Aadir una expresin a la ventana de Vigilancia (WATCH). <F9> Aade o suprime un punto de interrupcin en la posicin actual del cursor. <CTRL> + <SHIFT> + <F9> Suprime todos los puntos de interrupcin. <CTRL> + <F9> Busca y resalta el cdigo que dio origen a la ltima interrupcin. Herramientas de Desarrollo: <CTRL> + <SHIFT> + <E> Carga y evala el cdigo seleccionado. <CTRL> + <ALT> + <E> Carga y evala el cdigo contenido en la ventana activa del Editor. <CTRL> + <SHIFT> + <C> Comprueba la sintaxis de las expresiones seleccionadas. <CTRL> + <ALT> + <C> Comprueba la sintaxis del cdigo contenido en la ventana activa del Editor. <CTRL> + <SHIFT> + <F> Formatea las expresiones seleccionadas. <CTRL> + <ALT> + <F>

Formatea el cdigo contenido en la ventana activa del Editor. Controles de Ventanas: <ALT> + <F6> Ajusta la ventana activa al espacio disponible en pantalla. Comprobacin del cierre de parntesis Las combinaciones de teclas <CTRL> + <(> y <CTRL> + <)> permiten localizar el parntesis de apertura o el parntesis de cierre respectivamente que corresponda a partir de la posicin donde se sita el cursor. Si se pulsa simultneamente <SHIFT> el texto quedar seleccionado (en vdeo inverso). Completar Texto Cuando ya se ha tecleado un nombre anteriormente, El editor VLISP facilita el incorporarlo de nuevo al documento con slo teclear los caracteres iniciales. Si en el ejemplo de arriba quisiramos teclear de nuevo el nombre de la funcin PosVert bastara teclear Po y despus pulsar <CTRL> + <BARRA ESPACIADORA>. Si en lugar de encontrar PosVert encontrara el nombre de variable pos, bastara con volver a pulsar <CTRL> + <BARRA ESPACIADORA> cuantas veces fuera necesaro para llegar al texto deseado.

TIPOS DE DATOS

Antes de iniciarnos en la programacin LISP, examinaremos los datos con que este lenguaje opera. Las posibilidades de un lenguaje de programacin estn directamente relacionadas con la oferta de procedimientos y funciones y en sobre qu tipos de datos pueden ellos operar. Los tipos de datos originales son los TOMOS y las LISTAS. Los TOMOS y las LISTAS son mutuamente excluyentes: un objeto LISP es lo uno o lo otro. Con una excepcin: la lista vaca o NIL, que estudiaremos ms adelante. Las listas se construyen recursivamente a partir de tomos y/o listas. Ejemplos: TOMOS
a juan 45 z5mn

LISTAS
() (juan) (a juan 45 z5mn) ((juan 45) a ((z5mn)))

AutoLISP y Visual LISP utilizan adems otros tipos de datos que estudiaremos ms adelante y que resultan necesarios para la gestin de los dibujos en el entorno AutoCAD. Tanto los tomos como las listas son expresiones vlidas LISP que el intrprete lee y evala. Las reglas para la evaluacin de ambos tipos de objetos se describen a continuacin: TOMOS Los tomos son las expresiones LISP ms elementales. Siempre tienen un nombre constituido por una secuencia de caracteres y por ello se asemejan a las palabras de un lenguaje. Los nombres de tomos se separan de otras expresiones mediante espacios en blanco, parntesis o cambios de lnea. Un tomo no es divisible. Como norma general, todos los elementos que no sean una lista se consideran tomos. Al recibir un tomo, el evaluador lisp intenta determinar su valor. Este valor puede estar representado por el nombre mismo del tomo, que entonces consideraremos como una "constante" o puede ser un objeto LISP distinto, en cuyo caso estaremos ante un tomo "simblico". Los tomos simblicos se utilizan dentro de los programas para almacenar valores, siendo conocidos entonces como "variables". LISTAS: El nombre LISP viene de LISt Processing (Procesamiento de Listas), indicando el mecanismo fundamental sobre el que se desarrolla el lenguaje. Las listas LISP son grupos de valores relacionados, separados por espacios e incluidos entre parntesis redondos "(" y ")". En LISP, el orden de los elementos incluidos en una lista es significativo. En esto se distingue el concepto de lista del concepto de conjunto, en el que el ordenamiento de los trminos no tiene relevancia. Otra diferencia entre listas y conjuntos reside en que en una lista pueden haber trminos repetidos, mientras que en un conjunto cada trmino ocurre una sla vez. Las listas proporcionan un mtodo eficaz para almacenar valores relacionados. AutoCAD expresa los puntos 3D como una lista de tres nmeros reales donde el primer valor es el de la coordenada X, el segundo la coordenada Y, el tercero la coordenada Z. Esto indica que el orden de los trminos de una lista es significativo y en esto se diferencia del concepto de conjunto. Adems una lista admite trminos repetidos. Dentro de las posibles listas podemos distinguir tres casos:

Listas de un nivel Listas anidadas La lista vaca

TIPOS DE DATOS ESPECFICOS DE AUTOCAD:

CONJUNTOS DE SELECCIN Los conjuntos de seleccin son grupos compuestos por uno o varios objetos (entidades). Las rutinas de AutoLISP permiten aadir o suprimir de forma interactiva objetos de los conjuntos de seleccin. NOMBRES DE ENTIDAD Un nombre de entidad es un identificador numrico asignado a los objetos de un dibujo. En realidad, se trata de un puntero a un archivo mantenido por AutoCAD, en

el que AutoLISP puede encontrar el registro de la base de datos de objetos. Este puntero suele cambiar de una sesin de trabajo a otra. DESCRIPTORES DE ARCHIVO Los descriptores de archivo son identificadores alfanumricos asignados a archivos abiertos por Visual LISP. Cuando sea necesario que una funcin de Visual LISP lea o escriba en un archivo, debe hacerse referencia a su identificador. SUBRUTINAS, SUBRUTINAS EXTERNAS Y FUNCIONES DE USUARIO Funciones Nativas LISP o funciones externas cargadas desde archivos compilados FAS VLX y archivos fuente LISP. TABLAS DE PAGINACIN OBJETOS Y TIPOS DE DATOS ACTIVEX Objetos propios y determinados formatos para los datos que se pasan a los mtodos ActiveX.

COMPROBACIN DEL TIPO DE DATO:

FUNCIN TYPE Devuelve el tipo de un elemento designado (type elemento)

TOMOS

TOMOS SIMBLICOS (S-ATOMS): Un tomo simblico es un tomo que representa algo ms, como el nombre de una funcin o el valor de una variable. Un tomo simblico si no tiene asignado un valor, al evaluarse devolver una lista vaca. Las funciones como set, setq y defun permiten asignarle valores a los tomos-S. Los nombres de smbolos no distinguen entre maysculas y minsculas, y pueden ser cualquier secuencia de caracteres de notacin y alfanumricos a excepcin de los siguientes: ( ) . ' " ; . Un nombre de smbolo no puede estar compuesto slo por caracteres numricos ya que un nmero se representa a s mismo y es por tanto una constante. Lo mismo sucede con los nombres entrecomillados.

VARIABLES: Cuando un smbolo se utiliza para almacenar temporalmente datos necesarios para la ejecucin del programa suele identificarse como una variable. La funcin (atoms-family 0) nos devuelve todos los tomos-S evaluados como no-nil en un momento determinado. VARIABLES GLOBALES Y LOCALES: La funcin SETQ es el medio fundamental para asociar los smbolos a valores:
(SETQ <smbolo> <valor>)

Esto es equivalente a:
(SET (QUOTE <smbolo>) <valor>)

Es decir, que toma el nombre de smbolo sin evaluar, y le asigna el valor deseado. En este sentido se dice que SETQ es una "Forma Especial". Una variable creada con SETQ es una variable global. Esto quiere decir que retiene su valor fuera del programa que la utiliza. Una variable de este tipo afectara a cualquier otro programa que utilizara el mismo smbolo. Las variables locales son aquellas que retienen su valor slo mientras la funcin que las define est activa. Las variables locales se eliminan tan pronto termina la operacin de la funcin donde se definieron, se desechan automticamente y el sistema recupera el espacio de memoria que las variables ocupaban. Esto se conoce como "recoleccin de desechos" (garbage collection) automtica. Las variables locales resultan por ello ms eficientes en el uso de la memoria. Visual LISP no tiene una funcin especial para la creacin de variables locales. Las mismas deben declararse expresamente en la lista de parmetros de la funcin DEFUN. Para ms informacin consultar a R. Urban, Using Local Variables? CONSTANTES: Los nmeros y las cadenas son formas auto-evaluativas. Estos datos se distinguen de los tomos simblicos en que no pueden representar otra cosa que el su propio valor, es decir que se representan a s mismos. Entre los valores constantes tenemos los nmeros y las cadenas. NMEROS Los valores numricos que emplea Visual LISP pueden ser enteros o reales.

CADENAS DE TEXTO Una cadena se representa mediante una sucesin de caracteres (letras, nmeros y signos de puntuacin) encerrados entre comillas dobles. Estas comillas dobles de apertura y cierre no forman parte de la cadena de caracteres en s misma, sino que constituyen la manera de indicar al evaluador LISP que se trata de este tipo de dato. Si se quiere tener comillas dobles como parte de la cadena, deber precederse el carcter comillas por una contrabarra: "Esto es una \"Palabra\" entrecomillada". La contrabarra es un carcter de control que permite incluir cambios de lnea, tabuladores, y otros caracteres especiales en una cadena. Para incluir una contrabarra como parte de la cadena deben escribirse dos contrabarras, la primera como carcter de control y la segunda para graficar la contrabarra: "Cadena incluyendo \\". Las cadenas individuales tienen una limitacin de 132 caracteres. En versiones anteriores de AutoCAD, los nombres de tablas de smbolos se convertan automticamente a maysculas. En AutoCAD 2000 se conserva el tipo de carcter utilizado, sean maysculas o minsculas. Al hacer comprobaciones de igualdad de cadenas puede ser necesario por ello realizar conversiones a un mismo tipo de letra utilizando la funcin STRCASE. NMEROS ENTEROS Y REALES

ENTEROS Son nmeros sin coma decimal. Los enteros de AutoLISP son nmeros de 32 bits con signo cuyos valores estn comprendidos entre +2.147.483.648 y -2.147.483.647. Aunque AutoLISP utiliza internamente valores de 32 bits, los que se transmiten de AutoLISP a AutoCAD y viceversa estn limitados a 16 bits. Por tanto, no pueden transmitirse a AutoCAD valores superiores a +32767 ni inferiores a -32768. Sin embargo, VLISP acepta valores fixnum entre los valores lmite de:

MAX-SHORTINT = 32767 MOST-POSITIVE-FIXNUM = 2147483647 MOST-NEGATIVE-FIXNUM = -2147483647

Un nmero mayor o menor se convierte automticamente en real. REALES Contienen coma decimal. Los comprendidos entre -1 y 1 deben empezar por cero. Los nmeros reales se almacenan en formato de coma flotante de doble precisin, lo cual proporciona una precisin mnima de 14 dgitos significativos, aunque el rea de comandos de AutoCAD muestra slo 6.

Los valores lmites son: MOST-POSITIVE-DOUBLE-FLOAT = 1.797693134862315e+308 MOST-NEGATIVE-DOUBLE-FLOAT= -1.797693134862315e+308 Un nmero mayor, devuelve infinito: _$ 1.797693134862316e+308 1.#INF _$ (setq val 1.797693134862316e+308) 1.#INF _$ (type val) REAL _$ (setq *INFINITO* 2.797693134862316e+308) 1.#INF _$ (eq *INFINITO* val) T _$ (/ 125678 *INFINITO*) 0.0 Se puede establecer una variable global *INFINITO* con: (setq *INFINITO* 1.797693134862316e+308) y utilizarlo como tal en operaciones trigonomtricas. Pueden expresarse en notacin cientfica, que consta de una e o E opcional seguida por el exponente del nmero (por ejemplo, 0.0000041 es lo mismo que 4.1e-6). El smbolo pi se evala como la constante real 3,1415...
FUNCIONES DE CONVERSIN ENTRE ENTEROS Y REALES:
(fix nmero)

Devuelve la conversin de un nmero real en el prximo entero menor.


(float nmero)

Devuelve la conversin de un nmero entero en un nmero real. CONSIDERACIONES SOBRE LA CONVERSIN ENTRE NMEROS REALES Y ENTEROS

La funcin fix en realidad lo que ejecuta es un truncamiento del nmero real hacia cero. Es decir, devuelve el nmero entero ms prximo a cero. As (fix 4.7) devolver 4, es decir, el nmero entero menor ms cercano al suministrado como argumento. Pero (fix -4.7) devolver -4, que es el entero mayor ms cercano. En las definiciones de Common LISP, fix equivaldra a la funcin truncate. Steele menciona en CLTL2 otras posibilidades de conversin entre reales y enteros:
floor

convierte su argumento mediante un truncamiento hacia infinito negativo; es decir, que el resultado es el entero mayor que no es mayor que el argumento.
ceiling

convierte su argumento mediante un truncamiento hacia infinito positivo; es decir, que el resultado es el entero menor que no es menor que el argumento.
truncate

convierte su argumento mediante un trucamiento hacia cero; es decir, que el resultado es el entero del mismo signo que el argumento y que posee la mayor magnitud entera que no es mayor que el argumento.
round

convierte su argumento mediante el redondeo al entero ms cercano; si el nmero se encuentra exactamente a mitad de camino entre dos enteros (es decir, en la forma entero + 0.5), entonces se redondea al entero par ms prximo (divisible por 2).

Ms adelante desarrollaremos funciones para implementar algunos de estos conceptos que no aparecen como primitivas de Visual LISP.* *Ver el captulo REALES A ENTEROS: TRUCAMIENTO O REDONDEO.

TOMOS

TOMOS SIMBLICOS (S-ATOMS): Un tomo simblico es un tomo que representa algo ms, como el nombre de una funcin o el valor de una variable. Un tomo simblico si no tiene asignado un valor, al evaluarse devolver una lista vaca. Las funciones como set, setq y defun permiten asignarle valores a los tomos-S. Los nombres de smbolos no distinguen entre maysculas y minsculas, y pueden ser cualquier secuencia de caracteres de notacin y alfanumricos a excepcin de los siguientes: ( ) . ' " ; . Un nombre de smbolo no puede estar compuesto slo por caracteres numricos ya que un nmero se representa a s mismo y es por tanto una constante. Lo mismo sucede con los nombres entrecomillados.

VARIABLES: Cuando un smbolo se utiliza para almacenar temporalmente datos necesarios para la ejecucin del programa suele identificarse como una variable. La funcin (atoms-family 0) nos devuelve todos los tomos-S evaluados como no-nil en un momento determinado. VARIABLES GLOBALES Y LOCALES: La funcin SETQ es el medio fundamental para asociar los smbolos a valores:
(SETQ <smbolo> <valor>)

Esto es equivalente a:
(SET (QUOTE <smbolo>) <valor>)

Es decir, que toma el nombre de smbolo sin evaluar, y le asigna el valor deseado. En este sentido se dice que SETQ es una "Forma Especial". Una variable creada con SETQ es una variable global. Esto quiere decir que retiene su valor fuera del programa que la utiliza. Una variable de este tipo afectara a cualquier otro programa que utilizara el mismo smbolo. Las variables locales son aquellas que retienen su valor slo mientras la funcin que las define est activa. Las variables locales se eliminan tan pronto termina la operacin de la funcin donde se definieron, se desechan automticamente y el sistema recupera el espacio de memoria que las variables ocupaban. Esto se conoce como "recoleccin de desechos" (garbage collection) automtica. Las variables locales resultan por ello ms eficientes en el uso de la memoria. Visual LISP no tiene una funcin especial para la creacin de variables locales. Las mismas deben declararse expresamente en la lista de parmetros de la funcin DEFUN. Para ms informacin consultar a R. Urban, Using Local Variables? CONSTANTES: Los nmeros y las cadenas son formas auto-evaluativas. Estos datos se distinguen de los tomos simblicos en que no pueden representar otra cosa que el su propio valor, es decir que se representan a s mismos. Entre los valores constantes tenemos los nmeros y las cadenas. NMEROS Los valores numricos que emplea Visual LISP pueden ser enteros o reales.

CADENAS DE TEXTO Una cadena se representa mediante una sucesin de caracteres (letras, nmeros y signos de puntuacin) encerrados entre comillas dobles. Estas comillas dobles de apertura y cierre no forman parte de la cadena de caracteres en s misma, sino que constituyen la manera de indicar al evaluador LISP que se trata de este tipo de dato. Si se quiere tener comillas dobles como parte de la cadena, deber precederse el carcter comillas por una contrabarra: "Esto es una \"Palabra\" entrecomillada". La contrabarra es un carcter de control que permite incluir cambios de lnea, tabuladores, y otros caracteres especiales en una cadena. Para incluir una contrabarra como parte de la cadena deben escribirse dos contrabarras, la primera como carcter de control y la segunda para graficar la contrabarra: "Cadena incluyendo \\". Las cadenas individuales tienen una limitacin de 132 caracteres. En versiones anteriores de AutoCAD, los nombres de tablas de smbolos se convertan automticamente a maysculas. En AutoCAD 2000 se conserva el tipo de carcter utilizado, sean maysculas o minsculas. Al hacer comprobaciones de igualdad de cadenas puede ser necesario por ello realizar conversiones a un mismo tipo de letra utilizando la funcin STRCASE. LISTAS Y CONSES

Por la importancia dentro de LISP del tipo de datos LISTA, citamos in extenso el apartado 2.4 de CLTL2, Un CONS es una estructura de informacin que contiene dos componentes llamados el CAR y el CDR. La utilizacin fundamental de los CONSES es como representacin de LISTAS. Una LISTA se define recursivamente ya sea como la lista vaca o como un CONS cuyo componente CDR es una lista. Una lista es, por consiguiente, una cadena de CONSES enlazados por sus componentes CDR y terminada por un NIL, la lista vaca. Los componentes CAR de los conses son conocidos como los elementos de la lista. Para cada elemento de la lista hay un CONS. La lista vaca no tiene ningn elemento. Para comprender mejor lo anterior, adelantaremos la mencin de la funcin bsica de construccin de listas, que es la funcin CONS (que se explica en el apartado FUNCIONES DE CONSTRUCCIN DE LISTAS). Expresado en trminos de esta funcin, la anterior definicin de una lista como una cadena de CONSES sera:

Una LISTA se expresa mediante la escritura de los elementos de la lista ordenados, separados por espacios en blanco (caracteres de espacio, tabulador o retorno) y rodeados por parntesis. Por ejemplo:
(a b c) (2.0 (a 1) "*") ;Una lista de tres smbolos ;Una lista de tres cosas diferentes: un nmero real ;otra lista y un carcter asterisco

Nota: El cdigo del ejemplo anterior ha sido modificado para adaptarlo a las convenciones de AutoLISP/Visual LISP La lista vaca puede por lo tanto ser expresada como (), ya que se trata de una lista sin elementos. Una lista punteada (dotted list) es una cuyo ltimo cons no tiene NIL como su CDR, sino otro objeto de informacin (que tampoco ser un CONS, ya que entonces el CONS anteriormente mencionado no hubiera sido el ltimo CONS de la lista).

Tal tipo de lista se conoce como "punteada" debido a la notacin especial que se emplea en ella: los elementos de la lista se escriben, al igual que antes, entre parntesis, pero ... antes del parntesis derecho se escriben un punto (rodeado por espacios en blanco) y entonces el CDR del ltimo CONS. Como caso especial, un CONS aislado se expresa escribiendo el CAR y el CDR entre parntesis y separados por un punto rodeado de espacios (par punteado). Por ejemplo:
(a . 4) (a b c . d) ;Un cons cuyo car es el smbolo a ;y cuyo cdr es un entero ;Una lista punteada con tres elementos cuyo cons final ;tiene el smbolo d en su cdr

Con frecuencia se utiliza el trmino lista para hacer referencia tanto a verdaderas listas como a listas punteadas. Cuando resulta importante la distincin, se utilizar el trmino "verdadera lista" para referirnos a una lista terminada por NIL. La mayora de las funciones que se dice operan sobre listas esperan recibir verdaderas listas como argumento. Por ejemplo, si en el ejemplo de concatenacin de CONSES anterior el elemento de la derecha del ltimo CONS no hubiera sido NIL (lo que hubiera incluido un par punteado en la lista), el pasar esta lista como argumento a una funcin de tratamiento de listas hubiera producido en determinados casos un error:

A veces se utiliza el trmino rbol para referirse a algunos CONS y todos los dems CONSES accesibles a l de manera transitiva a travs de enlaces de CAR y CDR hasta alcanzar objetos NO-CONS; stos NO-CONSES son conocidos como las hojas del rbol.

Representacin de LISTAS como rboles. Tomado de: Corts y Sierra, LISP. Editorial Marcombo, Barcelona. 1987. Las listas, las listas punteadas y los rboles no son tipos de datos mutuamente excluyentes; no son ms que puntos de vista tiles en torno a las estructuras de CONSES. Hay an otros trminos tales como LISTA DE ASOCIACIN. Ninguno de stos son verdaderos tipos de datos LISP. Los CONSES constituyen un tipo de dato, y NIL es el nico objeto de tipo NULL. El tipo de dato LISTA significa en LISP la unin de los tipos de datos CONS y NULL, y por ello engloba tanto las listas verdaderas como las listas punteadas.
FORMATOS DE LISTAS:

Adems de lo apuntado ms arriba, es conveniente distinguir entre los siguientes tres formatos de listas:

LISTAS DE UN NIVEL Contienen slo tomos. LISTAS ANIDADAS Contienen a su vez otras listas que se dicen anidadas. Estas listas anidadas suelen ser conocidas como sub-listas. El nmero de niveles de anidacin no est restringido ni en su profundidad ni en su complejidad. El nivel ms externo lo llamamos nivel superior o primer nivel. A los elementos que conforman este nivel los llamamos elementos de primer nivel. LISTAS DE ASOCIACIN (A-LIST) Son listas anidadas que se utilizan con frecuencia como estructura de datos en LISP. Una A-LIST es una lista de pares (CONSES) en que cada par constituye una asociacin. El CAR de

uno de estos pares se conoce como la CLAVE y el CDR constituye el DATO. Una ventaja de la representacin como A-LIST es la posibilidad de incrementarla aadindole nuevas entradas al principio de la lista. Ms an, como la funcin de bsqueda ASSOC recorre la A-LIST de manera ordenada, las nuevas entradas pueden "enmascarar" las ms antiguas de manera que la informacin puede ser modificada de forma no destructiva. LA LISTA VACA (NIL) Como se dijo antes, es la que no contiene ningn elemento. Se indica como () y recibe un nombre particular, el de NIL. La lista vaca tiene un status peculiar en LISP. Es a la vez un tomo y una lista. Como smbolo representa el valor lgico de FALSO:

_$ () nil _$ (atom nil) T _$ (listp nil) T

CIERTO Y FALSO Su negacin (not nil) sera el smbolo T que representa la condicin lgica de CIERTO. El smbolo T es tambin una constante en el sentido de que slo se representa a s mismo. En Visual LISP, nil y T as como otros elementos que incluyen los operadores aritmticos (+, -. etc.) son smbolos protegidos. Cualquier intento de asignarle otro valor producir un mensaje de advertencia:

Este mensaje aparece como la opcin por defecto y pide si se desea entrar en un bucle de interrupcin (break loop). Si se escoge No, el valor del smbolo es modificado. Si se selecciona S, se interrumpe el procesamiento y se entra en un ciclo de interrupcin de Visual LISP, lo que se conoce por el aspecto del smbolo del evaluador, por ejemplo: _1_$.

El control se ha trasladado a la consola de Visual LISP. Para asignar valor al smbolo y continuar el procesamiento se deber pular el botn Continuar en la barra de . herramientas de Visual LISP. Para abortar el procesamiento se pulsar Reset

VALORES DEVUELTOS POR LA FUNCIN TYPE

(type dato)

La funcin TYPE permite examinar el tipo a que corresponde un dato determinado. Los datos que evalan como NIL (por ejemplo tomos simblicos no vinculados a un valor) devuelven nil.

El valor devuelto para cada tipo de dato ser alguno de los tomos que se describen a continuacin:
Tipos LISP:

INT Nmeros Enteros REAL Nmeros de Coma Decimal Flotante LIST Listas STR Cadenas

SYM Smbolos Tipos AutoCAD:

ENAME Nombres de entidades FILE Descriptores de archivo PAGETB Tablas de Paginacin de Funciones PICKSET Conjuntos de seleccin SUBR Funciones AutoLISP internas o funciones cargadas desde archivos (FAS o VLX) compilados. USUBR Funciones de usuario cargadas desde ficheros fuente LSP. EXRXSUBR Aplicaciones ObjectARX Externas. Tipos ActiveX:

SAFEARRAY Matriz del tipo Safearray. Las matrices que se pasan a los mtodos ActiveX deben ser del tipo safearray. Estas matrices son seguras (safe) porque no es posible el asignar de manera accidental valores fuera de los lmites de la matriz provocando una excepcin de datos.

VARIANT Datos del tipo Variant. Los Variant son en esencia estructuras que se autodefinen y que pueden contener diferentes tipos de datos. Por ejemplo, cadenas, enteros y matrices pueden ser representados por Variants. Junto a los datos se guarda la informacin que identifica el tipo de dato. Esta caracterstica de autodefinicin hace de los Variant tiles medios para pasar parmetros a los servidores ActiveX. VLA-object Objetos ActiveX

FUNCIONES

Una vez conocidos los tipos de datos pasaremos a estudiar cmo utilizarlos. LISP es un lenguaje de programacin funcional, es decir que suministra funciones para la manipulacin de los datos. Los programas LISP se estructuran como formas y funciones. Segn Corts y Sierra*, una FORMA es "una expresin simblica en posicin de ser evaluada. El cmputo de valores, en LISP, se realiza simplemente mediante la evaluacin de una FORMA. Todas las FORMAS tienen valor, sean estas constantes numricas, tomos literales o expresiones simblicas. Uno de los errores ms tpicos al programar en LISP es el de tratar de evaluar una FORMA que no tiene valor. El valor de una FORMA es el resultado de evaluarla... Hay que remarcar que los trminos expresin simblica y FORMA pueden aplicarse a la misma entidad; su aplicacin depender del contexto. Una LISTA puede considerarse como un dato, como una expresin simblica o considerarse como parte de un procedimiento; la misma LISTA puede ser considerada como una FORMA" . Las formas se evalan (en relacin con determinado contexto) para producir valores y efectos colaterales. Las funciones se invocan aplicndolas a argumentos. (Guy L. Steele Jr., Common Lisp the Language, captulo 5). En el entorno Visual LISP se identifican como FORMAS las funciones de usuario definidas dentro de un fichero fuente LSP. Al cargar un programa se recibe la confirmacin de la carga exitosa del mismo mediante el siguiente mensaje:

Las funciones son conocidas en matemticas. Mediante ellas se describe algn tipo de relacin entre un grupo de valores. La adicin y la multiplicacin son funciones simples. Una funcin ms compleja sera: f(x)=3x2+2x-15 Esta ltima funcin tambin describe una regla de clculo o algoritmo. Las funciones realizan los clculos (en trminos LISP, evaluacin) utilizando para ello sus argumentos y devuelven un resultado. A iguales argumentos correspondern iguales resultados. Segn Corts y Sierra**: En LISP, los programas se construyen a partir de la composicin de funciones. Esto permite que tales programas expresen sus propsitos ms claramente que los programas convencioneles, y que resulten ms fciles de entender y de mantener, adems de ser ms fciles de construir. AutoCAD identifica sus funciones LISP primitivas como el tipo de dato SUBR, mientras que las formas definidas a partir de ellas pertenecen al tipo de dato USUBR o "sub-rutina de usuario" La funcin typedevuelve los tipos correspondientes. La llamada a una funcin toma la forma de una lista cuyo primer elemento es un tomo simblico que representa a la funcin llamada. El resto de los elementos de esa lista pueden ser tomos y otras listas. Estas sublistas se consideran tambin llamadas a funciones y se evalan para que su valor resultante pueda ser pasado como argumento a la funcin que las contiene. FUNCIONES PRIMITIVAS Describimos una serie de funciones como primitivas en el sentido de que estn definidas en la norma del lenguaje, para distinguirlas de las funciones creadas por el usuario a partir de aqullas. En LISP se llama a una funcin mediante la siguiente sintaxis:
(NOMBREFUNCION <Argumento_1> ... <Argumento_n>) La suma de dos nmeros sera (+ 5 1)

Para evaluarla LISP procede de la siguiente manera: a. Lee la expresin completa (+ 5 1) b. La interpreta como una llamada a una funcin y la identifica como SUMAR <+> c. Interpreta 5 como primer argumento y 1 como segundo. El parntesis de cierre le indica que no hay ms argumentos. d. La funcin <+> se evala para 5 y 1, devolviendo 6 como resultado, que a falta de otro destino es impreso en pantalla. Programar LISP significa llamar a funciones. Bsicamente esto se hace usando el tipo de dato LISTA. Cualquier lista que no tenga otra interpretacin como forma especial se considerar una llamada a una funcin, donde el primer trmino se tomar como el nombre de la funcin y el resto como sus argumentos. Las listas de llamadas a funcin pueden estar anidadas, es decir, que una llamada a funcin se puede estar utilizando como argumento en otra lista que corresponda a una llamada a otra funcin. El resultado de la evaluacin de cada nivel de anidacin es devuelto al nivel de superior, hasta llegar al nivel ms alto, cuyo valor devuelto se imprimira en la pantalla de texto o la lnea de comandos.

ARGUMENTOS FUNCIONALES

De lo expuesto ms arriba se concluye que en LISP una funcin es adems un objeto de datos que puede ser suministrado a otra funcin como argumento. Esta posibilidad contribuye a la facilidad con que LISP se puede adaptar a las necesidades de cualquier programa mediante la incorporacin de nuevas funciones que en su comportamiento resultan idnticas a las primitivas. Un programa que admite funciones como datos debe tambin suministrar alguna manera de invocarlas. Esto se logra en Visual LISP mediante la funcin APPLY.
APPLY
(apply funcin lista-args) APPLY, como su nombre en ingls indica, aplica una funcin (que recibe como primer

argumento) a una lista de argumentos. La funcin puede ser un objeto de cdigo compilado, una expresin-lambda, o un smbolo. En este ltimo caso se utiliza el valor funcional global de dicho smbolo, aunque ste no puede ser una forma especial.
_$ (apply '+ '(2 4 6)) 12 _$ (apply '(lambda (x y z)(+ x y z)) '(2 4 6)) 12 _$ (apply 'quote '(2 4 6)) ; error: bad QUOTE syntax: ((QUOTE 2) (QUOTE 4) (QUOTE 6)) _1$ ; reset after error

Obsrvese el error provocado por utilizar la forma especial QUOTE. Otras muchas funciones LISP requieren argumentos funcionales. Entre las de uso ms frecuente estn las funciones de mapeado. MAPCAR, por ejemplo toma dos o ms argumentos: una funcin y una o ms listas (tantas como parmetros requiera la funcin) y aplica la funcin sucesivamente a los elementos de cada lista, devolviendo una lista con los resultados.
_$ (mapcar '+ '(1 2 3) '(10 100 1000)) (11 102 1003)

Otras muchas funciones admiten funciones como argumentos. Entre las ms utilizadas tenemos VL-SORT y VL-REMOVE-IF. La primera es una funcin de ordenacin de uso general. Requiere una lista y un predicado, y devuelve una lista ordenada pasando sus elementos dos a dos al predicado.
_$ (vl-sort '(3 2 1 3) '<) (1 2 3)

VL-REMOVE-IF acepta una funcin y una lista, y devuelve todos los elementos de la lista para los cuales la funcin devuelva NIL (falso).
_$ (vl-remove-if 'numberp '("a" 3 4 "c" 5 "d" "e")) ("a" "c" "d" "e")

El programar nuevas funciones utilitarias que aceptan argumentos funcionales es una parte importante del estilo de programacin funcional que caracteriza a LISP.
FUNCIONES ARITMTICAS BSICAS

Las funciones aritmticas que tienen como argumento un nmero devuelven distintos valores dependiendo de que el argumento proporcionado sea un nmero entero o real. Si todos los argumentos son enteros, el valor devuelto ser entero. Por el contrario, si alguno o todos los argumentos son reales, el valor devuelto ser un nmero real. Por ejemplo: (/ 12 5) devuelve 2, mientras que (/ 12.0 5) devuelve 2.4 Los argumentos de una funcin aritmtica no son necesariamente nmeros. Cualquier otra funcin que devuelva un nmero como resultado es admisible como argumento de una funcin aritmtica. Ejemplo (* (+ 1 5)(- 20 10))
FUNCIONES BSICAS DE TRATAMIENTO DE CADENAS

Para el tratamiento de cadenas tenemos funciones que permiten unificar cadenas diferentes, extraer subcadenas de una cadena mayor, determinar cuntos caracteres hay en una cadena y transformar los caracteres a maysculas o minsculas. El predicado WCMATCH permite determinar la semejanza de cadenas utiliando comodines.
FUNCIONES BSICAS DE ACCESO A LISTAS

Una lista es una manera de representar un conjunto de tomos y de otras listas. Una lista tiene la forma de un parntesis de apertura "(" seguido de una serie de tomos o listas, seguido por otro parntesis de cierre ")". De manera que cualquier cosa encerrada entre parntesis ser considerada una lista. Una lista pasada al evaluador LISP ser tratada como una expresin simblica (S-expresin), es decir, una llamada a funcin y se considerar el primer trmino de la lista como el nombre de la funcin. Para que una lista sea tratada como dato y no como una expresin simblica debe estar contenida en la forma especial QUOTE. Las funciones bsicas cuya comprensin es imprescindible para el acceso a la informacin contenida en listas se pueden reducir a cuatro: QUOTE, CAR, CDR, y NTH.
FUNCIONES DE CONSTRUCCIN DE LISTAS

Con las funciones del epgrafe anterior podemos descomponer listas, accediendo a suscomponentes a distintos niveles de anidacin. Existen otras funciones que podemos utilizar para componer nuevas listas a base de elementos individuales, ya sean tomos u otras listas. CONS, LIST y APPEND son funciones que construyen listas por distintos procedimientos y con resultados diversos, por lo que es necesario distinguirlas bien.

* Corts, Ulises y Sierra, Carlos. LISP. Editorial Marcombo, Barcelona-Mxico, 1987. pg. 44 ** ibid. pg. 43

FUNCIONES ARITMTICAS BSICAS

Cada una de las funciones incluidas en este apartado requiere que sus argumentos sean todos nmeros. El pasarle un argumnto no numrico provocar un error. Operan tanto sobre nmeros enteros como sobre nmeros reales, realizando los ajustes pertinentes cuando dichos argumentos fueran de diferente tipo.
+ (suma) (+ [nmero nmero] ...)

Si proporciona slo un argumento nmero, esta funcin devuelve el resultado de sumarlo a cero. Ningn argumento, devuelve 0.
_$ (+ 1 2 3) 6 _$ (+ 1.0 2 3) 6.0 - (resta) (- [nmero nmero] ...)

Si utiliza ms de dos argumentos nmero, esta funcin devuelve el resultado de restar del primer nmero la suma de todos los nmeros, desde el segundo hasta el ltimo. Si slo utiliza un argumento nmero, la funcin devuelve el valor resultante de restar nmero a cero. Ningn argumento, devuelve 0.
_$ (- 10 1 2 3) 4 _$ (- 10 1 2.0 3) 4.0 * (multiplicacin) (* [nmero nmero] ...)

Si proporciona slo un argumento nmero, esta funcin devuelve el resultado de multiplicarlo por uno. Ningn argumento, devuelve 0.
_$ (* 1 2 3) 6 _$ (* 1 2 3.0) 6.0 / (divisin) (/ [nmero nmero] ...)

Si utiliza ms de dos argumentos nmero, esta funcin divide el primer nmero por el producto de todos los nmeros del segundo al ltimo y devuelve el cociente final. Si proporciona slo un argumento nmero, esta funcin devuelve el resultado de dividirlo por uno. Ningn argumento, devuelve 0.

_$ (/ 30 2 4) 3 _$ (/ 30 2.0 4) 3.75 1+ (incremento) (1+ nmero)

Devuelve el argumento aumentado (incrementado) en 1


_$ (1+ 6) 7 1- (decremento) (1- nmero)

Devuelve el argumento reducido (decrementado) en 1


_$ (1- 6) 5

FUNCIONES DE ACCESO A LISTAS

Existen tres funciones bsicas para acceder a los trminos de una lista: CAR, QUOTE y CDR.
Funciones CAR y QUOTE:
CAR CAR admite un nico argumento que debe ser una lista o una expresin cuyo valor sea una lista y devuelve el primer elemento de dicha lista. Como LISP siempre interpreta una lista como una llamada a una funcin, necesitamos una manera de pasar una lista a CAR sin que LISP trate de procesarla como llamada a funcin. QUOTE

Con este objetivo se suministra la funcin QUOTE . Una lista dentro de una funcin QUOTE no se tratar de evaluar como llamada a una funcin. La llamada a la funcin QUOTE se puede abreviar utilizando el signo apstrofe < >. Funciones CDR y NTH:
CDR CDR recibe tambin una lista y devuelve el resto de la lista despus de eliminar el primer elemento (CAR lista). Por lo tanto puede contemplarse como la funcin complementaria de CAR. Una manera de interpretar una lista en LISP es como la conjuncin de un CAR y un CDR. Se podr acceder a cualquier trmino de una lista mediante los anidamientos apropiados de CAR y CDR.

(CAR lista) ;primer trmino (CAR (CDR lista)) ;segundo trmino (CAR (CDR (CDR lista))) ;tercer trmino

y as sucesivamente... Para simplificar las expresiones se permite crear nombres compuestos para anidamientos de CAR y CDR de la siguiente manera:

comenzando por una primera letra C una letra A por cada CAR o una D por cada CDR terminando con una letra R as (CAR (CDR (CDR lista))) sera lo mismo que (CADDR lista). De esta manera podemos construir hasta 28 funciones distintas para acceso a listas. Segn Johnson* estas 28 concatenaciones se pueden dividir en cuatro grupos, tomando como base la profundidad a que pueden acceder en listas anidadas en varios niveles.

Funciones de acceso al nivel superior:

Funciones de acceso al segundo nivel de anidamiento:

Funciones de acceso al tercer nivel de anidamiento:

Funciones de acceso al cuarto nivel de anidamiento:

Por supuesto, que estas funciones pueden a su vez combinarse para acceder a niveles an ms profundos de anidacin.
NTH NTH permite simplificar estas expresiones para listas muy largas: (nth n lista)

Donde el argumento n es el nmero del elemento que debe devolverse (cero es el primer elemento). Si n es mayor que el nmero de elemento mayor de la lista, NTH devuelve nil . EJEMPLOS:

De lo antes expuesto resultara:


_$ (car '(a b c)) ;Caso de una lista normal A _$ (cdr '(a b c)) (B C) _$ (cddr '(a b c)) (D) _$ (cdddr '(a b c)) ;el ltimo objeto es una lista vaca nil _$ (car '(a b . c)) ;Caso en que la lista termina en un par punteado A _$ (cdr '(a b . c)) (B . C) _$ (cddr '(a b . c)) C ;el ltimo objeto de la lista no es un CONS _$ (cdddr '(a b . c)) ;lo que provoca un error ; error: bad argument type: consp C _1$

* Johnson, Nelson. AutoCAD: Manual de Referencia. Osborne/McGraw-Hill, Madrid, 1990. ISBN 84-7615-451-8 FUNCIONES DE CONSTRUCCIN DE LISTAS

La funcin CONS
CONS es el constructor de lista bsico. Construye listas insertando elementos en listas existentes (incluso vacas). El nuevo elemento ocupa el primer lugar de la lista (CAR lista). (cons nuevo_elemento lista)

El nuevo_elemento puede ser un tomo o una lista. La funcin CONS tambin acepta un tomo en lugar del argumento lista, en cuyo caso construye una estructura denominada par punteado. El CDR de un par punteado es el segundo trmino ya extrado de la lista, es decir, sin los parntesis. Ejemplo: (cons 'a 'b) devuelve (A . B) y (cdr '(a . b)) devuelve B. Debe tenerse en cuenta que CONS, al igual que casi todas las funciones LISP es una funcin no destructiva, es decir que no altera los argumentos que recibe. As que para conservar la lista con el nuevo primer elemento, ser necesario utilizar SETQ. La funcin ms general para incorporar nuevos elementos a una lista sera entonces:
(setq nombre_lista (cons nuevo_elemento nombre_lista))

donde nombre_lista sera el smbolo asociado al objeto lista. la funcin opera aunque nombre_lista no hubiera sido previamente asociado a una lista, pues no debemos olvidar que un smbolo no asociado se evala como NIL, que es, a su vez, equivalente a una lista vaca. Ejemplo:
_$ (A _$ (A _$ (A (cons 'a 'b) . B) (cons 'a (cons 'b (cons 'c '()))) B C) (cons 'a '(b c d)) B C D)

Funciones de ejemplo usando CONS/CAR/CDR


La funcin LIST
(list expr ...) LIST Recupera cualquier nmero de expresiones y las combina en una lista. Admite tanto tomos como listas. Si uno de los agumentos es una lista vaca NIL aparecer como uno de los trminos de la lista. Ejemplo: _$ (list 3 4 'a (car '(b . c)) (+ 6 -2))

(3 4 A B 4) _$ (list (list 'a 'b) (list 'c 'd 'e)) ((A B) (C D E))

La funcin APPEND
(append lista lista ...) APPEND Se utiliza para combinar listas. Elimina el primer nivel de anidacin de cada una de

las listas que recibe para combinar todas en una misma lista. Si una de las listas que recibe est vaca esta lista no aparecer en la lista resultante. Ejemplo:
_$ (append '(a b c) '(d e f) '() '(g)) (A B C D E F G)

Una muestra de la utilizacin de APPEND para eliminar las sublistas vacas:


_$ (apply 'append '(("M") ("a") nil ("r") ("i") nil)) ("M" "a" "r" "i")

OTRAS FUNCIONES PARA TRATAMIENTO DE LISTAS

REVERSE devuelve una lista con sus elementos invertidos (reverse lista)

Opera nicamente sobre el primer nivel de anidacin. Las listas anidadas a otros niveles no son afectadas. Suele utilizarse para volver a su orden original los objetos en listas construidas mediante CONS.
_$ (reverse '("M" "a" "d" "r" "i" "d")) ("d" "i" "r" "d" "a" "M") LENGTH devuelve un nmero entero que indica el nmero de elementos de una lista (length lista)

Slo cuenta elementos en el primer nivel de anidacin. No se consideran los elementos incluidos en sub-listas.
_$ (length '((0 . "CIRCLE")(8 . "0")(10 242.426 157.686 0.0)(40 . 27.7503))) 4 ASSOC

(assoc elemento lista_asoc)

Busca una lista de asociaciones de un elemento y devuelve la entrada asociada de la lista


_$ (assoc 10 '((0 . "CIRCLE")(8 . "0")(10 242.426 157.686 0.0)(40 . 27.7503))) (10 242.426 157.686 0.0) SUBST (subst elemento_nuevo elemento_antiguo lista)

Busca un elemento antiguo en una lista y devuelve una copia de sta con un elemento nuevo en lugar de cada aparicin del elemento antiguo.
_$ (subst nil "d" '("M" "a" "d" "r" "i" "d")) ("M" "a" nil "r" "i" nil) _$

FUNCIONES BSICAS DE TRATAMIENTO DE CADENAS

Las funciones bsicas de tratamiento de cadenas aqu expuestas son las incluidas con AutoLISP nativo. A ellas se unen una serie de funciones adicionales suministradas con Visual LISP y los API especficos de las aplicaciones soportadas sobre AutoCAD como AutoCAD MAP.
ASCII

Devuelve el cdigo ASCII (un nmero entero) del primer carcter de una cadena
_$ (ascii "Madrid") 77 CHR

Devuelve el carcter que corresponde al cdigo ASCII (un nmero entero) que se ler pasa como argumento
_$ (chr 77) "M" STRCAT (strcat cadena1 [cadena2] ...)

Devuelve una cadena que es la concatenacin de varias cadenas


_$ (strcat (chr 77) "adrid") "Madrid" STRLEN (strlen [cadena] ...)

Devuelve un nmero entero que indica la cantidad de caracteres de una cadena


_$ (strlen "Madrid") 6 SUBSTR

(substr cadena inicio [longitud])

Devuelve una subcadena de una cadena


_$ (substr "Madrid" 3 2) "dr" STRCASE (strcase cadena [cul])

Devuelve todos los caracteres alfabticos de una cadena en maysculas o minsculas


_$ (strcase "Madrid") "MADRID" _$ (strcase "Madrid" T) "madrid" WCMATCH (wcmatch cadena patrn)

Realiza bsquedas con patrones de comodines en una cadena


_$ (wcmatch "Madrid" "?a?r*") T _$ (wcmatch "Madrid" "?d?r*") nil READ (read [cadena])

Devuelve el primer tomo o la primera lista contenida en una cadena


_$ (read "Madrid es una ciudad") MADRID _$ (read (strcat "(" "Madrid es una ciudad" ")")) (MADRID ES UNA CIUDAD)

FUNCIONES VISUAL LISP DE TRATAMIENTO DE CADENAS

(vl-prin1-to-string object) Devuelve la representacin como cadena de cualquier objeto LISP tal como si fuera la salida de la funcin PRIN1
_$ (setq file_id (open "test.tmp" "w")) #<file "test.tmp"> _$ (vl-prin1-to-string file_id) "#<file \"test.tmp\">"

(vl-princ-to-string object) Devuelve la representacin como cadena de cualquier objeto LISP tal como si fuera la salida de la funcin PRINC
_$ (setq file_id (open "test.tmp" "w")) #<file "test.tmp"> _$ (vl-princ-to-string file_id) "#<file test.tmp>"

(vl-string->list string) Convierte una cadena en una lista de cdigos de carcter numricos ASCII
_$ (vl-string->list "Madrid") (77 97 100 114 105 100)

(vl-string-elt string position) Devuelve la representacin ASCII del carcter situado en la posicin especificada en una cadena. El primer carcter ocupa la posicin cero
_$ (vl-string-elt "Madrid" 0) 77

_$ (chr 77) "M" _$

(vl-string-left-trim character-set string) Quita los caracteres especificados del inicio de una cadena
_$ (vl-string-left-trim "PRE" "PREFIJO") "FIJO"

(vl-string-mismatch cad1 cad2 [pos1 pos2 ignorar-caja]) Devuelve la longitud del prefijo comn ms largo para dos cadenas (cad1 cad2), comenzando en las posiciones que se especifican (pos1 pos2) teniendo en cuenta o no la diferencia entre maysculas y minsculas (ignorar-caja)
_$ 0 _$ 3 _$ 3 _$ 1 _$ 3 (vl-string-mismatch "vl-fun" "avl-var") (vl-string-mismatch "vl-fun" "avl-var" 0 1) (vl-string-mismatch "VL-FUN" "VL-VAR") (vl-string-mismatch "VL-FUN" "Vl-vAR") (vl-string-mismatch "VL-FUN" "Vl-vAR" 0 0 T)

(vl-string-position code-car cad [pos-inic [desde-final]]) Busca el carcter con el cdigo ASCII especificado en una cadena
_$ (vl-string-position 100 "Madrid") 2 _$ (vl-string-position 100 "Madrid" nil T) 5 ;a partir de la derecha se encuentra la ltima 'd'

(vl-string-right-trim conj-caracteres cadena) Quita los caracteres especificados del final de una cadena
_$ (vl-string-right-trim "FIJO" "PREFIJO") "PRE"

(vl-string-search patron cadena [pos-inicial]) Busca el patrn especificado dentro de una cadena
_$ (vl-string-search "dr" "Madrid") 2

(vl-string-subst nueva-cad patron cadena [pos-inicial]) Sustituye una subcadena (patron) por otra (nueva-cad) dentro de una cadena dada, a partir de la posicin (pos-inicial) especificada
_$ (vl-string-subst "leyenda" "cadena" "Una cadena sustituida") "Una leyenda sustituida" _$ (vl-string-subst "esta" "cadena" "Una cadena u otra cadena a sustituir" 0) "Una esta u otra cadena a sustituir" _$ (vl-string-subst "esta" "cadena" "Una cadena u otra cadena a sustituir" 10) "Una cadena u otra esta a sustituir"

(vl-string-translate conj-origen conj-dest cad) Reemplaza caracteres en una cadena con un conjunto especificado de caracteres
_$ "1 _$ "A (vl-string-translate "abcABC" "123123" "A = a, B = b, C = C") = 1, 2 = 2, 3 = 3" (vl-string-translate "abc" "123" "A = a, B = b, C = C") = 1, B = 2, C = C"

(vl-string-trim conj-caract cadena)

Quita los caracteres especificados del inicio y del final de una cadena
_$ (vl-string-trim "Ser" "Ser o no Ser") " o no "

FORMAS ESPECIALES

Algunas funciones LISP se consideran como Formas Especiales porque evalan los argumentos recibidos de una manera diferente que la mayora de las funciones llamadas desde Visual LISP. Una funcin tpica evala todos los argumentos que se le pasan antes de actuar sobre ellos. Las Formas Especiales o no evalan todos sus argumentos, o slo evalan algunos argumentos bajo determinadas condiciones. Por ejemplo, defun se considera una Forma Especial, ya que tiene como resultado el definir una nueva funcin de usuario a partir de los argumentos que recibe, sin evaluar los mismos. Las siguientes funciones AutoLISP y Visual LISP se incluyen en la categora de Formas Especiales:
AND COMMAND COND DEFUN DEFUN-Q FOREACH FUNCTION IF LAMBDA OR PROGN QUOTE REPEAT SETQ TRACE UNTRACE VLAX-FOR WHILE

FUNCIONES DEFINIDAS POR EL USUARIO

Un programa grande suele dividirse en una serie de pequeas formas o funciones de usuario ms fciles de implementar y depurar. Las mismas se componen a partir de llamadas a las funciones primitivas. Estas llamadas tendrn la forma de listas que podrn anidarse unas dentro de otras de acuerdo a lo que requiera la complejidad de la manipulacin que quiera realizarse de los datos aportados como argumentos. Para la definicin de funciones de usuario normalmente utilizaremos la forma especial DEFUN. Otra manera de representar funciones de usuario son las expresiones LAMBDA. El estudio de su relacin con DEFUN contribuir a una mejor comprensin del proceso. La carga de las funciones de usuario guardadas en ficheros se realiza mediante la funcin LOAD. Un fichero en que se guarda un programa LISP contiene las distintas formas o funciones de usuario, una a continuacin de la otra, terminando por la funcin que debe invocarse para iniciar la ejecucin del programa. Esto se debe a que la funcin LOAD imprimir en pantalla el nombre de la ltima forma evaluada. El nombre de esta funcin inicial se suele comenzar con los caracteres "C:" lo que indica al sistema que dicha funcin de usuario debe tratarse como si fuera un comando nativo de AutoCAD, en el sentido de que pueda invocarse tecleando el nombre (sin el prefijo "C:") sin encerrarlo entre parntesis. Una funcin de este tipo no admite argumentos en su lista de parmetros, aunque s la declaracin de variables locales.

FUNCIONES DEFINIDAS POR EL USUARIO

LA PRIMITIVA DEFUN
(defun sm lista-argumentos expresin ...) DEFUN permite definir una nueva funcin de usuario con el nombre sm (el nombre de la funcin se incluye automticamente en un QUOTE). Detrs del nombre de la funcin aparece una lista de parmetros (posiblemente vaca), con los argumentos a recibir, y que puede estar seguida por una barra oblicua y los nombres de uno o ms smbolos locales (variables locales) que sern definidas para uso exclusivo de esta funcin. Esta barra oblicua debe ir separada del primer smbolo local y del ltimo argumento, si existe, por un espacio como mnimo. Si no declara ningn argumento ni variable local, se debe incluir una lista vaca tras el nombre de la funcin. Los argumentos son tratados como una especie de variables locales en el sentido de que no estarn disponibles fuera de la funcin. Los nombres de argumentos deben ser nicos dentro de la misma funcin. A continuacin de la lista de parmetros se debern incluir todas las expresiones que debern ser evaluadas al llamar a la nueva funcin de usuario. A diferencia de muchas funciones primitivas AutoLISP, las funciones definidas por el usuario no pueden tener argumentos opcionales. Una llamada a una funcin de usuario debe suministrar valores para todos los argumentos declarados. DEFUN no es una funcin normal, sino lo que se incluye entre las llamadas formas especiales, en el sentido de que sus argumentos no son evaluados. Lo sern ms tarde, al llamar a la nueva funcin, sustituyendo sus argumentos por los valores que se desea procesar. La siguiente expresin define una funcin llamada DOBLE que devuelve el doble de su argumento (nmero real o entero). _$ (defun doble (x)(* x 2)) DOBLE

As hemos creado una nueva funcin Lisp que puede llamarse desde el nivel superior o anidada en otras funciones:
_$ (doble 1) 2

Un programa Lisp usualmente incluye una coleccin de tales defuns, asemejndose en ello a un fichero de definiciones de procedimientos en lenguajes tales como C o Pascal. Pero, segn puntualiza Graham, "algo muy diferente est sucediendo aqu. Las funciones Lisp son objetos por s mismas. Lo que realmente hace DEFUN es construir una funcin y guardarla bajo el nombre que aparece como primer argumento." Paul Graham, On Lisp, pg. 10

Podemos acceder a la funcin asociada al smbolo DOBLE utilizando la funcin Visual LISP vl-symbol-value:
_$ (vl-symbol-value 'DOBLE) #<USUBR @045677ac DOBLE>

En versiones anteriores de AutoLISP la funcin creada con defun era una lista:
Command: (defun doble (x) (* x 2)) DOBLE Command: !doble ((X) (* X 2)) Command: (car doble) (X) Command: (cdr doble) ((* X 2))

En Visual LISP la funcin de usuario creada con defun es una funcin compilada que contiene instrucciones en lenguaje de mquina, por lo tanto en Autocad 2000 obtendremos:
Command: (defun doble (x) (* x 2)) DOBLE Command: !doble #<SUBR @01d5ba28 DOBLE> Command: (car doble) ; error: bad argument type: consp #<SUBR @01d5ba28 DOBLE> Command: (cdr doble) ; error: bad argument type: consp #<SUBR @01d5ba28 DOBLE>

REALES A ENTEROS: TRUCAMIENTO O REDONDEO

Como explicbamos en un captulo anterior, la funcin FIX convierte los nmeros reales a enteros a base de un simple truncamiento de la parte no entera. Este procedimiento no es satisfactorio en muchos casos donde se requiere un grado mayor de precisin. As obtendremos el mismo resultado para (fix 6.1) que para (fix 6.9), en ambos casos simplemente 6. Una conversin ms precisa se obtiene utilizando para la conversin la funcin RTOS que adems de convertir el nmero real a binario, es capaz, cuando se especifica cero como nmero de decimales, de realizar unna aproximacin al entero ms cercano. As (rtos 6.1 2 0) devuelve 6 mientras que (rtos 6.9 2 0) devuelve 7. Podemos definir una funcin ROUND de redondeo como sigue:
(defun round (num) (read (rtos num 2 0)) ) ;_ fin de defun

Hasta ah bien, pero para 6.5 esta funcin realizara la aproximacin al entero mayor, que en este caso sera 7. Con lo que no se cumplira la definicin propuesta para la norma de Common LISP, donde se especifica que: si el nmero se encuentra exactamente a mitad de camino entre dos enteros (es decir, en la forma entero + 0.5), entonces se redondea al entero par ms prximo (divisible por 2). (Steele, CLTL2) Para cumplir esta especificacin deberemos desarrollar una funcin ms compleja, que llamaremos CL-ROUND, siguiendo la norma citada. Esta funcin requerir un predicado tambn norma de Common LISP, pero ausente an de AutoLISP-Visual LISP. El predicado EVENP que comprueba si un nmero entero es par.
(defun evenp (num) (zerop (rem num 2)) ) ;_ fin de defun

La nueva funcin cl-round recibe el nmero del cual comprueba:


si una vez redondeado el resultado NO es par (not (evenp (setq tmp (rnd
num))))

si la parte decimal (valor absoluto) es igual a 0.5 (=(abs (rem num 1)) 0.5)

En caso de que ambas condiciones sean ciertas:


si el nmero es negativo, se le suma 1 si el nmero es positivo se le resta 1

(defun cl-round (num / tmp) (if (and (not (evenp (setq tmp (rnd num)))) (= (abs (rem num 1)) 0.5) ) (if (minusp tmp)(setq tmp (1+ tmp))(setq tmp (1- tmp))) ) ;_ fin de if tmp ) ;_ fin de defun

NUEVAS FUNCIONES TRIGONOMTRICAS

Las funciones trigonomtricas que ofrece AutoLISP como primitivas se reducen a tres: SENO, COSENO y ARCOTANGENTE. Muchas operaciones geomtricas requerirn, sin embargo, recurrir a otros operadores trigonomtricos. Esto puede servir de ejemplo a la posibilidad de desarrollar nuevas funciones utilitaria dentro de LISP.

Funciones Trigonomtricas primitivas de AutoLISP: SIN


(sin ang)

Devuelve el seno de un ngulo expresado en radianes. COS


(cos ang)

Devuelve el coseno de un ngulo expresado en radianes. ATAN


(atan num1 [num2])

Devuelve el arcotangente de num1, en radianes, si se le suministra solamente num1. Si se suministraran ambos argumentos num1 y num2, ATAN devuelve el arcotangente de num1/num2, en radianes. Si num2 fuera cero, devolver un ngulo de ms o menos 1.570796 radianes (+90 grados o 90 grados), segn el signo de num1. El rango de ngulos devuelto es -pi/2 a +pi/2 radianes. Funciones de conversin:

Puesto que AutoLISP trabaja con radianes mientras que AutoCAD lo hace por defecto en ngulos sexagesimales, sera necesario tener a mano siempre las funciones de conversin grados-radianes. Conversin entre grados y redianes:
;;;recibe ang en radianes y lo devuelve en grados (defun grados (rad) (* (/ rad pi) 180.0) );_fin de defun ;;;recibe ang en grados y lo devuelve en radianes (defun radianes (grd) (* (/ grd 180.0) pi) );_fin de defun

Las funciones trigonomtricas no incluidas con AutoLISP: Las siguientes funciones trigonomtricas han sido publicadas por Jon Fleming. Autor: Jon Fleming <jonf@fleming-group.com>, Mayo 20 1997. fuente: Grupo de Noticias autodesk.autocad.customization Obsrvese que:

Algunas de las funciones (ASEC -arcosecante- y ACSC -arcocosecante-) utilizan otras funciones definidas en este mismo archivo.

Ninguna de estas funciones comprueban la validez de los argumentos que reciben. Esta comprobacin debe hacerse en los programas que las invocan. Las funciones se han desarrollado evitando la posibilidad de un error de divisin por cero. Se ha determinado experimentalmente que 9.7E307 es el nmero mayor que puede ser generado en AutoLISP (R14). Visual LISP en Autocad 2000 (R15) y 2002 al producirse un nmero en exceso del mayor valor real admitido, en lugar de generar un error devuelve el smbolo 1.#INF, que puede asignarse a una variable que sea devuelta en caso de divisin por cero: Podemos definir una funcin que nos devuelva este smbolo. Para ello contamos con el predicado no documentado VL-INFP que detecta cuando un nmero rebasa el mximo valor admitido para los nmeros reales:

(defun infinito ( ) (setq *INF* 2.0) (while (not (VL-INFP *INF*)) (setq *MAX-REAL* *INF* *INF* (expt *INF* 2)))) _$ (infinito) 1.#INF _$ *MAX-REAL* 1.34078e+154 _$ *inf* 1.#INF

as tendremos que cualquier nmero dividido entre *INF* devolver cero y tendremos definida una variable global *MAX-REAL* que nos permitir comprobar si un valor se aproxima al mximo valor real admitido por el sistema:
(/ 254.98 *INF*) 0.0

TAN acepta cualquier ngulo en radianes y devuelve la tangente en un rango de 9.7E307+epsilon a 9.7E307, ambos inclusive. Se analiza la posibilidad de que el coseno del valor pasado sea igual a cero, para evitar un error de divisin por cero.
(defun tan (z / cosz) (if (zerop (setq cosz (cos z))) *INF* (/ (sin z) cosz) ) ;_fin de if ) ;_fin de defun

SEC Acepta cualquier ngulo en radianes, devolviendo la secante en los rangos de 9.7E307+epsilon a -1.0, ambos inclusive y de 1.0 a 9.7E307, ambos inclusive
(defun sec (z / cosz) (if (zerop (setq cosz (cos z))) *INF*

(/ 1.0 cosz) ) ;_fin de if ) ;_fin de defun

CSC Acepta cualquier ngulo en radianes, devolviendo la cosecante en los rangos de -9.7E307+epsilon a -1.0, ambos inclusive y de 1.0 a 9.7E307, ambos inclusive
(defun csc (z / sinz) (if (zerop (setq sinz (sin z))) *INF* (/ 1.0 sinz) ) )

ASIN (seno inverso) acepta un argumento en el rango -1.0 a 1.0 ambos inclusive, y devuelve un ngulo en radianes en el rango de (-pi/2) a (pi/2) ambos inclusive.
(defun asin (z /) (atan z (sqrt (- 1.0 (* z z)))) ) ;_fin de defun

ACOS (coseno inverso) acepta un argumento en el rango -1.0 a 1.0 ambos inclusive, y devuelve un ngulo en radianes en el rango de pi a 0 ambos inclusive
(defun acos (z /) (atan (sqrt (- 1.0 (* z z))) z) ) ;_fin de defun

ASEC (secante inversa) acepta un argumento en uno de dos rangos: menos infinito a -1 ambos inclusive o 1 a infinito, ambos inclusive, y devuelve un ngulo en radianes en el rango de pi a 0, ambos inclusive (excepto EXACTAMENTE pi/2 que nunca ser devuelto en un ordenador con precisin numrica finita)
(defun asec (z /) (acos (/ 1.0 z)) ) ;_fin de defun

ACSC (cosecante inversa) acepta un argumento en uno de dos rangos: menos infinito a -1, ambos inclusive o 1 a infinito, ambos inclusive, y devuelve un ngulo en radians en el

rango -pi/2 a pi/2, ambos inclusive (excepto EXACTAMENTE 0.0 que nunca ser devuelto en un ordenador con precisin numrica finita)
(defun acsc (z /) (asin (/ 1.0 z)) ) ;_fin de defun

ACOT (cotangente inversa) acepta un argumento en el rango de menos infinito a ms infinito, ambos inclusive y devuelve un ngulo en radianes en el rango de pi a 0, ambos inclusive.
(defun acot (z /) (- (/ pi 2.0) (atan z)) ) ;_fin de defun

jrf
EXPRESIONES LAMBDA

La independencia de ambos procesos, la construccin de la funcin y el asignarle un nombre se comprende claramente si analizamos la funcin LAMBDA.
(lambda argumentos expr ...)

Mediante ella, podemos referirnos a una funcin literalmente de la misma manera que lo haramos con un nmero o una cadena de texto. Un nmero se representa a s mismo. Una cadena se representa mediante una serie de caracteres rodeados de comillas dobles. Para representar una funcin se utilizan expresiones-lambda. Una expresin-lambda es una lista de tres componentes:
1. El smbolo lambda 2. Una lista de parmetros 3. Una serie de expresiones que se evalan al ejecutar la funcin.

Una funcin equivalente a doble es la referida por la siguente expresin-lambda:


_$ (lambda (x)(* x 2)) #<USUBR @0344f0dc -lambda->

La forma especial setq puede servir a su vez para asignar esta funcin a un smbolo:
_$ (setq doble (lambda (x)(* x 2))) #<USUBR @0344f104 -lambda-> _$ (doble 4) 8

que podemos ejecutar perfectamente como funcin de usuario. LAMBDA suele usarse conjuntamente con APPLY y/o MAPCAR para ejecutar una funcin sobre una lista.
FUNCTION

El operador FUNCTION le indica al compilador Visual LISP que enlace y optimice un argumento tal como si fuera una funcin primitiva.
(function smbolo | expresin-lambda) FUNCTION es idntico a la funcin QUOTE excepto en que fuerza la compilacin del argumento de la misma manera que lo hara DEFUN. Si inclumos las funciones internas en

expresiones del tipo (function (lambda <parmetros> <expresiones> ...) en lugar de (quote (lambda <parmetros> <expresiones> ...)) '(lambda <parmetros> <expresiones> ...), nos aseguraremos que el cdigo sea enlazado (linked) y optimizado en tiempo de compilacin (como una USUBR annima) en lugar de ser simplemente evaluado en tiempo de ejecucin. Las expresiones-LAMBDA compiladas contendrn informacin para su depuracin al ser cargadas en el IDE Visual LISP. Admite un argumento smbolo que nombra una funcin y una expresin-lambda de la forma: (LAMBDA argumentos
{expresin-S}*)

Ejemplos: El compilador Visual LISP no puede optimizar la expresin lambda precedida de apstrofe (QUOTE) en la siguiente expresin:
(mapcar '(lambda (x) (* x x)) '(1 2 3))

Pero una vez incluida la expresin dentro de FUNCTION el compilador podr optimizar la expresin lambda:
(mapcar (function (lambda (x) (* x x))) '(1 2 3))

Lo que redundar en un incremento de la velocidad de ejecucin al generarse el correspondiente cdigo optimizado en lenguaje de mquina. LOAD

Una de las virtudes de LISP es la posibilidad de construir, a partir de las primitivas aportadas por el lenguaje, las funciones necesarias para el desarrollo de una aplicacin

especfica. Estas funciones operan de manera idntica a las funciones primitivas. Si bien podemos evaluar las funciones LISP desde la Consola de Visual LISP o desde la propia lnea de comandos de AutoCAD, cuando se trata de funciones ms extensas lo usual es escribirlas en un fichero de texto (con extensin LSP) y cargarlas mediante la funcin LOAD. El IDE (Entorno de Desarrollo Integrado) Visual LISP incluye un editor de programacin que facilita la redaccin de programas lisp mediante una serie de ayudas, tales como el texto coloreado segn la sintaxis y la identacin y formateo automtico del texto. Trabajando en este IDE se pueden cargar las funciones o "formas" contenidas en el archivo fuente en desarrollo mediante el correspondiente botn de la barra de herramientas u opciones de men. La instruccin LISP para cargar en memoria un programa LISP contenido en un fichero es LOAD:

(load nombre_archivo [si_falla])


La funcin LOAD puede ser usada desde dentro de otra funcin LISP e incluso de manera recursiva (en el fichero que se est cargando). nombre_archivo debe ser una cadena que representa el nombre del fichero. Si no se incluye la extensin LOAD comprobar la existencia de un fichero con ese nombre y alguna de las siguientes extensiones en el orden que se especifica a continuacin:

.vlx .fas .lsp

Se cargar el primer fichero encontrado. Si load no se ejecuta de forma correcta, devuelve el valor del argumento si_falla. Sin embargo, si si_falla no se especifica, un fallo de load genera un error de Visual LISP. Si la operacin es correcta, load devuelve el valor de la ltima expresin del archivo. El nombre_archivo puede incluir un prefijo de directorio, como en "/ funcin/prueba1". En los sistemas DOS tambin se admite una letra de unidad. Una barra oblicua (/) o dos contrabarras (\\ ) son delimitadores de directorio vlidos. Si no incluye un prefijo de directorio en la cadena nombre_archivo, load busca el archivo especificado en el camino de la biblioteca AutoCAD. Si lo encuentra en cualquier parte de este camino, load lo carga. Si el argumento si_falla es una funcin vlida de Visual LISP, se calcula. En la mayora de los casos, el argumento si_falla debera ser una cadena o un tomo. Esto permite que una aplicacin Visual LISP que llame a load tome una accin alternativa cuando se produce un fallo. ESTRUCTURAS DE CONTROL Los predicados son funciones que devuelven respuestas lgicas (cierto-falso), mientras que las estructuras de control controlan la ejecucin del programa y permiten mltiples ramificaciones. PREDICADOS

Permiten comprobar caractersticas relacionadas con el tipo de dato con que se est operando en cada momento. Devuelve T (cierto) si la condicin se cumple y nil (falso) en caso contrario.

PREDICADOS GENERALES: Suelen distinguirse por terminar el nombre de la funcin en la letra P que significa predicado. Se utiliza la siguiente regla para decidir si la P est precedida por un guin: si el nombre del predicado se forma aadiendo la P a un nombre existente, tal como el nombre de un tipo de dato, se aade un guin slo en el caso de que el nombre original incluya alguno (BOUNDP, LISTP, NUMBERP sin guin VLFILE-DIRECTORY-P, VLAX-ERASED-P con guin). Los predicados que fueron introducidos con Visual LISP se conocen por los prefijos que se adicionan VL-, VLAX- o VLR- (VL-CONSP, VLAX-PROPERTY-AVAILABLEP, VLR-ADDED-P). En casos como VL-CONSP se hace una excepcin a la regla anterior, puesto que en realidad se est renombrando un predicado standard de Common LISP. PREDICADOS SOBRE TOMOS Y LISTAS PREDICADOS ARITMTICOS: Corresponden a las funciones de comparacin (mayor que, menor que, igual a...). OTROS PREDICADOS DEFINIDOS POR EL USUARIO: muestra de la extensibilidad de LISP.

OPERADORES LGICOS Corresponden a las operaciones Booleanas bsicas. LISP suministra tres operadores sobre valores Booleanos: and, or, y not. De ellos, and y or son tambin en cierto modo estructuras de control ya que sus argumentos son evaluados condicionalmente. Permiten agrupar las condiciones de prueba, casi siempre a partir de la utilizacin de predicados que se utilizan dentro de las estructuras de programacin descritas ms adelante.La funcin not tiene un slo argumento que analizar, y es por ello una funcin simple. ESTRUCTURAS CONDICIONALES Visual LISP provee las dos estructuras de control tradicionales de LISP. La estructura condicional de ms tradicin en LISP es COND. Sin embargo IF resulta ms simple y es directamente comparable a las estructuras condicionales de otros lenguajes de programacin. PREDICADOS GENERALES:

TOMOS O LISTAS o TOMOS SIMBLICOS o TOMOS NUMRICOS LISTAS VACAS O CONSES IGUALDAD O IDENTIDAD

TOMOS O LISTAS:

ATOM Sabemos que dentro de las expresiones LISP se distinguen los tomos y las listas. El predicado ATOM verifica si un elemento determinado es un tomo
(atom elemento) Devuelve nil si elemento es una lista y devuelve T en caso contrario. Debe

tenerse cuidado, si se trata de un tomo simblico, en tener claro si lo que se quiere evaluar es el sbolo o su contenido. Si no est precedido de QUOTE <'>, lo que se evala es el valor asociado:
_$ (atom T _$ (atom T _$ (setq (A B C) _$ (atom nil _$ (atom T a) 'a) a '(a b c)) a) 'a)

LISTP Comprueba si un elemento es una lista (listp elemento) Devuelve T si elemento es una lista y devuelve nil en caso contrario. Obsrvese que como NIL es una lista vaca, (listp nil) devolver T. Es decir, que todo tomo simblico no asociado a un valor, devover T tanto para ATOM como para LISTP:
_$ !b nil _$ (atom b) T _$ (listp b) T _$ (listp 'b) nil

TOMOS SIMBLICOS:

VL-SYMBOLP Identifica si un objeto especificado es o no un smbolo.


(vl-symbolp objeto)

Devuelve T si el objeto es un smbolo y nil si se trata de una constante (nmero o cadena) o una lista. Este predicado ha sido incorporado por Visual LISP
_$ (vl-symbolp T _$ (vl-symbolp nil _$ (vl-symbolp nil _$ (vl-symbolp nil 'a) 15) "abc") '(a b c))

BOUNDP Cuando se trata de un tomo simblico, puede ser necesario determinar si tiene asociado un valor. BOUNDP verifica la existencia de dicha asociacin.
(boundp sm)

Devuelve T si sm tiene un valor asociado. Si no hay ningn valor asociado a sm (o se ha asociado a nil), boundp devuelve nil. Si sm es un smbolo no definido, se crea y se asocia a nil de forma automtica.

NUMRICOS:

NUMBERP Los tomos no simblicos o constantes pueden ser nmeros o cadenas. NUMBERP comprueba si el objeto es un nmero (real o entero)
(numberp elemento)

Devuelve T si elemento es un valor numrico y devuelve nil en caso contrario. El predicado complementario STRINGP, que comprobara si se trata de una cadena no est definido en Visual LISP, aunque se puede encontrar entre los mensajes de error a la hora de depurar un programa. En el ejemplo que sigue el mensaje

"STRINGP 2" significara que se ha recibido un valor numrico (2) en lugar del

argumento esperado del tipo cadena.


_$ (strcat 2 "b") ; error: bad argument type: stringp 2

MINUSP Tratndose de valores numricos en ocasiones se deber comprobar si son negativos. MINUSP realiza dicha comprobacin.
(minusp nmero)

Devuelve T si nmero es negativo y nil en caso contrario. Si el argumento no es numrico se recibir un mensaje de error. ZEROP Igual que en el caso anterior, cuando se trata de valores numricos ZEROP permite comprobar si un elemento se evala como cero
(zerop nmero)

Devuelve T si nmero es cero y nil en caso contrario. LISTAS VACAS O CONSES:

En LISP el valor asociado al smbolo NIL (condicin de falso) es la lista vaca <'()>. Cualquier smbolo que evale como NIL, devolver T (cierto) al pasarlo al predicado LISTP. Para comprobar que se trata efectivamente de una lista, pero que dicha lista contiene algo (aunque fuera NIL) en las versiones anteriores de AutoLISP era necesario utilizar adems de LISTP otros predicados tales como BOUNDP o NULL. NULL Comprueba si un elemento est definido como nil (null elemento) Devuelve T si elemento est asociado a nil y devuelve nil en caso contrario. Puede emplearse para probar si se ha alcanzado el fin de una lista en sustitucin del predicado ENDP de Common Lisp que falta en Visual LISP
_$ (null (caddr '(a b))) T

VL-CONSP La situacin descrita en el prrafo anterior se resuelve empleando en su lugar el predicado CONSP (vl-consp para Visual LISP), que comprueba si el elemento analizado evala como una lista no nula
(vl-consp elem-lista)

Devuelve T, si elem-lista es una lista y no est vaca, de lo contrario devuelve nil. El trmino CONSP se deriva de la funcin bsica de construccin de listas, que es la funcin CONS. Una lista no vaca es el resultado de aplicar, al menos una vez la funcin CONS. Este predicado ha sido incorporado por Visual LISP
_$ (vl-consp a) nil _$ (setq a (cons 1 a)) (1) _$ (vl-consp a) T

El valor contenido en la lista puede incluso ser una lista vaca:


_$ (setq b (cons nil b)) (nil) _$ (vl-consp b) T _$ (vl-consp '(())) ;equivalente a la lnea anterior T

PERTENENCIA A UNA LISTA:

MEMBER Es un tipo particular de predicado, que comprueba si un tomo pertenece a una lista dada.
(member expr lista)

Si expr no aparece en la lista, member devuelve NIL. En caso de encontrarlo, devuelve el resto de la lista, desde el primer caso de la expresin encontrada. Lo devuelto por MEMBER acta como T (cierto) ya que cualquier valor no nulo actuar como la negacin de NIL (not NIL), es decir, cierto. Debe tenerse cuidado en el caso de los tomos simblicos de pasar el nombre del smbolo precedido de QUOTE <'>.
_$ (member a '(c d 2 4 a '(a b) "a" 3.0 j)) nil _$ (member 'a '(c d 2 4 a '(a b) "a" 3.0 j)) (A (QUOTE (A B)) "a" 3.0 J)

IGUALDAD O IDENTIDAD

Dos expresiones pueden considerarse iguales sin necesidad de que sean idnticas. Los predicados EQUAL y EQ permiten comprobar estas situaciones.

EQUAL Determina si dos expresiones son iguales


(equal expr1 expr2 [aproximacin]) La funcin equal determina si expr1 y expr2 se evalan igual. Cuando se

comparan dos nmeros reales (o dos listas de nmeros reales, como en el caso de los puntos), los dos nmeros idnticos pueden presentar ligeras diferencias derivadas de los mtodos utilizados para su clculo. Para resolver esta situacin, puede utilizarse un argumento numrico optativo, aproximacin, para especificar la diferencia mxima que se puede admitir entre expr1 y expr2, para que sigan considerndose iguales. EQ Determina si dos expresiones son idnticas
(eq expr1 expr2) La funcin eq determina si expr1 y expr2 estn asociadas al mismo objeto (si apuntan a la misma direccin de memoria). Devuelve T si las dos expresiones son iguales y nil en caso contrario. _$ (M _$ (M _$ son iguales T _$ (eq a b) ;pero NO son la misma lista nil _$ (eq (cons 'a 'b) (cons 'a 'b)) nil ;cada llamada a cons crea una nueva lista _$ (eq '(a . b) '(a . b)) nil (setq a (list 'm 'n 'o)) N O) (setq b (list 'm 'n 'o)) N O) (equal a b) ;las listas representadas por a y b

En el caso de los valores constantes, equal y eq devuelven resultados similares, salvo lo explicado respecto a los nmeros reales.
_$ (setq a 8) 8 _$ (setq b (+ 5 3)) 8 _$ (eq a b) T

PREDICADOS ARITMTICOS

Todos los argumentos pueden ser nmeros o cadenas.

COMPARACIONES BSICAS:

Permiten comparar nmeros o cadenas.


> (mayor que...) Devuelve T si cada argumento es numricamente mayor que el situado detrs de l y nil en caso contrario (> cadnm [cadnm] ...) < (menor que...) Devuelve T si el primer argumento es numricamente menor o igual que el situado detrs de l y nil en caso contrario (< cadnm [cadnm] ...) =(igual que...) Devuelve T si todos los argumentos son numricamente iguales; de lo contrario, devuelve nil (=cadnm [cadnm] ...) /=(desigual a...) Equivale a (not (=cadnm [cadnm] ...)) PREDICADOS COMPUESTOS: (<=cadnm [cadnm] ...) Devuelve T si cada argumento es numricamente menor o igual que el situado detrs de l y nil en caso contrario (> cadnm [cadnm] ...) Devuelve T si cada argumento es numricamente mayor que el situado detrs de l y nil en caso contrario (>=cadnm [cadnm] ...) Devuelve T si cada argumento es numricamente mayor o igual que el situado detrs de l y nil en caso contrario

OPERADORES LGICOS

NOT

Negacin lgica. Cualquier expresin cuyo valor no sea NIL evala como falsa. En cambio, (not NIL) evala como T. Esto sucede puesto que cualquier cosa que no tenga el valor NIL (o la lista vaca) evala en LISP como T (cierto). OR Devuelve el OR lgico de una lista de expresiones (or expr...) La funcin o calcula las expresiones de izquierda a derecha en busca de una expresin distinta de nil. Si la encuentra, OR deja de realizar clculos y devuelve T. Si el valor de todas las expresiones es nil, or devuelve nil. AND Devuelve el operador lgico AND de una lista de expresiones (and expr ...) Si alguna de las expresiones da como resultado nil, se interrumpe la operacin y la funcin devuelve nil; en caso contrario, devuelve T. FUNCIONES LGICAS BINARIAS

Si un tema ha sido poco explicado en los manuales de programacin LISP para AutoCAD, al menos, en los que se puede consultar en espaol, que no son muchos, es la utilizacinde los operadores lgicos binarios. Su importancia y posibilidades de aplicacin son inversamente proporcionales a esa escasa atencin que se le dedica. Su uso permite la gestin de una multitud de parmetros de la aplicacin que estn codificados como nmeros en formato binario. Uno de estos parmetros es el de las referencias a objeto. El valor de la variable de sistema OSMODE es el equivalente decimal de un nmero binario. Al nmero binario 0000 0001 corresponde la referencia punto FINal y al nmero binario 0000 0100 corresponde la referencia CENtro. Si el valor de OSMODE fuera equivalente al nmero binario 0000 0101 eso significara que estn activas a la vez las referencias punto FINal y CENtro. Cada posicin de un nmero binario representa un BIT. Un BIT es la unidad de informacin mnima que es capaz de manejar un computador, y slo puede uno de dos valores, ACTIVADO o DESACTIVADO, que en su representacin numrica simbolizamos mediante 1 0. Por eso decimos que en la referencia punto FINal se ACTIVA el primer BIT y para la referencia CENtro se ACTIVA el tercer BIT. El valor binario 1111 1111 1111 activara todas las referencias a objeto posibles. Dicho as resulta secillo, pero las dificultades comienzan cuando tenemos en cuenta que AutoCAD espera recibir no esta representacin a base de ceros y unos, sino su equivalente en formato DECIMAL. Y el equivalente dcimal de cada BIT vendra dado por 2(n-1) dinde n sera la la posicin del bit cuyo valor decimal se desea. Expresado en trminos de una funcin LISP (expt 2 (1- n)). Las operaciones lgicas sobre nmeros binarios disponibles en Visual LISP son cuatro:

~ (NOT binario) LOGAND (AND lgico binario) LOGIOR (OR lgico binario) BOOLE (operador lgico binario de carcter general)

A estas operaciones debemos aadir la funcin LSH, desplazamiento binario, que ser la primera funcin que estudiaremos. SISTEMA BINARIO

Internamente, la mquina computadora representa los valores numricos mediante grupos de bits. agrupados en bytes. Por ejemplo, el nmero 3 se representa mediante un byte que tiene "activos" los bits primero y segundo (contando desde la derecha); 00000011. Esta sera la forma de representacin del nmero 3 en un sistema numrico de base 2, tambin conocido como BINARIO. El sistema que utilizamos normalmente es un sistema DECIMAL o de base 10. En un sistema DECIMAL, contamos desde el 0 hasta el 9 antes de aadir un nuevo dgito. El nmero 22 en un sistema decimal significa que tenemos dos conjuntos de 10s y 2 conjuntos de 1s. En un sistema BINARIO slo pueden haber dos valores para cada dgito: ya sea un 0=DESACTIVADO un 1=ACTIVADO. Para representar el nmero 22 en notacin BINARIA lo haramos como 00010110, notacin que se explica segn la siguiente tabla:
Po sici n del BIT: Va lor Binar io: Va lor Decim al: Va lores a Sumar :

1 2 8 4

6 2

3 6

1 6

Valor Resultante: 16 + 4 + 2=22

Todos los valores que corresponden a posiciones a las que se asigna el valor binario de 0 (cero) no se cuentan, ya que 0 representa DESACTIVADO. De la misma manera, los nmeros que corresponden a las posiciones con valor binario 1 se sumarn, (16 + 4 + 2=22) ya que 1 representa ACTIVADO.
Valores Decimales y sus equivalentes Binarios: VALO R DECIMAL 1 2 3 4 5 6 7 8 9 10 16 32 64 100 256 512 1000 1024

POSICI N BIT 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

VALOR BINARIO 1 10 11 100 101 110 111 1000 1001 1010 10000 100000 1000000 1100100 10000000 0 10000000 00 11111101 00 10000000

000

Bits, Bytes y Palabras... Se suelen escribir los nmeros binarios como una secuencia de grupos de cuatro bits, tambin conocidos como NIBBLES. Segn el nmero de estas agrupaciones los nmeros binarios se clasifican como:
Nm. bits 1 4 8 16 32

Unidad: Bit Nibble Byte (Octeto) Palabra Doble Palabra

Ejemplo: 1 0101 0000 0101 0000 0000 0000 0101 0000 0000 0000 0000 0000 0000 0000 0101

Los computadores personales con el sistema operativo MS DOS utilizaban palabras de 16 BITS. Los sistemas operativos actuales sobre los que corre AutoCAD 2000 utilizan Palabras de 32 BITS. Funcin LSH

Para el clculo del valor decimal de un determinado BIT sera ms adecuado, como veremos ms adelante, utilizar la funcin LSH. Sgn la explicacin de Reini Urban*: (lsh <integer> <num>) LSH quiere decir Left-SHift, en ingls desplazamiento a la izquierda. Si se interpreta el nmero entero como una matriz de bits ("bit-array") podemos interpretar LSH como el desplazamiento de la matriz n-veces a la izquierda (insertando ceros a la derecha) Ejemplo:
int: 9 = 8+1 => (1 0 1) como "bit-array" (2^3 + 2^0) (lsh 9 1) => (1 0 1 0) que es (2^4 + 2^1) = 18.

Fcil, puesto que (LSH i 1) es siempre igual a i*2 LSH con un nmero negativo es un desplazamiento a la derecha (suprimir el bit ms a la derecha). (LSH i -1) es lo mismo que i/2 ( i dividido entre 2, "divisin de enteros") De acuerdo con esto el valor decimal del primer BIT vendra dado por (lsh 1 0) equivalente a 0000 0001 y devolvera el valor decimal 1. Con un desplazamiento de dos a la izquierda obtendramos 0000 0100 que ya hemos visto que equivale a OSMODE CENtro y (lsh 1 2) devuelve el valor decimal de 4. Con LSH podemos disear la funcin utilitaria siguiente, que nos devuelve el valor decimal de cualquier BIT:
(defun bit (posicion) (lsh 1 (1- posicion)) )

De manera que (bit 1) devolvera 1, (bit 5) devolvera 16, etc. Con lo que tenemos una manera sencilla de dar el valor decimal que corresponde a la posicin de cualquier bit. Activar el bit 8 (referencia PERpendicular) significara sumar (bit 8) al valor actual de OSMODE:
(setvar "osmode" (+ (getvar "osmode")(bit 8)))

Claro que sera lo mismo


(setvar "osmode" (+ (getvar "osmode") 128))

e incluso:
(setvar "osmode" (+ (getvar "osmode") (expt 2 8)))

Pero (bit 8) resulta ms fcil de memorizar y seguramente ms claro en cuanto a la intencin del programador. Debo advertir que la cosa no es tan sencilla, pues debemos primero haber comprobado que el bit 8 no estaba ya activado. Ms adelante veremos cmo hacerlo valindonos de los operadores LOGAND y LOGIOR. Pero si continuamos incrementando los valores que pasamos a la funcin BIT, descubriremos que hay un lmite:

Como se puede ver, cuando se activa el bit 32 (en un sistema operativo de 32 bits) es decir, cuando la ltima posicin a la izquierda de la palabra toma el valor de 1, su signo pasa a negativo y un nuevo desplazamiento a la izquierda devolvera de nuevo el valor del primer bit. Esta propiedad nos permite definir una funcin para determinar la longitud de palabra del sistema operativo actual:
(defun LongPalabra ( / pos) (setq pos 0) (while (not (minusp (lsh 1 pos))) (setq pos (1+ pos)) ) (alert (strcat "Longitud de Palabra:\n\t" (itoa (1+ pos)) " Bits")) )

En AutoCAD 2000 obtendramos como resultado:

Es inportante tener esto en cuenta para comprender el funcionamiento del prximo operador a estudiar, el NOT lgico binario (~ num).

* De: Reini Urban <rurban@sbox.tu-graz.ac.at> Newsgroup: autodesk.autocad.customization Asunto: Logand, logior, lsh, etc... Fecha: Jueves, 03 Mar 1998 00:13:08 +0100 Traduccin del ingls: Reinaldo Togores Funcin ~ (NOT lgico binario)*

Esta funcin resulta especialmente incomprensible si consultamos los manuales AutoLISP habituales, incluyendo la "ayuda" que viene con el programa. Nos dirn que "esta funcin devuelve la negacin lgica de una cifra binaria, es decir, el complemento a uno". Y se nos ilustra con ejemplos como: (~ 3) devuelve -4 Si bien la explicacin es del todo correcta, a los que no poseemos conocimientos matemticos tan completos no nos aprovecha gran cosa esa explicacin. Para encontrar una respuesta ms comprensible hemos tenido que recurrir al viejo manual de Nelson Johnson** cuya traduccin al espaol fuera publicada en 1990 por McGraw-Hill. Explica Johnson que:
(~ <nmero>)

Puede que deseemos verificar un nmero para encontrar su funcin NOT bit a bit. En este caso, se invierten todos los bits. el valor devuelto por la funcin "~" ser un nmero que tenga todos los bits a 0 del argumento puestos a 1 y, viceversa, todos los bits del argumento que estaban a 1 estarn a cero. El nmero 9 en binario sera 1001, o mejor, considerando un tamao de palabra de 32 bits:
0000 0000 0000 0000 0000 0000 0000 1001

(~ 9) devolvera -10 Lo que sera igual en nmeros binarios con tamao de palabra de 32 bits a:
1111 1111 1111 1111 1111 1111 0110

El valor negativo se explica, segn lo dicho al explicar la funcin LSH, al ocupar la posicin extrema izquierda un valor 1. La posibilidad de construir este "filtro negativo" de un valor binario es extremadamente valioso para gestionar los valores guardados en trminos de posiciones de bits. Pero para la gestin de estos valores binarios nos deberemos auxiliar de otras funciones como LOGAND, LOGIOR, y BOOLE No es muy frecuente el uso de esta funcin en los programas LISP dentro de AutoCAD. Revisando los programas suministrados con la aplicacin podemos encontrar ejemplos de su uso en AI_UTILS.LSP y DDMODIFY.LSP de las versiones 13 y 14 y FORMAT.LSP de la versin 12.

* En los computadores que se utilizan en Espaa el carcter ~ (tilde) se ha suprimido para incluir en su lugar la letra . Para escribir el carcter tilde ser necesario utilizar la combinacin de teclas ALT 126, es decir, manteniendo pulsada la tecla ALT teclear 126 en el teclado numrico.

** Johnson, Nelson. AutoCAD: Manual de Referencia. Osborne/McGraw-Hill, Madrid, 1990. ISBN 84-7615-451-8 LOGAND

Para LOGAND transcribimos la explicacin de Jon Fleming * en el mismo hilo de discusin donde fu expuesta la explicacin anterior de Reini Urban:
(logand 13 22) es el AND lgico de [8 + 4 + 1] con [16 + 4 + 2] o, escribiendo los nmeros en binario, de 00001101 con 00010110.

Escribiendo los nmeros uno sobre el otro, podemos entonces escribir la respuesta en binario de inmediato, escribiendo un 1 bajo dos nmeros uno y un 0 en cualquier otro lugar:
13 = 22 = 13 y 22 = 00001101 00010110 00000100

es decir, 4 en notacin decimal. Por lo tanto, (logand 13 22) devuelve 4. El AND lgico se suele utilizar como filtro. Uno de los nmeros que definimos contendr un 1 en su representacin binaria dondequiera que deseamos que un posible 1 en un nmero desconocido pase por el filtro. Esto se debe a que un entero es un lugar muy eficiente para guardar varios valores lgicos verdadero/falso relacionados como unos y ceros en posiciones definidas en la representacin binaria de un entero. Un ejemplo perfecto lo constituye la variable de sistema OSMODE. Queremos saber si la referencia a objeto INTERSECCIN se encuentra activa? Nuestra referencia de comandos nos dice que la presencia de 32 en el valor de OSMODE indica la referencia INTERSECCIN. Como slo nos interesa la referencia INTERSECCIN, escribimos la representacin binaria de OSMODE con "x" en las posiciones que no interesa comprobar: El valor de OSMODE podra ser:
xxxxxx1xxxxx o: xxxxxx0xxxxx

As que si pasamos a (logand ...) cualquiera de esos valores con 0000 0010 0000 que es 32 en base 10, obtenemos, ya sea 32 (si est activa la referencia INTERSECCIN) o 0 (cero) si no lo est. En otras palabras:
(if (logand 32 (getvar "OSMODE")) (prompt "\nLa referencia INTERSECCIN est ACTIVA") (prompt "\nLa referencia INTERSECCIN NO est ACTIVA") )

Utilizando las funciones LSH, ~ y LOGAND pudiramos desarrollar funciones para la conversin de decimales en binarios y viceversa, tiles al menos para comprender mejor la operacin de estas funciones binarias. Este ser el tema de la prxima seccin. Los ejemplos de LOGAND en los programas LISP que vienen con AutoCAD s son numerosos. Podemos enumerar para la versin 14: BMAKE.LSP, DDATTDEF.LSP, DDGRIPS.LSP, ATTREDEF.LSP, DDCHPROP.LSP, DDCOLOR.LSP, DDINSERT.LSP, DDMODIFY.LSP, DDPTYPE.LSP, DDSELECT.LSP, DDUNITS.LSP, DDVIEW.LSP, 3D.LSP, EDGE.LSP, MVSETUP.LSP, BLK_LST.LSP, COUNT.LSP, LMAN.LSP, TREXBLK.LSP, CLIPIT.LSP, EXCHPROP.LSP, EXTRIM.LSP, XPLODE.LSP, CURSDLG.LSP, SQLEDDLG.LSP. Mucchos de estos programas ya aparecan en la versin 13. Para indicar alguno de aquella versin que ha desaparecido desde entonces podemos mencionar DDOSNAP.LSP. Enumerando slo algunos de la versin 12 tendramos: CHELEV.LSP, MAKE2D.LSP, MAKE3D.LSP, PTEXT.LSP, CL.LSP y PROJECT.LSP, y de la versin 10 TABLES.LSP, lo que nos puede dar una idea de lo til que resulta esta funcin.

* De: Jon Fleming <jonf@fleming-group.com> Newsgroup: autodesk.autocad.customization Asunto: Logand, logior, lsh, etc... Fecha: Jueves, 26 Feb 1998 20:35:37 EST Organizacin: The Fleming Group Traduccin del ingls: Reinaldo Togores CONVERSIN ENTRE BINARIOS Y DECIMALES (I)

CONVERSIN DECIMAL->BINARIO

Aplicando lo visto hasta ahora podemos crear una funcin que convierta cualquier nmero decimal, positivo o negativo, en su representacin binaria. El manual de Personalizacin de AutoCAD * propone una solucin, pero que es aplicable slo a enteros positivos:
;;;Del manual de Personalizacin: ;;;convierte un entero POSITIVO a una cadena ;;;en la base dada: (defun base (bas int / ret yyy zot) (defun zot (i1 i2 / xxx) (if (> (setq xxx (rem i2 i1)) 9) (chr (+ 55 xxx)) (itoa xxx) ) ;_ fin de if ) ;_ fin de defun (setq ret (zot bas int) yyy (/ int bas) ) ;_ fin de setq

(while (>= yyy bas) (setq ret (strcat (zot bas yyy) ret)) (setq yyy (/ yyy bas)) ) ;_ fin de while (strcat (zot bas yyy) ret) ) ;_ fin de defun

Para nmeros enteros positivos opera correctamente pero no as para los negativos, como puede verse en los siguientes ejemplos:

Nuestra funcin BINARIO tiene en cuenta la longitud de palabra del sistema operativo y devuelve la secuencia correcta de ceros y unos incluso cuando se trate de valores negativos. La funcin espera recibir un entero, pero prev el caso de un nmero real, truncndolo al entero menor ms cercano. Se definen las funciones utilitarias BIT y POSBIT, esta ltima utilizada para guardar el valor de la posicin del bit que se analiza. La conversin en s misma la realiza la funcin ConvierteBinario que recibe como argumentos el nmero a convertir y una funcin predicado a plicar segn el nmero sea positivo o negativo. Esta funcin de conversin es llamada desde la funcin principal BINARIO que analiza si el nmero recibido es positivo o negativo. En caso de ser negativo pasa a la funcin de conversin su NOT lgico (~ numdec) y el predicado '= en lugar del nmero recibido y el predicado '/= que pasara en caso de ser el nmero positivo.
;;;Binario.lsp ;;;El ciclo continuar hasta que LSH devuelva un valor negativo ;;;significando que se ha llegado al final de la palabra (posicin ;;;extrema izquierda). El valor binario es devuelto en formato de lista. ;;; ;;; Funcin auxiliar Bit: devuelve el valor decimal del bit en la posicin indicada. ;;; (defun Bit (pos) (lsh 1 (1- pos))) ;;; ;;; ;;Funcin utilizada como acumulador del valor de la posicin ;;; (defun PosBit () (if (null posicion) (setq posicion 1) (setq posicion (1+ posicion))

) ;_ fin de if ) ;_ fin de defun ;;; ;;; ;;;Funcin para procesamiento del nmero decimal ;;;Recibe como argumento el predicado a aplicar ;;;segn sea el argumento numrico positivo o negativo ;;; (defun ConvierteBinario (numdec predicado / posicion numbin) (while (not (minusp (bit (1- (PosBit))))) (setq numbin (cons (if (apply predicado (list (logand (bit posicion) (fix numdec)) 0) ) ;_ fin de apply 1 0 ) ;_ fin de if numbin ) ;_ fin de cons ) ;_ fin de setq ) ;_ fin de while ) ;_ fin de defun ;;; ;;;Funcin principal ;;;Tiene en cuenta si se trata de un nmero positivo o negativo: ;;; (defun Binario (numdec /) (if (minusp numdec) (ConvierteBinario (~ numdec) '=) (ConvierteBinario numdec '/=) ) ;_ fin de if ) ;_ fin de defun

A diferencia de la funcin BASE, se obtiene una respuesta correcta tanto de enteros positivos como negativos:

Si deseramos el resultado en formato cadena en lugar de lista, bastara mapear 'ITOA a la lista devuelta para convertir los enteros en cadena y aplicarle despus 'STRCAT para unir los caracteres en una cadena nica:

Dedicaremos la prxima seccin a la conversin en el otro sentido, de binario a decimal.

** AutoCAD Versin 13. Manual de Personalizacin. Autodesk, Inc. 1994. ISBN: 288447-327-0. pg. 249 CONVERSIN ENTRE BINARIOS Y DECIMALES (II)

CONVERSIN BINARIO->DECIMAL

Esta funcin, complementaria de la anterior, nos permite hacer la conversin en sentido inverso, partiendo de un valor binario y convirtindolo en decimal. Aunque lo ms probable es que el tipo de entrada del dato sea numrico, hemos diseado una funcin como filtro de entrada que analizar mediante un COND las posibles entradas admitiendo listas y cadenas y rechazando cualquier otro tipo de dato. en caso de que el dato no sea de uno de estos tres tipos admitidos, se imprimir un mensaje de error. Si el dato es admitido pero no es de carcter binario (incluye trminos distintos de cero uno, la funcin devolver NIL.
;;;DECIMAL.LSP ;;;Recibe un nmero binario y lo convierte en decimal ;;;debe comprobar el tipo de dato recibido, ;;;que puede ser cadena, nmero o lista ;;; ;;;Funcin utilitaria BIT ;;;devuelve el valor decimal del bit en la posicin recibida: ;;; (defun Bit (pos) (lsh 1 (1- pos))) ;;; ;;; ;;;Funcin utilizada como acumulador del valor de la posicin: ;;; (defun PosBit () (if (null posicion) (setq posicion 1) (setq posicion (1+ posicion)) ) ;_ fin de if ) ;_ fin de defun ;;; ;;;PREDICADOS DEFINIDOS PARA ESTA FUNCIN:

;;;Como filtro de entrada se emplean tres predicados ;;;definidos expresamente para ella: ;;;STRINGP, STD-DOTTED-PAIR-P y BINARIOP ;;; ;;;Predicado STRINGP ;;;Comprueba si el dato es una cadena ;;;(ver PREDICADOS DEFINIDOS POR EL USUARIO) ;;; (defun stringp (dato) (equal (type dato) 'STR)) ;;; ;;;Predicado STD-DOTTED-PAIR-P ;;;Comprueba de que se trate de un par punteado: ;;;Adaptado de la Standard Lisp Library ;;;de Reini Urban: ;;; (defun STD-DOTTED-PAIR-P (lst) (and (vl-consp lst) (not (listp (cdr lst)))) ) ;_ fin de defun ;;; ;;;Predicado Binariop ;;;Comprueba que la lista incluya valores slo 0 1 ;;; (defun Binariop (numbin /) (apply 'and (mapcar '(lambda (term) (or (equal term 0) (equal term 1))) numbin ) ;_ fin de mapcar ) ;_ fin de apply ) ;_ fin de defun ;;; ;;;Funcin utilitaria NUMLISTA ;;;Recibe cualquier nmero decimal y devuelve los dgitos aislados ;;;en formato de lista ;;;Si el nmero es real, lo trunca despreciando los decimales ;;; (defun Numero->Lista (numero / lista) (while (> numero 0) (setq lista (cons (rem (fix numero) 10) lista)) (setq numero (/ (fix numero) 10)) ) ;_ fin de while lista ) ;_ fin de defun ;;; ;;;Funcin utilitaria Cadena->Lista ;;;Recibe una cadena de caracteres y devuelve los caracteres ;;;aislados en formato de lista ;;; (defun Cadena->Lista (cadena) (mapcar 'chr ;3.- convierte los cdigos ASCII a caracteres (vl-string->list ;2.- convierte la cadena a lista de cdigos ASCII cadena ) ;_ fin de vl-string->list ) ;_ fin de mapcar ) ;_ fin de defun

;;; ;;;Funcin ConvierteDecimal ;;;Realiza la conversin, al ser la evaluacin siempre de izquierda a derecha, ;;;debe invertir la lista para iniciar la comprobacin por el bit ltimo de la derecha. ;;;Esta comprobacin se hace mediante el mapeado de una funcin LAMBDA a la lista, ;;;que comprueba si el nmero es cero y en caso que no lo sea, inserta el valor ;;;decimal del bit en la lista ;;;Una vez concluido este mapeado, se le aplica la funcim '+ para sumar todos ;;;los valores, con lo que obtenemos el resultado de la conversin Binario->Decimal. ;;;Devuelve un nmero decimal ;;; (defun ConvierteDecimal (numbin / posicion) (if (Binariop numbin) (apply '+ ; suma los valores de la lista devuelta por MAPCAR (mapcar (function (lambda (x) (PosBit) ;5.- valora la variable posicion (if (not (zerop x)) (bit posicion) 0 ; en caso contrario devuelve cero ) ;_ fin de if ) ;_ fin de lambda 7.- y los valores devueltos quedan en una lista ) ;_ fin de function (reverse numbin) ) ;_ fin de mapcar ) ;_ fin de apply nil ) ;_ fin de if ) ;_ fin de defun ;;; ;;;Funcin filtro de entrada, considerando los posibles tipos de entrada: ;;;Lista, cadena o nmero ;;;los nicos trminos aceptados sern en cualquier caso ceros o unos ;;;de detectarse otro valor, la funcin devuelve NIL ;;;Otro error derivara de que la lista fuera un par punteado ;;;Para comprobarlo utilizaramos la funcin STD-DOTTED-PAIR-P adaptada de ;;;la Standard LISP library de Reini Urban ;;; (defun Decimal (numbin /) (cond ((STD-DOTTED-PAIR-P numbin) (terpri) (princ numbin) (princ " no es un valor admitido.") (princ)

) ((listp numbin) ;;si es lista, convierte los trminos (setq numbin ;;que sean cadenas en nmeros (o tomos simblicos si fueran letras) (mapcar (function (lambda (term) (if (stringp term) (read term) term ) ;_ fin de if ) ;_ fin de lambda ) ;_ fin de function numbin ) ;_ fin de mapcar ) ;_ fin de setq (ConvierteDecimal numbin) ) ((numberp numbin) ;;si es nmero lo convierte en cadena para despus hacerlo lista (setq numbin (Numero->Lista numbin)) (ConvierteDecimal numbin) ) ((stringp numbin) (setq numbin (mapcar 'read (Cadena->Lista numbin))) (ConvierteDecimal numbin) ) (t (terpri) (princ numbin) (princ " no es un valor admitido.") (princ) ) ) ;_ fin de cond ) ;_ fin de defun

A continuacin algunos ejemplos tomados de la consola de VISUAL Lisp:

A continuacin analizaremos la funcin LOGIOR. LOGIOR

Ms arriba plantebamos que para activar un BIT determinando mediante la suma del valor decimal que devuelve nuestra funcin (bit posicin) era necesario verificar que ese BIT no estuviera ya activo. Esto lo podemos lograr con la funcin LOGIOR. Tambin para LOGIOR recurriremos a Jon Fleming * en su aporte a la mencionada discusin en autodesk.autocad.customization:
(LOGIOR ...) trabaja exactamente de la misma manera, excepto de que escribimos un 1

en la posicin donde uno de los valores o ambos valores de los argumentos que se le pasan tienen un 1, y ponemos un 0 donde ambos argumentos deben tener un 0. Esto es til para combinar nmeros. Quiere asegurarse de que la referencia a objeto INTERSECCIN est activa sin afectar a otros modos de referencia que se hubieren establecido previamente?
(setvar "OSMODE" (logior 32 (getvar "OSMODE")))

Por supuesto, tanto (logand ...) como (logior ...) pueden aceptar ms de dos argumentos. En este caso:
1. Se aplica la funcin a los dos primeros argumentos, obteniendo un resultado provisional.

2. Se aplica la funcin al resultado provisional y al tercer argumento, obteniendo un nuevo resultado provisional. 3. Se repite el proceso de aplicar la funcin al resultado provisional actual y al siguiente argumento hasta agotar los argumentos pasados a la funcin. ALGUNOS EJEMPLOS:

De Tony Tanzillo <tony.tanzillo@worldnet.att.net> tomamos los siguientes ejemplos del uso de estas funciones: Determinar si un bloque es una Referencia Externa (RefX): Esta funcin toma la lista de asociacin devuelta por (tblsearch/siguiente), y devuelve T si el bloque es una referencia externa:
(defun isXref (data) (eq 4 (logand 4 (cdr (assoc 70 data)))) )

Comprobar el valor de la variable CMDACTIVE: No debemos utilizar la funcin = para comprobar el valor de CMDACTIVE, ya que su valor puede variar (y de hecho asumir valores no documentados y totalmente inesperados). En lugar de
(= 1 (getvar "cmdactive")),

se debe utilizar:
(eq 1 (logand 1 (getvar "cmdactive")))

Desactivar REFENT: Para dejar sin efecto mediante LISP las referencias a objeto de carcter permanente (establecidas mediante REFENT) sin cambiar los valores preestablecidos (lo que equivaldra a pulsar la tecla F3), se puede activar el noveno bit (valor decimal de 16384):
(setvar "OSMODE" (logior (getvar "osmode") 16384))

o utilizando la funcin BIT antes definida:


(setvar "OSMODE" (logior (getvar "osmode")(bit 9)))

Otros ejemplos los podemos obtener de los mismos programas LISP que acompaan a AutoCAD. Para el uso de LOGIOR puede consultarse DDOSNAP.LSP de la versin 13, AI_UTILS.LSP, DDCHPROP.LSP, DDMODIFY.LSP y DDSELECT.LSP, de las versiones 13 y 14 y EXCHPROP.LSP y MPEDIT.LSP, estos ltimos de la versin 14.

* De: Jon Fleming <jonf@fleming-group.com> Newsgroup: autodesk.autocad.customization Asunto: Logand, logior, lsh, etc... Fecha: Jueves, 26 Feb 1998 20:35:37 EST Organizacin: The Fleming Group Traduccin del ingls: Reinaldo Togores BOOLE

BOOLE opera como una funcin lgica binaria de carcter general, con lo que incluira las estudiadas LOGAND y LOGIOR y otras hasta completar las 16 posibles. su sintaxis es:
(Boole operador entero1 [entero2 ...])

El argumento operador es un entero que representa un nmero binario de 4 bits. cada bit establecido representa una opcin segn la tabla siguiente: Bit
1

Entero1 Entero2 Resultado:


1 1 _$ (boole 1 1 1) 1 _$ (boole 2 1 0) 1 _$ (boole 4 0 1) 1 _$ (boole 8 0 0) -1

Cda bit de entero1 es comparado con el correspondiente bit de entero2, especificando una fila de la table de resultados anterior. El bit resultante ser 0 1 segn est activado el bit del nmero entero que damos como operador que corresponde a esta posicin. Si el bit en cuestin est activado el bit resultante es 1; de no ser as el resultado ser 0. Para ciertos valores del operador, BOOLE equivale a las operaciones Booleanas standard de AND, OR, XOR, y NOR. Operador Binario
1

Operacin Booleana
AND

Resultado igual a 1 si de los bits analizados:


Ambos son 1

6 (4 + 2) 7 (4 + 2 + 1) 8

XOR OR NOR

Slo uno de ellos es igual a 1 Cualquiera de ellos es 1 Ambos son 0 (complemento de 1)

Para tratar de comprender mejor lo anterior analizaremos un ejemplo tomado de la ayuda de Visual LISP: (boole 6 6 5) devuelve 3 Aprovechando las funciones antes definidas hallaremos el equivalente binario de 6, que sera (despreciando los ceros a la izquierda) igual a 110. Lo mismo para 5 devolvera 101. ahira podemos hacer la comparacin para cada pareja de bits: Primera pareja: (boole 6 0 1) devuelve 1 Segunda pareja (boole 6 1 0) devuelve 1 Tercera pareja: (boole 6 1 1) devuelve 0 Con lo que tendramos el nmero binario 011, que como podemos comprobar aplicando la funcin DECIMAL equivale a 3. Todo esto visto desde la consola de Visual LISP sera:

Normalmente sera ms cmodo emplear LOGAND y LOGIOR cuando fuera posible reservando BOOLE para otras operaciones lgicas binarias. Si revisamos los programas LISP incluidos con la aplicacin AutoCAD encontraremos al gunos ejemplos del uso de esta funcin. Para ello podemos consultar los archivos DDMODIFY.LSP, MPEDIT.LSP, BURST.LSP y ASESMP.LSP de la versin 14, y PROJECT.LSP y FACE.LSP de la Versin 12.

PREDICADOS GENERALES DEFINIDOS POR EL USUARIO

La posibilidad de desarrollar funcuiones de carcter utilitario nos permiten completar los predicados de Visual Lisp con otros de uso probable dentro de las utilidades que se desarrollen dentro de Autocad.
Predicados para comprobacin de tipo de objeto: Tipos de Datos LISP:
INTEGERP

Comprueba si el argumento es un nmero entero.


(defun integerp (dato)(eq (type dato) 'INT)) REALP

Comprueba si el argumento es un nmero real.


(defun realp (dato)(eq (type dato) 'REAL)) STRINGP

Comprueba si el argumento es una cadena.


(defun stringp (dato)(eq (type dato) 'STR))

Tipos de Datos AutoCAD:


ENAMEP

Comprueba si el argumento es un nombre de entidad.


(defun enamep (dato)(eq (type dato) 'ENAME)) FILEP

Comprueba si el argumento es un identificador de archivo.


(defun filep (dato)(eq (type dato) 'FILE)) PAGETBP

Comprueba si el argumento es una Tablas de Paginacin de Funciones.


(defun pagetbp (dato)(eq (type dato) 'PAGETB)) PICKSETP

Comprueba si el argumento es un Conjunto de Seleccin.


(defun picksetp (dato)(eq (type dato) 'PICKSET))

SUBRP

Comprueba si el argumento es una Funcin AutoLISP interna o compilada.


(defun subrp (dato)(eq (type dato) 'SUBR)) USUBRP

Comprueba si el argumento es una funcin de usuario cargada desde un fichero fuente LSP.
(defun usubrp (dato)(eq (type dato) 'USUBR)) EXRXSUBRP

Comprueba si el argumento es una Aplicacin ObjectARX Externa.


(defun exrxsubrp (dato)(eq (type dato) 'EXRXSUBR))

Tipos de Datos ActiveX


SAFEARRAYP

Comprueba si el argumento es una Matriz del tipo Safearray.


(defun safearrayp (dato)(eq (type dato) 'SAFEARRAY)) VARIANTP

Comprueba si el argumento es del tipo Variant.


(defun variantp (dato)(eq (type dato) 'VARIANT)) VLA-OBJECT-P

Comprueba si el argumento es un Objeto ActiveX.


(defun vla-object-p (dato)(eq (type dato) 'VLA-object))

ESTRUCTURAS CONDICIONALES

CONDICIONAL IF ESTRUCTURA IF-THEN-ELSE Evala expresiones condicionalmente:


(if expr_prueba expr_then [expr_else])

Si expr_prueba no es nil, evala expr_then; en caso contrario evala expr_else. La funcin if devuelve el valor de la expresin seleccionada. Si expr_else no existe y expr_prueba es nil, entonces la funcin if devuelve nil.

Funcin PROGN Calcula las expresiones secuencialmente y devuelve el valor de la ltima expresin
(progn [expr]...)

Se suele utilizar progn para calcular varias expresiones cuando slo se espera, como en cada una de las ramas del IF, una sola expresin. CONDICIONALES DE USO GENERAL

En muchos casos nos encontraremos que hay ms de dos condiciones sobre las que decidir. En estos casos podemos acudir a la funcin COND, que evala una serie de condiciones de prueba secuencialmente.
COND Se utiliza como la funcin condicional primaria de Visual LISP
(cond (prueba1 resultado1 ...) ...)

La funcin cond acepta cualquier nmero de listas como argumentos. Evala el primer elemento de cada lista (en el orden indicado) hasta que uno de ellos devuelva un valor distinto de nil. A continuacin, evala las expresiones que siguen a este elemento y devuelve el valor de la ltima expresin de la sublista. Si esta sublista slo contiene un valor (es decir, si falta resultado), se obtiene el valor de la expresin prueba. COND se puede utilizar como una funcin de tipo case. Es habitual utilizar T como ltima (por defecto) expresin de prueba. FUNCIONES RECURSIVAS E ITERATIVAS

Muchos de las tareas que tratamos de resolver con ordenadores implican la ejecucin de procedimientos en forma repetitiva. LISP suministra dos paradigmas para el control de las tareas repetitivas: la recursin y la iteracin. La definicin de nuevas funciones consiste bsicamente en la combinacin de llamadas a otras funcin que resulten adecuadas a los fines que nos proponemos. Un caso particular surge cuando la funcin se llama a s misma. Estas funciones suelen llamarse funciones recursivas. Obsrvese que la funcin recursiva se repite invocndose a s misma. Esto lo hace desde la llamada inicial al programa. As que para cada repeticin hay una nueva llamada a la funcin original. Cualquier otro procedimiento repetitivo que no implique una recursin es un procedimiento iterativo. Visual LISP suministra una serie de funciones especficas para la implementacin de procedimientos iterativos. Las formas ms simples de establecer una iteracin seran las funcin REPEAT y FOREACH para listas y VLAX-FOR para colecciones de objetos ActiveX (VLA-object). REPEAT realiza los procedimientos especificados el nmero de veces que se especifique en su primer argumento que debe ser un nmero entero positivo.

FOREACH suministra una iteracin de manera directa sobre los elementos de una lista. FOREACH debe recibir como segundo argumento una forma que evale como lista. Entonces ejecuta el cuerpo de instrucciones suministrado como sucesivos argumentos una vez para cada uno de los elementos de la lista. Cuando la conclusin del ciclo de repeticiones dependa de que se alcance determinado estado y no sea posible predeterminar el nmero de iteraciones que ello exigir podemos utilizar la funcin WHILE que admite como primer argumento una funcin predicado cuyo no cumplimiento (evaluacin como NIL) determinar la salida del bucle iterativo. Existen tambin las llamadas funciones de mapeado. El Mapeado es un tipo de iteracin en la cual una funcin se aplica sucesivamente a elementos de una o ms secuencias de objetos. El resultado de la iteracin es una secuencia que contiene los resultados de las aplicaciones de la funcin. Visual LISP provee dos funciones de mapeado: MAPCAR, para listas y VLAX-MAP-COLLECTION para colecciones de objetos ActiveX. FUNCIONES RECURSIVAS

El ejemplo clsico de una funcin recursiva es el clculo del factorial de un nmero. Por ejemplo, 4! (factorial) es igual a 4 X 3 X 2 X 1. Algebraicamente, podemos considerar un factorial como (n!) as n X (n-1) X (n-2) X (n-3)...(n - (n+1)). sta sera la definicin recursiva del factorial:
(defun factorial (n) (cond ((zerop n) 1) (T (* n (factorial (1- n)))) ) ;_ fin de cond ) ;_ fin de defun

Se analizan dos condiciones:


1. que el argumento recibido sea cero (predicado ZEROP). En ese caso se devuelve 1. 2. en cualquier otro caso, se multiplica el argumento por el resultado que devuelve aplicar de nuevo la funcin de usuario factorial al argumento menos 1. Lgicamente la evaluacin de esta operacin deber esperar al resultado de la nueva llamada a la funcin factorial, que si an no es cero, provocar una nueva llamada a la misma funcin factorial y quedar a la espera de que esta sea evaluada y as sucesivamente. Al llegar a cero el argumento pasado a factorial, ya no se producir una nueva llamada a la funcin y se comenzar a devolver respuestas a todas la evaluaciones que han quedado pendientes. Este comportamiento puede verse claramente en la ventana TRACE de visua LISP, despus de haber evaluado la funcin (trace factorial) .

La recursin, aunque aporta soluciones de gran elegancia, debe ser utilizada con cautela. Lo ideal sera usarla con funciones que no utilicen, o utilicen muy pocos argumentos, ya que la recursin coloca cada vez una nueva copia de la funcin en la memoria de pila junto con sus argumentos. Es muy posible que una funcin efecte tantas recursiones que se agote la memoria disponible provocando un error de desbordamiento de la pila. Para ms detalles, consultar el artculo WHAT IS RECURSION? de Glenn Grotzinger.
ANLISIS DE UNA FUNCIN RECURSIVA

La siguiente funcin demuestra la posibilidad de desarrollar funciones de usuario a partir de un corto nmero de primitivas. La funcin BUSCA_EN_LISTA recibe como argumentos una expresin cualquiera y una lista. En caso que la expresin est contenida en la lista, la funcin devolver la expresin y todos los trminos de la lista que ocurren despus de la expresin. Si expresin no pertenece a la lista, la funcin devuelve nil. Los resultados obtenidos son los mismos que los de la funcin primitiva MEMBER. De hecho muchas de las funciones hoy incorporadas a cualquiera de los dialectos modernos de LISP surgieron como funciones utilitarias que eran incorporadas de manera habitual por los usuarios.
;;;Funcin recursiva busca_en_lista. ;;;Equivale a la funcin member de LISP ;;;Esta funcin ha sido adaptada del tutorial ;;;LISP del ELM Research Group (defun busca_en_lista (expresion lista) (cond ((null lista) nil) ;si lista est vaca o se acaba ((equal expresion (car lista)) lista) ;si se encuentra expresion (t (busca_en_lista expresion (cdr lista))) ;en otro caso se efcta la recursin ) ) _$ (busca_en_lista '(a b) (list 2 r "sdf" '(a b) "KLM" 77 21 jfk)) ((A B) "KLM" 77 21 nil) _$ (member '(a b) (list 2 r "sdf" '(a b) "KLM" 77 21 jfk)) ((A B) "KLM" 77 21 nil) _$

Si antes de ejecutar esta funcin invocamos la funcin TRACE:


(trace busca_en_lista)

podemos seguir en la ventana TRACE de Visual LISP los pasos seguidos en la evaluacin de esta funcin:
Entering (BUSCA_EN_LISTA (A B) (2 nil "sdf" (A B) "KLM" 77 21 nil)) Entering (BUSCA_EN_LISTA (A B) (nil "sdf" (A B) "KLM" 77 21 nil)) Entering (BUSCA_EN_LISTA (A B) ("sdf" (A B) "KLM" 77 21 nil)) Entering (BUSCA_EN_LISTA (A B) ((A B) "KLM" 77 21 nil)) Result: ((A B) "KLM" 77 21 nil) Result: ((A B) "KLM" 77 21 nil) Result: ((A B) "KLM" 77 21 nil) Result: ((A B) "KLM" 77 21 nil)

Los objetivos perseguidos implican el recorrido de la lista, elemento a elemento, comparando cada uno con la expresin dada. La manera ms sencilla para extraer un elemento de la lista (el primero) es utilizar la funcin CAR. Un segundo elemento pudiera extraerse con CADR y as sucesivamente. Pero este mtodo sera demasiado rgido si queremos que la funcin sea aplicable a una lista de cualquier longitud. Una solucin estara en que si el primer elemento no es el buscado, volviramos a ejecutar la funcin pero que esta vez el segundo argumento (lista) fuera el resto de la lista, quitando el primer trmino ya analizado: (cdr lista). As continuaramos probando el primer trmino (CAR de la lista) del resto (CDR) de la lista hasta que o termine la lista o que el primer trmino sea el elemento buscado. Las condiciones que se prueban corresponden a los tres casos posibles al suministrar a la funcin BUSCA_EN_LISTA dos argumentos, el primero de los cuales puede ser un tomo o una lista y el segundo debe evaluar como una lista, incluso vaca.
Primer caso: ((null lista) nil) Cuando se encuentra esta condicin, la evaluacin termina. La funcin evaluar en este caso como nil, sealando que el trmino no ha sido encontrado. Este sera tambin el caso si el segundo argumento fuera una lista vaca. Segundo caso: ((equal expresion (car lista)) lista) Al igual que en el primer caso, la evaluacin termina. Pero en este caso el primer trmino de la lista (car lista) es el trmino buscado, y se devuelve el valor de lista. Tercer caso: (t (busca_en_lista expresion (cdr lista)))

Este es el caso en que se produce la recursin. Siempre que lista no est vaca (null lista) y que el primer elemento de lista no sea igual al trmino buscado, se llama de nuevo a la funcin BUSCA_EN_LISTA pero esta vez se le pasa como argumento lista (cdr lista), el resto de la lista, desechando el primer trmino. As a cada ciclo, lista se acorta en un trmino. Al final, si expresion no formara parte de lista, la recursin terminara al llegar a ser una lista nula.

Si observamos lo devuelto en la ventana TRACE por una y otra de estas dos funciones recursivas, observamos una diferencia. Lo devuelto por el ltimo nivel de recursin en la funcin FACTORIAL es diferente a lo devuelto por el nivel superior. De hecho cada nivel devuelve un resultado diferente. Para llegar al resultado definitivo, debemos esperar a lo que devuelve cada uno de los ciclos de la recursin. Sin embargo, en la segunda funcin BUSCA_EN_LISTA, el resultado del ltimo nivel es ya el resultado definitivo. Es evidente que resulta una prdida de tiempo el esperar a que cada nivel devuelva ese mismo resultado hasta llegar al nivel superior. Los compiladores LISP ms avanzados reconocern una funcin de este tipo y cortarn el proceso en el instante que se obtiene el resultado del ltimo nivel, mejorando sustancialmente la velocidad de operacin de las funciones. Este tipo de funciones recursivas se conocen por el trmino ingls de TAIL-RECURSIVE (~ recursivas por la cola). En muchos casos, hacer una funcin recursiva por la cola (tail-recursive) es posible empleando tcnicas adecuadas de programacin. Siempre que esto se logre podemos esperar un incremento significativo en la eficacia de los programas. Nota: Segn afirma Reini Urban, VLISP no es capaz de reconocer la recursividad por la cola o tail-recursion, de manera que an resulta en una utilizacin exhaustiva de la memoria de pila (stack). Sobre los lmites valores mximos admitidos de anidacin (tamao de pila) dicho autor propone ejemplos en http://xarch.tu-graz.ac.at/autocad/stdlib/STDINIT2.LSP SU UTILIZACIN PRCTICA DENTRO DE AUTOCAD Como ejemplo de la utilidad de los mtodos de programacin expuestos, desarrollaremos un programa encaminado a resolver un problema concreto dentro de la aplicacin. En ocasiones tenemos la necesidad de extraer la informacin de las coordenadas de los vrtices de una polilnea. En este caso analizaremos una polilnea del tipo LWPOLYLINE, que se introdujo con la versin 14 de AutoCAD. Las entidades de AutoCAD guardan su informacin en forma de listas de asociacin, una lista con sublistas donde el nmero inicial de cada sublista identifica el tipo de dato de que se trata. Un proceso recursivo sera especialmente adecuado para recorrer dicha lista extrayendo de ella la informacin requerida. Pasaremos entonces a estudiar el desarrollo de una FUNCIN RECURSIVA PARA LA LECTURA DE LOS VRTICES DE UNA POLILNEA Extraccin de los vrtices de una LWPOLYLINE

Los datos que sirven para definir cada una de los objetos grficos de AutoCAD estn organizados en forma de una lista de asociacin, es decir, una lista de listas, donde la informacin guardada en cada sublista se identifica mediante un cdigo numrico (entero) que aparece como el primer trmino (CAR) cada sublista. El significado de cada cdigo coincide en trminos generales con los cdigos que identifican los datos contenidos en los archivos del formato de fichero DXF utilizado para la transferencia de dibujos AutoCAD a otras aplicaciones. Para el desarrollo de la siguiente funcin basta saber que los valores que corresponden a las coordenadas X e Y de cada vrtice aparecen en sucesivas sublistas identificadas mediante el cdigo de asociacin 10. La coordenada Z aparece en una nica sublista (ya que debe ser la misma para todos los vrtices) identificada mediante el cdigo 38. La funcin recursiva descrita a continuacin ser llamada desde otra funcin que permita seleccionar un objeto del dibujo, compruebe a continuacin que se trata de la entidad deseada (del tipo "LWPOLYLINE"), extraiga del objeto grfico seleccionado la correspondiente lista de asociacin y la pase, junto con el valor de la elevacin, como argumentos a la funcin recursiva de extraccin VertPoly.
Funcin ExtraeVertices:

Existen varias formas para seleccionar objetos del dibujo. Utilizaremos en este caso la funcin ENTSEL que pide al usuario designar un objeto en el dibujo y devuelve una lista con el nombre de entidad y la lista de coordenadas XYZ del punto que ocupaba el cursor en el momento de hacer la designacin. Este segundo dato no nos es necesario, por lo que anidamos la funcin ENTSEL dentro de una funcin CAR. El nombre de entidad que obtenemos de esta manera es en realidad un puntero al archivo temporal que crea AutoCAD al abrir un dibujo. Utilizando dicho puntero podemos localizar la definicin interna del objeto grfico designado en pantalla y extraerla mediante la funcin ENTGET:
(entget (car (entsel)))

Una sublista determinada se puede encontrar mediante la funcin ASSOC, pero en este caso, las sublistas que guardan las coordenadas de los vrtices todas poseen el cdigo 10. Por este motivo, ser necesario recorrer toda la lista, trmino a trmino para encontrar todos los valores de coordenadas correspondientes a los vrtices. Estos valores son slo de las coordenadas X e Y. La Z se encuentra en una lista asociada al cdigo 38. Habr que extraer este valor inicialmente y luego agregarlo a cada uno de los vrtices. Esto se har utilizando la funcin APPEND en lugar de CONS, de manera que se aada el valor de Z en la tercera posicin y no al principio de la lista. La funcin devolver una lista de listas, estas ltimas cada una de tres valores, correspondiendo a la X,Y,Z de cada vrtice.
;;;Extraccin de los vrtices de una LWPOLYLINE ;;;Funcin recursiva: ;;;Recorre la lista y extrae el valor de los cdigos 10 ;;;Estas listas de asociacin slo incluyen los valores ;;;de las coordenadas X e Y, el valor de Z para toda la ;;;polilnea est asociado al cdigo 38 este valor as ;;;como la lista de entidad se extraen en una funcin ;;;inicial que adems sirve para declarar como variables ;;;locales las que almacenan la lista definitoria de la ;;;entidad y la lista de vrtices. ;;;Esta funcin devuelve la lista de vrtices, que se

;;;puede asignar a una variable mediante setq: ;;; (setq vertlis (ExtraeVertices)) ;;;(c) Reinaldo Togores, Santander, Julio 1999. (defun VertPoly (lista elevacion / ) (cond ((null lista) nil) ;funcin de salida ((equal (caar lista) 10) ;si se trata de un vrtice (cons ;la funcin append permite incluir la (append (cdr (car lista))(list elevacion)) ;coordenada Z en la posicin correcta (VertPoly (cdr lista) elevacion) ;y contina la recursin ) ) (t (VertPoly (cdr lista) elevacion)) ;si no es un vrtice ) ;_ fin de cond ) ;_ fin de defun (defun ExtraeVertices ( / lista_entidad) (if (equal (cdr (assoc 0 (setq lista_entidad (entget (car (entsel)))))) "LWPOLYLINE" ) (VertPoly lista_entidad (cdr (assoc 38 lista_entidad))) (alert "La entidad seleccionada no es una LWPOLYLINE") ) ;_ fin de if ) ;_ fin de defun

Sin duda este cdigo cumplir su cometido, pero puede ser mejorado. Este programa est redactado de manera tal que ninguna de sus partes pudiera reutilizarse en otros futuros programas. Un enfoque ms eficaz consistira en analizar qu procesos de carcter ms general intervienen en la solucin y programarlos como funciones utilitarias que se incorporen como nuevas herramientas al lenguaje. Ms adelante, y despus de estudiar algunos otros procedimientos y tcnicas, intentaremos precisamente esto, cmo abordar de una manera ms eficaz la solucin a este programa. FUNCIONES ITERATIVAS

ITERACIONES SIMPLES

En algunos casos puede ser conveniente otro enfoque de las operaciones repetitivas, mediante estructuras en bucle que no implican procedimientos de auto-referencia. Los operadores REPEAT y FOREACH ejecutan las expresiones dadas un nmero defterminado de veces. En el primer caso se trata del nmero de veces que resulta de la evaluacin del primero de sus argumentos y en el segundo de la cantidad de elementos que pertenecen a una lista. Esta ltima funcin tiene en Visual LISP su equivalente aplicable a objetos de coleccin ActiveX bajo el nombre de VLAX-FOR

Tanto para REPEAT como para FOREACH se puede establecer de antemano el nmero de ciclos a realizar. Pero esa no es siempre la situacin. En muchas ocasiones no hay manera de saberlo. En estos casos se deber establecer, al igual que en los procedimientos recursivos una condicin de prueba que determine la conclusin del ciclo. Para ello disponemos de la funcin WHILE. REPETICIN UN NMERO DETERMINADO DE VECES

REPEAT Evala cada expresin el nmero de veces que se especifique en el argumento entero, y devuelve el valor de la ltima expresin
(repeat entero expresin ...)

El argumento entero debe ser un nmero entero positivo. Ejemplos de iteraciones con REPEAT:
FACTORIAL ITERATIVO

Como primer ejemplo analizaremos la funcin FACT2 propuesta por Dennis Shinn <jeeper@halcyon.com> en el newsgroup comp.cad.autocaden septiembre de 1996. La explicacin es nuestra traduccin libre del original.
(defun fact2 (n / x y) (setq x 1 y 1) (repeat (1- n) (setq x (1+ x) y (* x y) ) ) )

En la primera lnea se asigna el valor inicial correcto a las dos variable que llamamos x e y. La repeticin se establece para un nmero especfico de veces segn el nmero que se pase como argumento a la funcin. Puesto que la operacin del clculo del factorial implica la cantidad de nmeros a multiplicar menos 1, establecemos en (1- n) el nmero de repeticiones. Ahora vienen los clculos matemticos: (setq x (1+ x) y (* x y)) Durante cada iteracin de esta expresin, la x se incrementa por un valor de 1 cada vez, e y se incrementa como el producto de ella misma y el prximo valor mayor de x, etc., etc. Obsrvese que no se ha implementado un control de errores, que es algo deseable en un lenguaje de programacin. Tanto 0 como 1 quedan indefinidos, ya que ninguno de los dos permitir que ocurra la iteracin. El REPEAT simplemente no repite. Vale, sin embargo para demostrar las posibilidades de un verdadero

lenguaje de programacin (como LISP) para realizar verdaderas operaciones de recursin e iteracin. Como muestra de una implementacin para atrapar posibles errores podramos crear otra rutina fact3 que llame a la rutina fact2 slo en los casos apropiados:
(defun fact3 (n) (cond ((and (numberp n)(> n 1)) (fact2 n) ) ((= n 1) 1) (t nil) ) )

En este caso se prueba primero si el argumento n es un nmero mayor que 1, en cuyo caso se ejecuta la funcin fact2. En caso de ser igual a 1 se devuelve 1, y en cualquier otro caso se devolver NIL. Predicado PALINDROMOP El predicado PALINDROMOP debe devolver T (cierto) si una cadena de texto es un palndromo, es decir, si se lee lo mismo de izquierda a derecha que al revs. Se ha utilizado la funcin STRLEN para determinar el nmero de repeticiones, la funcin SUBSTR para ir extrayendo caracteres para compararlos, uno a uno, comenzando de izquierda a derecha y de derecha a izquierda, y la funcin STRCASE de manera que se ignore la caja (maysculas o minsculas). Se emplean dos variables locales, cont y resultado. Esta segunda se establece inicialmente como T y bastar que no sea igual una de las parejas de letras analizadas para que adopte el valor de NIL (falso). Es obvio que bastar con un nmero de repeticiones igual a la mitad de la longitud de la cadena de texto, pues ms all de eso se estara comparando las mismas parejas de caracteres. Al ser ambos argumentos de la divisin nmeros enteros, el resultado tambin lo sera, truncando los decimales, por lo que en una cadena con nmero impar de caracteres no se comparara el carcter centras consigo mismo.
(defun palindromop (cadena / cont resultado) (setq cont 0 resultado t ) ;_ fin de setq (repeat (/ (strlen cadena) 2) (if (not (equal (strcase (substr cadena (1+ cont) 1)) (strcase (substr cadena (- (strlen cadena) cont) 1)) ) ;_ fin de equal ) ;_ fin de not (setq resultado nil) ) ;_ fin de if (setq cont (1+ cont)) ) ;_ fin de repeat

resultado ) ;_ fin de defun

ITERACIONES SOBRE ELEMENTOS DE UNA SECUENCIA

FOREACH

Evala cada expresin para todos los miembros de una lista


(foreach nombre lista expresin ...)

Recorre la lista, asignando sucesivamente cada elemento de la lista a la variable nombre y evaluando de esta manera cada expresin para cada uno de los elementos de la lista representados por nombre. Puede especificar tantas expresiones como desee. La funcin FOREACH devuelve el resultado de la ltima expresin evaluada.
VLAX-FOR

Efecta una iteracin a travs de una coleccin de objetos evaluando cada expresin
(vlax-for smbolo coleccin [expresin1 [expresin2 ...]])

El argumento smbolo ser asignado a cada Objeto-VLA de la coleccin. El argumento coleccin representa un objeto ActiveX del tipo coleccin. [expresin1 [expresin2 ...]] son las expresiones a evaluar. La funcin devuelve el valor de la ltima expresin evaluada para el ltimo objeto de la coleccin. Ejemplos de iteraciones con FOREACH:

Esta pequea subrutina, parte de un programa mayor, imprime en pantalla en formato de columna la lista que se le pase como argumento. En el ejemplo se usa para imprimir de manera ordenada la lista de definicin deuna entidad polilnea (AutoCAD 2000).
;;;Listado de entidades ;;;Salida por pantalla (defun disp_l (lis_e /) (foreach sublista lis_e (print sublista) ) ;_ fin de foreach (princ) ;evita la repeticin de la ltima lnea ) ;_ fin de defun Command: (entget(car(entsel))) Select object: ((-1 . <Entity name: 1487558>) (0 . "LWPOLYLINE") (330 . <Entity name: 14874f8>) (5 . "2B") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 .

"0") (100 . "AcDbPolyline") (90 . 4) (70 . 0) (43 . 0.0) (38 . 0.0) (39 . 0.0) (10 99.3432 134.975) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 130.202 185.828) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 202.747 163.648) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 269.336 215.041) (40 . 0.0) (41 . 0.0) (42 . 0.0) (210 0.0 0.0 1.0)) ;La lista impresa en pantalla resulta difcil de leer, al no estar ordenada en columna Command: (disp_l (entget(car(entsel)))) (-1 . <Entity name: 1487558>) (0 . "LWPOLYLINE") (330 . <Entity name: 14874f8>) (5 . "2B") (100 . "AcDbEntity") (67 . 0) (410 . "Model") (8 . "0") (100 . "AcDbPolyline") (90 . 4) (70 . 0) (43 . 0.0) (38 . 0.0) (39 . 0.0) (10 99.3432 134.975) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 130.202 185.828) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 202.747 163.648) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 269.336 215.041) (40 . 0.0) (41 . 0.0) (42 . 0.0) (210 0.0 0.0 1.0)

Ejemplos de iteraciones con VLAX-FOR: LISTADO DE CAPAS

Considerado desde el punto de vista de la jerarqua de objetos ActiveX a la que podemos acceder con Visual LISP, AutoCAD y sus dibujos consisten en muchos objetos diferentes tales como tipos de lneas, capas, bloques, etc. Estos objetos se agrupan en colecciones. Las colecciones de Bloques (Block), Grupos (Group), Conjuntos de Seleccin (SelectionSet), EspacioModelo (ModelSpace) y EspacioPapel (PaperSpace) pueden contener una variedad de objetos

grficos diferentes, tales como lneas, arcos, texto, etc. Todas las dems colecciones contienen objetos de un slo tipo. Las colecciones AutoCAD son de base cero, es decir que se enumeran a partir de cero en sentido ascendente. Algunas colecciones poseen objetos de manera automtica. Por ejemplo, la coleccin Layers (capas) simpre contiene un objeto capa de nombre "0", mientras que otras se encuentran vacas inicialmente. Sutphin, J. AutoCAD 2000 VBA Programmers Reference, pg 47. La rutina que exponemos a continuacin extrae los nombres de las capas de un dibujo aplicando la funcin VLAX-FOR a la coleccin "Layers". Para obtener la coleccin "Layers" tenemos que recorrer la jerarqua de objetos, a partir del nico objeto accesible pblicamente que es el objeto "Application" (Aplicacin). La secuencia a seguir es la siguiente:
1. Obtener el objeto "Aplicacin": (vlax-get-acad-object) 2. Obtener el objeto "Documento Activo" es decir, el dibujo en que se trabaja: (vla-getActiveDocument (vlax-get-acad-object))

En caso de que se vaya a hacer referencia a este objeto en mltiples ocasiones, sera conveniente extraerlo una sla vez y guardarlo en una variable global:
(setq *EsteDibujo* (vla-get-ActiveDocument (vlax-get-acad-object)))

Esta lnea la situamos fuera del defun. Se ejecutara al cargar el programa. 3. Obtener la coleccin "Layers" (Capas): (vlax-get *EsteDibujo* "Layers" )

Una vez obtenida la coleccin de capas se aplica mediante VLAX-FOR a cada objeto-VLA de dicha coleccin la funcin
(setq ListaCapas (cons (vlax-get objeto-VLA "Name") *ListaCapas*))

Aqu primero extraemos el nombre de la capa. El nombre de cada objeto "Layer" se encuentra en la propiedad "Name" y se puede extraer mediante (vlax-get objeto-VLA "Name"). Una vez obtenido el nombre de la capa, la incluimos mediante CONS en una variable local ListaCapas. Esta lista contendr al terminar el ciclo de VLAX-FOR los nombres de todas las capas del dibujo activo. Ya para terminar, ordenamos la lista de capas mediante la funcin ACAD_STRLSORT. Esta lista servira, por ejemplo para llenar una casilla de lista en un cuadro de dilogo creado mediante el lenguaje DCL.
;;;Funcin ListaCapas ;;;Devuelve una lista con los nombres de capas ordenados alfabticamente ;;;Obsrvese la posibilidad aqu demostrada de tener una funcin y una variable ;;;con idntico nombre en un mismo entorno. Para ello ser necesario que dicha ;;;variable, en este caso ListaCapas sea una variable local de la funcin. (setq *EsteDibujo* (vla-get-ActiveDocument (vlax-get-acad-object))) ;se ejecuta previamente (defun ListaCapas (/ ListaCapas) (vlax-for objeto-VLA (vlax-get *EsteDibujo* "Layers") (setq ListaCapas (cons (vlax-get objeto-VLA "Name") ListaCapas)) ;el mismo nombre se utiliza para la variable local que guarda ;temporalmente el listado de capas. ) ;_ fin de vlax-for

(acad_strlsort ListaCapas) ) ;_ fin de defun

Ejemplo de su utilizacin:
Command: (LOAD "C:/Mis documentos/Lisp/Fuentes/ListaCapas.lsp") LISTACAPAS Command: !*EsteDibujo* <#VLA-OBJECT IAcadDocument 00eb6aa4> Command: (listaCapas) ("0" "DEFPOINTS" "DOTACIONES" "IT" "RBA" "RE-2" "RI" "RI-1" "RIA" "SG-EL" "SG-M" "SGP")

Ms adelante se estudiar en ms detalle el acceso a los objetos ActiveX desde Visual LISP.
Unos ejemplos para concluir...

Como ejemplo del empleo dentro de AutoCAD de estas ltimas funciones estudiadas, aqu van algunas pequeas utilidades creadas por Vladimir Nesterovsky. La primera de ellas, SEL2LST crea una lista de nombres de entidad a partir de un conjunto de seleccin. La segunda, LST2SEL, realiza el proceso inverso, creando un conjunto de seleccin a partir de una lista de nombres de entidad:
;;;SEL2LST ;;;Recibe un conjunto de seleccin y devuelve una lista (defun sel2lst( sel / n l) (repeat (setq n (sslength sel)) (setq n (1- n) l (cons (ssname ss n) l)) ) ) ;;;LST2SEL ;;;La funcin opuesta, recibe una lista y devuelve un conjunto de seleccin (defun lst2sel(l / ss) (setq ss (ssadd)) (foreach e l (ssadd e ss)) )

La siguiente funcin extrae el resto de una lista l a partir del trmino n indicado en el primer argumento:
(defun cdnr ( n l ) (repeat n (setq l (cdr l)) ) )

La funcin STRTOL recibe una cadena de caracteres s y devuelve los caracteres aislados (cadenas de un slo carcter) agrupados en una lista:

(defun strtol ( s / lst c ) (repeat (setq c (strlen s)) (setq lst (cons (substr s c 1) lst) c (1- c) ) ) lst )

Como se ve, esta puede ser otra va para abordar el desarrollo del predicado PALINDROMOP: obtener mediante STRTOL la cadena de caracteres en forma de lista y entonces compararla con la lista invertida por reverse:
(defun palindromop (cadena) (setq cadena (strtol cadena)) (equal cadena (reverse cadena)) ) ;; Created by Vladimir Nesterovsky ;; YOU MAY USE THIS FUNCTION AS IT IS FOR ANY PURPOSE ;; AT YOUR OWN RISK IF YOU RETAIN THIS NOTICE COMPLETE ;; AND UNALTERED. NO WARRANTIES GIVEN WHATSOEVER.

CICLOS DEPENDIENTES DE UNA CONDICIONAL

Cuando no hay manera de establecer al incio del proceso iterativo el nmero de repeticiones que sern necesarias se deber establecer, al igual que en los procedimientos recursivos una condicin de prueba que determine la conclusin del ciclo. Para ello disponemos de la funcin WHILE.
WHILE Evala una expresin de prueba y, si sta no da como resultado nil, evala otras expresiones para volver de nuevo a la expresin de prueba
(while expr_prueba expr...)

La funcin while contina hasta que expr_prueba es nil . Entonces devuelve el valor ms reciente de la ltima expresin. Ejemplos de Iteraciones con WHILE: CONTEO DE ENTIDADES:

Un caso lo tendramos en una funcin que tuviera como propsito el contar las entidades que forman parte de un dibujo. Para acceder de manera secuencial a las entidades que forman parte de un dibujo tenemos la funcin ENTNEXT. Si establecemos un contador que se incremente por cada entidad del dibujo tendramos, al llegar a la ltima entidad, el nmero

total de entidades. La funcin concluir en el momento que la variable ent evale como NIL , es decir, cuando ENTNEXT ya no devuelva ms ninguna entidad por haber alcanzado el final de la base da datos del dibujo.
;;;Funcin iterativa para conteo simple ;;;de las entidades en un dibujo ;;;Se establece la variable cont como contador ;;;y la variable ent para guardar el nombre de ;;;cada entidad leda (defun CuentaEntidades ( / cont ent) (setq cont 1 ent (entnext) ;la funcin entnext sin argumentos ;devuelve la primera entidad del dibujo ) ;_ fin de setq (while ent (setq cont (1+ cont) ent (entnext ent) ;devuelve la entidad que le sigue a ent ) ;_ fin de setq ) ;_ fin de while cont ;devuelve el valor final del contador ) ;_ fin de defun

Ms adelante utilizaremos este procedimiento para desarrollar funciones ms sofisticadas dirigidas a inventariar los objetos contenidos en un dibujo.
PREDICADO PALINDROMOP OPTIMIZADO:

La versin anterior del predicado PALINDROMOP no resulta muy eficiente, pues comprueba de manera exhaustiva todos los caracteres de la cadena, cuando bastara con detectar una primera desigualdad para decidir que no se trata de un palndromo. Una solucin ms eficaz debera interrumpir la evaluacin en ese momento. Eso lo podemos lograr mediante un ciclo condicional usando WHILE con dos condiciones encerradas en un AND (que devolver NIL en cuanto una de ellas deje de ser cierta): que no se hubiera alcanzado el nmero de repeticiones determinado por (/ (strlen cadena) 2), y que el valor de resultado sea T. En cuanto se encuentre una pareja de caracteres desigual resultado pasar a ser NIL, con lo cual se detendr el ciclo.
(defun palindromop (cadena / cont resultado) (setq cont 0 resultado t ) ;_ fin de setq (while (and (<= cont (/ (strlen cadena) 2)) resultado) (if (not (equal (substr cadena (1+ cont) 1) (substr cadena (- (strlen cadena) cont) 1) ) ;_ fin de equal ) ;_ fin de not (setq resultado nil) ) ;_ fin de if

(setq cont (1+ cont)) ) ;_ fin de while resultado ) ;_ fin de defun

No basta que un programa alcance los resultados deseados. Debe hacerlo de manera rpida y eficaz. Este es un principio que no debe olvidarse. FUNCIONES DE MAPEADO

LISP provee funciones que procesan secuencialmente los trminos de una lista suministrada como argumento.
MAPCAR
(mapcar funcin lista1 ... listan) MAPCAR opera sobre los elementos sucesivos de las listas. Primero se aplica la funcin al CAR de cada lista, entonces al CADR de cada una y as sucesivamente.

Lo ideal sera que todas las listas fueran de igual longitud. Si no lo fueran, la iteracin concluye al agotarse la lista ms corta y los elementos en exceso de las dems listas se ignoran. MAPCAR devuelve una lista con los resultados de las sucesivas llamadas a la funcin. Por ejemplo:
_1$ (mapcar 'cons '(a b c) '(1 2 3)) ((A . 1) (B . 2) (C . 3))

Una expresin-LAMBDA puede ser utilizada con MAPCAR. Esto resulta til cuando algunos de los argumentos de funcin son constantes o se proporcionan mediante variables u otros mtodos.

Sobre la funcin MAPCAR seguramente no encontraremos una explicacin ms entusiasta que la de Vladimir Nemerovski a quien citamos a continuacin: Ahora trataremos de MAPCAR. Esta es una funcin que requiere:
1. un smbolo dentro de QUOTE o una EXPRESIN-LAMBDA (tabin dentro de un QUOTE ) o una lista de funcin de usuario (igualmente dentro del QUOTE) 2. alguna lista 3. y otras listas opcionales ms...

Digamos que la invocamos con (mapcar 'mifuncin milista) El resultado ser una LISTA de los RESULTADOS de invocar MIFUNCIN con cada elemento de MILISTA. Por ejemplo, (defun mysqr(x)(* x x)) (mapcar 'mysqr (list 1 2 3 4))

devolvera (1 4 9 16) De nuevo MYSQR aparece aqu precedida de un apstrofe (QUOTE), ya que MAPCAR espera que as sea. MYSQR espera un argumento numrico y eso es lo que obtiene. Si yo la invocara como (MAPCAR 'MYSQR (list 1 2 "3")) LISP intentara construir una lista de resultados como [1] (list (mysqr 1) (mysqr 2) (mysqr "3")) y yo obtendra un error de BAD ARGUMENT TYPE al intentar procesar el "3". Observe de nuevo que en esta expresin [1], MYSQR es de nuevo un QUOTED-SYM de una funcin de usuario previamente definida cuyo resultado evala como una lista, teniendo tambin una lista como primer argumento, de manera que en este punto LISP reconoce tal lista como una funcin de usuario, tratando de evaluarla, sustituyendo los argumentos ficticios de su lista de parmetros por los argumentos reales. De manera que si usted quiere que alguna funcin sea usada en MAPCAR y no desea que sta permanezca por ah sin ser utilizada de nuevo, usted puede emplear LAMBDA. Esta funcin crea un tipo de FUNCIN ANNIMA y la devuelve como encerrada en QUOTE, tal como lo hara DEFUN (slo que esta creara una funcin vinculada a un NOMBRE que de esta manera permanecera formando parte del entorno).
MAPCAR es grandiosa en que no necesita saber cual es la longitud de una lista de datos. No le importa. Simplemente la recorre hasta llegar al final, con lo que lo sabr en tiempo de ejecucin. De manera que usted al escribir la funcin (que en LISP equivaldra al tiempo de compilacin de lenguajes compilados como C, etc.), no necesita saber la longitud exacta de su lista de datos, lo que ES FENOMENAL! Le permite tratar fcilmente con informacin de longitud variable, y no olvidemos que toda la informacin real sin duda lo es.

As que puedo (mapcar 'mysqr '(1 2 3)) o puedo (mapcar 'mysqr '(1 2 3 4 5)), segn haga falta. Y hay algo ms. Digamos que tengo esta funcin que SUMA todos sus argumentos. Es un '+, que puedo invocar como: (+ 1 2) (+ 1 2 3) etc. Ahora cuando escribo (mapcar '+ '(1 2 3) '(4 5 6)) es lo mismo que (list (+ 1 4)(+ 2 5)(+ 3 6)) Tambin puedo escribir (mapcar '+ '(1 2 3)'(4 5 6)'(7 8 9)), que equivale a (list (+ 1 4 7)(+ 2 5 8)(+ 3 6 9)) etc. De manera que tenemos algo ms de flexibilidad aqu. Por supuesto que yo ser el responsable de suministrar a la funcin invocada con el nmero adecuado de argumentos que le sern alimentados por MAPCAR, ya que de otra manera obtendr un error de DEMASIADOS/MUY POCOS ARGUMENTOS cuando LISP eventualmente la evale.
Fuente:

Subject: A short course in LISP, LAMBDA, QUOTE, MAPCAR... Date: Sat, 02 Nov 1996 08:50:38 -0800 From: Lu <learly@ix.netcom.com>

VLAX-MAP-COLLECTION Aplica una funcin a todos los objetos de una coleccin.


(vlax-map-collection coleccin funcin)

El argumento coleccin representa un Objeto-VLA de tipo coleccin. El argumento funcin ser un smbolo o una expresin-LAMBDA que ser aplicada a coleccin. Ejemplo de utilizacin de VLAX-MAP-COLLECTION:

Hemos visto anteriormente el desarrolo de una fincin que devuelve una lista con los nombres de las capas contenidas en el dibujo utilizando la funcin VLAX-FOR. Una funcin similar puede desarrollarse con VLAX-MAP-COLLECTION, con un cdigo resultante aun ms claro y conciso. La funcin que se pasa a VLAX-MAP-COLLECTION se definir en este caso como una expresin-LAMBDA. Obsrvese que esta expresin debe pasarse dentro de un QUOTE.
;;Funcin ListaCapas utilizando VLAX-MAP-COLLECTION ;;;Devuelve una lista con los nombres de capas ordenados alfabticamente (setq *EsteDibujo* (vla-get-ActiveDocument (vlax-get-acad-object))) ;se ejecuta previamente (defun ListaCapas (/ ListaCapas objeto-VLA) (vlax-map-collection (vlax-get *EsteDibujo* "Layers") '(lambda (objeto) (setq ListaCapas (cons (vlax-get objeto "Name") ListaCapas)) ) ;_ fin de lambda ) ;_ fin de vlax-map-collection (acad_strlsort ListaCapas) ) ;_ fin de defun

Su utilizacin devuelve idnticos resultado que la anterior definida con VLAX-FOR. Unos ejemplos para concluir...
Conversin de cadena a lista:

Conversin de cadena a lista, con MAPCAR, en una sla lnea. Utilizando esta funcin podemos convertir al instante cadenas en listas con sus caracteres aislados:
_$ (defun CadenaLista (cadena)(mapcar 'chr (vl-string->list cadena))) CADENALISTA _$ (cadenalista "Madrid") ("M" "a" "d" "r" "i" "d")

REMOVE en una sla lnea:

Gracias a Reini Urban hemos podido conocer este brillante ejemplo desarrollado por Sergei Volkov, implementando la funcin REMOVE (QUITAR) en una sla lnea:
;;;REMOVE, por Segei Volkov ;;;Recibe una expresin expr y una lista lst. ;;;Devuelve la lista eliminando de ella todas las ocurrencias de la expresin. ;;;Paso 1: Mediante MAPCAR aplica la funcin LIST a cada trmino de la lista ;;; Si recibe '(a b c) obtendr '((a) (b) (c)) ;;;Paso 2: Utiliza la funcin SUBST para sustituir por NIL cada aparicin de ;;; la expresin expr ;;;Paso 3: Aplica mediante APPLY la funcin APPEND a los miembros de la lista. ;;; de esta manera desaparecen los NIL (listas vacas) que sustituyeron ;;; a la expresin eliminada (defun remove (expr lst) (apply 'append (subst nil (list expr) (mapcar 'list lst))) )

Ejemplo:
_$ (remove 'a '( b c d f a g h j)) (B C D F G H J) _$

Extraccin de los vrtices de una Polilnea:

En un captulo anterior, al estudiar los procesos recursivos, habamos desarrollado una funcin destinada a extraer los valores de los vrtices de una polilnea. Con los procesos que hemos estudiado hasta ahora pudiramos intentar el enunciado de una funcin ms concisa y clara para obtener este resultado. A ello dedicaremos el prximo apartado. EXTRACCIN DE LOS VRTICES DE UNA POLILNEA: Una manera ms eficaz de abordar el problema.

El programa expuesto en el captulo sobre los procedimientos recusivos, ha sido elaborado utilizando slo las funciones primitivas conocidas entonces de AutoLISP. Una manera ms eficaz de encarar su anlisis sera la de tener en cuenta si algunos de los procesos que se llevan a cabo dentro del mismo pudieran programarse independientemente, como funciones utilitarias. Una funcin utilitaria es un nuevo operador que aadimos al lenguaje de programacin para resolver situaciones que pueden presentarse con cierta frecuencia dentro de nuestros programas. En el caso que estamos analizando, podemos concebir la necesidad de una nueva funcin que recorra una lista y de acuerdo con el resultado de una funcin que

se le pase como predicado elimine unos trminos y conserve otros. Como resultado tendramos una lista que slo incluyera los trminos deseados, en este caso las listas de asociacin identificadas con los cdigos 10. Estas funciones que pudiramos llamar QUITAR-SI y su complementaria QUITAR-SI-NO han estado siempre entre las primeras que los programadores LISP han aadido a su repertorio de utilidades. Una definicin de las mismas pudiera ser:
;;;QUITAR-SI ;;;Implementacin de la funcin REMOVE-IF ;;;en contexto AutoLISP (defun quitar-si (predicado lista) (cond ((null lista) nil) ((apply predicado (list (car lista))) (quitar-si predicado (cdr lista)) ) (t (cons (car lista)(quitar-si predicado (cdr lista)))) ) ) ;;;QUITAR-SI-NO ;;;Implementacin de la funcin REMOVE-IF-NOT ;;;en contexto AutoLISP (defun quitar-si-no (predicado lista) (cond ((null lista) nil) ((apply predicado (list (car lista))) (cons (car lista)(quitar-si-no predicado (cdr lista))) ) (t (quitar-si-no predicado (cdr lista))) ) )

Tanto es as que se han incorporado como operadores a la norma de Common LISP bajo los nombres de REMOVE-IF (QUITAR-SI) y de REMOVE-IF-NOT (QUITAR-SI-NO). Visual LISP les incorpora el prefijo VL- para distinguirlos de las funciones del antiguo AutoLISP, y as las encontraremos en el catlogo de funciones Visual LISP como VL-REMOVE-IF y VL-REMOVE-IF-NOT. Utilizando VL-REMOVE-IF-NOT y con la ayuda de la funcin de mapeado sobre listas MAPCAR, estudiada en el apartado anterior, nuestra funcin VertPoly pudiera escribirse de la siguiente manera:
;;;Funcin VertPoly utilizando VL-REMOVE-IF-NOT ;;;Paso 1: ;;;Eliminar todos las sublistas que no correspondan al cdigo 10 ;;;Paso 2: ;;;Extraer el CDR de cada una de las sublistas. ;;;Se utiliza el mapeado de la funcin CDR a la lista mediante MAPCAR ;;;Paso 3: ;;;Se aade el valor de la elevacin mapeando a la lista una expresin LAMBDA. (defun VertPoly (lista elevacion) (mapcar ;Paso 3

(function (lambda (x) (append x (list elevacion)))) (mapcar ;Paso 2 'cdr (vl-remove-if-not ;Paso 1 (function (lambda (x) (equal (car x) 10))) lista ) ;_ fin de vl-remove-if-not ) ;_ fin de mapcar ) ;_ fin de mapcar ) ;_ fin de defun

Obsrvese el uso de la funcin FUNCTION que fuerza la compilacin de las dos expresionesLAMBDA. Se utiliza en lugar de QUOTE (o apstrofe) procurando una mayor eficacia y rapidez. Esta segunda formulacin resulta ms clara y ms econmica en cuanto a esfuerzo de programacin. Por otra parte, supera las limitaciones de Visual LISP en cuanto a la recursin que pudiera provocar en caso de polilneas con un gran nmero de vrtices un error por desbordamiento de pila. Nota: esta funcin devuelve los resultados correctos para Visual LISP en AutoCAD 2000. Sin embargo hemos encontrado que falla si se ejecuta desde el IDE Visual LISP para la versin 14. El error se encuentra en los valores de la lista de asociacin para el objeto LWPOLYLINE que se obtienen desde este entorno:
(entget(car(entsel))) aplicado a una LWpolyline en la lnea de comandos de

AutoCAD R14 devuelve:


Command: (entget(car(entsel))) Select object: ((-1 . <Entity name: 43b0500>) (0 . "LWPOLYLINE") (5 . "20") (100 . "AcDbEntity") (67 . 0) (8 . "0") (100 . "AcDbPolyline") (90 . 7) (70 . 0) (43 . 0.0) (38 . 0.0) (39 . 0.0) (10 103.882 154.494) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 180.771 201.906) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 186.224 143.05) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 267.476 167.028) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 256.569 105.994) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 298.558 123.432) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 293.651 89.1) (40 . 0.0) (41 . 0.0) (42 . 0.0) (210 0.0 0.0 1.0))

Obsrvese que las listas asociadas al cdigo 10 contienen dos nmeros reales adems del cdigo de asociacin: (10 256.569 105.994) es decir, las coordenadas X e Y solamente. Sin embargo, al ejecutarlo desde la consola de Visual LISP aparece un tercer nmero real: (10 256.569 105.994 0.0), representando el valor de Z:
_$ (entget(car(entsel))) ((-1 . <Entity name: 43b0500>) (0 . "LWPOLYLINE") (5 . "20") (100 . "AcDbEntity") (67 . 0) (8 . "0") (100 . "AcDbPolyline") (90 . 7) (70 . 0) (43 . 0.0) (38 . 0.0) (39 . 0.0)

(10 103.882 154.494 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 180.771 201.906 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 186.224 143.05 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 267.476 167.028 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 256.569 105.994 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 298.558 123.432 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (10 293.651 89.1 0.0) (40 . 0.0) (41 . 0.0) (42 . 0.0) (210 0.0 0.0 1.0)) _$

Este comportamiento constituye un error que ya ha sido superado en la versin 2000. Cundo usar la Recursin y cundo la Iteracin? Tomado del tutorial por Collin Allen y Maneesh Dhagat, April 1997. Traduccin del ingls: Reinaldo Togores, 1999.

Hay muchos problemas para los cuales la recursin resulta natural y para los cuales la iteracin resulta extremadamente difcil. Esto sucede usualmente cuando se tienen en cuenta objetos con una estructura compleja de listas anidadas. Por ejemplo, consideremos esta expresin matemtica en formato LISP: (setq math-formula '(+ 3 (* (- 5 pi) 4 (/ 3 7))(* 15 2)) ) Math-formula contiene listas dentro de listas dentro de listas.

Supongamos que quisiramos saber cuntos nmeros estn sepultados en las profundidades de esta frmula. He aqu una funcin recursiva que lo averiguar:
(defun num-nums (mf) (cond ((null mf) 0) ((numberp (car mf)) (1+ (num-nums (cdr mf)))) ((atom (car mf)) (num-nums (cdr mf))) (t (+ (num-nums (car mf)) (num-nums (cdr mf))))))

;; ;; ;; ;; ;; ;; ;;

la lista vaca no contiene ninguno si el primer trmino es un nmero sumar al nmero en el resto si es cualquier otro tomo ignorarlo, contar el resto o se trata de una lista a contar y sumar al numero en el resto

Pruebe esta funcin y examine su operacin usando TRACE. Observe que la profundidad de recursin flucta a medida que las sublistas son procesadas. >(num-nums math-formula) 1> (NUM-NUMS (+ 3 (* (- 5 PI) 4 (/ 3 7)) (* 15 2))) 2> (NUM-NUMS (3 (* (- 5 PI) 4 (/ 3 7)) (* 15 2))) 3> (NUM-NUMS ((* (- 5 PI) 4 (/ 3 7)) (* 15 2))) 4> (NUM-NUMS (* (- 5 PI) 4 (/ 3 7))) 5> (NUM-NUMS ((- 5 PI) 4 (/ 3 7))) 6> (NUM-NUMS (- 5 PI)) 7> (NUM-NUMS (5 PI)) 8> (NUM-NUMS (PI))

9> (NUM-NUMS NIL) <9 (NUM-NUMS 0) <8 (NUM-NUMS 0) <7 (NUM-NUMS 1) <6 (NUM-NUMS 1) 6> (NUM-NUMS (4 (/ 3 7))) 7> (NUM-NUMS ((/ 3 7))) 8> (NUM-NUMS (/ 3 7)) 9> (NUM-NUMS (3 7)) 10> (NUM-NUMS (7)) 11> (NUM-NUMS NIL) <11 (NUM-NUMS 0) <10 (NUM-NUMS 1) <9 (NUM-NUMS 2) <8 (NUM-NUMS 2) 8> (NUM-NUMS NIL) <8 (NUM-NUMS 0) <7 (NUM-NUMS 2) <6 (NUM-NUMS 3) <5 (NUM-NUMS 4) <4 (NUM-NUMS 4) 4> (NUM-NUMS ((* 15 2))) 5> (NUM-NUMS (* 15 2)) 6> (NUM-NUMS (15 2)) 7> (NUM-NUMS (2)) 8> (NUM-NUMS NIL) <8 (NUM-NUMS 0) <7 (NUM-NUMS 1) <6 (NUM-NUMS 2) <5 (NUM-NUMS 2) 5> (NUM-NUMS NIL) <5 (NUM-NUMS 0) <4 (NUM-NUMS 2) <3 (NUM-NUMS 6) <2 (NUM-NUMS 7) <1 (NUM-NUMS 7) 7 Sera difcil definir num-nums de forma iterativa. No es imposible, pero exige el saber utilizar una pila para simular la recursin.

Muchas tareas de inteligencia artificial implican el buscar a travs de estructuras anidadas. Por ejemplo, las representaciones en rbol de los movimientos en un juego se representan mejor como listas anidadas. Examinar este rbol implica un rastreo recursivo a travs del mismo. Para este tipo de aplicacin las funciones recursivas resultan una herramienta esencial. Cundo debemos utilizar la iteracin y cundo la recursin? Hay por lo menos estos tres factores a considerar: (1) La funciones iterativas son usualmente ms rpidas que sus contrapartes recursivas. Si la velocidad es importante, normalmente usaramos la iteracin. (2)

Si la memoria de pila es un limitante, se preferir la iteracin sobre la recursin. (3) Algunos procedimientos se programan de manera recursiva de forma muy natural, y resultan prcticamente inabordables iterativamente. Aqu la eleccin es clara.

EXPORTAR LA LISTA DE ENTIDAD

Para los usuarios de DOS, las siguientes rutinas permiten escribir en pantalla (con salto de lnea) o en fichero las listas definitorias de las entidades seleccionadas. Para utilizar el cdigo que sigue, seleccinelo en su browser, utilizando el ratn, desde la lnea que dice -INICIO DEL PROGRAMA- hasta la lnea -FIN DEL PROGRAMA-, copie el texto seleccionado (Ctrl+C), abra un editor (Notepad o Visual LISP) y pguelo all (Ctrl+V). Guarde el fichero as creado con el nombre LISTENT.LSP en el subdirectorio SUPPORT . Para cargarlo teclee (load "listent") Reinaldo Togores. Profesor Asociado. Departamento de Ingeniera Geogrfica y Tcnicas de Expresin Grfica Universidad de Cantabria. Diciembre de 1996. Se autoriza la utilizacin del cdigo de estos programas, mencionando siempre su origen. Para comentarios y sugerencias: reinaldo.togores@unican.es

;;;----------------------INICIO DEL PROGRAMA-----------------------------------------------;;;(c) Reinaldo Togores, Santander, 1997. ;;Listado de entidades ;;Salida por pantalla ;;Rutina DISP_L: Escribe lista de entidad en pantalla (defun disp_l ( lis_e / ) (repeat (length lis_e) (princ (nth cont lis_e))(terpri) (setq cont (1+ cont)) ) ) ;;Rutina PRN_L: Escribe lista de entidad en fichero de texto (defun prn_l (lis_e / ) (repeat (length lis_e) (print (nth cont lis_e) if_w) (setq cont (1+ cont)) ) ) ;;Rutina OPN_L: Abre fichero de texto para escribir lista de entidad (defun opn_l () (if (null nomls)(setq nomls "")) (if (setq nomls (getfiled "Lista de Entidad:" nomls "txt" 5)) (if (wcmatch nomls "*`.*") (setq if_w (open nomls "w"))

(setq if_w (open (strcat nomls ".txt") "w") ) ) ) ) ;;Programa Principal LISTX: Escribe la lista de entidad a un fichero de texto (defun c:listx ( / n_e lis_e ctrl cont) (if (setq s_set (ssget)) (progn (opn_l)(setq s_c 0) (repeat (sslength s_set) (if (setq n_e (ssname s_set s_c))(setq lis_e (entget n_e (list "*")))) (setq cont 0) (prn_l lis_e) (if (or (= (cdr (assoc 0 lis_e)) "POLYLINE") (= (cdr (assoc 0 lis_e)) "INSERT") ) (progn (setq ctrl t) (while (and ctrl (setq n_e (entnext n_e))) (setq cont 0) (if (= (cdr (assoc 0 (setq lis_e (entget n_e (list "*"))))) "SEQEND") (progn (setq ctrl nil)(prn_l lis_e)) (prn_l lis_e) ) ) ) ) (setq s_c (1+ s_c)) ) (close if_w) ) ) ) ;;Programa Principal LIS: Salida por pantalla (defun c:lis ( / n_e lis_e ctrl cont) (if (setq n_e (car (entsel)))(setq lis_e (entget n_e (list "*")))) (setq cont 0) (disp_l lis_e) (setq ctrl t) (while (and ctrl (setq n_e (entnext n_e))) (setq cont 0) (if (= (cdr (assoc 0 (setq lis_e (entget n_e (list "*"))))) "SEQEND") (setq ctrl nil) (disp_l lis_e) ) ) ) (alert "Lista de Entidades\teclee LIS para salida por pantalla\nTeclee LISTX para salida a fichero...")

;;;----------------------FIN DEL PROGRAMA------------------------------------------------

SOLUCIONES CON SPLINE


por Reinaldo Togores

Este plano topogrfico construido con polilneas de tramos rectos, sin amoldar a curva, ocupaba originalmente 1.268 Kbytes. Con la aplicacin al mismo del programa AutoLISP PL2SP logr una reduccin a 581 Kbytes, un 46 % del original.

La aplicacin de este programa a polilneas adaptadas a curva-B, como se explica en el texto, logra reducciones mucho ms espectaculares. Segn pruebas realizadas, hasta 17 veces menor.

PolyLINES & BYTES

Al utilizar AutoCAD para la realizacin de mapas, usualmente tenemos que trabajar con ficheros extremadamente grandes. En muchos casos el tamao de estos ficheros resulta de las curvas de nivel, y son provocados por la manera en que estas son generadas. Las curvas de nivel se digitalizan como polilneas en modo "LINEA". Para curvarlas se aplica despus el comando EDITPOL (PEDIT) con la opcin SPLINE. Este procedimiento genera una gran cantidad de vrtices suplementarios, provocando con ello un incremento en el tamao del fichero respecto del original que contena slo polilneas sin amoldar. Otra consecuencia de esta adaptacin es que la polilnea as adaptada no pasar por todos los vrtices, suavizndose el perfil original. He realizado algunas pruebas para determinar la incidencia de este factor sobre el tamao del fichero, dibujando una polilnea y creando con ella una matriz de 10 x 10 elementos.

PLINE.DWG Utilizando los parmetros por defecto de AutoCAD, y adaptando las polilneas con EDITPOL(PEDIT)/SPLINE, el resultado ha sido el siguiente:
Polilnea sin adaptar: PLINE DWG 238.770 bytes Polilnea adaptada a B-Spline: B-SPLINE DWG 1.930.838 bytes

Como se ve, el tamao del fichero se incrementa algo ms de ocho veces. Este factor de incremento puede sin embargo reducirse si antes de realizar la adaptacin se reduce el valor de la variable SPLINESEGS (que por defecto es 8). Con SPLINESEGS en 2 el resultado es:
Con SPLINESEGS=2 B-SPLIN1 DWG 375.520 bytes

Con ello se reduce el nmero de segmentos que se emplean para aproximar la curva terica. Esta adaptacin, sin embargo presentar un aspecto de lnea quebrada, tanto ms cuanto menor sea el valor de SPLINESEGS empleado, pues los segmentos generados son rectos. Un mejor resultado desde el punto de vista de su apariencia se lograra a partir de dar a la variable SPLINESEGS un valor negativo, en este caso -2 de manera que la adaptacin se hiciera empleando arcos en lugar de segmentos rectos. En este caso se estara combinando la adaptacin tipo "curva-B" (B-spline) que se realiza a partir de segmentos rectos, con un posterior curvamiento del tipo "adaptar curva" (fit curve) tradicional de AutoCAD, a base de arcos de crculo. Para lograr una aproximacin mejor a los vrtices originales, resulta tambin conveniente ajustar la variable SPLINETYPE, cuyo valor por defecto es 6 (B-spline cbica), hacindola igual a 5 (B-spline cuadrtica). Esto sera una solucin para nuevos planos, pero resultara bastante laborioso aplicarlo manualmente a los ya existentes, pues implicara el "readaptar" las polilneas con el nuevo valor de SPLINESEGS, para lo cual sera necesario

seleccionarlas una a una con la orden EDITPOL (PEDIT). Algo de este tipo pudiera implementarse a partir de un programa AutoLISP que automatizara el proceso. Ms recomendable para los ficheros existentes, sera utilizar algn programa que optimizara las curvas adaptadas, eliminando los vrtices superfluos. Existen en el mercado varias aplicaciones que cumplen este propsito. La ms interesante parece ser la aplicacin CURVEFIT de TCI Software. Esta aplicacin transforma las polilneas en "poliarcos" aproximando los mismos a los vrtices originales dentro del factor de tolerancia fijado por el usuario eliminando aqullos que no fueran imprescindibles a esta aproximacin. Otras utilidades que realizan una depuracin de vrtices segn determinados parmetros ajustables por el usuario son WEED (incluido en el paquete de utilidades shareware de Jerry Workman VECTOR) distribuido por Mountain Software y PFILTER, una utilidad de distribucin libre creada por Steve Johnson para WAWA, la Water Authority of Western Australia.

LA SOLUCIN SpLINE

La versin 13 de AutoCAD introduce una entidad "SPLINE", que dibuja directamente curvas cbicas o cuadrticas del tipo NURBS. Esta curva se genera como tal, sin necesidad de un amoldamiento posterior, y pasa por todos los vrtices que se designen. Es una entidad nica, no como la polilnea que resulta de una concatenacin o secuencia de entidades VERTEX individuales, con lo que se logra adems un formato mucho ms compacto en cuanto a su almacenaje en disco. Una spline trazada con los mismos vrtices que la polilnea original (y como ella reproducida 100 veces en matriz) dio el siguiente resultado:
Curva NURBS SPLINE DWG 109.090 bytes

Otro indicador de la eficacia en la gestin grfica a partir de esta entidad la obtenemos de aplicar sobre los distintos dibujos el comando STATUS:
DIBUJO UTILIZANDO SPLINES:
Command: _status 131 objects in C:\USR\DWG\spline Free physical memory: 6.8 Mbytes (out of 31.4M). Free swap file space: 84.6 Mbytes (out of 100.9M). Virtual address space: 57.4 Mbytes.

DIBUJO UTILIZANDO POLILNEAS SIN ADAPTAR:


Command: status 5731 objects in C:\USR\DWG\pline Free physical memory: 5.6 Mbytes (out of 31.4M). Free swap file space: 84.3 Mbytes (out of 100.9M). Virtual address space: 57.8 Mbytes.

DIBUJO CON POLILNEAS ADAPTADAS:


Command: _status 47431 objects in C:\USR\DWG\b-spline

Free physical memory: 0.2 Mbytes (out of 31.4M). Free swap file space: 78.4 Mbytes (out of 100.9M). Virtual address space: 76.3 Mbytes.

Es notable la diferencia en la cantidad de entidades registradas en el dibujo: de 131 en el realizado con splines a 47.431 en el de las polilneas adaptadas. Tambin merece atencin el hecho de que despus de cargado el dibujo, el hecho con splines deja libres 5.6 Megabytes de 31.4 totales, mientras que con el de las polilneas adaptadas se consume prcticamente la totalidad de la RAM, con lo que se empezara a paginar a disco de inmediato, ralentizando con ello el proceso de trabajo. La solucin ideal para la optimizacin de estos planos estara en un programa (AutoLISP o ADS) que, una vez depuradas las polilneas (con CURVEFIT, WEED, PFILTER u otro programa similar), creara splines a partir de una lectura de los vrtices resultantes, con lo que se lograra una dimensin ptima del dibujo.

De SpLINES a PolyLINES:

Como nueva entidad en AutoCAD, SPLINE deja an muchos cabos sueltos. Como de costumbre, estos cabos sueltos son campo propicio para la accin de los programadores AutoLISP, que vienen a aportar soluciones que en muchos casos se incorporan a las prximas versiones del programa. Uno de estos cabos sueltos est en la conversin entre las entidades POLILNEA y SPLINE. La conversin polilnea - spline est resuelta, siempre que se haya realizado previamente su adaptacin mediante la opcin "curva-B" (SPLINE). Esta posibilidad, que forma parte de las opciones del comando SPLINE, tiene el inconveniente de exigir un amoldamiento previo a curva-B utilizando el incmodo comando EDITPOL (PEDIT). Algo que no ofrece AutoCAD es la conversin en sentido inverso: la conversin SPLINE > POLILNEA. Decimos "no ofrece" pues no es que no est resuelta. Lo que no est es disponible de manera directa, como tal conversin. El proceso que habr de seguir resulta bastante alambicado: habr que salvar el dibujo (o la parte de l que querramos convertir) como dibujo de la versin 12 (saveasR12). Al reabrir el dibujo en la versin 13 encontraremos que nuestra SPLINE es ahora una perfecta polilnea. Aunque esta conversin deja an mucho que desear, pues es polilnea, pero siempre 3D. Faltara la capacidad de discriminar si se trata de entidades coplanares para entonces convertirla a una polilnea 2D. Si la opcin de conversin no aparece como tal, quizs se deba a que Autodesk desea reservarse algunas "novedades" para vendernos la prxima versin. De nuevo pudiramos ingeniarnos para, aprovechando la posibilidad de salvar los splines como versin 12, crear una orden que automatizara (recurriendo a un simple SCRIPT) el siguiente proceso:

seleccionar las entidades spline del dibujo exportarlas mediante la orden BLOQUEDISC (WBLOCK)

salir del dibujo actual y entrar en el nuevo dibujo creado salvar este nuevo dibujo como R12 volver al dibujo anterior importar, insertndolo, el dibujo salvado como R12 borrar los dibujos creados en los dos pasos intermedios

Un intento de programa AutoLISP que realiza una conversin aproximada de una Spline en Polilnea fue publicado hace algn tiempo por Vladimir Nesterowsky en el foro de discusin comp.cad.autocad. An cuando la polilnea que se logra no resulta idntica al spline original, resulta interesante como ejemplo del procesamiento de entidades recurriendo al examen de sus datos de entidad. Que la conversin no resulta sencilla a nivel de programacin de usuario, lo demuestra la rutina de conversin de B. Stamm y G. Stoykov publicada por AutoDESK en su coleccin de documentacin tcnica on-line, fit_spln.lsp - Converting Splines to Polylines . Esta rutina, mucho menos pretenciosa que la de Vladimir, se reduce a marcar puntos sobre la spline mediante el comando DIVIDE, para despus unir los puntos con una polilnea de tramos lineales. Cabra preguntar porqu sera necesario transformar una curva spline en polilnea. Se me ocurren, al menos, los cuatro siguientes motivos:

Muchos programas que reciben sus datos de ficheros DWG an no reconocen las splines. AutoCAD no suministra la manera de "juntar" splines. Si se interrumpiera accidentalmente el dibujo de una spline, habra que iniciarla desde el principio para lograr continuidad. Tampoco permite darle un grosor a la entidad, cosa que s hace con las polilneas. El comando EQDIST (OFFSET) no opera de manera satisfactoria con las SPLINES, fragmentndolas de manera imprevisible. La opcin TTR del comando CIRCULO no funciona con SPLINES (y tampoco con ELIPSES)

El primero de estos problemas seguramente se resolver en las prximas versiones de dichas aplicaciones. El segundo sera tema para un programa AutoLISP. Seguramente alguno de vosotros ya lo ha intentado. Si es as tendra mucho gusto en publicarlo. En cuanto al grosor de las entidades, es un tema pendiente para AutoCAD. Hasta cundo, AutoDESK? Mientras tanto puede seguirse gestionando como se ha hecho para todas las dems entidades (excepto polilneas) hasta ahora, asignndole un grosor al color en el momento de trazar. En cuanto al ltimo aspecto, suponemos que se trata de un "bug" reparable en el futuro.

HACERLO AL REVS: DE PolyLINE A SpLINE

Desde mi punto de vista, el programa ms urgente a elaborar era uno que convirtiera una polilnea en spline, pero no mediante la opcin EDITPOL (PEDIT) que incrementa el tamao de la entidad introduciendo nuevos vrtices y que no acierta a pasar por los puntos originalmente digitizados. Esta nueva funcin simplemente podra leer los vrtices originales de la polilnea, descartando aqullos que fueran producto del curvado. Con ello

reduciramos en gran medida la dimensin de los ficheros de dibujo que como los planos topogrficos incluyan una gran cantidad de polilneas curvadas. La solucin que proponemos para ello se encuentra en el fichero PL2SP.LSP . Los resultados de su aplicacin son impresionantes. Como prueba hemos utilizado uno de los ficheros de dibujo mencionados ms arriba: el de las polilneas adaptadas a B-Spline, BSPLINE DWG de 1.9 Megabytes, el que llega a reducirse a slo 110 Kbytes. Debo advertir que la reduccin no es aparente a primera vista. Es necesario, una vez ejecutado el programa, comprimir el dibujo mediante la orden LIMPIA (PURGE), o salvndolo habiendo establecido previamente el valor de la variable ISAVEPERCENT en 0 (cero), o exportndolo mediante BLOQUEDISC (WBLOCK) Los efectos conseguidos pueden verse en el siguiente listado:
Dibujo original: B-SPLINE Ejecutado PL2SP: PRUEBA Limpiando el DWG: PURGE bytes Salvando con BLOQUEDISC: WBLOCK DWG 1.930.838 bytes DWG 2.027.294 bytes DWG 110.683 DWG 110.228 bytes

LISTADO DEL PROGRAMA EDITAR Y CARGAR PROGRAMAS LISP EXTRACCIN DE LISTAS DE ENTIDAD OTROS DOCUMENTOS SOBRE EL TEMA: http://xarch.tu-graz.ac...nestr/polyline_vertices

CONVERSIN PolyLINE>SpLINE

Para utilizar el cdigo que sigue, seleccinelo en su browser, utilizando el ratn, desde la lnea que dice "-INICIO DEL PROGRAMA-" hasta la lnea "-FIN DEL PROGRAMA-", copie el texto seleccionado (Ctrl+C), abra un editor (Notepad o Visual LISP) y pguelo all (Ctrl+V). Guarde el fichero as creado con el nombre PL2SP.LSP en un directorio que figure en la variable de entorno ACAD (por ejemplo, el subdirectorio SUPPORT) . Para cargarlo teclee (load "PL2SP") Reinaldo Togores. Profesor Asociado. Departamento de Ingeniera Geogrfica y Tcnicas de Expresin Grfica Universidad de Cantabria. Marzo de 1997. Se autoriza la utilizacin del cdigo de estos programas, mencionando siempre su origen.

Para comentarios y sugerencias: reinaldo.togores@unican.es Una versin de este programa, capaz de procesar LWPOLYINES ha sido elaborado por Oscar Rodrguez de Sevilla, Espaa. Para acceder al mismo, pulse AQU.

;;--INICIO DEL PROGRAMA/PROGRAM BEGINS HERE-------------;:******************************************************* ;;Sustitucin PLINE->SPLINE ;;Lee los vrtices originales de una polilnea y crea a ;;partir de ellos una SPLINE. Borra la pollnea original. ;;(C) Reinaldo Togores, Santander, 1997 ;;------------------------------------------------------;;Nota: Este programa slo funcionar correctamente si el ;;Sistema de Coordenadas de Objeto de la polilnea a convertir ;;coincide con el Sistema de Coordenadas Universal, es decir ;;que la polilnea est contenida en un plano paralelo ;;al plano XY Universal. ;;******************************************************** ;;Rutina de seleccin de objetos: ;;Del conjunto de seleccin original, crea un nuevo ;;conjunto de seleccin que incluya slo polilneas: (defun pl_sel ( / orig_selset pl_selset count) (prompt "\nSeleccione Polilneas/Select Polylines: ") (setq orig_selset (ssget) pl_selset (ssadd) count -1 ) (repeat (sslength orig_selset) (setq count (1+ count)) (if (= (cdr (assoc 0 (entget (ssname orig_selset count)))) "POLYLINE") (ssadd (ssname orig_selset count) pl_selset) ) ) pl_selset ) ;;Rutina de lectura de los vrtices de la polilnea ;;crea una lista de entidad SPLINEa partir de los ;;vrtices originales de la polilnea, (sealados por ;;el cdigo 70=0 16) cambiando el cdigo 10 de la ;;entidad POLYLINE por el cdigo 11 de la entidad ;;SPLINE. ;;Slo se incluyen en la nueva lista los cdigos ;;imprescindibles para la creacin de la SPLINE. ;;Cada lista creada se pasa a entmake ;;para crear la nueva SPLINE. Despus se borra la ;;polilnea original (defun vertex ( sset / count ent_sup act_ent spl_list) (setq count 0) (repeat (sslength sset) (setq ent_sup (ssname sset count) act_ent (entnext ent_sup) count (1+ count)

spl_list nil ) (while (/= (cdr (assoc 0 (entget act_ent ))) "SEQEND") (if (or (= (cdr (assoc 70 (entget act_ent))) 0) (= (cdr (assoc 70 (entget act_ent))) 16) ) (setq spl_list (cons (cons 11 (cdr (assoc 10 (entget act_ent)))) spl_list) ) ) (setq act_ent (entnext act_ent) ) ) (setq spl_list (reverse spl_list)) ;;Consruccin de la nueva lista de entidad (foreach cod (list (assoc 8 (entget ent_sup)) (cons 74 (length spl_list)) (cons 71 3) (cons 100 "AcDbSpline") (cons 100 "AcDbEntity") (cons 0 "SPLINE") ) (setq spl_list (cons cod spl_list)) ) ;;Hacer la SPLINE (entmake spl_list) ;;Borrar la POLILNEA (entdel ent_sup) ) ) ;;Funcin Principal/Command line function (defun c:pl2sp ( / oce) (setq oce (getvar "cmdecho")) (setvar "cmdecho" 0) (vertex (pl_sel)) (redraw) (setvar "cmdecho" oce) (princ) ) ;;----------------FIN DEL PROGRAMA-----------------------

TEMAS DE PROGRAMACIN AUTOLISP

BLOQUES DEFINIDOS DESDE EL MISMO PROGRAMA QUE LOS INSERTA

La portabilidad de los programas que efectan inserciones de bloques est limitada por la necesidad de inclur junto al programa las bibliotecas de dibujos que se han de insertar. Esto obliga a empaquetar los ficheros que contienen el cdigo junto a los dibujos y requiere de parte del usuario una instalacin cuidadosa que asegure que el programa encontrar los dibujos adecuados. Un cambio en la estructura de directorios o en el nombre de los ficheros provocar irremediablemente el fallo de la aplicacin. Tampoco queda asegurada la uniformidad de los resultados, al ser los ficheros de dibujo suceptibles de manipulacin. Una manera de evitar estas dificultades consiste en definir cada vez, mediante el mismo programa que los inserta, los bloques necesarios. Esto puede lograrse de una manera muy eficaz mediante la funcin entmake que crea, accediendo directamente a la base de datos del dibujo, nuevas entidades. La funcin entmake resulta especialmente apropiada para la definicin de bloques sin necesidad de dibujar previamente las entidades que lo componen. Estos bloques pueden incluir cualquier entidad vlida de dibujo, incluyendo atributos de texto. La sintaxis de esta funcin es:
(entmake [lista_entidad])

donde [lista_entidad] contiene la informacin necesaria para la definicin de la entidad en un formato similar al que devuelve la funcin entget. Una forma sencilla de obtener esta lista para el programador consiste en dibujar previamente las entidades que le interesan, utilizar la funcin entget -tecleando, por ejemplo (entget (car (entsel)))y copiando la lista de entidad resultante. Esta operacin, directamente accesible a los usuarios de las versin 13 y 14 bajo Windows puede implementarse para los usuarios de DOS mediante una rutina que escriba el resultado de esta lectura a un fichero de texto. Los bloques y otras entidades complejas debern crearse mediante varias llamadas sucesivas a entmake que definan, una a una sus elementos componentes (vrtices, atributos, etc.). Cuando entmake detecta la creacin de una entidad compleja, genera un archivo temporal para almacenar los datos de la definicin. Cada vez que se utiliza entmake, se comprueba si este archivo temporal existe y se incluye en l la nueva informacin. Una vez terminada la definicin de la entidad compleja, (definiendo las entidades SEQEND o ENDBLK, segn corresponda) se validan los datos y se aade la entidad al dibujo. Si tiene xito en la creacin de la entidad entmake devuelve la lista de entidad o, en el caso de un bloque, el nombre de dicho bloque. Si la entidad no es creada, entonces devuelve nil. Para evitar su redefinicin, en caso de que exista un bloque del mismo nombre, es recomendable explorar la tabla de bloques previamente mediante la funcin tblsearch. La funcin entmake tambin puede ser utilizada para crear objetos NO-GRFICOS, tales como capas, estilos, etc.

LISTADO DEL PROGRAMA UTILIDADES DE PROGRAMACIN (EDLISP)

DEFINICION INTERNA DE BLOQUES DESDE UN PROGRAMA AUTOLISP

Las funciones de usuario col_def, niv_def y alt_def utilizan la funcion entmake para generar bloques que incluyen entidades de dibujo y atributos de texto, tanto visibles como invisibles. Para utilizar el cdigo que sigue, seleccinelo en su browser, utilizando el ratn, desde la lnea que dice INICIO DEL PROGRAMA hasta la lnea FIN DEL PROGRAMA, copie el texto seleccionado (Ctrl+C), abra un editor (Notepad o Visual LISP) y pguelo all (Ctrl+V). Guarde el fichero as creado con el nombre BLK_DEF.LSP en el subdirectorio SUPPORT . Para cargarlo teclee (load "blk_def") Reinaldo Togores. Profesor Asociado. Departamento de Ingeniera Geogrfica y Tcnicas de Expresin Grfica Universidad de Cantabria. Diciembre de 1996. Se autoriza la utilizacin del codigo de estos programas, mencionando siempre su origen. Para comentarios y sugerencias: reinaldo.togores@unican.es

;;;----------------------INICIO DEL PROGRAMA-----------------------------------------------;;;(c)Reinaldo Togores. Santander, 1997. ;;Definicin del Bloque NIV_ID ;;Este bloque incluye una marca de punto y un atributo de texto para ;;representar la cota de nivel ;;compuesto por una marca de PUNTO y un atributo de texto visible: (defun niv_def () ;Definicin de la cabecera de bloque: (entmake '((0 . "BLOCK")(2 . "NIV_ID")(70 . 2)(10 0.0 0.0 0.0))) ;Definicin de la entidad PUNTO: (entmake '((0 . "POINT")(8 . "0")(10 0.0 0.0 0.0)(210 0.0 0.0 1.0)(50 . 0.0))) ;Definicin del atributo de texto: (entmake '((0 . "ATTDEF")(8 . "0")(10 4.0 -2.0 0.0)(1 . "")(2 . "COT_NIV") (3 . "Cota de Nivel")(40 . 4.0)(41 . 1.0)(50 . 0.0)(70 . 0)(71 . 0)(72 . 0)(73 . 2)) ) ;Definicin de FIN del Bloque:

(entmake '((0 . "ENDBLK"))) ) ;;Definicin del Bloque ALT_ID ;;Este bloque contiene solamente un atributo de texto para representar las alturas ;;de edificacin en un plano catastral. (defun alt_def () ;Definicin de la cabecera de bloque: ;El cdigo 70 indica que siguen atributos.El cdigo 10 contiene el ;punto de insercin. (entmake '((0 . "BLOCK")(2 . "ALT_ID")(70 . 2)(10 0.0 0.0 0.0))) ;Definicin del atributo de texto: (entmake '((0 . "ATTDEF")(8 . "0")(10 0.0 0.0 0.0)(1 . "I")(2 . "NUM_ALT") (3 . "Alturas")(40 . 2.0)(41 . 1.0)(50 . 0.0)(70 . 0)(71 . 0)(72 . 4)(73 . 2)) ) ;Definicin de FIN del Bloque: (entmake '((0 . "ENDBLK"))) ) ;;Definicin del Bloque COL_SIM. Este bloque se utilizar para representar torres ;;portantes de una linea de alta tensin. Esta funcion es invocada desde el ;;programa C:COL, que realiza la insercion, en el caso de que dicho programa ;;detecte que no existe dicho bloque en el dibujo actual. (defun col_def () ;Definicin de la cabecera de bloque: (entmake '((0 . "BLOCK")(2 . "COL_SIM")(70 . 2)(10 0.0 0.0 0.0))) ;Definicin de la cabecera de la entidad POLILINEA: ;Observe que se trata de una polilinea cerrada (codigo 70=1) (entmake '((0 . "POLYLINE")(8 . "0")(66 . 1)(10 0.0 0.0 0.0)(70 . 1)(40 . 0.0) (41 . 0.0)(210 0.0 0.0 1.0)(71 . 0)(72 . 0)(73 . 0)(74 . 0)(75 . 0)) ) ;Definicin de cada uno de los vertices: (entmake '((0 . "VERTEX")(8 . "0")(10 -2.0 -2.0 0.0)(40 . 0.0)(41 . 0.0) (42 . 0.0)(70 . 0)(50 . 0.0)(71 . 0)(72 . 0)(73 . 0)(74 . 0)) ) (entmake

'((0 . "VERTEX")(8 . "0")(10 -2.0 2.0 0.0)(40 . 0.0)(41 . 0.0) (42 . 0.0)(70 . 0)(50 . 0.0)(71 . 0)(72 . 0)(73 . 0)(74 . 0)) ) (entmake '((0 . "VERTEX")(8 . "0")(10 2.0 2.0 0.0)(40 . 0.0)(41 . 0.0) (42 . 0.0)(70 . 0)(50 . 0.0)(71 . 0)(72 . 0)(73 . 0)(74 . 0)) ) (entmake '((0 . "VERTEX")(8 . "0")(10 2.0 -2.0 0.0)(40 . 0.0)(41 . 0.0) (42 . 0.0)(70 . 0)(50 . 0.0)(71 . 0)(72 . 0)(73 . 0)(74 . 0)) ) ;Definicin del fin de secuencia para la Polilinea (entmake '((0 . "SEQEND"))) ;Definicin de una lnea diagonal (entmake '((0 . "LINE")(8 . "0")(10 -2.0 2.0 0.0)(11 2.0 -2.0 0.0)(210 0.0 0.0 1.0)) ) ;Definicin de la otra linea diagonal (entmake '((0 . "LINE")(8 . "0")(10 -2.0 -2.0 0.0)(11 2.0 2.0 0.0)(210 0.0 0.0 1.0)) ) ;Definicin del atributo de texto: ;Observe que se trata de un atributo invisible (codigo 70=1) (entmake '((0 . "ATTDEF")(8 . "0")(10 -2.0 -8.0 0.0)(1 . "00")(2 . "COL_ID") (3 . "Columna Num.")(40 . 4.0)(41 . 1.0)(50 . 0.0)(70 . 1)(71 . 0)(72 . 0)(73 . 0)) ) ;Definicin de FIN del Bloque: (entmake '((0 . "ENDBLK"))) ) ;;;--------PROGRAMAS DE INSERCIN---------------------------------------------------------;;Programa para insertar las cotas de nivel: (defun C:NIV () (setq oce (getvar "cmdecho"))(setvar "cmdecho" 0) (setq oad (getvar "attdia"))(setvar "attdia" 0) (setvar "luprec" 2)(setvar "pdmode" 0) ;Si NO existe el bloque NIV_ID, crearlo: (if (null (tblsearch "BLOCK" "NIV_ID"))(niv_def))

(command "_layer" "_make" "nivel" "_color" "7" "nivel" "") ;Inicio del ciclo de insercin de niveles. Se conserva el valor anterior como ;valor por defecto (variable OLDNIV) (if (null oldniv)(setq oldniv "0.0")) (while (setq ptniv (getpoint "\nSituar NIVEL: ")) (setq txniv (getstring (strcat "\nCota <" oldniv "> : "))) (if (= txniv "")(setq txniv oldniv)(setq oldniv txniv)) (command "insert" "niv_id" ptniv 1 1 0 txniv) ) (setvar "attdia" oad)(setvar "cmdecho" 1) ) ;;Programa para insertar el codigo identificador de alturas: (defun C:ALT ( / oce oad ptalt txalt ) (setq oce (getvar "cmdecho"))(setvar "cmdecho" 0) (setq oad (getvar "attdia"))(setvar "attdia" 0) (setvar "luprec" 2)(setvar "pdmode" 0) (if (null (tblsearch "BLOCK" "ALT_ID"))(alt_def)) (command "_layer" "_make" "alturas" "_color" "1" "alturas" "") (if (null oldalt)(setq oldalt "I")) (while (setq ptalt (getpoint "\nAlturas: ")) (setq txalt (getstring (strcat "\nNmero <" oldalt ">: "))) (if (= txalt "")(setq txalt oldalt)(setq oldalt txalt)) (command "insert" "alt_id" ptalt 1 1 0 txalt) )(setvar "attdia" oad)(setvar "cmdecho" oce) ) ;;Programa de insercin de COLUMNAS (bloque COL_ID) ;;Rutina para determinar el inicio de la numeracion: (defun nxtcol ( / ) (if (null (setq cnt_col (getint "\nPrximo Num. COLUMNA: "))) (setq cnt_col 0) ) ) ;;Programa Principal: (defun C:COL ( / oce col1 col2 prang) (setq oce (getvar "cmdecho"))(setvar "cmdecho" 0) ;Si no existe el bloque, lo crea: (if (null (tblsearch "BLOCK" "COL_SIM"))(col_def)) (if (null cnt_col)(nxtcol)(setq cnt_col (1+ cnt_col))) ;Las siguientes lineas permiten seleccionar un color si el que hubiera establecido ;para la creacion de entidades fuera PORCAPA o PORBLOQUE. Este color se ;utiliza en la creacin de una capa para la insercin de las columnas. (setq ncolor (if (=(type (read (getvar "cecolor"))) 'INT) (getvar "cecolor") (acad_colordlg 1 nil) ) )

;Aqu se inicia el ciclo de insercin de columnas, que se numeran secuencialmente y se ;giran de acuerdo al angulo con las columnas anterior y posterior: (if (setq col1 (getpoint (strcat "\nSituar COLUMNA " (itoa (setq cnt_col (1+ cnt_col))) ": "))) (progn (command "_layer" "_make" "columnas" "_color" ncolor "columnas" "") (initget 33) (while (setq col2 (getpoint col1 (strcat "\nSituar COLUMNA " (itoa (1+ cnt_col)) ": "))) (command "insert" "col_sim" col1 1 1 (if prang (/ (* (/ (+ prang (angle col1 col2)) 2) 180.0) pi) (/ (* (setq prang (angle col1 col2)) 180.0) pi) ) (itoa cnt_col) ) (setq prang (angle col1 col2) col1 col2 cnt_col (1+ cnt_col))(initget 32) ) (command "insert" "col_sim" col1 1 1 (/ (* prang 180.0) pi)(itoa (1+ cnt_col))) ) ) (redraw)(setvar "cmdecho" oce) ) ;;Dilogo que visualiza los programas cargados: (alert (strcat "PROGRAMAS CARGADOS:" "\nCOL=Inserta COLUMNAS" "\nNIV=Cotas de Niveles" "\nALT=Indica Alturas" ) ) ;;;--------------------------FIN DEL PROGRAMA------------------------------------------------

ENTMAKE-ando Objetos NO-GRFICOS

Del Newsgroup comp.cad.autocad:


Benoit Bissonnette escribi: > > Hola, He estado considerando si es posible crear/modificar una capa, un > estilo de cotas o un estilo de texto con una llamada a entmake. He intentado > lo siguiente, y por supuesto, no funciona: > > (entmake '((100 . "AcDbSymbolTableRecord") > (0 . "LAYER") > (2 . "TEST_1")

> > > > > > > > >

(70 . 64) (62 . 5) (6 . "CONTINUOUS") ) ) ;entmake Cualquier ayuda sera apreciada. Gracias! Benoit Bissonnette

La cuestin es interesante. Por mi parte nunca lo haba intentado. As que estuve revisando la cosa un poco. Aqu est la respuesta que hube de enviarle: He estado repasando mis entmakes. Pues s, se pueden crear capas con entmake! Antes debes obtener la lista patrn con entget, utilizando el nombre de objeto de la tabla como argumento. Este nombre de objeto que corresponde a la tabla puede leerse empleando la funcin tblobjname:
(entget (tblobjname "LAYER" "cualquier_nombre_de_capa"))

Esta funcin AutoLISP se introdujo con la versin 13. La siguiente rutina crear una capa con el nombre que introduzca el usuario:
(defun c:mlay () (setq laynam (getstring "\nNombre de la capa: ")) (entmake (list '(0 . "LAYER") '(5 . "28") '(100 . "AcDbSymbolTableRecord") '(100 . "AcDbLayerTableRecord") (cons 2 laynam) '(70 . 64) '(62 . 7) '(6 . "CONTINUOUS") ) ) )

A tu cdigo parece faltarle solamente la lista: '(100 . "AcDbLayerTableRecord")


> > > > > > > > (entmake '((100 . "AcDbSymbolTableRecord") (0 . "LAYER") (2 . "TEST_1") (70 . 64) (62 . 5) (6 . "CONTINUOUS") ) )

Espero que esto te sea de utilidad

La parte de imagen con el identificado r de relacin rId397 no se encont

Entidades y sistemas de coordenadas

por Reinaldo Togores Fernndez <reinaldo.togores@unican.es> Este artculo fu publicado en el nmero 53, febrero-marzo 1998 de AUTOCAD Magazine.

1. 2. 3. 4.

Sistemas de Coordenadas Vector normal y definicin del SCO Transformacin de coordenadas entre sistemas Descripcin del Programa

En nuestro artculo anterior (AUTOCAD Magazine, nmero 49), proponamos un programa para la conversin de polilneas 3D en polilneas 2D. Dicho programa posea una limitacin: slo operaba sobre polilneas 3D contenidas en el plano XY o en planos paralelos a l. El motivo de esta limitacin reside en la diferente manera en que se expresan las coordenadas de los vrtices de las polilneas 3D y 2D. En las primeras, los vrtices se expresan en coordenadas referidas al Sistema de Coordenadas Universal (SCU). En las segundas las coordenadas estaran expresadas en el Sistema de Coordenadas de Objeto (SCO) de cada entidad particular. Ambos sistemas slo coincidiran en caso de que el SCO sea idntico al SCU. An cuando este anlisis tena en cuenta slo las polilneas clsicas, lo mismo vale para las polilneas optimizadas de la versin 14. Como prometimos entonces, en este segundo artculo abordamos la problemtica de aplicar dicha conversin a polilneas 3D coplanares situadas en cualquier posicin en el espacio.
La pa rte

I. Sistemas de Coordenadas:

Comenzaremos por una breve discusin de los sistemas de coordenadas implicados. Examinemos los datos utilizados por AutoCAD para definir dos entidades 2D, en este caso crculos, con el centro en el mismo punto del espacio, contenido uno de ellos (que llamaremos A) en el plano XY del SCU y el otro (B) en un plano paralelo al plano XY de un Sistema de Coordenadas Personales (SCP) definido a partir de un giro de 45 en torno al eje Y "Universal".

Lista de entidad Crculo A: ( Nombre de Entidad Tipo de Entidad (-1 . <Entity name: 25e0558>) (0 . "CIRCLE")

Lista de entidad Crculo B: ( (-1 . <Entity name: 25e0560>) (0 . "CIRCLE")

Identificad or Subclase Espacio Capa Subclase Centro Radio Vector Normal

(5 . "2B") (100 . "AcDbEntity") (67 . 0) (8 . "0") (100 . "AcDbCircle") (10 10.0 10.0 0.0) (40 . 5.0) (210 0.0 0.0 1.0) )

(5 . "2C") (100 . "AcDbEntity") (67 . 0) (8 . "0") (100 . "AcDbCircle") (10 10.0 -7.07107 7.07107) (40 . 5.0) (210 0.707107 0.0 0.707107) )

De la lista de asociacin identificada con el cdigo 10 obtenemos con (cdr (assoc 10 lista_entidad)) la informacin que corresponde a las coordenadas del centro del crculo.

Crculo A: X=10.0 Y=10.0 Z=0.0 Crculo B: X=10.0 Y=-7.07107 Z=7.07107

Pero este centro que genera dos series de valores XYZ diferentes es en realidad el mismo punto. Ms an, si investigamos el valor de sus coordenadas utilizando el comando ID obtendramos:

En el SCU: X=10.0000 Y=10.0000 Z=0.0000 En el SCP: X=7.0711 Y=10.0000 Z=7.0711

El resultado es harto sorprendente: Tres valores distintos (a-c, b y d) para un mismo punto del espacio. La explicacin reside en que los tres valores resultan de los tres sistemas diferentes en que dichas coordenadas se expresan:

Sistema de Coordenadas Universales (SCU): es el sistema "de referencia", en funcin del cual se definen todos los dems. Este sistema es siempre el mismo, por lo que los valores medidos con respecto a l permanecen constantes cuando se pasa a otros sistemas. Es el valor que obtenemos en respuesta al comando ID estando activo el SCU.

Sistema de coordenadas Personales (SCP): es el sistema "de trabajo". El usuario puede especificar en cada momento el SCP mas adecuado a las tareas de dibujo que realiza. Todos los puntos que se transmiten a los

comandos de AutoCAD, incluidos los devueltos por funciones externas y rutinas de AutoLISP, estn en el sistema SCP actual (a menos que el usuario los preceda de un * en la solicitud Comando). Los valores que obtuvimos a partir del comando ID son fcilmente explicables teniendo en cuenta el giro de 45 en torno al eje Y de nuestro SCP (resultando el valor de X e Y=10 x cos 45).

Sistema de Coordenadas de Objeto (SCO): en este sistema, que hace referencia al propio objeto, se expresan los valores de los puntos en la lista de entidad (grupos DXF 10 al 37) devuelta por la funcin ENTGET.

La pa rte

II. Vector normal y definicin del SCO:

Observemos el otro campo en que difieren los registros de entidad de ambos crculos:

Vector Normal:

(210 0.0 0.0 1.0)

(210 0.707107 0.0 0.707107)

El cdigo 210 identifica el vector unitario normal, un vector 3D de longitud igual a la unidad que describe (salvo excepciones que ms adelante sealaremos) el eje Z del SCO. Para una direccin dada del eje Z o extrusin, hay un nmero infinito de sistemas de coordenadas, definidas mediante la traslacin del origen en el espacio 3D y la rotacin de los ejes X e Y en torno al eje Z. Sin embargo, para una direccin del eje Z, hay un nico SCO que se define a partir de los siguientes criterios:

Su origen coincide con el origen del SCU. La orientacin de los ejes X e Y dentro del plano XY se calculan de una manera que es descrita en la documentacin de AutoCAD como "arbitraria pero consistente", mediante el llamado Algoritmo de Eje Arbitrario, cuya discusin hara demasiado extensa esta exposicin.

Estos dos criterios explican que el SCO no coincida necesariamente con el SCP vigente en el momento de dibujarse la entidad. Y de ah los valores discordantes que pueden obtenerse para los puntos de una entidad segn se investiguen con comandos como ID y LIST o provengan de la lectura de la lista de entidad del objeto que se obtiene a partir de la funcin ENTGET, an cuando la lectura de esos valores se realice estando vigente el mismo SCP en que fue dibujada originalmente la entidad. Obviamente, ser necesario convertir siempre a coordenadas del SCO los valores de los puntos que se pasen a las funciones ENTMOD o ENTMAKE para la modificacin de estas entidades o para la creacin de otras nuevas de las mismas caractersticas. En algunos casos el SCO coincidir con el SCU. Este es el caso de las entidades 3D, es decir, las entidades que pueden dibujarse en planos no paralelos al plano XY del SCP actual. Estas entidades incluyen lneas, puntos, 3Dcaras, polilneas y vrtices 3D, mallas y

vrtices de mallas 3D y splines. En todos estos casos, los valores XYZ estarn dados con referencia al SCU. No sucede lo mismo con las Entidades 2D (crculo, arco, slido 2D, trazo, texto, atributo y definicin de atributo, forma, insercin de bloque, polilnea 2D, vrtice 2D) que slo pueden dibujarse en el plano XY del SCP actual o en planos paralelos al mismo. Sus coordenadas se expresan siempre en valores referidos al SCO. Al referirnos ms arriba al significado del cdigo 210 lo describamos como vector normal que permite definir la direccin Z del SCO. El vector normal que describira el SCU estara dado por la lista de tres nmeros reales (0.0,0.0,1.0). Pero el dato de la lista asociada al cdigo 210 no nos permite siempre determinar si el SCO y el SCU coinciden. Ser necesario tener en cuenta una serie de excepciones en que el valor asociado a este cdigo sera mejor descrito como vector de extrusin. En general, las entidades 3D no pueden tener "Altura de Objeto". Se dan dos excepciones a esta regla: la lnea y el punto. En ambas entidades este vector no representa el sistema de coordenadas que definen su posicin en el espacio, sino la direccin del vector normal del SCP en que dichas entidades fueron creadas y que sirve para determinar la direccin en el espacio en que se producir su "extrusin" al establecerse un valor diferente de cero para su Altura de Objeto. Aunque no es susceptible de ser extruda, tambin presenta una "anomala" de este tipo la entidad SPLINE cuando la misma es coplanar. Cuando en la lista de entidad no aparece este cdigo, se sobreentiende que sus coordenadas estn referidas al SCU.
La pa rte

III. Transformacin de coordenadas entre sistemas

Para la conversin entre sistemas de coordenadas AutoLISP dispone de la funcin TRANS:


(trans pto orig dest [desp])

En el caso que nos ocupa, la conversin se hara desde el SCU (ya que nos proponemos transformar una entidad 3D) al SCO que correspondera al plano que contiene los vrtices de la 3DPOL. La funcin TRANS admite como primer argumento pto un punto o vector de desplazamiento (lista de tres nmeros reales), un segundo argumento orig que indica el sistema de coordenadas al que se refieren los valores de pto, y un tercer argumento dest que especifica el sistema de coordenadas al que se transformarn los valores de pto. Un cuarto argumento opcional desp indica, si es distinto de cero que se trata de un vector en lugar de un punto. En el caso que nos ocupa. La funcin trans se aplicara a las coordenadas de cada vrtice (dato asociado al cdigo 10 de la lista de entidad) y el sistema de coordenadas de origen siempre sera, segn hemos explicado ms arriba, el SCU. El problema estara en definir cul sera el SCO que correspondera a la nueva entidad Polilnea 2D que pretendemos construir. Analicemos para ello las formas de especificar los sistemas de coordenadas que acepta la funcin TRANS.

Sistema de Coordenadas: Universal SCU Personal SCP Pantalla SCV E. Papel SCVEP Objeto SCO

Especificacin: 0 1 (SCP actual) 2 (actual) 3 (slo en combinacin con el cdigo 2) Un nombre de entidad (asociado al cdigo 1 en la lista de entidad)

Un vector de extrusin (vector unitario normal 3D) Como no tenemos an una entidad a la que podamos recurrir para identificar el SCO empleando el primer procedimiento, no habr otra va que la de acometer el clculo del vector normal al plano que contiene la polilnea original. Como se trata de una polilnea 3D, lo primero que tendremos que hacer ser asegurarnos que todos sus vrtices se encuentran en el mismo plano. De no ser as, la conversin sera imposible. El procedimiento a seguir sera:

Extraer de la entidad seleccionada la lista de sus vrtices. Extraer de dicha lista de vrtices tres que no sean colineales. Comprobar que cada uno de los vrtices restantes se encuentre situado en el plano definido por los tres vrtices seleccionados en el paso anterior, es decir que sean coplanares. Si la condicin anterior se cumple, calcular el vector normal al plano y proceder a la conversin.

Dichos procedimientos se abordarn como funciones de librera de uso general, susceptibles de ser incorporadas a cualquier programa.
La pa rte

IV. DESCRIPCIN DEL PROGRAMA

Funcin extpt Funcin colineal Funcin trio Funcin plano Funcin normal Funcin test

La pa rte

Funcin extpt: Extraccin de la lista de vrtices.

Prepara una lista de puntos a partir de las listas de entidad "POLYLINE". Debe ser llamada desde una funcin que compruebe que se trata de una polilnea (2D o 3D) y obtenga lista de entidad que debe pasar a esta funcin como argumento. Establece un bucle que termina al encontrar la entidad SEQEND. Devuelve la lista de valores asociados al cdigo 10 de cada vrtice. Utiliza la variable local tmplst .
(defun extpt ( lista_ / tmplst ) (while (/= (cdr (assoc 0 (setq lista_ (entget (entnext (cdr (assoc -1 lista_)))) ) ) ) "SEQEND" ) (setq tmplst (cons (cdr (assoc 10 lista_)) tmplst)) ) (setq tmplst (reverse tmplst)) )
La pa rte

Funcin colineal: Comprobacin de la Colinealidad.

El algoritmo empleado para determinar la condicin de colinealidad parte de la consideracin de las propiedades de los vectores determinados por tres puntos no coincidentes. En un sistema tridimensional de coordenadas rectangulares podemos representar los vectores unitarios desde el origen a los puntos (1,0,0), (0,1,0) y (0,0,1) por i, j y k. Cualquier vector en el espacio puede ser representado en funcin de estos vectores unitarios. De esta manera, el vector desde el origen al punto A(a,b,c) ser:

Los vectores ai, bj, y ck son los componentes x, y, z, del vector A. La longitud del vector A puede obtenerse a partir de las longitudes de los lados de los tringulos rectngulos OCA y ODC (Fig. 1).

La parte de imagen con el identificador de relacin rId419 no se encontr en el archivo.

Segn el teorema de Pitgoras tenemos que


(OA)2=(OC)2 + (CA)2 =(OD)2 + (DC)2 + (CA)2 =a2 + b2 + c2.

De aqu que la longitud de A sea:

Generalizando el caso, un vector entre cualesquiera dos puntos del espacio, P1(x1,y1,z1) y P2(x2,y2,z2) tendra los componentes (x2-x1)i , (y2-y1)j, ( z2-z1)k y se representara mediante la expresin (Fig. 2):

P1P2=(x2-x1)i+ (y2-y1)j+ (z2-z1)k

Y su longitud, la distancia entre P1 y P2, sera:

El criterio que nos permitir detectar la colinealidad de los tres puntos examinados se deriva de la formulacin del producto escalar de dos vectores:

Donde es el ngulo entre los vectores si se trazaran desde un origen comn. Los puntos seran colineales cuando cos =1 en:

El producto AB se obtendr mediante:

De ah que si se cumple que:

podemos afirmar que los vectores A y B son colineales. El programa toma los tres primeros puntos de la lista que recibe como argumento y determina los valores de los coeficientes a1, a2 y a3 del primer vector y los coeficientes b1, b2 y b3 del segundo, sustituyendo dichos valores en la ecuacin anterior. Si la condicin es cierta devuelve T y si es falsa nil.
(defun colineal ( ptlist / ) (setq p1 (car ptlist) p2 (cadr ptlist) p3 (caddr ptlist) ;;Vector A = p1->p2 a1 (- (car p2)(car p1)) a2 (- (cadr p2)(cadr p1)) a3 (- (caddr p2)(caddr p1)) ;;Vector B = p1->p3 b1 (- (car p3)(car p1)) b2 (- (cadr p3)(cadr p1)) b3 (- (caddr p3)(caddr p1)) ) (if (equal (abs (/ (float(+ (* a1 b1)(* a2 b2)(* a3 b3))) (* (sqrt (float (+ (expt a1 2) (expt a2 2) (expt a3 2)))) (sqrt (float (+ (expt b1 2)(expt b2 2)(expt b3 2)))) ) ) ) 1 0.00000001 ) T nil ) )

Slo cabra observar que la igualdad se comprueba mediante la funcin EQUAL, que permite establecer un pequeo margen de error teniendo en cuenta el redondeo de las cifras en las operaciones efectuadas con nmeros reales.
La pa rte

Funcin trio: seleccin de tres vrtices no colineales.

Esta funcin recorre la lista de vrtices de tres en tres hasta encontrar aqullos que pasados a la funcin colineal antes descrita obtengan nil como resultado. En el caso de que la lista incluya solamente dos vrtices, o que todos los vrtices fueran colineales (lo que implica que sern tambin coplanares), se construir un vrtice de manera arbitraria con el

objetivo de poder definir uno de los infinitos planos que contienen a dichos vrtices. Cualquier punto del espacio sera vlido. En este caso hemos optado por incrementar en la unidad el valor de X del ltimo vrtice.
;;Funcin trio (defun trio (ptlist / tmplst) (setq tmplst ptlist) (cond ((= (length tmplst) 2) ;;Si slo hay dos vrtices, (setq p1 (car tmplst) p2 (cadr tmplst) p3 ;;se construye uno arbitrario. (list (1+ (car (last tmplst))) (cadr (last tmplst)) (caddr (last tmplst)) ) ) ) ((= (length tmplst) 3) (setq p1 (car tmplst) p2 (cadr tmplst) p3 (last tmplst) ) ) ;;mientras sean ms de tres ;;y sean colineales (t (while (and (colineal tmplst) (> (length tmplst) 3)) (setq tmplst (cdr tmplst)) ) ) ) ;;Si todos son colineales, ;;se modifica el tercer vrtice (if (colineal (list p1 p2 p3)) (setq p3 (list (1+ (car p3)) (cadr p3) (caddr p3))) ) )
La pa rte

Funcin plano: Comprobacin de la Coplanaridad:

De los puntos incluidos en la lista la funcin trio ha seleccionado los tres primeros vrtices no colineales. A partir de ellos se determinar la frmula del lugar geomtrico del plano. Para hacerlo tendremos en cuenta que un vector perpendicular a dos lados del tringulo definido por dichos tres vrtices ser el vector normal al plano que contiene el tringulo en cuestin. Para encontrar este vector planteamos que:
P1P2=(x2-x1)i+(y2-y1)j+(z2-z1)k

P1P3=(x3-x1)i+(y3-y1)j+(z3-z1)k N=Ai + Bj + Ck

El problema consistira en hallar los coeficientes A, B y C de manera que N fuera perpendicular a los otros vectores. As que:
N P1P2=(x2-x1)A+(y2-y1)B+(z2-z1)C=0 N P1P3=(x3-x1)A+(y3-y1)B+(z3-z1)C=0

Para simplificar el sistema, asignamos el valor de C=1. Una vez determinados los coeficientes A, B y C, se puede establecer la ecuacin del plano:
Ax + By + Cz + D=0

Cualquier punto cuyas coordenadas XYZ satisfagan dicha ecuacin pertenecer al plano considerado.
(defun plano ( ptlist / tmplst resultado) (trio ptlist) (setq ;;Hallar los coeficientes de la ecuacin del plano: ;;Ecuacin vector 1->2: (x2-x1)A+(y2-y1)B+(z2-z1)C=0 ;;Ecuacin vector 1->3: (x3-x1)A+(y3-y1)B+(z3-z1)C=0 ;;Despejando A en 1->2: ;; A = (( -(y2-y1)B -(z2-z1)) / (x2-x1)) ;;Despejando A en 1->3: ;;A = ((-(y3-y1)B-(z3-z1)) / (x3-x1)) A;;Coeficiente A= (/ (float ((* (- (caddr p3)(caddr p1))(- (cadr p2)(cadr p1))) (* (- (caddr p2)(caddr p1))(- (cadr p3)(cadr p1))) ) ) (float ((* (- (car p2)(car p1))(- (cadr p3)(cadr p1))) (* (- (car p3)(car p1))(- (cadr p2)(cadr p1))) ) ) ) B ;;Coeficiente B = (/ (float ((* (- (caddr p3)(caddr p1))((* (- (caddr p2)(caddr p1))()

(car p2)(car p1))) (car p3)(car p1)))

) (float ((* (- (car p3)(car p1))(- (cadr p2)(cadr p1))) (* (- (cadr p3)(cadr p1))(- (car p2)(car p1))) ) ) ) D;;Coeficiente D: ((+ (* A (car p1)) (* B (cadr p1)) (caddr p1) ) ) ) ;;Ahora se comprueban todos los puntos de la lista original contra la frmula del plano (setq resultado T tmplst ptlist) (repeat (length tmplst) (if (equal (+ (* A (car (car tmplst))) (* B (cadr (car tmplst))) (caddr (car tmplst)) D ) 0 0.00000001 ) ( ) (setq resultado nil) ) (setq tmplst (cdr tmplst)) ) resultado ;;La funcin devuelve cierto "T" o falso "nil" )

La pa rte

Funcin normal: Determinacin del vector unitario normal.

Una ecuacin del tipo Ax + By + Cz + D=0 representa un plano perpendicular al vector N=Ai + Bj + Ck. De ah que una vez conocidos los coeficientes A y B necesarios para determinar la ecuacin del plano. Para obtener el vector unitario habr que dividir dichos coeficientes por la longitud del vector que respondera a la relacin que vimos ms arriba, obtenida a partir del teorema de Pitgoras:
(defun normal ( A B / ) ;;Determinar el vector normal unitario (list

(/ A (sqrt (+ (expt A 2) (expt B 2) (expt 1 2))) ) (/ B (sqrt (+ (expt A 2) (expt B 2) (expt 1 2))) ) (/ 1 (sqrt (+ (expt A 2) (expt B 2) (expt 1 2))) ) ) )
La pa rte

Funcin test: prueba de las funciones propuestas.

Para no hacer ms extenso este artculo, considerando ya haber abusado ms de la cuenta de la benevolencia de nuestros lectores, acabaremos integrando las funciones elaboradas a una pequea funcin de prueba. Esta funcin informara sobre la coplanaridad de cualquier polilnea seleccionada, y de ser coplanar, suministrara los valores del vector unitario normal. Si se trata de una polilnea 2D, pueden comprobarse estos valores con los asociados al cdigo 210 de la lista de entidad. En un prximo artculo aplicaremos estas funciones a la transformacin de polilneas 3D en polilneas 2D cuando las primeras no resultaran paralelas al plano XY del SCU.
(defun c:test () (if (plano (extpt (entget (car (entsel))))) (progn (alert "Los vrtices de esta polilnea \nson coplanares") (setq vector_unitario (normal A B)) (alert (strcat "El vector normal unitario es: \n (" (rtos (car vector_unitario)) " " (rtos (cadr vector_unitario)) " " (rtos (caddr vector_unitario)) ")" ) ) ) (alert "Los vrtices de esta polilnea \nNO son coplanares") ) )
La pa rte

Conversin de Polilneas 3D->2D (Programa) CONVERSIN DE DATOS DE ENTIDAD:


La parte de imagen con el identificado r de relacin rId435 no se encont

DE COORDENADAS UNIVERSALES A COORDENADAS DE OBJETO.


por Reinaldo Togores Fernndez <reinaldo.togores@unican.es>

1. 2. 3. 4. 5.

Transformacin de la Entidad Cabecera ( POLYLINE). Descripcin del programa. Funciones Auxiliares. Funcin principal C:3A2POL. Conclusiones.

En este tercer artculo abordamos el problema de convertir las coordenadas de puntos extradas de la lista de datos de entidad de un objeto 3D (en este caso una polilnea 3D), que vienen expresados en valores XYZ referidos al Sistema de Coordenadas Universal (SCU) a valores referidos al Sistema de Coordenadas del Objeto (SCO). La problemtica descrita en el primero de los artculos de esta serie ha sido superada en gran medida a partir de la salida al mercado de la versin 14, que discrimina entre splines cuyos vrtices son coplanares y aqullas en que no lo son, para exportarlas en formato versin 12 como Polilneas 2D 3D. Esto no resta, sin embargo, inters al tema de las transformaciones de coordenadas que pueden valer para un gran nmero de aplicaciones. Y, por supuesto, estamos convencidos de que muchos de nuestros lectores an siguen utilizando la versin 13. Aunque atendiendo a las ventajas que ofrece la 14, seguramente ser por poco tiempo. Recordemos que aqul programa era solamente vlido para polilneas 3D paralelas al Sistema de Coordenadas Universal (SCU ). El motivo, como explicbamos entonces, es que slo en este caso coincidirn el SCU (al que se refieren los valores de coordenadas para las entidades 3D) y el SCO (en el que se expresan las coordenadas de los objetos 2D). En aquella ocasin nos interesaba demostrar el procedimiento para manipular las listas de asociacin con el propsito de definir entidades empleando la funcin entmake. La generalizacin del procedimiento para incluir objetos que presentaran cualquier orientacin en el espacio 3D exiga el desarrollo de una serie de funciones auxiliares que fueron el tema de un segundo artculo. Ahora ya podemos abordar las transformaciones de coordenadas de un sistema a otro. Para estas transformaciones habremos de recurrir a la funcin trans. La transformacin en este caso se har desde el SCU al SCO, siendo el tipo de dato un punto y no un desplazamiento. Al no tener una entidad a la que recurrir para determinar el SCO, deberemos calcular el vector unitario normal al plano que contiene los vrtices, cosa que se

logra mediante el uso de las funciones auxiliares ya explicadas en nuestro artculo anterior. Estas funciones realizan adems una comprobacin previa de la condicin de coplanaridad en los vrtices de la polilnea 3D original. El programa de conversin es similar al que se expuso en el primer artculo. Por un momento hemos dudado si desarrollar un nuevo programa que hiciera la conversin directamente al nuevo tipo de POLILNEA OPTIMIZADA. Pero nos hemos decidido por mantener el formato de la polilnea clsica sobre la base de dos consideraciones: hacer accesible esta funcin a los usuarios de la versin 13 y hacer posible la transformacin de las polilneas 3D adaptadas a curva-B (B-spline) que no pueden convertirse a polilneas optimizadas. Si se quisiera hacer posteriormente la conversin a polilneas optimizadas bastara con aplicar la nueva herramienta CONVERTIR que transforma las polilneas y sombreados de versiones anteriores a las nuevas entidades ms compactas de la versin 14. Recordemos que la polilnea es una secuencia de tres tipos de entidad:

una cabecera o entidad POLYLINE, una serie de vrtices (entidades VERTEX) que incluyen tanto los que se han introducido por el usuario para definir la entidad como aqullos que se generan de manera automtica al adaptarse la entidad a curva mediante la herramienta EDITPOL. Una entidad SEQEND, que indica el fin de secuencia.

Consideremos cules de las sublistas que definen estas entidades se vern afectadas por la transformacin de las coordenadas del SCU al SCO. Debemos recordar que todos los cambios que se hacan en el programa original siguen siendo necesarios, y que los descritos a continuacin se aaden a aqullos.
La pa rte

I. Transformacin de la Entidad Cabecera (POLYLINE):

Tenemos dos listas de asociacin que sern afectadas por las transformaciones:

Cdigo 210 Cdigo 10

Direccin de la extrusin. Expresado como un vector 3D. El valor a utilizar ser el mismo calculado mediante la funcin normal, que adems servir de argumento a la
funcin trans.

Segn la documentacin del programa, un punto "ficticio" construido de manera tal que los valores de X e Y son siempre 0, y el valor de Z es la elevacin de la polilnea (en SCO en 2D y SCU en 3D).

La descripcin anterior, en lo que se refiere al cdigo 10, puede resultar confusa. Cuando hablamos de entidades 3D, y en particular de la Polilnea 3D, en realidad no tiene sentido referirnos a la "elevacin" del objeto. Si estudiamos las listas de asociacin que definen la entidad, encontraremos que la lista asociada al cdigo 10 siempre es igual a (10 0.0 0.0 0.0), independientemente del valor asignado a la variable ELEVATION (utilizando el comando ELEV). No sucede as con las polilneas 2D donde, aunque cada vrtice

individual est definido por sus coordenadas XYZ, la entidad cabecera tambin tendr asignado un valor de "elevacin" asociado a este cdigo 10. Una asignacin incorrecta de este valor resultar en un desplazamiento de la entidad transformada respecto a la original, an cuando los valores de las coordenadas de los vrtices hayan sido correctamente calculados. El valor que corresponde a la Z del punto ficticio asociado al cdigo 10 lo calcularemos como la distancia entre el plano que pasa por el origen del sistema de coordenadas y el plano que contiene a la entidad. Para ello ha sido necesario desarrollar la nueva funcin auxiliar pt_elev a partir de las siguientes consideraciones: Suponiendo que R sea el origen (0,0,0) y P un punto cualquiera de la polilnea, por ejemplo el primer vrtice (ver figura 1).

Sea N el vector unitario normal calculado segn la funcin normal que fue desarrollada en el artculo anterior. Podemos definir la distancia entre el plano que contiene al origen y el plano paralelo que contiene a la entidad como la proyeccin escalar del vector RP (p1i,p2j,p3k) sobre el vector unitario normal N (n1,n2,n3). De manera tal que:
RPN=p1n1 + p2n2 + p3n3

Vase el listado de esta funcin ms abajo. Entidades Vrtice (VERTEX): La transformacin de SCU a SCO afectar solamente a la lista de asociacin que contiene las coordenadas del vrtice:

Cdig o 10

Punto de ubicacin del vrtice, expresado en coordenadas referidas al SCO para la polilnea 2D. Este valor se obtendr de aplicar la funcin trans al valor del punto referido al SCU (que es el ledo de las listas de asociacin de la polilnea 3D. La funcin aplicada se regir por la siguiente sintaxis: (trans coordenadas_punto 0 vector_normal nil) donde:

el argumento 0 (cero) indica el sistema de coordenadas de origen (SCU ), el argumento vector_normal indica el sistema de coordenadas de destino ( SCO),

el argumento nil indica que el valor se refiere a un punto y no a un desplazamiento.

Entidad Fin de Secuencia (SEQEND): Ninguno de los datos asociados a esta entidad contienen valores expresados en coordenadas XYZ. Por ello en esta entidad no se introduce ninguna transformacin adicional.

La pa rte

II. DESCRIPCIN DEL PROGRAMA:

Funcin chk_plano

La pa rte

Funcin chk_plano:

Esta funcin viene a sustituir a la funcin chk_2D del programa original. En esta nueva funcin se insertan las funciones auxiliares que fueron desarrolladas en nuestro segundo artculo del nmero anterior, ENTIDADES Y SISTEMAS DE COORDENADAS. La funcin chk_plano comprueba si una polilnea 3D en cualquier posicin del espacio est contenida en un plano. Dicha comprobacin sigue el siguiente proceso:

Verificar si se trata de una polilnea 3D. En caso afirmativo, se extraer una lista con las coordenadas de cada vrtice (funcin extpt) la lista de coordenadas se pasa a la funcin plano que a su vez: extrae mediante la funcin trio los primeros tres vrtices no colineales de la lista (la comprobacin del carcter de colinealidad la realiza la funcin colineal) a partir de estos tres vrtices se calcula la frmula del plano que los contiene (funcin plano) se evala la funcin para el resto de los puntos de la lista. Si algn punto no satisface la ecuacin, la misma evala como nil. Si los puntos son coplanares, se calcula (funcin normal) el valor del vector unitario normal del plano.

(defun chk_plano ( lista_ / resultado) ;Comprueba de que se trata de ;una Polilnea 3D: (if (member '(100 . "AcDb3dPolyline") lista_) (if (plano (extpt lista_)) ;Extrae (funcin extpt) la lista de ;vrtices y comprueba si son ;coplanares, de serlo calcula ;el vector normal (setq resultado (normal A B)) ;en caso de que la entidad no sea una Polilnea 3D

;o que no sea coplanar, se emiten los ;correspondientes mensajes de advertencia. (progn (setq resultado nil) (alert "La Polilnea \nNO es coplanar") ) ) (alert "La entidad seleccionada \nNO es una 3Dpol") ) )

La pa rte

III. FUNCIONES AUXILIARES (llamadas desde chk_plano): Funcin extpt Funcin pt_elev Funcin colineal Funcin trio Funcin plano Funcin normal Funcin cabecera Funcin vertices

La pa rte

Funcin extpt

Se modifica la anterior funcin extpt para no incluir los vrtices introducidos como puntos de control de una armadura B-spline. Esta comprobacin se realiza mediante la funcin logand, comprobando la existencia del bit 16.
(defun extpt ( lista_ / tmplst ) (while (/= (cdr (assoc 0 (setq lista_ (entget (entnext (cdr (assoc -1 lista_))))) )) "SEQEND") (if (/= (logand 16 (cdr (assoc 70 lista_))) 16) (setq tmplst (cons (cdr (assoc 10 lista_)) tmplst)) ) ) (setq tmplst (reverse tmplst)) )

La pa rte

Funcin pt_elev:

Nueva funcin. Vase la explicacin ms arriba.


(defun pt_elev ( lista_ vector_normal / tmplst ) (setq tmplst (extpt lista_)) (+ (* (car (car tmplst))(car vector_normal)) (* (cadr (car tmplst))(cadr vector_normal)) (* (caddr (car tmplst))(caddr vector_normal)) ) )

La pa rte

Funcin colineal: Para una explicacin detallada ver el artculo anterior

(defun colineal ( ptlist / ) (setq p1 (car ptlist) p2 (cadr ptlist) p3 (caddr ptlist) a1 (- (car p2)(car p1)) a2 (- (cadr p2)(cadr p1)) a3 (- (caddr p2)(caddr p1)) b1 (- (car p3)(car p1)) b2 (- (cadr p3)(cadr p1)) b3 (- (caddr p3)(caddr p1)) ) (if (equal (abs (/ (float(+ (* a1 b1)(* a2 b2)(* a3 b3))) (* (sqrt (float (+ (expt a1 2) (expt a2 2) (expt a3 2)))) (sqrt (float (+ (expt b1 2)(expt b2 2)(expt b3 2))))) )) 1 0.00000001) T nil) )

La pa rte

Funcin trio: Para una explicacin detallada ver el artculo anterior

(defun trio (ptlist / tmplst) (setq tmplst ptlist) (cond ((= (length tmplst) 2) (setq p1 (car tmplst) p2 (cadr tmplst) p3 (list (1+ (car (last tmplst)))(cadr (last tmplst))(caddr (last tmplst))) ) ) ((= (length tmplst) 3) (setq p1 (car tmplst) p2 (cadr tmplst) p3 (last tmplst)) ) (t (while (and (colineal tmplst) (> (length tmplst) 3)) (setq tmplst (cdr tmplst)) )

) ) (if (colineal (list p1 p2 p3)) (setq p3 (list (1+ (car p3)) (cadr p3) (caddr p3))) ) )

La pa rte

Funcin plano: Para una explicacin detallada ver el artculo anterior

(defun plano ( ptlist / tmplst resultado) (trio ptlist) (setq A (/ (float (- (* (- (caddr p3)(caddr p1))(- (cadr p2)(cadr p1))) (* (- (caddr p2)(caddr p1))(- (cadr p3)(cadr p1))))) (float (-(* (- (car p2)(car p1))(- (cadr p3)(cadr p1))) (* (- (car p3)(car p1))(- (cadr p2)(cadr p1))))) ) B (/ (float (-(* (- (caddr p3)(caddr p1))(- (car p2)(car p1))) (* (- (caddr p2)(caddr p1))(- (car p3)(car p1))))) (float (- (* (- (car p3)(car p1))(- (cadr p2)(cadr p1))) (* (- (cadr p3)(cadr p1))(- (car p2)(car p1))))) ) D (- (+ (* A (car p1))(* B (cadr p1))(caddr p1))) ) (setq resultado T tmplst ptlist) (repeat (length tmplst) (if (equal (+ (* A (car (car tmplst)))(* B (cadr (car tmplst))) (caddr (car tmplst)) D) 0 0.00000001) ( )(setq resultado nil) ) (setq tmplst (cdr tmplst)) ) resultado )

La pa rte

Funcin normal: Para una explicacin detallada ver el artculo anterior


) (expt A 2) (expt B 2) (expt 1 2)))) (expt A 2) (expt B 2) (expt 1 2)))) (expt A 2) (expt B 2) (expt 1 2))))

(defun normal ( A B / (list (/ A (sqrt (+ (/ B (sqrt (+ (/ 1 (sqrt (+ ) )

La pa rte

Funcin cabecera:

Realiza las modificaciones necesarias a la entidad POLYLINE. A las modificaciones del programa original se aaden la sustitucin de los valores asociados a los cdigos 10 y 210.
(defun cabecera ( lista_ vector_normal / n_lista cont ) (setq cont 0 n_lista (quote ()) ) (repeat (length lista_) (cond ;;Cdigos -1 y 5: nombre de la entidad e identificador, Autocad los crear ;;de manera automtica por ello no deben incluirse en la lista definitoria ;;de la nueva entidad. ((or (= (car (nth cont lista_)) -1)(= (car (nth cont lista_)) 5))()) ;;Se sustituir, al encontrarlo, el nombre de subclase "AcDb3dPolyline" por ;;el de "AcDb2dPolyline" ((= (cdr (nth cont lista_)) "AcDb3dPolyline") (setq n_lista (cons (cons 100 "AcDb2dPolyline") n_lista)) ) ;;Cdigo 70: si est establecido el bit 8 (comprobado mediante LOGAND), se ;;resta del valor: ((= (car (nth cont lista_)) 70) (if (= (logand (cdr (assoc 70 lista_)) 8) 8) (setq n_lista (cons (cons 70 (- (cdr (assoc 70 lista_)) 8)) n_lista) ) ) ) ;;Cdigo 210: Sustituirlo por el vector normal del plano que contiene la polilnea: ((= (car (nth cont lista_)) 210) (setq n_lista (cons (cons 210 vector_normal) n_lista)) )

;; Cdigo 10: Elevacin: calculada a partir de la distancia desde el origen al plano: ((= (car (nth cont lista_)) 10) (setq n_lista (cons (cons 10 (list 0.0 0.0 (pt_elev lista_ vector_normal))) n_lista ) ) ) ;;y las dems sublistas se transfieren sin modificacin: (t (setq n_lista (cons (nth cont lista_) n_lista))) ) (setq cont (1+ cont)) ) ;;invierte la lista y crea la cabecera de la polilnea ;;en caso de que la operacin no tenga xito, se establece la variable p_err. (if (not (entmake (reverse n_lista)))(setq p_err t)) )

La pa rte

Funcin vertices:

(defun vertices ( lista_ vector_normal / ) (while (/= (cdr (assoc 0 (setq lista_ (entget (entnext (cdr (assoc -1 lista_))))) ) ) "SEQEND" ) (setq cont 0 n_lista (quote ())) (repeat (length lista_) (cond ;;Cdigos -1 y 5: nombre de la entidad e identificador, se suprimen. ((or (= (car (nth cont lista_)) -1)(= (car (nth cont lista_)) 5)) () )

;;Se sustituir, al encontrarlo, el nombre de subclase "AcDb3dPolylineVertex" ;;por el de "AcDb2dVertex" ((= (cdr (nth cont lista_)) "AcDb3dPolylineVertex") (setq n_lista (cons (cons 100 "AcDb2dVertex") n_lista)) ) ;;Cdigo 70: si est establecido el bit 32, se elimina. ((= (car (nth cont lista_)) 70) (if (= (logand (cdr (assoc 70 lista_)) 32) 32) (setq n_lista (cons (cons 70 (- (cdr (assoc 70 lista_)) 32)) n_lista) ) ) ) ;; Cdigo 10: se transforman las coordenadas SCO en SCU, ;; utilizando para ello la funcin TRANS. ((= (car (nth cont lista_)) 10) (setq n_lista (cons (cons 10 (trans (cdr (assoc 10 lista_)) 0 vector_normal nil)) n_lista ) ) ) ;;y las dems sublistas se copian sin cambios (t (setq n_lista (cons (nth cont lista_) n_lista)) ) ) (setq cont (1+ cont)) ) (if (not (entmake (reverse n_lista)))(setq v_err t)) ) ;;La variable lista_ contiene ahora la lista de asociacin de la entidad SEQEND. ;;Se proceder a crear ahora la nueva entidad SEQEND (setq cont 0 n_lista (quote ())) (repeat (length lista_) (cond ;;Es necesario suprimir el cdigo -2, nombre de la entidad cabecera. ;;Este cdigo ser asignado por AutoCAD.

( (or (= (car (nth cont lista_)) -1) (= (car (nth cont lista_)) -2) (= (car (nth cont lista_)) 5) ) () ) (t (setq n_lista (cons (nth cont lista_) n_lista)) ) ) (setq cont (1+ cont)) ) (reverse n_lista) (if (not (entmake (reverse n_lista)))(setq s_err t)) ;;Antes de borrar el objeto original se comprueba ;;que no existan errores en la creacin de ;;las entidades componentes. (if (or p_err v_err s_err) (alert "Error en la \ncreacin de entidades. \nNO se borrar el original." ) (entdel (cdr (assoc -1 lista_ent))) ) )

La pa rte

IV. Funcin principal C:3A2POL:

(defun C:3A2POL ( / p_err v_err s_err lista_ent prev oce A B D ptlist p1 p2 p3) (setq oce (getvar "cmdecho")) (setvar "cmdecho" 0) ;;Seleccin de la entidad a convertir. ;;Para selecciones mltiples crear un ;;conjunto de seleccin con SSGET (setq lista_ent (entget (car(entsel)))) ;;Comprueba que sea una 3Dpol, y si lo es ;;comprueba que sea coplanar. ;;si la funcin chk_plano NO devuelve nil, ;;entonces realiza la transformacin. (if (setq vector_normal (chk_plano lista_ent)) (progn (cabecera lista_ent vector_normal) (vertices lista_ent vector_normal) )

) (setvar "cmdecho" oce) (princ) ) (prompt "\n\t3A2: Conversin de Polilneas 3D a 2D, versin 2")(princ)

La pa rte

V. CONCLUSIONES:

Completamos con este tercer artculo una investigacin en torno los mecanismos empleados por AutoCAD para la definicin de entidades mediante la escritura directa a la base de datos del dibujo a travs de la funcin entmake. Como dijimos en el primero de esta serie, dicho procedimiento tiene como ventajas sobre la creacin de entidades mediante la funcin command una independencia total de los ajustes establecidos en materia de sistemas de coordenadas, referencias a entidades, elevacin, etc. as como una limpieza y rapidez de ejecucin que se evidencian en el presente programa. Pero con esto no se agotan las aplicaciones posibles de estos procedimientos basados en la funcin entmake. Como muestra de las posibilidades an no tratadas podemos mencionar la creacin de bloques de cualquier complejidad directamente por el mismo programa que los inserta, sin tener que disponer previamente de una biblioteca externa, o la creacin por el mismo procedimiento de los objetos no grficos del dibujo.

Reinaldo Togores Fernndez, Arquitecto Profesor asociado de Tcnicas de Expresin Grfica, Escuela Tcnica Superior de Ingenieros de Caminos, Canales y Puertos, Universidad de Cantabria Instructor de CAD del Instituto de Formacin y Estudios Sociales. Pgina WEB personal: http://personales.unican.es/togoresr/

Anda mungkin juga menyukai