You are on page 1of 25

Operaciones matemticas en AutoLISP

Hemos visto las operaciones matemticas bsicas: suma, resta, multiplicacin y divisin y las funciones 1+ y 1-. Ahora vamos con otras funciones de AutoLISP que nos permitiran realizar casi cualquier operacin matemtica en nuestras rutinas. (ABS numero) Esta funcin devuelve el valor absoluto del nmero que se le pase como argumento. Por ejemplo: (abs 23.8) devuelve 23.8 (abs -23.8) tambin devuelve 23.8 Si el nmero que recibe como argumento es entero, devuelve un nmero entero y si es un nmero real, devuelve un real. (abs -7) devuelve 7 (abs -7.0) devuelve 7.0 (abs 0) devuelve 0 (FIX numero) Esta funcin devuelve la parte entera de un nmero. De modo que devuelve un nmero entero. Ojo! esta funcin no redondea, sino que elimina lo que est detrs del punto decimal. (fix 15.8) devuelve 15. (fix -15.8) devuelve -15 (fix 0.99) devuelve 0 (REM numero1 numero2 [numero3] ) Esta funcin devuelve el resto de la divisin de numero1 entre numero 2. (rem 2.5 2) devuelve 0.5 (rem 3 2) devuelve 1 Cuando se indican ms de 2 nmeros (rem 1 2 3) es equivalente a (rem (rem 1 2) 3). Es decir, primero calcula el resto de la divisin entre 1 y 2, que es 1, y despus lo divide entre 3 y devuelve su resto, que es 1. Si todos los nmeros que recibe como argumentos son enteros, devuelve un nmero entero y si alguno de ellos es un nmero real, devuelve un real. (rem 3 2.0) devuelve 1.0

(SIN angulo) Devuelve el seno de un ngulo indicado en radianes. (sin 0) devuelve 0.0 (sin (/ pi 2)) devuelve 1.0 (COS angulo) Funciona igual que la anterior, pero devuelve el coseno del ngulo, que recibe en radianes. (cos 0) devuelve 1.0 (cos pi) devuelve -1.0 (ATAN numero 1 [numero2]) Devuelve el arco cuya tangente sea numero1. Por ejemplo: (atan 0) devuelve 0.0 ya que el ngulo que tiene tangente 0 es el 0.0 Si se indica un segundo nmero (ATAN num1 num2) lo que hace es dividir num1 entre num2 y devuelve el arco cuya tangente sea el resultado de la divisin. Esto se hace para facilitar lo siguiente (atan (sin angulo) (cos angulo)) devuelve angulo (SQRT numero) Esta funcin devuelve la raiz cuadrada del numero que recibe como argumento. Siempre devuelve un nmero real, no entero. (sqrt 4) devuelve 2.0 (sqrt 2.0) devuelve 1.41 (EXPT num exp) Devuelve el nmero num elevado al exponente exp. (expt 2 2) devuelve 4 (expt 2 3) devuelve 8 Si todos los nmeros que recibe como argumentos son enteros, devuelve un nmero entero y si alguno de ellos es un nmero real, devuelve un real. (expt 3 2.0) devuelve 9.0 (EXP num)

Devuelve el nmero e ( e = 2.71828 ) elevado al nmero num. Siempre devuelve un nmero real. (exp 1) devuelve 2.71828 (exp 2) devuelve 7.38906 (LOG numero) Esta funcin devuelve el logaritmo neperiano del nmero que recibe como argumento. (log 1) devuelve 0.0 (log 2) devuelve 0.693147 (GCD entero1 entero2) Esta funcin recibe dos nmeros enteros y devuelve su mximo comn divisor (o denominador). Siempre devuelve un nmero entero. (gcd 15 5) devuelve 5 (gcd 9 33) devuelve 3 (MAX num1 num2 ) Devuelve el mayor de los nmeros que recibe como argumentos. (max 2 4 1 3 6) devuelve 6 (max 8 4 -9) devuelve 8 Si todos los nmeros que recibe como argumentos son enteros, devuelve un nmero entero y si alguno de ellos es un nmero real, devuelve un real. (max 8 4.0 -9) devuelve 8.0 (MIN num1 num2 ) Devuelve el menor de los nmeros que recibe como argumentos. (min 2 3 6) devuelve 2 (min 8 4 -9) devuelve -9 Si todos los nmeros que recibe como argumentos son enteros, devuelve un nmero entero y si alguno de ellos es un nmero real, devuelve un real. (min 8 4.0 -9) devuelve -9.0

