AutoCad - Llamar un comando de una función dentro de un lisp

 
Vista:
sin imagen de perfil
Val: 19
Ha aumentado 1 puesto en AutoCad (en relación al último mes)
Gráfica de AutoCad

Llamar un comando de una función dentro de un lisp

Publicado por jose (9 intervenciones) el 02/05/2020 19:28:35
Buenas.
En esta temporada de confinamiento, he estado haciendo pequeñas rutinas dentro de mi nulo desconocimiento del tema .
No tengo ni idea de programación y muy poca idea de lisp.... lo poco que he hecho es viendo otras ya hechas y adaptando a lo que necesito.
El tema es que he hecho una rutina para descomponer bloques cargando previamente otra rutina de lee mac para poder descomponer bloques anidados y estáticos a la vez.
Al principio, intenté meter la orden (nburst) de la rutina de lee mac como comando... pero no funciona.... y a lo máximo que he llegado es a llamar a la función, pero se queda parada y le tengo que dar por teclado para que acabe correctamente.
después de varias pruebas... no he sabido pasar de ese punto
así que ahí va mi consulta
¿como se podría evitar esa parada?
Un saludo y muchas gracias
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil
Val: 19
Ha aumentado 1 puesto en AutoCad (en relación al último mes)
Gráfica de AutoCad

Llamar un comando de una función dentro de un lisp

