Applicare funzione lisp ai blocchi selezionati

psluca91

Utente poco attivo
Professione: disegnatore
Software: autocad
Regione: marche
#1
Buon pomeriggio a tutti,

Chiedo in anticipo scusa se l'argomento è già stato affrontato in altri topic e per la banalità della questione, ma non sono riuscito a trovare una guida o discussioni che mi aiutino tramite la funzione cerca.

Ho scritto il seguente LISP prendendo codice da altri LISP trovati in rete:

Codice:
;;;Cambia Colore By layer nel rispettivo colore e Layer "0"
(defun C:CCB (/ B_name COL)
(setq B_name (cdr (assoc 2 (entget (car (entsel "\nSelezionare il Blocco "))))))
(command "-BEDIT" B_name)
(setq ListaObj (ssget "X"))

(setq Nobj (sslength Listaobj))

(setq controllo 0)

(while (< Controllo Nobj)




 (setq Obj (entget (ssname Listaobj Controllo) ))
 (setq Color (assoc '62 Obj))

  (if (= Color Nil)
   (progn
    (setq ObjLay (assoc '8 Obj))
    (setq LayCol (cdr (assoc '62 (tblsearch "LAYER" (cdr ObjLay)))))
    (command "_change" (cdar obj) "" "_prop" "_color" LayCol "")
    );; chiusura progn
   );; chiusura if Color Nil

(setq Controllo (+ Controllo 1))

) ;;chiusura while controllo
(command "_CHPROP" "_ALL" "" "_LAYER" 0 "" "_BCLOSE" "")
);;chiusura defun
Il lisp funziona ma devo selezionare i blocchi uno a uno. Come posso fare per eseguire il LISP su più blocchi contemporaneamente?

Grazie anticipatamente!
 

Cristallo

Utente Standard
Professione: Leggo e confronto
Software: Lettura critica
Regione: Fuori dalla cerchia
#2
Tu assegni il nome del blocco da modificare alla variabile B_name
(setq B_name (cdr (assoc 2 (entget (car (entsel "\nSelezionare il Blocco "))))))

Se vuoi selezionare piu di un blocco, devi per prima cosa selezionare (mediante una cosa tipo SSGET)
una lista di blocchi ed assegnarli ad una variabile, diciamo BLKLIST.
Per non far andare il lisp in errore, ti consiglio un filtraggio sull'SSGET che prenda solo i blocchi (SSGET '((0 . "BLOCK")))
Poi fai contare quanti sono i blocchi che hai selezionato (sslength BLKLIST)e lo assegni ad una variabile - diciamo NUM
Setti un contatore che chiameremo COUNT a 0 (SETQ COUNT 0)

e poi racchiudi tutto il tuo lisp dentro un repeat di quanti oggetti hai nella lista BLKLIST



;;;Cambia Colore By layer nel rispettivo colore e Layer "0"
(defun C:CCB (/ B_name COL)

selezione multipla e calcolo numero oggetti

(
repeat NUM
(
setq B_Name ssname BLKLIST COUNT)
(
setq COUNT (+ COUNT 1))

..... tuo lisp

) ;;; chiusura del repeat

);;chiusura defun
 

psluca91

Utente poco attivo
Professione: disegnatore
Software: autocad
Regione: marche
#3
Cristallo, intanto ti ringrazio per la velocissima risposta!

Ho provato a creare il codice come da tuo suggerimento, ma ho riscontrato degli errori:

- Se imposto (setq BLKLIST (SSGET '((0 . "BLOCK")))), mi esclude tutto dalla selezione (compresi i blocchi) e non riesco quindi a far partire il LISP che mi da il seguente errore: "Select objects: ; error: bad argument type: lselsetp nil".

- Se tolgo il filtro "BLOCK" e seleziono manualemente i blocchi, mi da sempre lo stesso errore....

ti riporto il codice da me scritto.

Codice:
;;;Cambia Colore Blocco E LAYER 0
(defun C:CCB4 (/ B_name COL)
(setq BLKLIST (ssget ))

(setq NUM (sslength Listaobj))

(setq COUNT 0)

(repeat NUM
(setq B_Name ssname BLKLIST COUNT)
(setq COUNT (+ COUNT 1))
(command "-BEDIT" B_name)
(setq ListaObj (ssget "X"))

(setq Nobj (sslength Listaobj))

(setq controllo 0)

(while (< Controllo Nobj)




 (setq Obj (entget (ssname Listaobj Controllo) ))
 (setq Color (assoc '62 Obj))

  (if (= Color Nil)
   (progn
    (setq ObjLay (assoc '8 Obj))
    (setq LayCol (cdr (assoc '62 (tblsearch "LAYER" (cdr ObjLay)))))
    (command "_change" (cdar obj) "" "_prop" "_color" LayCol "")
    );; chiusura progn
   );; chiusura if Color Nil

(setq Controllo (+ Controllo 1))

) ;;chiusura while controllo
(command "_CHPROP" "_ALL" "" "_LAYER" 0 "" "_BCLOSE" "")
) ;;; chiusura repeat
);;chiusura defun
Dove sto sbagliando?
 

psluca91

Utente poco attivo
Professione: disegnatore
Software: autocad
Regione: marche
#4
Ho trovato un errore qui:

setq BLKLIST (ssget ))

(setq NUM (sslength Listaobj))

corretto in:

setq BLKLIST (ssget ))

(setq NUM (sslength BLKLIST))

ora il comando parte, ma si blocca all'apertura del BLOCEDITOR, dove mi appare come nome del blocco "-change" e all'interno del blocco non vi è nulla. Nella barra di comando mi appare questa dicitura:
"Command: CCB4
Select objects: Specify opposite corner: 2 found
Select objects: -BEDIT
Enter block name or [?]:
Invalid block name.
Enter block name or [?]: _change Regenerating model.
Command: <Bad Entity name: FFA818B0>"
 

Cristallo

Utente Standard
Professione: Leggo e confronto
Software: Lettura critica
Regione: Fuori dalla cerchia
#5
(0 . "BLOCK") deve diventare (0 . "INSERT") - questo per il filtraggio

(setq NUM (sslength Listaobj)) - fai contare il numero di entita ad una lista che non esiste. prova sostituendolo con (setq NUM (sslength BLKLIST))
 

psluca91

Utente poco attivo
Professione: disegnatore
Software: autocad
Regione: marche
#6
Ho apportato le modifiche come da te suggerito, ma continua a bloccarsi all'interno del editor blocchi di un blocco inesistente....

Queste le righe di comando che mi escono...

Command: _appload CCB5.lsp successfully loaded.
Command: ; error: malformed list on input
Command:
Command: CCB5
Select objects: Specify opposite corner: 2 found
Select objects: -BEDIT
Enter block name or [?]:
Invalid block name.
Enter block name or [?]: _change Regenerating model.
Command: <Bad Entity name: A468A920>
 

Cristallo

Utente Standard
Professione: Leggo e confronto
Software: Lettura critica
Regione: Fuori dalla cerchia
#7
il problema sta nell'uso del comando BEDIT.

Il nome dell'entità che conservi nella variabile B_name è il nome interno di quella e solo di quella entità.
Se hai 5 istanze del blocco PIPPO, avrai 5 valori di B_name diversi, non so se sono stato chiaro

Al comando BEDIT devi passare il nome del blocco, non quello della sua istanza, altrimenti BEDIT crede tu voglia editare un blocco che si chiama <Entity name: 7ff75520dc10> e non il PIPPO che tu vuoi editare

Come risolvere? Rapidamente, assegnando il nome del blocco (non della sua istanza) ad una nuova variabile, diciamo NAME_BL
Come si fa?
(setq NAME_BL (cdr (assoc '2 (entget B_Name))))

stai dicendo assegna a NAME_BL la restante parte (cdr) del gruppo 2 (assoc '2) prendendola dalla lista completa (entget) dell'entità B_name.

A questo punto al BEDIT non devi passare più B_name, ma NAME_BL
(command "-BEDIT" NAME_BL)

Comunque, visto che tu selezioni un numero di blocchi diversi in cui ci saranno più istanze dello stesso blocco, ti ritroverai ad editare più volte lo stesso blocco già editato, e non so se questo può generarti ulteriori crash di programma.
Potresti anche avere problemi sui blocchi dinamici, in quanto questi ultimi quando variati rispetto a quello "base" assumono un nuovo nome, di tipo anonimo (iniziano per asterisco)

Per avere più velocità d'esecuzione dovresti approfondire il comando TBLSEARCH e cercare di ottenere i nomi dei blocchi esistenti nel disegno in maniera da editare una sola volta il blocco sorgente, non le sue istanze