Solicitar textos y puntos al usuario Recuerdas las funciones GETINT y GETREAL? Nos sirven para solicitar al usuario un nmero entero y real, respectivamente. Pues la funcin que se utiliza para solicitar textos al usuario es muy parecida. (GETSTRING [modo] [mensaje]) Se puede ejecutar sin parmetros (getstring) pero no es recomendable. Se suele indicar un mensaje de texto que explique al usuario lo que se le est solicitando. Por ejemplo: (getstring Cual es tu nombre?) Supongamos que te llamas Pepe, a (getstring Cual es tu nombre?) responderas Pepe y ya est. Incluso se podra asignar el nombre que indique el usuario a una variable: (setq nombre (getstring Cual es tu nombre?)) Pero que sucede si te llamas Jos Luis? Pues que en cuanto pulses el espacio es como si hubieras pulsado Intro. No nos permite insertar textos con espacios. Para que admita textos con espacios, debemos hacer un pequeo cambio: (setq nombre (getstring T Cual es tu nombre?)) Le estamos indicando el argumento [modo] = T. Este argumento puede ser cualquier expresin de AutoLISP, en este caso le pasamos el valor T = Cierto, verdadero. Si no se indica el modo, o si al evaluarlo devuelve nil = Falso, vaco; entonces no admite espacios. Y si se pone cualquier expresin que al evaluarse no devuelva nil, permite espacios. (setq nombre (getstring (+ 1 2) Cual es tu nombre?)) permite responder con espacios, ya que (+ 1 2) devuelve 3 que es distinto de nil. (setq nombre (getstring (setq var1 nil) Cual es tu nombre?)) no permite responder con espacios, ya que (setq var1 nil) devuelve nil. Solicitar puntos al usuario Para solicitar puntos se utilizan dos funciones que tambin son parecidas a GETINT y a GETREAL. (GETPOINT [pto_base] [mensaje]) Esta funcin le pide un punto al usuario y devuelve una lista con las coordenadas del punto indicado. El usuario puede indicar el punto en pantalla con el ratn o tecleando sus coordenadas, tal y como se hara al dibujar en AutoCAD. Se puede ejecutar sin parmetros (getpoint) pero no es recomendable. Se suele indicar un mensaje de texto que explique al usuario lo que se le est solicitando. Por ejemplo: (getpoint Punto inicial)

Lo habitual es que adems ese punto se almacene en una variable (setq pto (getpoint Punto inicial)) As asignamos a la variable pto algo parecido a lo siguiente: (120.56 135.88 0.0) Veamos ahora para que sirve el argumento opcional [pto_base] aprovechando que tenemos el punto pto definido. (getpoint pto Siguiente punto:) Aparece una lnea elstica entre el punto pto y la posicin del cursor. (GETCORNER pto_base [mensaje]) Esta funcin se utiliza tambin para solicitar puntos al usuario. En este caso el punto base no es opcional, hay que indicarlo. Veamos la diferencia entre las dos expresiones siguientes: (getpoint pto Siguiente punto:) (getcorner pto Siguiente punto:) Al utilizar getpoint, se muestra una lnea elstica entre el punto pto y la posicin del cursor. Si se utiliza getcorner, en lugar de una lnea elstica, aparece un rectngulo. Fijmonos un momento en lo que devuelven tanto getpoint como getcorner: (125.68 117.68 0.0). Se trata de una lista, una lista con las corrdenadas de un punto. Bien, pues en el prximo artculo veremos algunas funciones para manejar listas. Funciones para manejar listas

AutoLISP es un lenguaje de programacin basado en listas as que es lgico que el tratamiento que reciban las listas de elementos sea muy bueno. Por otra parte, en AutoCAD nos encontraremos listas continuamente y en todas partes, desde las coordenadas de los puntos como se indicaba en el artculo anterior, hasta los datos de las entidades que son almacenados en la base de datos de AutoCAD. As que vamos a introducir ahora una serie de funciones para manipular listas de elementos. (CAR lista) Esta funcin devuelve el primer elemento de la lista que recibe como argumento. De modo que si (siguiendo con el ejemplo del tema anterior) en la variable pto hemos asignado el valor devuelto por getpoint, tenemos una lista con las coordenadas X, Y y Z del punto designado. Supongamos que pto = (10.0 20.0 0.0). (car pto) devuelve la coordenada X del punto pto. Es decir 10.0

(CDR lista) Esta funcin devuelve la lista que recibe como argumento pero sin el primer elemento. (cdr pto) devolver una lista formada por las coordenadas Y y Z del punto pto. Es decir, (20.0 0.0) (CADR lista) Basndonos en las dos funciones anteriores y recordando que podemos ejecutar listas de instrucciones dentro de otras (a esto le llamamos anidamiento): Cmo se obtendra la coordenada Y del punto pto? Veamos: CDR devuelve la lista sin el primer elemento CAR devuelve el primer elemento de una lista

De modo que (cdr pto) devuelve (Y Z). As que para obtener la coordenada Y podemos escribir: (car (cdr pto)) devuelve la coordenada Y del punto pto. y, cmo obtenemos la coordenada Z? Pues, volviendo a aplicar la funcin CDR para llegar a la coordenada Z (cdr pto) devuelve (Y Z) (cdr (cdr pto)) devuelve (Z)

Podras pensar que escribiendo (cdr (cdr pto)) obtenemos la coordenada Z, sin embargo no es as. La expresin (cdr (cdr pto)) devuelve una lista con un nico elemento, la coordenada Z del punto pto. Para obtener la coordenada Z del punto pto tenemos que escribir: (car (cdr (cdr pto))) devuelve la coordenada Z del punto pto. En resumen, las coordenadas del punto pto se obtendrian mediante: X ==> (car pto) Y ==> (car (cdr pto)) Z ==> (car (cdr (cdr pto)))

Otras funciones combinando CAR y CDR Si en las expresiones indicadas anteriormente para obtener las coordenadas X, Y y Z ponemos las letras A y D de cAr y cDr en maysculas, lo anterior quedara: X ==> (cAr pto) Y ==> (cAr (cDr pto)) Z ==> (cAr (cDr (cDr pto)))

Este ejemplo es simplemente para introducir una simple regla de mnemotecnia ya que las funciones CAR y CDR se pueden agrupar. Para ello, existen una serie de funciones que se denominan juntando las Aes y las Des de cAr y cDr respectivamente. El ejemplo anterior, queda:

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

Esto nos servir como regla para recordar el nombre de estas funciones. Debes recordar tambin que tan solo se permiten 4 niveles de anidacin, as que entre la c y la r solo puede haber 4 letras (Aes o Des). Supongamos que tenemos la siguiente lista asignada a la variable lst = ((a b) (c d) (e f)). OJO!! es una lista en la que sus elementos son a su vez listas. Puedes definir la variable lst escribiendo: (setq lst (list (list a b) (list c d) (list e f))) Cmo obtendramos a ?? (car lst) devuelve (a b) que es el primer elemento de lst, y a es el primer elemento de (a b) as que: (car (car lst)) devuelve a, o lo que es lo mismo:

(cAAr lst) devuelve a y el elemento c? (cDr lst) devuelve la lista sin el primer elemento, es decir ((c d) (e f)). Ahora si hacemos (cAr (cDr lst)) devuelve el primer elemento de la lista anterior, es decir (c d). As que (cAr (cAr (cDr lst))) devuelve c, o lo que es lo mismo:

(cAADr lst) devuelve c Cmo obtener d ? (cDr lst) devuelve ((c d) (e f)) (cAr (cDr lst)) devuelve el primer elemento de ((c d) (e f)), es decir devuelve (c d) Si ahora hacemos (cDr (cAr (cDr lst))) obtenemos (d), que no es lo mismo que d. Ya que se trata de una lista cuyo primer elemento es d. As que (cAr (cDr (cAr (cDr lst)))) devuelve d, o lo que es lo mismo:

(cADADr lst) devuelve d Y cmo obtener e ? (cDr lst) devuelve ((c d) (e f)) y (cDr (cDr lst)) devuelve ((e f)). Ojo! se trata de una lista cuyo primer (y nico) elemento es a su vez otra lista con dos elementos. As que (cAr (cDr (cDr lst))) devuelve (e f), de modo que (cAr (cAr (cDr (cDr lst)))) devuelve e, o lo que es lo mismo:

(cAADDr lst) devuelve e Por ltimo, veamos cmo se obtiene f.

(cAr (cDr (cDr lst))) devuelve (e f) tal como se vio en el ejemplo anterior. As que (cDr (cAr (cDr (cDr lst)))) devuelve (f), que os recuerdo que se trata de una lista y que no es lo mismo que f. Por tanto (cAr (cDr (cAr (cDr (cDr lst))))) devuelve f.

Podramos pensar que (cADADDr lst) tambin devuelve f. Pero al ejecutar esta lnea AutoCAD nos dice que la funcin cADADDr no est definida. Ya dijimos antes que se pueden agrupar hasta 4 funciones cAr y cDr, pero aqu estamos intentando agrupar 5, y lgicamente no podemos. Para obtener f podramos escribir, por ejemplo: (cAr (cDADDr lst)) (cADADr (cDr lst))

(LENGTH lista) En la variable pto tenamos una lista con las coordenadas de un punto, pero si solo trabajamos en 2D, la coordenada Z no nos interesa. As que muchas veces los puntos tan slo tendrn 2 coordenadas (X Y). Pero para un programa no es lo mismo que tenga 2 que 3 coordenadas, a lo mejor va a buscar la coordenada Z y no existe producindose un error en nuestra rutina. As que necesitamos conocer el nmero de elementos que tienen las listas. Para ello se utiliza la funcin length, que devuelve el nmero de elementos de la lista que recibe como argumento. Por ejemplo: (length pto) devuelve 3. y si el punto pto estuviera en 2D (X Y) devolvera 2. Y qu devolvera (length lst) ? siendo lst = ((a b) (c d) (e f)). Pues devolvera 3, ya que lst es una lista con 3 elementos, que a su vez son listas de dos elementos cada una. Qu devolvera (length (car lst)) ? El nmero de elementos del primer elemento de lst, es decir el nmero de elementos de (a b), que es 2. (LIST elemento1 elemento2 ) Esta funcin devuelve una lista formada por los elementos indicados. De modo que se utiliza para crear listas. Por ejemplo: (list 1 2 3) devuelve (1 2 3) (list pepe 2 Juan) devuelve (pepe 2 Juan) Veamos que hace la siguiente expresin: (list (list a b) c (list d e) f) Recuerda que en AutoLISP cuando nos encontramos con listas anidadas unas dentro de otras, siempre se evalan primero las listas interiores. (list a b) devuelve (a b) (list d e) devuelve (d e)

As que (list (list a b) c (list d e) f) devuelve la siguiente lista ((a b) c (d e) f). Ejecutar comandos de AutoCAD Una de las mayores ventajas de la programacin en AutoLISP es la posibilidad de ejecutar directamente comandos de AutoCAD en nuestras rutinas. (COMMAND comando [datos]) Esta es la funcin que nos permite ejecutar comandos de AutoCAD. Hay dos cosas a tener en cuenta con esta funcin: siempre devuelve nil los nombres de los comandos de AutoCAD, y sus opciones, se indican como textos por lo que van incluidos entre comillas

(command linea (list 0.0 0.0) (list 100.0 200.0)) Dibujar una lnea desde el origen al punto 100,200. Pero, nos falta algo: Al dibujar lneas en AutoCAD se van indicando puntos y siempre pide Siguiente punto: de modo que para terminar el comando LINEA hay que pulsar INTRO. Pues ese Intro tambin hay que pasrlo a la funcin command: (command linea (list 0.0 0.0) (list 100.0 200.0) ) o as (command linea (list 0.0 0.0) (list 100.0 200.0) ) Lo realmente potente de COMMAND es que podemos ejecutar casi todos los comandos de AutoCAD. Cules no? Son muy pocos, por ejemplo Nuevo para empezar un dibujo nuevo. Pero todos los comandos de dibujo, edicin, etc se pueden ejecutar. Los datos dependern del comando de AutoCAD indicado. Por ejemplo para el comando circulo, ser: (command circulo (list 0.0 0.0) 25.0) Esto dibujar una circunferencia de radio 25 con centro en el origen. Los idiomas de AutoCAD Supongamos que no disponemos de una versin en castellano de AutoCAD, sino que est en ingls, o en Francs, o Chino Mandarn; qu pasa si ejecutamos esto: (command linea (list 0.0 0.0) (list 100.0 200.0) ) AutoCAD no conocer el comando linea, as que nos dar un error. Por suerte se puede solucionar, ya que sino un programa realizado para AutoCAD en Francs slo servira para las versiones en Francs. AutoCAD en realidad no habla un nico idioma, sino que es bilingue, dispone de una lengua que es la que muestra (que corresponde con la versin idiomtica del programa: Castellano, Francs, etc) y una lengua interna, el Ingls. De modo que los comandos de AutoCAD (y sus opciones) se pueden escribir en Castellano o en ingls. Pero para diferenciar unos de otros a los comandos en la lengua nativa de AutoCAD (Ingls) se les antepone un guin bajo:

(command _circle (list 0.0 0.0) 25.0) (command _line (list 0.0 0.0) (list 100.0 200.0) ) Las opciones de los comandos tambin se deben indicar en ingls anteponiendo un guin bajo. Por ejemplo: (command _circle (list 0.0 0.0) _d 25.0) Esta lnea dibuja una circunferencia de Dimetro 25 con centro en el origen. Comandos de AutoCAD originales Por otra parte, ya se ha dicho anteriormente que los comandos de AutoCAD se podran redefinir para que funcionen de forma distinta. As se podra cambiar el comando circulo para que dibuje pentgonos y el comando linea para que dibuje circunferencias. Si redefinimos el comando lnea para que dibuje circunferencias, entonces deberamos indicar algo similar a (command linea centro radio) en lugar de (command linea pt0 pt1) . Pero cmo haramos entonces para dibujar una lnea? Para ejecutar los comandos originales de AutoCAD, y no los redefinidos (si lo estn) debemos anteponer al nombre del comando un punto, por ejemplo: (command .circulo (list 0.0 0.0) 25.0) (command .linea (list 0.0 0.0) (list 100.0 200.0) ) Podemos adems indicar los comandos en Ingls anteponiendo un guin bajo as que tambin los podramos escribir as: (command ._circle (list 0.0 0.0) 25.0) (command _.circle (list 0.0 0.0) 25.0) Da igual si se pone antes el punto o el guin bajo. Redefinir un comando de AutoCAD Para redefinir un comando de AutoCAD debemos: 1. Ejecutar el comando ANULADEF (En Ingls undefine) indicando el nombre del comando a redefinir. De este modo se elimina la definicin del comando de AutoCAD, y la nica forma de ejecutarlo ser anteponiendo al nombre del comando un punto. 2. Crear y cargar una macro en la que est definido un nuevo comando con el nombre del comando que acabamos de anular. Veamos un ejemplo: 1. primero anulamos la definicin del comando lnea. 1. Podemos hacerlo desde AutoCAD con el comando ANULADEF (En ingls undefine)