Publicado por jose (9 intervenciones) el 02/05/2020 19:46:46
os dejo lo que yo he hecho aqui

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(defun C:dbq( / origen ent nent cap)
	(if (not c:nbrust)(load "d:/lsp/BurstUpgradedV1-7.lsp"))
	(alert "Se descomponen los bloques existentes \n \nASEGURATE DE TRABAJAR EN UN ARCHIVO COPIA")
	(INITGET 1 "Todos Capa")
	(setq origen (GETKWORD "\nIndica Seleccionar Todos o por Capa [Todos/Capa]: "))
	(cond
		((= origen "Todos")
			(setq bloc (ssget "_X" '((0 . "*insert"))))
		)
		((= origen "Capa")
			(While (not (setq ent (entsel "\nDesignar objeto: "))))
			(setq nent (car ent ))
			(setq cap (cdr (assoc 8 (entget nent))))
			(setq bloc (ssget "_x" (list (cons 0 "*insert") (cons 8 cap))))
		)
	)
	(setq nums (sslength bloc))
	(princ "\n<<<< OJO >>>>...Ya Seleccionados...teclea <P> <intro> e <intro>: ")
	(c:nburst)
	(command "-limpia" "t" "*" "n")
	(princ (strcat "\nTerminado.... " (itoa nums) " BLOQUES SE HAN DESCOMPUESTO. "))
(princ)
)
(princ "... **** escribe DBQ para ejecutar. ****")
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 1.285
Oro
Ha mantenido su posición en AutoCad (en relación al último mes)
Gráfica de AutoCad

Llamar un comando de una función dentro de un lisp

Publicado por Gerardo (997 intervenciones) el 02/05/2020 22:59:12
Hola

Tu parte parece bien escrita. Además la corrí en mi autocad con un archivo simple y funcionó bien

( Tienea un errorcillo en (if (not c:nbrust)(load "d:/lsp/BurstUpgradedV1-7.lsp")) porque la funcion es burst y no brust, pero eso no causa error, simplemente que el if siempre obtiene un negativo y vuelve a cargar el lsp, pero eso no es una falla )

Echando un vistazo no vi nada con el idioma del Autocad tampoco. Podría ser algo con un bloque que tengas donde la estás ejecutando, diferente a los que habia en el archivo que yo probé.

Te recomiendo que utilices la herramienta debug del vlide. En el menú "debug" marca la opción "Break on error". Así cuando se de un error se parará la ejecución y te llevará al editor Vlide, y ahí haces click en el botón "last error" (un punto rojo entre paréntesis) y te señalará la línea o sentencia donde se paró. Si fuera por ejemplo dentro de la función LM:burstobject, puedes evaluar la variable obj - invocandola en la consola o visualizando su valor en tiempo real en el monitor "watch" - para ver cual es el bloque en el que falló. O correr la rutina pero seleccionando solo ciertos bloques a ver en cual es que falla. Si no es en un objeto sino en cierta parte del codigo funcional, pues ver bien esa sentencia donde falla y el valor de las variables involucradas a ver que es lo que pasa

Suerte
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil
Val: 19
Ha aumentado 1 puesto en AutoCad (en relación al último mes)
Gráfica de AutoCad

Llamar un comando de una función dentro de un lisp

Publicado por jose218 (9 intervenciones) el 03/05/2020 09:32:11
Gracias por tu respuesta.
Creo que no me he explicado correctamente en mi exposición inicial.
En principio, dentro de mi mínimo conocimiento de lisp, pensaba que después de cargar la rutina "burstupgrade", podría usar la función "nburst" como si fuese un comando.... y en el código tenía:
(command "nburst" "p" "" "")
en lugar de
(c:nburst)
pero con el command... autocad dice que es un comando erróneo... cosa que no entiendo pues si lo hago por teclado es lo que escribo y funciona.

Tal como está el código en mi mensaje anterior, funciona, pero a medias.... se queda esperando a que se le diga que es lo que hay que descomponer.
Lo que quiero es que no se pare.... y que entienda que lo que hay que descomponer son los bloques previamente seleccionados.

Por cierto.... no había visto el error de (if ...) gracias de nuevo
Uso Autocad 2012 en español

un saludo y muchas gracias.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 1.285
Oro
Ha mantenido su posición en AutoCad (en relación al último mes)
Gráfica de AutoCad

Llamar un comando de una función dentro de un lisp

Publicado por Gerardo (997 intervenciones) el 04/05/2020 16:31:15
ahh, ya veo

Busca en la ayuda la función vlax-add-cmd, esa registra un defun como si fuera un comando nativo. Yo la verdad nunca la he usado y preferiría modificar el lisp que estás llamando para que reciba la selección como parámetro y no pregunte, que meterla en una llamada de command para pasarle parámetros, pero creo que con vlax-add-cmd se podrá hacer como lo quieres
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil
Val: 19
Ha aumentado 1 puesto en AutoCad (en relación al último mes)
Gráfica de AutoCad

Llamar un comando de una función dentro de un lisp

Publicado por jose218 (9 intervenciones) el 04/05/2020 19:58:11
Gracias Gerardo
He hecho la modificación que me apuntas con vlax-add-cmd y funciona bien....... pero solo una vez.
si la ejecuto dos veces, a la hora de seleccionar el elemento que define la capa.... se queda pensando y hay que cerrar autocad a lo burro.
he probado a descargar el comando después de usarlo con vlax-remove-cmd y nada..... he añadido un (setq c:nburst nil) al principio y tampoco.... he añadido un (setq c:dbq nil) y entonces funciona.... pero la tengo que cargar cada vez que la quiera usar.... cuando lo hago desde teclado Herr-Autiolisp-cargar aplicacion, funciona....pero he creado un botón personalizado con ^c^c(load....... y al ejecutarlo y ticar el objeto que define la capa.... se queda colgado.

La segunda opción que me propones de modificar el lisp que llama.... creo que no soy capaz.... pero le echaré un vistazo
un saludo y muchas gracias
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 19
Ha aumentado 1 puesto en AutoCad (en relación al último mes)
Gráfica de AutoCad

Llamar un comando de una función dentro de un lisp

Publicado por jose218 (9 intervenciones) el 05/05/2020 07:33:12
Esto es lo que tengo ahora.... y se cuelga el programa en segunda ejecución con la opción por "Capa" (con opción "Todos" no he probado)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(defun C:dbq ( / origen ent nent cap)
	(if (not c:nburst) (load "d:/lsp/BurstUpgradedV1-7.lsp"))
	(alert "Se descomponen los bloques existentes \n \nASEGURATE DE TRABAJAR EN UN ARCHIVO COPIA")
	(INITGET 1 "Todos Capa")
	(setq origen (GETKWORD "\nIndica Seleccionar Todos o por Capa [Todos/Capa]: "))
	(cond
		((= origen "Todos")
			(setq lst (ssget "_X" '((0 . "*insert"))))
		)
		((= origen "Capa")
			(While (not (setq ent (entsel "\nDesignar objeto: "))))
			(setq nent (car ent ))
			(setq cap (cdr (assoc 8 (entget nent))))
			(setq lst (ssget "_x" (list (cons 0 "*insert") (cons 8 cap))))
		)
	)
	(setq nums (sslength lst))
	(if (not c:mburst) (vlax-add-cmd "mburst" 'c:nburst))
	(command "mburst" lst "")
	(command "-limpia" "t" "*" "n")
	(princ (strcat "\nTerminado.... " (itoa nums) " BLOQUES SE HAN DESCOMPUESTO. "))
(princ)
)
(princ "... **** escribe DBQ para ejecutar. ****")

Un saludo y gracias
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 1.285
Oro
Ha mantenido su posición en AutoCad (en relación al último mes)
Gráfica de AutoCad

Llamar un comando de una función dentro de un lisp

Publicado por Gerardo (997 intervenciones) el 07/05/2020 12:52:01
Te ayudaría mucho aprender a usar el debug del vlide. Al hacerlo yo encontré el error.

Te dejo por aquí la explicación del error y porque no va a funcionar como lo estamos haciendo. (Luego te paso alguna solución alternativa)

Lo que se cuelga es un ciclo sin fin (como casi siempre); en el while de esta función:

1
2
3
4
5
(defun LM:endundo ( doc )
    (while (= 8 (logand 8 (getvar 'undoctl)))
        (vla-endundomark doc)
    )
)

Lo que pasa es que tu generas un command que llama a "mburst", pero el comando al que estás llamando tiene dentro otro command interno, en la línea 129 donde dice:
1
(vl-cmdf "_.explode" (vlax-vla-object->ename tmp))

Al parecer autocad no tiene problema con llamar a uno dentro del otro, pero lo que hace ese while es que mientras haya un comando activo (el comando explode en la intención de Lee Mac) - que la variable undoctl va a devolver 8 (significa comando activo), ese bucle acumula todas las llamadas para que después un solo "UNDO" deshaga todo el burst. Pero el problema es que aún cuando el "explode" termine tu comando "mburst" se mantiene activo. Por eso el bucle se encicla.

Si quitamos el control de undos al parecer trabajaría bien, solo que si quieres deshacer el comando vas a tener que aplicar deshacer una serie de veces y en cada una se va a ir deshaciendo la explosión de un único bloque a la vez. No suena muy elegante
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil
Val: 1.285
Oro
Ha mantenido su posición en AutoCad (en relación al último mes)
Gráfica de AutoCad

Llamar un comando de una función dentro de un lisp

Publicado por Gerardo (997 intervenciones) el 07/05/2020 13:10:38
Y bueno - Te dejo aquí una propuesta de solución, volviendo a la idea de llamar a c:nburst entre paréntesis y aprovechando que LeeMac hizo una función aparte para pedir el selectionset al usuario, y no como parte del código de la funciín principal, entonces lo unico que tenemos que hacer es hackear esa función temporalmente.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
(defun C:dbq ( / origen ent nent cap)
	(if (not c:nburst) (load "d:/lsp/BurstUpgradedV1-7.lsp"))
	(alert "Se descomponen los bloques existentes \n \nASEGURATE DE TRABAJAR EN UN ARCHIVO COPIA")
	(INITGET 1 "Todos Capa")
	(setq origen (GETKWORD "\nIndica Seleccionar Todos o por Capa [Todos/Capa]: "))
	(cond
		((= origen "Todos")
			(setq lst (ssget "_X" '((0 . "*insert"))))
		)
		((= origen "Capa")
			(While (not (setq ent (entsel "\nDesignar objeto: "))))
			(setq nent (car ent ))
			(setq cap (cdr (assoc 8 (entget nent))))
			(setq lst (ssget "_X" (list '(0 . "*insert") (cons 8 cap))))
		)
	)
	(setq nums (sslength lst))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Respaldamos la función LM:ssget para no perderla y que si
;c:nburst se invoca por otro lado después siga funcionando
	(setq funcionLM LM:ssget)
 
;redefinimos nuestra propia LM:ssget para que en vez de pedirle
;al usuario que seleccione devuelva la seleccion que ya hicimos
	(defun LM:ssget (msg arg)
		lst
	)
 
;llamamos a c:nburst como función, no como comando
	(c:nburst)
 
;Restauramos LM:ssget original
	(setq LM:ssget funcionLM)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 
	;(command "-limpia" "t" "*" "n")
	(princ (strcat "\nTerminado.... " (itoa nums) " BLOQUES SE HAN DESCOMPUESTO. "))
(princ)
)
(princ "... **** escribe DBQ para ejecutar. ****")
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar

Llamar un comando de una función dentro de un lisp

Publicado por Cristina (1 intervención) el 09/09/2023 02:48:13
Hola, me podrias ayudar a reparar unos lisp?
es una interfaz CUIX que tiene asociados varios lisp, los cuales llaman a una biblioteca de bloques, los logre cargar pero no me aparecen los bloques... ¿me podrias ayudar por favor?

Saludos
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 1.285
Oro
Ha mantenido su posición en AutoCad (en relación al último mes)
Gráfica de AutoCad

Llamar un comando de una función dentro de un lisp

Publicado por Gerardo (997 intervenciones) el 10/09/2023 06:17:24
Hola
Supongo que si se te podría ayudar si muestras lo que tienes, la forma en que las rutinas llaman a los bloques y los errores que lanza el cad cuando no los encuentra
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 19
Ha aumentado 1 puesto en AutoCad (en relación al último mes)
Gráfica de AutoCad

Llamar un comando de una función dentro de un lisp

Publicado por jose218 (9 intervenciones) el 08/05/2020 19:08:17
Gracias por tu tiempo Gerardo
Si llamas "debug de vlide" al editor de visual lisp de Autocad.... estuve viendo algún vídeo y leí algún manual,... pero no entendí muy bien como era.... hice alguna prueba con el código mio y no sabía muy bien lo que tenía que preguntar, mirar....

Como me comentabas en anteriores mensajes, también revisé el código de Lee Mac para intentar modificarlo (uniendo los dos) y deduje que era tema de la función que citas.... pero no supe modificarlo.... ya comenté que llevo muy poco con esto de lisp ( a parte de que soy algo negado para estos temas)....leí un par de tutoriales y hasta ahora sólo he sido capaz de hacer 2 ó 3 códigos muy sencillos.
El de este hilo, como ya comenté, pensaba que iba a ser sencillo y podría usar "command nburst".

Te vuelvo a agradecer tu tiempo y trabajo.... eres Grande Gerardo.
Un saludo
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil
Val: 1.285
Oro
Ha mantenido su posición en AutoCad (en relación al último mes)
Gráfica de AutoCad

Llamar un comando de una función dentro de un lisp

Publicado por Gerardo (997 intervenciones) el 08/05/2020 23:59:08
no con todo gusto. Lo unico que tengo yo es muchos años programando en lisp y he aprendido algunas cosillas.

Para depurar lo que puedes hacer es, primero establecer un punto de parada:

En caso de que estés buscando un error, marcas la opción "Break on error" en el menú "Debug". Así cuando la rutina falle en vez de salirse o pegarse el autocad se abrirá el código en el vlide detenido en el punto de error. (La opción "Last break" o "Last break source" te ubica señalando la sentencia del error.

En caso de que quieras solo probar una sección de código te colocas en un paréntesis de apertura de sentencia y aplicas "Toggle breakpoint" (f9 o la manita blanca) Ejecutas la rutina y se detendrá en ese punto. (puedes aplicar varios puntos de parada en una misma rutina)

Lo siguiente sería ir avanzando con las opciones step into, step over, step out y continue (F8, shift+f8, ctrl+shift+f8 y ctrl+f8) y donde falla revisar lo que estás haciendo o evaluar lo que contienen las variable o lo que retornan las sentencias. Para esto se puede agregarlas al observador (watch) para monitorearlas en tiempo de ejecución o en cualquier momento puedes digitar una sentencia o variable en la consola para ver que resultado arroja

El resto será experiencia, ir aprendiendo al ver un error el tipo de origen que puede tener
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil
Val: 19
Ha aumentado 1 puesto en AutoCad (en relación al último mes)
Gráfica de AutoCad

Llamar un comando de una función dentro de un lisp

Publicado por jose218 (9 intervenciones) el 09/05/2020 18:39:35
Intentaré aprender su uso.
gracias de nuevo.
un saludo
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar