Aller au contenu

Blocs référencés ?


(gile)

Messages recommandés

Salut,

 

Suite à ce sujet, je propose 3 petites routines qui utilisent les codes de groupes 331 des données DXF des objets BLOCK_RECORD (AcDbBlockTableRecord), autrement dit les définitions de bloc.

 

gc:IsReferenced : Évalue s'il existe des références du bloc non effacées (dans le dessin ou dans un bloc). Retourne T ou nil

 

;; gc:IsReferenced
;; Evalue si le bloc est référencé
;;
;; Argument
;; bname : nom du bloc
(defun gc:IsReferenced (bname / blk blkRec blkRefs)
 (and
   (setq blk (tblobjname "BLOCK" bname))
   (setq blkRec (cdr (assoc 330 (entget blk))))
   (setq blkRefs (vl-remove nil (mapcar 'entget (gc:massoc 331 (entget blkRec)))))
   (vl-some 'vl-consp (mapcar '(lambda (x) (entget (cdr (assoc 330 x)))) blkRefs))
 )
)

 

gc:PurgeBlock Purge les blocs (même imbriqués) dont le nom correspond au modèle.

Le modèle accepte les caractères génériques et n'est pas sensible à la casse.

Exemple : (gc:PurgeBlock "*") purge tous les blocs.

 

;; gc:PurgeBlock
;; Purge les blocs dont le nom correspond au modèle (insensible à la casse)
;;
;; Argument
;; pat : un modèle pour le nom de bloc, accepte les caractères génériques ("*" pour tous)

(defun gc:PurgeBlock (pat / blk name blst loop)
 (vl-load-com)
 (while (setq blk (tblnext "BLOCK" (not blk)))
   (if
     (and
(wcmatch (strcase (setq name (cdr (assoc 2 blk)))) (strcase pat))
(< (cdr (assoc 70 (setq elst (entget (tblobjname "BLOCK" name))))) 4)
     )
     (setq blst (cons (cdr (assoc 330 elst)) blst))
   )
 )
 (setq loop T)
 (while (and loop blst)
   (setq loop nil)
   
   (foreach b blst
     (or (vl-some 'entget (gc:massoc 331 (entget b)))
(progn
  (setq blk (vlax-ename->vla-object b))
  (vlax-for o blk
    (if	(= (vla-get-ObjectName o) "AcDbBlockReference")
      (vla-Delete o)
    )
  )
  (vla-delete blk)
  (setq blst (vl-remove b blst))
  (setq loop T)
)
     )
   )
 )
)

 

gc:GetReferences Retourne la liste des références du bloc insérées dans le dessin et/ou imbriqués dans des blocs en fonction de la valeur du 'drapeau'.

Cette routine peut avantageusement remplacer un (ssget "_X" ...) pour obtenir toutes les références d'un bloc dans le dessin.

 

Exemple avec un dessin contenant 17853 entités dont 29 références du bloc "poste-ria" :

_$ (benchmark '((ssget "_x" '((0 . "INSERT") (2 . "poste-ria")))(gc:GetReferences "poste-ria" 2)))

Benchmarking .............Elapsed milliseconds / relative speed for 1024 iteration(s):

 

(GC:GETREFERENCES "poste-ria" 2)..............1170 / 16.17

(SSGET "_x" (QUOTE ((0 . "INSERT") (...).....18922 / 1

 

;; gc:GetReferences
;; Retourne la liste des références de bloc non effacées
;;
;; Arguments
;; bname : nom du bloc
;; flag : drapeau (somme des codes binaires suivants
;;	  1 = imbriqués dans des blocs
;;	  2 = insérés dans l'espace objet
;;        4 = insérés dans un espace papier
(defun gc:GetReferences	(bname flag / blk refs elst)
 (if
   (and
     (setq blk (tblobjname "BLOCK" bname))
     (setq refs
     (vl-remove-if-not
       'cdr
       (mapcar
	 (function
	   (lambda (x)
	     (if (setq elst (entget x))
	       (cons x (entget (cdr (assoc 330 elst))))
	     )
	   )
	 )
	 (gc:massoc 331 (entget (cdr (assoc 330 (entget blk)))))
       )
     )
     )
   )
    (if (= 7 flag)
      (mapcar 'car refs)
      (if (< 0 flag 7)
 (mapcar 'car
	 (vl-remove-if
	   (function
	     (lambda (x)
	       (wcmatch	(strcase (cdr (assoc 2 (cdr x))))
			(cond
			  ((= 1 flag) "`**_SPACE*")
			  ((= 2 flag) "~`*MODEL_SPACE")
			  ((= 3 flag) "`*PAPER_SPACE*")
			  ((= 4 flag) "~`*PAPER_SPACE*")
			  ((= 5 flag) "`*MODEL_SPACE*")
			  ((= 6 flag) "~`**_SPACE*")
			)
	       )
	     )
	   )
	   refs
	 )
 )
      )
    )
 )
)

 

Ces routines utilisent gc:massoc

;; gc:massoc
;; Retourne la liste de toutes les valeurs pour le code spécifié dans une liste d'association
;;
;; Arguments
;; code : la clé recherchée (code de groupe pour les listes DXF)
;; alst : la liste d'association
(defun gc:massoc (code alst)
 (if (setq alst (member (assoc code alst) alst))
   (cons (cdar alst) (gc:massoc code (cdr alst)))
 )
)

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

La différence de performances entre ssget et GetReferences est impressionnante... :exclam:

 

Elle le sera d'autant plus que le dessin comportera beaucoup d'entités et peu (ou pas) de références de bloc.

Un (ssget "X" ...) doit parcourir tout le dessin pour filtrer les entités et un jeu de sélection est un objet plus complexe qu'une liste de ENAMEs (il contient aussi des informations sur la façon dont a été faite la sélection).

La différence de performances devrait encore être un peu augmentée si on parcourt le jeu de sélection ce qui est plus couteux que de parcourir une liste.

 

Mais il faut relativiser tout ça, dans l'exemple ci-dessus une sélection est faite en environ 18 millisecondes quand gc:GetReferences crée une liste en un peu plus d'une milliseconde la différence sera probablement impalpable pour l'utilisateur.

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Créer un compte ou se connecter pour commenter

Vous devez être membre afin de pouvoir déposer un commentaire

Créer un compte

Créez un compte sur notre communauté. C’est facile !

Créer un nouveau compte

Se connecter

Vous avez déjà un compte ? Connectez-vous ici.

Connectez-vous maintenant
×
×
  • Créer...

Information importante

Nous avons placé des cookies sur votre appareil pour aider à améliorer ce site. Vous pouvez choisir d’ajuster vos paramètres de cookie, sinon nous supposerons que vous êtes d’accord pour continuer. Politique de confidentialité