2. o desde AutoLISP ejecutando: (command _undefine linea) o (command _undefine _line) 2. podemos comprobar que el comando lnea ya no funciona 1. Puedes tratar de ejecutarlo en castellano, en ingls, directamente en AutoCAD o en una expresin de AutoLISP 2. la nica forma de ejecutarlo es anteponiendo a su nombre un punto .linea. 3. Iniciamos el editor de Visual LISP: Herr. >AutoLISP > Editor de Visual LISP 1. Creamos la macro que se indica a continuacin, la guardamos y la cargamos en AutoCAD (defun C:LINEA ( ) (setq pt (getpoint Centro del crculo: )) (setq rad (getreal Radio del crculo)) (command ._circle pt rad) ) Ahora el comando linea dibujar crculos. Para recuperar el valor original del comando podemos hacer dos cosas: 1. cerrar AutoCAD y abrirlo de nuevo, de modo que la macro que hemos creado se borre de la memoria del ordenador 2. ejecutar el comando de AutoCAD redefine (En Ingls es igual, pero con un guin bajo delante) e indicarel nombre del comando del que queremos recuperar su definicin original, es decir linea. Bueno, por ltimo un ejercicio: Crear una macro que defina un nuevo comando de Autocad llamado CIRCPERI que dibuje una circunferencia indicando su centro y la longitud de su permetro. Operaciones lgicas en AutoLISP Existe una serie de funciones de AutoLISP que nos permiten realizar operaciones lgicas. Suelen emplearse en combinacin con las operaciones de comparacin. (AND expr1 expr2 ) Esta funcin devuelve T si ninguna de las expresiones que recibe como argumento es (devuelve) nil. Si una sola de las expresiones devuelve nil, la funcin AND devolver nil. Es decir, comprueba que se cumplan todas las expresiones que recibe como argumento. (and (< 3 4) (= 5 5.0)) devuelve T, porque las dos expresiones devuelven T (and (> 3 4) (= 5 5.0)) devuelve nil, porque (> 3 4) devuelve nil En el ejemplo anterior, como la primera expresin (> 3 4) devuelve nil, ya no se continan evaluando el resto de expresiones. Cmo hay una expresin que

devuelve nil, AND devolver nil. De modo que la expresin (= 5 5.0) ya no se evala. Vamos a complicarlo un poco Qu devolver la siguiente expresin? (and (= 5 5.0) (< 3 4) Soy un texto 5.8) Preguntando de otra forma: Alguna de las expresiones que recibe AND como argumentos es nil? No, as que AND devuelve T. (setq a Soy otro texto b 15 c T d nil) (and a b) devolver T (and a d) devolver nil porque d es nil (and a b c d) devolver nil, porque d es nil (OR expr1 expr2 ) Devuelve nil si todas las expresiones son nil. En caso de que alguna de las expresiones no devuelva nil, OR devuelve T. Es decir, comprueba si alguna de las expresiones se cumple. (or (/= 5 5.0) (> 3 4)) devuelve nil, porque ambas expresiones son nil (or (= 5 5.0) (> 3 4)) devuelve T, pues la primera expresin se cumple En el ejemplo anterior, como la primera expresin (= 5 5.0) devuelve T, ya no se continan evaluando el resto de expresiones. Cmo hay una expresin que devuelve T, OR devolver T. De modo que la expresin (> 3 4) ya no se evala. (setq a Soy otro texto b 15 c T d nil) (or a b) devuelve T (or c d) devuelve nil (or d d) devuelve nil (EQUAL expr1 expr2 [precision]) En el tema anterior vimos la funcin de comparacin = que nos sirve para determinar si dos nmeros o textos son iguales. Pero que pasa si queremos comparar otra cosa, por ejemplo dos listas (como dos puntos). (setq pt1 (list 10.0 20.0 0.0) pt2 (list 10.0 (* 10.0 2) 0.0) pt3 (list 9.99 20.0 0.0) pt4 (list 9.99 20.02 0.0)) Al comparar estas listas (puntos) con la funcin = siempre nos devuelve nil. Aunque pt1 y pt2 sean iguales, y muy parecidos a pt3 y pt4. Por tanto, la funcin = no nos servir para comparar listas. Para comparar dos listas se utilizar la funcin EQUAL.

(equal 5 5.0) devuelve T, al igual que la funcin =, porque 5 vale lo mismo que 5.0 (equal pt1 pt2) devuelve T EQUAL adems ofrece un argumento opcional [precisin]. Veamos como funciona : (equal 4.99 5.0 0.1) devuelve T, porque compara 4.99 y 5 pero con una precisin de 0.1. As que con esa precisin 4.99 == 5.0 Sin embargo, si subimos la precisin (equal 4.99 5.0 0.001) devuelve nil Y qu pasa con las listas? Tambin podemos indicarle una precisin? Veamos.. (equal pt1 pt3 0.1) devuelve T, porque compara los elementos de las listas (coordenadas) con la precisin que hemos indicado, 0.1 Si subimos la precisin (equal pt1 pt3 0.001) devuelve nil (equal pt1 pt4 0.01) devuelve nil (equal pt1 pt4 0.02) devuelve T, porque la precisin es 0.02 que es exactamente la diferencia entre 20.02 y 20 El utilizar una precisin muy elevada no implica que todas las comparaciones devuelvan T, todo depender de los valores a comparar: (equal 15 20 100) devuelve T (equal 5000 4200 100) devuelve nil (NOT expr) A esta funcin le gusta llevarle la contraria a la expresin que recibe como argumento. si la expresin devuelve nil, entonces NOT devuelve T. si la expresin devuelve cualquier cosa que no sea nil, entonces NOT devuelve nil.

(not 5) devuelve nil (not Texto) devuelve nil (not (+ 5 1)) devuelve nil Si hacemos (setq a 5 b nil c T d Nuevo texto)

(not b) devolver T, porque b es nil (not c) devolver nil. Veamos que devuelve la siguiente expresin: (and (not c) 5) Como c es T, (not c) devuelve nil. Al no cumplirse la primera expresin de AND, esta devuelve nil y no contina evaluando.

Operaciones de comparacin En este artculo veremos las funciones de AutoLISP que nos permiten realizar comparaciones, por ejemplo, para ver si algo es mayor que algo, o menor, o si es igual. (= expr1 expr2 ) Compara si expr1 devuelve el mismo resultado que expr2, en caso afirmativo devuelve T y en caso contrario devuelve nil. (= 5 (+ 1 4)) devuelve T porque (+ 1 4) devuelve 5 (= 5 (+ 1 4.0)) devuelve T aunque (+ 1 4.0) devuelve 5.0 y no 5. Pero 5 y 5.0 valen lo mismo, no? (= 5 5.0) devuelve T No solo podemos evaluar nmeros, tambin textos: (setq txt1 Curso de Lisp) (= txt1 Curso de Lisp) devuelve T (= txt1 Curso de LISP) devuelve nil. No es lo mismo un texto en maysculas que en minsculas. (= LISP Lisp) devuelve nil Estamos comparando expresiones, as que: (= (+ 1 5) (/ 12 2)) devuelve T porque ambas expresiones devuelven como resultado 6. La funcin = puede aceptar ms de dos expresiones: (= 6 (+ 1 5) 6.0 (/ 12 2)) devuelve T, pues las cuatro expresiones devuelven 6 o 6.0 (que vale lo mismo). (/= expr1 expr2 ) Es muy similar a la anterior. Devuelve T si las expresiones no devuelven el mismo valor y devuelve nil si todas las expresiones devuelven el mismo valor.

(/= 6 6.0) devuelve nil, porque 6 y 6.0 no son distintos (valen lo mismo). (/= (+ 5 5) (/ 12 2)) devuelve T, pues la primera expresin devuelve 10 y la segunda 6. (/= LISP Lisp) devuelve T (< expr1 expr2 ) Compara si expr1 es menor q expr2 (< 4 5) devuelve T, ya que 4 es menor que 5 (< 4 -5) devuelve nil (< 5 5.0) devuelve nil Si se ponen ms de 2 expresiones, se comprueba que estn ordenadas de menor a mayor y devuelve T si lo estn y nil si no lo estn. (< 1 2 3) devuelve T (< 1 2 0) devuelve nil (< (+ 1 2) (* 2 2.0) (/ 12 2)) devuelve T Tambin podemos comparar textos. El interprete de AutoLISP evala los cdigos ASCII de los textos. Es decir los ordena alfabticamente de la a a la z. (< Albacete Barcelona) devuelve T (< a c) devuelve T (< d c) devuelve nil (< C c) devuelve T, puesto que los cdigos ASCII de la maysculas son inferiores a los de las letras minsculas. Los cdigos ASCII, son una serie de nmeros que se asignaron a las letras del alfabeto y a algunos de los carcteres ms usuales. El carcter a tiene asociado el cdigo 97, la b el 98, etc. hasta la z. El carcter A tiene asociado el cdigo 65, la B el 66, etc. hasta la Z. (> expr1 expr2 ) Supongo que ya os imaginis como funciona, no? Comprueba si las expresiones estn ordenadas de mayor a menor. (> 5 3) devuelve T (> -2 3) devuelve nil

(> 5 2 3) devuelve nil (> 5 4 3) devuelve T Y ahora con los textos: (> a c) devuelve nil, pues el cdigo ASCII de a es menor que el de c. (<= expr1 expr2 ) Comprueba si las expresiones son menores o iguales que las anteriores. (<= 1 2 2.0 3) devuelve T (<= 1 3.0 2 3) devuelve nil (>= expr1 expr2 ) Comprueba si las expresiones son mayores o iguales que las anteriores (>= 3 2 2.0 1) devuelve T (>= 3 1.0 2 1) devuelve nil (>= 3 3 3 3) devuelve T Macro de ejemplo Veamos como se hara el ejercicio propuesto en el artculo anterior: Crear un nuevo comando llamado CIRCPERI que dibuje una circunferencia indicando su centro y la longitud de su permetro. Qu es lo primero que hay que hacer? Esta respuesta tiene que ser instintiva, como un acto reflejo: El pseudocdigo. Siempre comenzaremos nuestras rutinas escribiendo el pseudocdigo (o haciendo un diagrama de flujo) de lo que se pretende hacer. Bien, cmo podra ser el pseudocdigo de esta rutina?, vamos a ver: 1. 2. 3. 4. Pedir al usuario el centro de la circunferencia. Pedir al usuario el permetro de la circunferencia. Calcular el radio de la circunferencia a partir de su permetro. Dibujar la circunferencia.

Una vez que terminamos el pseudocdigo, ya tenemos el 80% de la rutina. Si el pseudocdigo es correcto, el traducirlo a cdigo es de lo ms simple. Iniciamos en editor de Visual LISP Herr. > AutoLISP > Editor de Visual LISP y creamos una nueva macro. Primero hay que aadir la definicin del nuevo comando CIRCPERI: (defun C:CIRCPERI ( ) Vamos a ver que es lo que nos indica el pseudocdigo:

1) Pedir al usuario el centro de la circunferencia. Podramos escribir (getpoint Centro de la circunferencia) pero tendramos que almacenar el punto indicado en una variable, as que aadiremos (setq pto (getpoint Centro de la circunferencia)) almacena el punto centro de la circunferencia en la variable pto. 2) Pedir al usuario el permetro de la circunferencia . Por ejemplo (setq peri (getint Permetro:)) pero al usar getint, solo permite obtener nmero enteros. As que podramos cambiarlo por: (setq peri (getreal Permetro:)) almacena el permetro de la circunferencia en la variable peri 3) Calcular el radio de la circunferencia a partir de su permetro . Peri = 2* pi * rad as que rad = Peri / ( 2 * pi). Traduciendo esta frmula a cdigo: (setq rad (/ peri (* pi 2))) calcula el valor del radio de la circunferencia 4) Dibujar la circunferencia (command _.circle pto rad) dibuja la circunferencia Slo nos falta una cosa. Recuerda: El nmero de parntesis de apertura tiene que ser igual al nmero de parntesis de cierre. As que: ) El cdigo completo de la rutina sera: (defun C:CIRCPERI ( ) (setq pto (getpoint Centro de la circunferencia)) (setq peri (getreal Permetro:)) (setq rad (/ peri (* pi 2))) (command _.circle pto rad) )

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

1. SI> Mensaje El lmite superior debe ser mayor que el inferior 2. NO > intervalo = lmite superior lmite inferior (IF condicin expr_si_cumple [expr_no_cumple]) La funcin IF es una de las ms empleadas al programar. Devuelve el valor de la ltima expresin evaluada. Si condicin es distinto de nil, entonces evala la expr_si_cumple. Si condicin devuelve nil evala la expr_no_cumple, si existe y si no existe no hace nada. Veamos algunos ejemplos: (if (= 2 2.0) (alert Los nmeros son iguales)) La condicin a evaluar es: (= 2 2.0) en la que tenemos un nmero entero 2 y uno real 2.0, pero su valor es el mismo. Aunque sean de distinto tipo 2 y 2.0 valen igual. As que la condicin devuelve T, evalundose la condicin si cumple que muestra un mensaje de alerta. La funcin IF devuelve el valor de la ltima expresin evaluada, es decir alert, que es nil. (if (= 2 3) (alert Los nmeros son iguales)) En este caso la condicin devuelve nil y al no existir expresin no cumple, no hara nada ms. Qu valor devolvera IF? El de siempre, el valor de la ltima expresin evaluada, que en este caso ha sido la propia condicin que devuelve nil. De modo que IF devolver nil. (if (= 2 3) (alert Los nmeros son iguales) (alert Los nmeros son distintos) ) En este caso el cdigo se ha escrito en varias lneas y tabulado para facilitar su comprensin. Ahora si tenemos una expresin no cumple, que ser evaluada ya que la condicin devuelve nil. Veamos el siguiente ejemplo: (setq liminf (getint \nLmite inferior)) (setq limsup (getint \nLmite superior)) (if (> liminf limsup) (alert El lmite superior debe ser mayor que el inferior) (setq limsup (getint \nLmite superior)) (setq intervalo (- limsup liminf)) (setq intervalo (- limsup liminf)) ) Viendo el cdigo anterior, tal vez pienses que si la condicin (> liminf limsup) se cumple, entonces se evaluar la lnea siguiente de cdigo completa. Pero no es as,

se evala la expresin si cumple, que es la primera expresin (alert El lmite superior debe ser mayor que el inferior). Si la condicin no se cumple, devuelve nil, se evaluar la expresin no cumple, que en este caso ser (setq limsup (getint \nLmite superior)). Tanto la expresin si cumple, como la no cumple solo pueden ser una nica expresin. El ejemplo de cdigo anterior nos dara un error ya que IF no puede tener ms que 3 expresiones: La condicin La expresin si cumple La expresin no cumple

(PROGN expr1 expr2 ) Para que se pueda indicar ms de una expresin si cumple, o no cumple, en la funcin IF se suele emplear la funcin PROGN. El valor devuelto por PROGN es el de la ltima expresin que recibe como argumento. Esta funcin en realidad no hace nada, tan solo nos permite agrupar una serie de expresiones. Cmo quedara el ejemplo anterior? (setq liminf (getint \nLmite inferior)) (setq limsup (getint \nLmite superior)) (if (> liminf limsup) (progn (alert El lmite superior debe ser mayor que el inferior) (setq limsup (getint \nLmite superior)) (setq intervalo (- limsup liminf)) ) (setq intervalo (- limsup liminf)) ) En este caso la condicin si cumple es todo lo siguiente: (progn (alert El lmite superior debe ser mayor que el inferior) (setq limsup (getint \nLmite superior)) (setq intervalo (- limsup liminf)) )

Si se cumple la condicin, se evala la condicin si cumple, es decir el progn. De modo que se van evaluando las expresiones contenidas en la funcin PROGN, que devuelve el valor de la ltima expresin (setq intervalo (- limsup liminf)), que ser el valor de la variable intervalo. En caso de que la condicin no se cumpla, se evala la condicin no cumple, (setq intervalo (- limsup liminf)) que curiosamente tambin devuelve el valor de la variable intervalo. Veamos ahora algunos ejemplos ms de estructuras condicionales: (if (and (= 2 2.0) (< 2 3)) (alert Las dos condiciones se cumplen) (alert Al menos una condicin no se cumple) ) En este caso la condicin es (and (= 2 2.0) (< 2 3)) que en este caso devolvera T, ya que se verifican las dos expresiones que recibe la funcin AND. (if (not var1) (alert Variable no definida) (alert Variable definida) ) En este caso si var1 es nil, (not var1) devolver T, indicando que la variable no se ha definido. En caso contrario, (not var1) devolver nil evalundose la expresin no cumple. Otro mtodo para hacer lo mismo, sera: (if var1 (alert Variable definida) (alert Variable no definida) ) Si var1 es distinto de nil, se evala la expresin si cumple. En caso de que var1 sea nil, se evaluara la expresin no cumple. Estructuras condicionales mltiples Con la funcin IF tan solo podemos indicar una condicin y dos opciones, si cumple y no cumple. Veamos ahora como se pueden indicar varias condiciones con sus respectivas expresiones si cumple. (COND (condicion1 [expr1_1] [expr1_2] ) [ (condicion2 [expr2_1] [expr2_2] ) ] )

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

Por ltimo, si tenemos (setq a 2 b 1.0 c 1.5) ninguna de las tres condiciones anteriores se verifica, de modo que pasamos a la siguiente condicin T, que lgicamente siempre devuelve T, as que siempre se verifica. Esto se suele utilizar mucho en la funcin COND, aadir como ltima condicin una que se verifique siempre. En lugar de T se poda haber puesto (not nil) o (= 1 1.0) que tambin son expresiones que siempre se cumplen. Para qu aadir una expresin que siempre se cumple? Muy sencillo, para incluir el cdigo que se desea ejecutar en caso de que no se verifique ninguna de las condiciones anteriores. Y qu sucede si se pone la condicin T como primera condicin? Pues sucede que las que estn a continuacin nunca se evaluarn, ya que T siempre se cumplir. Si en el ejemplo anterior hubiramos puesto: (cond (T (alert A no es igual a B) (alert A no es menor que C) (alert A no es menor que B) ) ((= a b) (alert A y B son iguales) (setq b (getreal Introduzca de nuevo B: )) ) ((< a c) (alert A es menor que C) ) ((< a b)) ) Independientemente de los valores de las variables a b y c siempre nos mostrar los mensajes de alerta indicando que A no es igual a B, A no es menor que C y A no es menor que B. Mostrar textos al usuario en AutoLisp Hay varias funciones para mostrar textos al usuario en AutoLisp. De momento vamos a ver un par de ellas, pero habr ms. (PROMPT mensaje) Muestra el texto indicado como argumento en pantalla, y siempre devuelve nil.

(prompt Bienvenidos al Curso) (ALERT mensaje) Muestra el texto que recibe como argumento en un letrero. Tambin devuelve nil. Se utiliza principalmente para avisar al usuario en caso de error, o para mostrarl alguna informacin importante. (alert Error: Dato no vlido) (TERPRI) En artculo correspondiente a las Operaciones de comparacin, creamos un nuevo comando para AutoCAD denominado CIRCPERI. Si has cargado y ejecutado el comando, habrs observado que los mensajes para solicitar el centro de la circunferencia y su permetro aparecen en la misma lnea de la ventana de comandos y sin separacin entre s, estn pegados. Para que los mensajes aparezcan en lneas distintas, se puede emplear la funcin TERPRI. Esta funcin mueve el cursor a una nueva lnea en la ventana de comandos de AutoCAD, y devuelve nil. El cdigo de la rutina quedara as: (defun C:CIRCPERI ( ) (setq pto (getpoint Centro de la circunferencia)) (terpri) (setq peri (getreal Permetro:)) (terpri) (setq rad (/ peri (* pi 2))) (command _.circle pto rad) ) As los mensajes de solicitud aparecern en lneas separadas. Los caracteres de control Como ya se ha comentado anteriormente, AutoLISP no reconoce una serie de caracteres. Por ejemplo, al indicar la ruta de un archivo no reconoce el carcter \ y hay que indicarlo as: \\. Pues existen ms caracteres de control predefinidos: \\ Equivale al caracter \ \ Equivale al caracter \e Equivale a ESCape \n Equivale al retorno de carro \r Equivale a pulsar Intro \t Equivale a pulsar la tecla del tabulador

\ nos permite escribir las comillas dentro de un texto. Por ejemplo: (alert Esto son un par de comillas \ o no?)

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

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

You might also like