Aller au contenu

Filtres de propriétés sous-jacents


Luna

Messages recommandés

Coucou,

J'ai un soucis que je n'arrive pas à comprendre. Sur l'image ci-dessous, j'ai créer une liste de filtres de propriétés ("000-SITE", "100-IMPLANTATION", "300-RESAUX SECS" et "Actifs" ainsi que "Inactifs" dans la rubrique "100-IMPLANTATION") :
image.png.d44255f5cbf10cbb5b512388e54ad4d0.png

J'aimerais voir s'il est possible de modifier, créer, ou supprimer ces filtres de propriétés de manière automatique (donc en LISP pour ne pas avoir à créer cette liste manuellement à chaque fois, ou simplement pour la mettre à jour). Pour chat, rien de bien compliqué, on peut accéder à cette liste via la ligne suivante :

(dictsearch (cdr (assoc 360 (entget (cdr (assoc 330 (entget (tblobjname "LAYER" "0"))))))) "ACAD_LAYERFILTERS")
;; On commence par récupérer l'entité correspondant au calque "0" (via (tblobjname)) puis en passant respectivement
;; par les codes 330 et 360 on peut récupérer la liste de dictionnaires concernant les Calques (enfin je crois)
;; Puis on récupère les informations contenues dans le dictionnaires nommé "ACAD_LAYERFILTERS"
;; Ci-dessous le résultat avant le (dictsearch) :

Explore DXF in progress from "DICTIONARY" (<Nom d'entité: c376a1e0>) :
|      (-1 . <Nom d'entité: c376a1e0>)
|      (0 . "DICTIONARY")
|      (330 . <Nom d'entité: c376c020>)
|      (5 . "18E")
|      (100 . "AcDbDictionary")
|      (280 . 1)
|      (281 . 1)
|      (3 . "ACAD_LAYERFILTERS")
|      (360 . <Nom d'entité: 3810b1c0>)
|      (3 . "ACAD_LAYERSTATES")
|      (360 . <Nom d'entité: c376a1f0>)
|      (3 . "ACLYDICTIONARY")
|      (360 . <Nom d'entité: 3810b1b0>)
|
End of exploration...

;; Ci-dessous le résultat après le (dictsearch) :

Explore DXF in progress from "DICTIONARY" (<Nom d'entité: 3810b1c0>) :
|      (-1 . <Nom d'entité: 3810b1c0>)
|      (0 . "DICTIONARY")
|      (5 . "AF4C")
|      (102 . "{ACAD_REACTORS")
|      (330 . <Nom d'entité: c376a1e0>)
|      (102 . "}")
|      (330 . <Nom d'entité: c376a1e0>)
|      (100 . "AcDbDictionary")
|      (280 . 0)
|      (281 . 1)
|      (3 . "000-SITE")
|      (350 . <Nom d'entité: 3810b250>)
|      (3 . "100-IMPLANTATION")
|      (350 . <Nom d'entité: 3810b1e0>)
|      (3 . "300-RESEAUX SECS")
|      (350 . <Nom d'entité: 3810b230>)
|      (3 . "Actifs")
|      (350 . <Nom d'entité: 3810b2b0>)
|
End of exploration...

On peut ensuite récupérer les propriétés du filtre en accédant aux codes 350 (bien que leur construction ne soit pas très simple à gérer et je n'ai pas dresser la correspondance des valeurs du code 70 par rapport aux propriétés, mais passons). Donc cela semble relativement simple de prime abords ! Cependant, mon soucis vient du fait que le filtre "Inactifs"...n'existe pas...
J'ai eu beau creuser un peu plus, je n'arrive pas à le faire apparaître, or si AutoCAD est en mesure de l'afficher, il doit forcément exister quelque part...donc je ne sais pas bien comment accéder aux filtres de propriétés "subalternes" finalement !
Ci-dessous un petit aperçu de la structuration des listes (ne faites pas attention à la numérotation, je n'ai pas encore corrigé ce soucis sur ma fonction d'exploration...) :

Explore DXF in progress from "DICTIONARY" (<Nom d'entité: 3810b1c0>) :
|      (-1 . <Nom d'entité: 3810b1c0>)
|      (0 . "DICTIONARY")
|      (5 . "AF4C")
|      (102 . "{ACAD_REACTORS")
|      (330 . <Nom d'entité: c376a1e0>)
|      (102 . "}")
|      (330 . <Nom d'entité: c376a1e0>)
|      (100 . "AcDbDictionary")
|      (280 . 0)
|      (281 . 1)
|      (3 . "000-SITE")
|      (350 . <Nom d'entité: 3810b250>)
|      (3 . "100-IMPLANTATION")
|      (350 . <Nom d'entité: 3810b1e0>)
|      (3 . "300-RESEAUX SECS")
|      (350 . <Nom d'entité: 3810b230>)
|      (3 . "Actifs")
|      (350 . <Nom d'entité: 3810b2b0>)
|
1.  "DICTIONARY" (<Nom d'entité: c376a1e0>) at 330 code, from "DICTIONARY" object :
|         (-1 . <Nom d'entité: c376a1e0>)
|         (0 . "DICTIONARY")
|         (330 . <Nom d'entité: c376c020>)
|         (5 . "18E")
|         (100 . "AcDbDictionary")
|         (280 . 1)
|         (281 . 1)
|         (3 . "ACAD_LAYERFILTERS")
|         (360 . <Nom d'entité: 3810b1c0>)
|         (3 . "ACAD_LAYERSTATES")
|         (360 . <Nom d'entité: c376a1f0>)
|         (3 . "ACLYDICTIONARY")
|         (360 . <Nom d'entité: 3810b1b0>)
|
2.  "DICTIONARY" (<Nom d'entité: c376a1e0>) at 330 code, from "DICTIONARY" object :
|         (-1 . <Nom d'entité: c376a1e0>)
|         (0 . "DICTIONARY")
|         (330 . <Nom d'entité: c376c020>)
|         (5 . "18E")
|         (100 . "AcDbDictionary")
|         (280 . 1)
|         (281 . 1)
|         (3 . "ACAD_LAYERFILTERS")
|         (360 . <Nom d'entité: 3810b1c0>)
|         (3 . "ACAD_LAYERSTATES")
|         (360 . <Nom d'entité: c376a1f0>)
|         (3 . "ACLYDICTIONARY")
|         (360 . <Nom d'entité: 3810b1b0>)
|
3.  "XRECORD" (<Nom d'entité: 3810b250>) at 350 code, from "DICTIONARY" object :
|         (-1 . <Nom d'entité: 3810b250>)
|         (0 . "XRECORD")
|         (5 . "AF55")
|         (102 . "{ACAD_REACTORS")
|         (330 . <Nom d'entité: 3810b1c0>)
|         (102 . "}")
|         (330 . <Nom d'entité: 3810b1c0>)
|         (100 . "AcDbXrecord")
|         (280 . 1)
|         (1 . "000-SITE")
|         (1 . "0,Calque#*,UBS-000-*")
|         (1 . "*")
|         (1 . "*")
|         (70 . 0)
|         (1 . "*")
|         (1 . "*")
|
4.  "XRECORD" (<Nom d'entité: 3810b1e0>) at 350 code, from "DICTIONARY" object :
|         (-1 . <Nom d'entité: 3810b1e0>)
|         (0 . "XRECORD")
|         (5 . "AF4E")
|         (102 . "{ACAD_REACTORS")
|         (330 . <Nom d'entité: 3810b1c0>)
|         (102 . "}")
|         (330 . <Nom d'entité: 3810b1c0>)
|         (100 . "AcDbXrecord")
|         (280 . 1)
|         (1 . "100-IMPLANTATION")
|         (1 . "0,Calque#*,UBS-100-*")
|         (1 . "*")
|         (1 . "*")
|         (70 . 0)
|         (1 . "*")
|         (1 . "*")
|
5.  "XRECORD" (<Nom d'entité: 3810b230>) at 350 code, from "DICTIONARY" object :
|         (-1 . <Nom d'entité: 3810b230>)
|         (0 . "XRECORD")
|         (5 . "AF53")
|         (102 . "{ACAD_REACTORS")
|         (330 . <Nom d'entité: 3810b1c0>)
|         (102 . "}")
|         (330 . <Nom d'entité: 3810b1c0>)
|         (100 . "AcDbXrecord")
|         (280 . 1)
|         (1 . "300-RESEAUX SECS")
|         (1 . "0,Calque#*,UBS-300-*")
|         (1 . "*")
|         (1 . "*")
|         (70 . 0)
|         (1 . "*")
|         (1 . "*")
|
6.  "XRECORD" (<Nom d'entité: 3810b2b0>) at 350 code, from "DICTIONARY" object :
|         (-1 . <Nom d'entité: 3810b2b0>)
|         (0 . "XRECORD")
|         (5 . "AF5B")
|         (102 . "{ACAD_REACTORS")
|         (330 . <Nom d'entité: 3810b1c0>)
|         (102 . "}")
|         (330 . <Nom d'entité: 3810b1c0>)
|         (100 . "AcDbXrecord")
|         (280 . 1)
|         (1 . "Actifs")
|         (1 . "*")
|         (1 . "*")
|         (1 . "*")
|         (70 . 48)
|         (1 . "*")
|         (1 . "*")
|
End of exploration...

Mais on voit bien qu'on tourne en boucle... (les codes 350 renvoient au Dictionnaire "ACAD_LAYERFILTERS" donc on ne peut pas aller plus loin) et je suis allé jusqu'à 4 niveaux sur les codes 330 360 et 350 et bien que le dictionnaire "ACLYDICTIONARY" permet lui aussi d'atteindre la liste des filtres de propriétés (la construction de la liste est différente cependant) :

             (-1 . <Nom d'entité: 3810b1d0>)
             (0 . "XRECORD")
             (5 . "AF4D")
             (102 . "{ACAD_XDICTIONARY")
             (360 . <Nom d'entité: 3810b1f0>)
             (102 . "}")
             (102 . "{ACAD_REACTORS")
             (330 . <Nom d'entité: 3810b1b0>)
             (102 . "}")
             (330 . <Nom d'entité: 3810b1b0>)
             (100 . "AcDbXrecord")
             (280 . 1)
             (1 . "AcLyLayerFilter")
             (90 . 1)
             (300 . "100-IMPLANTATION")
             (301 . "NAME==\"UBS-100-*\" OR NAME==\"0\" OR NAME==\"Calque#*\"")

Je n'ai ici aussi que les 4 filtres de propriété principaux, mais le filtre nommé "Inactifs" n'apparaît pas...

Bref, chat fait beaucoup de texte pour pas grand chose et je m'en excuse, mais si jamais quelqu'un s'est déjà attardé sur le sujet des filtres de propriétés et la manière d'avoir la liste complète (et pas uniquement les principaux), je ne suis pas contre quelques explications ! ^^"
Pour la partie modification/création/suppression je verrais de mon côté comment je peux gérer cette histoire (surtout si les informations sont présentes dans 2 dictionnaires différents, les liaisons risquent d'être complexes).

Merci d'avance !
Luna

Lien vers le commentaire
Partager sur d’autres sites

salut,

j'avais initié un post sur ce sujet en 2007, je ne retrouve pas ...

as tu essaye mon "handle_explorer" pour se balader dans la structure démoniaque des dwg ?

On peut bien entendu créer ces filtres par programmation, moi j'ai des filtres stockés dans un fichier ini qui sont crées au chargement.

ci dessous des fonctions que j'utilise pour ce sujet:

;;**************************************************************************
;;§/calques/Affiche la hierarchie de filtre de calques imbriqués / none

(defun c:LayerFiltersTree ( /  )
  ;;1er niveau
  (setq eg1 (entget  (PW_ELAYERFILTERDIC)))
  (setq ldics1 (cdr (assoc 3 (pw_regroup_assoc eg1))))
  ;;2eme niveau
  (foreach nomfiltre1 ldics1
    (prompt (strcat "\n " nomfiltre1))
    (setq dic3 (pw_eLayerFilterByName nomfiltre1))
    (setq eg2 (entget (setq dic5 (pw_eLayerFilterAclyDictionary5 dic3))))
    (setq l-350-2 (cdr (assoc 350 (pw_regroup_assoc eg2))))
    (setq ldics2 (mapcar '(lambda (x) (cdr (assoc 300 (entget x)))) l-350-2))
    ;;3eme niveau
    (foreach nomfiltre2 ldics2
    (prompt (strcat "\n- - - -  " nomfiltre2))
      (setq dic5 (pw_eSousLayerFilterByName dic3 nomfiltre2))
      (setq dic8 (pw_eLayerFilterAclyDictionary5 dic5))
      (setq eg3 (entget dic8))
      (setq l-350-3 (cdr (assoc 350 (pw_regroup_assoc eg3))))
      (setq ldics3 (mapcar '(lambda (x) (cdr (assoc 300 (entget x)))) l-350-3))
          (foreach nomfiltr3 ldics3
    (prompt (strcat "\n- - - - > - - - -" nomfiltr3))
	   )
    )  
  )
)
;;************************************************************************
;;Niveau 1 : dictionnaire
;;;( (0 . "DICTIONARY")(100 . "AcDbDictionary") (280 . 1) (281 . 1) (3 . 
;;;"ACAD_LAYERFILTERS") (3 . "ACLYDICTIONARY") )
;;;;; - * - *  - * - * - * - * - * - * - * - * - * - * - *
;;;
;;;		Niveau 2 : dictionaire
;;;		( (0 . "DICTIONARY") (100 . "AcDbDictionary") (280 . 0) (281 . 1) (3 . "*A1"))
;;;		- - - - - - - - - - - - - -
;;;
;;;
;;;				Niveau 3 : Xrecord contenant les infos du 1er filtre
;;;				( (0 . "XRECORD") (102 ."{ACAD_XDICTIONARY")  (100 . "AcDbXrecord") (280 . 1) (1 . "AcLyLayerFilter") 
;;;				(90 . 1) (300 . "essai") (301 . "NAME==\"*filtre-essai\""))
;;;				- - - - - - - - - - - - - -
;;;
;;;						Niveau 4 : dictionaire étendu
;;;						((-1 . <Nom d'entité: 7efd8168>) (0 . "DICTIONARY") (330 . <Nom d'entité: 
;;;						7efd8158>) (5 . "ED") (100 . "AcDbDictionary") (280 . 1) (281 . 1) (3 . 
;;;						"ACLYDICTIONARY") (360 . <Nom d'entité: 7efd8170>))
;;;						- - - - - - - - - - - - - -
;;;
;;;								Niveau 5 : dictionaire
;;;								( (0 . "DICTIONARY")  (100 . "AcDbDictionary") (280 . 0) (281 . 1) (3 . "*A1"))
;;;								- - - - - - - - - - - - - -
;;;
;;;										Niveau 6  : Xrecord contenant les infos du 2eme filtre
;;;										( (0 . "XRECORD") (100 . "AcDbXrecord") (280 . 1) (290 . 1) (1 . 
;;;										"AcLyLayerFilter") (90 . 1) (300 . "sous") (301 . "NAME==\"*filtre-sous\""))
;;;										- - - - - - - - - - - - - -
;;;Récapitulation simplifiée:
;;;1 DICTIONARY
;;;	2 DICTIONARY
;;;		3 XRECORD du 1er filtre
;;;			4 DICTIONARY (ACAD_XDICTIONARY: ne peux pas etre créé par dictadd, mais par la méthode getextensiondictionary)
;;;				5 DICTIONARY
;;;					6 XRECORD du sous filtre
;;----------------------------------
;;**************************************************************************
;;§/calques/supprime tous les filtres de calques/none
;;; Purge/delete all layer filter or filters compatible with 2005 or later
;;; Example: (DeleteLayerFilters2)
(defun c:DeleteLayerFilters ()
  (vl-Catch-All-Apply
    '(lambda ()
       (vla-Remove
  (vla-GetExtensionDictionary
    (vla-Get-Layers
      (vla-Get-ActiveDocument
               (vlax-Get-Acad-Object))))
  "AcLyDictionary")))
)
;;**************************************************************************
;;§/calques/Liste tous les filtres de calques/none
(defun c:ListeLayerFilters ()
  (setq filtXdic 
  (vla-GetExtensionDictionary
    (vla-Get-Layers
      (vla-Get-ActiveDocument
               (vlax-Get-Acad-Object))))
	)
  (print (pw_vlax_list_nom_items (setq xdAcad_layerfilters (vla-item filtXdic "ACAD_LAYERFILTERS"))))
  (print (pw_vlax_list_nom_items (setq xdAcad_layerstates (vla-item filtXdic "ACAD_LAYERSTATES"))))
  (print (pw_vlax_list_nom_items (setq XdAcLyDictionary (vla-item filtXdic "ACLYDICTIONARY"))))

)
;;**************************************************************************
;;§/calques/supprime le dictionaire de filtres de calques simple de nom "monfiltre"/monfiltre
;
(defun pw_eraseLayerFilter ( monfiltre /  dic  )
 
  (setq	dic (pw_eLayerFilterDic))
  (if (dictsearch dic monfiltre)
    (dictremove dic monfiltre)
  )
)

;;**************************************************************************
;;§/calques/supprime le dictionaire de filtres de calques Acly = avec sous filtre en cascade de nom "monfiltre"/monfiltre
;
(defun pw_eraseLayerFilterAcly ( monfiltre /  dic  ) 
 (setq	dic (pw_eLayerFilterAclyDic))
 ;;(foreach l (pw_vlax_list_items dic)
 (foreach l (pw_ListAclyLayerFilter)    
  (if (= (strcase (last l)) (strcase monfiltre))
    
    (dictremove dic (car l))
  )
 )
)

;;**************************************************************************
;;§/calques/retourne une liste d'assoc ((nomfiltreanno nomfiltre))  /none
;;soit la lsite des élement du dict ACLY de niveau 2, avec leur nom en clair
;;(pw_ListAclyLayerFilter) -> (("*A1" "_NOXREF") ("*A2" "NADIAA") ("*A3" "RESEAUX") ("*A4" "REL"))
;
(defun pw_ListAclyLayerFilter ( / 2dic lsousdic l nom eg  )
  ;;accede au dictionaire de niveau 2
  (setq 2dic (pw_eLayerFilterAclyDic))
  ;;cherche un nom anonyme
  (if (setq lsousdic (pw_vlax_list_items (vlax-ename->vla-object 2dic)))      
    (mapcar '(lambda (l) 
              (list (vla-get-name l)
               (setq nom (cdr (assoc 300 (entget (vlax-vla-object->ename l)))))
	      )
	       )
	    lsousdic
    )
  )
)
;;**************************************************************************
;;§/calques/retourne le ename du dictionaire des filtres de calques simple/none
;
(defun pw_eLayerFilterDic ( / dict dic cur )
 
  (setq	dict	(vlax-vla-object->ename (vla-GetExtensionDictionary (vla-get-layers pw-acaddocument )))
	dic	(cdar (dictsearch dict "ACAD_LAYERFILTERS"))
  )
  ;(print "************")

  ; check to see if "ACAD_LAYERFILTERS" exists. if not, make it
  (if (not dic)
    (progn (setq cur '((0 . "DICTIONARY") (100 . "AcDbDictionary")))
	   (setq dic (dictadd dict "ACAD_LAYERFILTERS" (entmakex cur)))
    )
  )
  dic
)

;;**************************************************************************
;;§/calques/retourne le ename du dictionaire des filtres de calques Acly = avec sous filtre en cascade /none
;
(defun pw_eLayerFilterAclyDic ( / dict aclydic cur )
 
  (setq	dict	(vlax-vla-object->ename (vla-GetExtensionDictionary (vla-get-layers pw-acaddocument )))
	aclydic	(cdar (dictsearch dict "ACLYDICTIONARY"))
  )
  ;(print "************")
  ; check to see if "ACAD_LAYERFILTERS" exists. if not, make it
  (if (not aclydic)
    (progn (setq cur '((0 . "DICTIONARY") (100 . "AcDbDictionary")))
	   (setq aclydic (dictadd dict "ACLYDICTIONARY" (entmakex cur)))
    )
  )
  aclydic
)

;;**************************************************************************
;;§/calques/retourne le ename du dictionaire du filtres de calques nomfiltre /nomfiltre
;;retourne le niveau 3:
;;;		3 XRECORD du 1er filtre
;
(defun pw_eLayerFilterByName (nomfiltre / 2dic lsousdic leg nom eg res )
  ;;accede au dictionaire de niveau 2
  (setq 2dic (pw_eLayerFilterAclyDic))
  ;;cherche un nom anonyme
  (if (setq lsousdic (pw_vlax_list_items (vlax-ename->vla-object 2dic)))
    (progn
      
     ;;ci dessous methode pour acceder au xrecordata en vba: un dump ne donne rien !		   
;;;     (foreach l lsousdic
;;;       ;;verification de ce qui a été écrit
;;;      (vla-GetXRecordData
;;;	l
;;;	'ArrayType
;;;	'ArrayValue
;;;      )
;;;      (print (mapcar 'vlax-variant-value (vlax-safearray->list ArrayValue)))
;;;     )
    (setq leg (mapcar 'entget (mapcar 'vlax-vla-object->ename lsousdic)))
    (foreach eg leg
      (setq nom (cdr (assoc 300 eg)))
      (if (= (strcase nom )(strcase nomfiltre))
       (setq res (cdr (assoc -1 eg)))
      )
    )
  )
    )
  res
)
;;**************************************************************************
;;§/calques/retourne le ename du sous dictionaire du filtres de calques nomfiltre /baseDic nomfiltre
;;retourne le niveau 5:
;;;		5 DICTIONARY
;
(defun pw_eSousLayerFilterByName (baseDic nomfiltre / 2dic lsousdic leg nom eg res )
;; niveau 4
     (setq objxdic (vla-GetExtensionDictionary (vlax-ename->vla-object baseDic)))     
          ;; (print (vlax-get-property objxdic 'Count))
     (if (setq itm (vlax-invoke-method objxdic 'Item 0))
       (progn
        (setq litm (pw_vlax_list_items itm))
       
    (setq leg (mapcar 'entget (mapcar 'vlax-vla-object->ename litm)))
    (foreach eg leg
      (setq nom (cdr (assoc 300 eg)))
      (if (= (strcase nom )(strcase nomfiltre))
       (setq res (cdr (assoc -1 eg)))
      )
    )
  )
    )
  res
)

;;**************************************************************************
;;§/calques/retourne le ename du dictionaire de niveau 5 à partir d'un dic niveau 3/edic3
;;               5 DICTIONARY
;;utile pour ajouter un sous filtre à un filtre existant
;
(defun pw_eLayerFilterAclyDictionary5 ( 3dic / objxdic exdic xdlist   xname )
 
  ;; niveau 4
     (setq objxdic (vla-GetExtensionDictionary (vlax-ename->vla-object 3dic)))
     
          ;; (print (vlax-get-property objxdic 'Count))
     (if ;; (setq itm (vlax-invoke-method objxdic 'Item 0))
        (setq itm (car (pw_vlax_list_items objxdic)))
        ;; niveau 5 existe

        (vlax-vla-object->ename itm)
       (progn

       ;; niveau 5 créé
     (setq xdlist
	 (list '(0 . "DICTIONARY") '(100 . "AcDbDictionary") '(280 . 0) '(281 . 1))
	   xname	 (entmakex xdlist))
     (dictadd (vlax-vla-object->ename objxdic) "ACLYDICTIONARY"  xname)
     )
    )

)

 

----------------------------------------------------------------------

Site: https://www.g-eaux.fr

Blog: http://g-eaux.over-blog.com

Lien vers le commentaire
Partager sur d’autres sites

Salut,

Je ne veux pas te priver du plaisir d'explorer la structure des filtres de calque, je vais donc essayer de juste te donner des pistes.

Schématiquement, ça se présente comme ça :

Table des calques
    |_Dictionnaire d'extension
        |_Dictionnaire "ACAD_LAYERFILTERS"
        |_Dictionnaire "ACAD_LAYERSTATES"
        |_Dictionnaire "ACLYDICTIONARY"
            |_Xrecord "*A1"
            |_Xrecord "*A2"
                |_Dictionnaire d'extension
		            |_Dictionnaire "ACLYDICTIONARY"
	                    |_Xrecord "*A1"
						...

Avec quelques routines de la bibliothèque Dictionaries sur cette page, on peut parcourir récursivement cette arborescence de façon plus "lisible".

;; gc:GetExtDict (gile)
;; Retourne le dictionnaire d'extension de l'entité (ou nil)
;;
;; Argument : ent (ENAME)
(defun gc:GetExtDict (ent)
  (cdadr (member '(102 . "{ACAD_XDICTIONARY") (entget ent)))
)

;; gc:GetDictEntries
;; Retourne la liste des entrées du dictionnaire
;; sous forme de paires pointées (Nom . ENAME)
;;
;; Argument : dict le dictionnaire (ENAME ou liste DXF)
(defun gc:GetDictEntries (dict / result)
  (and (= (type dict) 'ENAME) (setq dict (entget dict)))
  (while
    (setq dict (vl-member-if (function (lambda (x) (= (car x) 3))) (cdr dict)))
     (setq result (cons (cons (cdar dict) (cdadr dict)) result))
  )
  (reverse result)
)

(defun getSymbolTable (table)
  (cdr (assoc 330 (entget (tblobjname table (cdr (assoc 2 (tblnext table T)))))))
)

(defun getFilters (/ traverse layerTable)
  (defun traverse (xdict / dict)
    (if	(and
	  xdict
	  (setq dict (cdr (assoc "ACLYDICTIONARY" (gc:GetDictEntries xdict))))
	)
      (mapcar '(lambda (x)
		 (cons x (traverse (gc:GetExtDict (cdr x))))
	       )
	      (gc:GetDictEntries dict)
      )
    )
  )
  (setq layerTable (cdr (assoc 330 (entget (tblobjname "layer" "0")))))
  (traverse (gc:GetExtDict layerTable))
)

Pour une structure comme celle ci-dessus getFilters renvoie :
((("*A1" . <Nom d'entité: 27a10c510a0>)) (("*A2" . <Nom d'entité: 27a10c510c0>) (("*A1" . <Nom d'entité: 27a10c51100>))))

Un entget sur chaque ename te permettra de retrouver le nom du filtre, sa "formule" etc.

Sinon, dans la pratique, tu peux utiliser le petit plugin .NET LayerFilterImportExport téléchargeable depuis cette page.

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Lien vers le commentaire
Partager sur d’autres sites

♥w♥

J'en déduis donc que j'aurais dû aller plus loin que 4 niveaux finalement ! >w<

Quand j'avais regardé, j'étais bien arrivé à retrouver les XRECORD depuis le dictionnaire ACLYDICTIONARY, mais en regardant ces XRECORD, je tournais en boucle...Donc mon soucis était simplement de ne pas avoir continué plus loin...?
Bon donc chat veut dire qu'il va falloir que je retravaille mon (explore-dxf) pour avoir la possibilité de ne pas afficher les doublons pour alléger le fichier d'export (sinon les boucles prennent 80% du fichier et chat devient vite illisible ^^")

En tous cas, merci beaucoup à vous deux, j'y vois déjà un peu plus clair et je vais voir ce que je peux apprendre pour gérer ces filtres de propriétés de ma plume :3

Bisous,
Luna

Lien vers le commentaire
Partager sur d’autres sites

Par contre, je n'ai jamais trouvé le moyen d'initier le filtre de calque actif  ?

il me semble que par défaut Autocad le positionne sur la dernière xref trouvée

(lorsque l'on active l'option "Appliquer le filtre de calque à la barre d'outils de calque")

alors que je le voudrais par défaut sur un filtre "noxref'

des idées ?

----------------------------------------------------------------------

Site: https://www.g-eaux.fr

Blog: http://g-eaux.over-blog.com

Lien vers le commentaire
Partager sur d’autres sites

  • 4 semaines après...

Coucou,

Bon n'ayant que trop peu de temps pour la programmation ces derniers temps, je n'ai pas vraiment pu explorer les listes DXF comme je l'aurais souhaité...
Je pensais dans un premier temps gérer les filtres de propriétés via des (entmake), mais je n'ai pas pu aller bien loin et je n'avais pas le temps d'apprendre à utiliser les dictionnaires via (dictadd) &co. Du coup je me suis rapatrié sur la version (command) et en utilisant les fonctions de @(gile) pour récupérer la liste mais...au vu de la composition de la liste de sortie de (getfilters), je n'arrive pas à régurgiter uniquement le nom des filtres pour les supprimer via (command).

Je ne maîtrise clairement pas les fonctions récursives donc je n'arrive pas à "décomposer" la liste pour ne conserver que les nom d'entités...
Dans l'exemple ci-dessous, je voudrais passer de :

(
	(
    	("*A1" . <Nom d'entité: 167a7796aa0>)
	)
	(
		("*A2" . <Nom d'entité: 167a7796ac0>)
		(
			("*A1" . <Nom d'entité: 167a7796b00>)
		)
		(
			("*A2" . <Nom d'entité: 167a7796b10>)
		)
	)
	(
		("*A3" . <Nom d'entité: 167a7796b20>)
	)
	(
		("*A4" . <Nom d'entité: 167a7796b40>)
	)
	(
		("*A5" . <Nom d'entité: 167a7796b60>)
	)
	(
		("*A6" . <Nom d'entité: 167a7796b80>)
		(
			("*A1" . <Nom d'entité: 167a7796bc0>)
		)
		(
			("*A2" . <Nom d'entité: 167a7796bd0>)
		)
	)
	(
		("*A7" . <Nom d'entité: 167a7796be0>)
	)
	(
		("*A8" . <Nom d'entité: 167a7796c00>)
	)
	(
		("*A9" . <Nom d'entité: 167a7796c20>)
		(
			("*A1" . <Nom d'entité: 167a7796c60>)
			(
				("*A1" . <Nom d'entité: 167a7796c90>)
			)
		)
	)
)

à :

(
	<Nom d'entité: 167a7796aa0>
	<Nom d'entité: 167a7796ac0>
	<Nom d'entité: 167a7796b00>
	<Nom d'entité: 167a7796b10>
	<Nom d'entité: 167a7796b20>
	<Nom d'entité: 167a7796b40>
	<Nom d'entité: 167a7796b60>
	<Nom d'entité: 167a7796b80>
	<Nom d'entité: 167a7796bc0>
	<Nom d'entité: 167a7796bd0>
	<Nom d'entité: 167a7796be0>
	<Nom d'entité: 167a7796c00>
	<Nom d'entité: 167a7796c20>
	<Nom d'entité: 167a7796c60>
	<Nom d'entité: 167a7796c90>
)

J'ai eu beau essayer des lignes de codes, je n'y arrive pas...Donc même si je n'aime pas chat : avez-vous une fonction qui permettrait de faire cela ?
Il me faut vraiment apprendre à maîtriser les fonctions récursives et les dictionnaires à minima mais le temps commence à manquer malheureusement...

Bisous,
Luna

Lien vers le commentaire
Partager sur d’autres sites

  • 9 mois après...
Le 26/05/2021 à 18:19, (gile) a dit :

Le Xrecord du filtre actif (et lui seul) a un groupe DXF (290 . 1).

Salut,

malheureusement, même si le entmod avec le code ( 290 . 1) fonctionne, pas moyen de rendre le filtre actif !

grr !

 

----------------------------------------------------------------------

Site: https://www.g-eaux.fr

Blog: http://g-eaux.over-blog.com

Lien vers le commentaire
Partager sur d’autres sites

Le 18/06/2021 à 15:20, Luna a dit :

Je ne maîtrise clairement pas les fonctions récursives donc je n'arrive pas à "décomposer" la liste pour ne conserver que les nom d'entités...

Pour voir comment "aplatir" un arbre tel que celui-ci, commençons par étudier la structure : chaque branche de l'arbre est une liste qui peut contenir des feuilles (paires pointées) et des branches. on a bien à faire à une structure récursive dont on veut récupérer les feuilles (plus précisément le cdr de chaque feuille).

Notre fonction récursive devra donc pourvoir identifier une feuille pour en récupérer le cdr, mais aussi traiter une branche, et bien sûr, avoir une condition d'arrêt pour terminer le traitement.
Le traitement récursif des listes consiste le plus souvent à agréger le résultat du traitement du premier élément de la liste (car) au traitement récursif du reste de la liste (cdr).

La condition d'arrêt est simple dans ce cas, comme il faut traiter toute la liste, on s'arrête quand celle-ci est vide.
Le traitement d'un branche est identique au traitement de l'arbre (récursivité), il suffit donc de passer la branche à un appel récursif de la fonction.
Le traitement d'une feuille nécessite de construire la valeur de retour en récupérant le contenu de la feuille pour l'agréger au traitement récursif de reste de la liste. Pour ce faire il faut identifier une feuille à savoir une paire pointée.
Une paire pointée est une liste dont le 'cdr' est un atome, mais attention, comme 'nil' 'est aussi un atome, il faut aussi s'assurer que le 'cdr' n'est pas 'nil'.

Notre fonction, qui doit renvoyer une liste peut donc être définie comme suit :

  1. la liste vide, on renvoie nil ;
  2. le premier élément de la liste est une paire pointée, on construit la liste qui sera finalement renvoyée en ajoutant la valeur de la paire pointée avec 'cons' à la liste renvoyée en passant le reste de la liste à l'appel récursif de la fonction ;
  3. le premier élément est une branche, on concatène la liste renvoyée par le traitement de la branche avec celle renvoyée par le reste de la liste.
(defun flatten (tree)
  (cond
    ((null tree) nil)
    ((and (cdar tree) (atom (cdar tree)))
     (cons (cdar tree) (flatten (cdr tree))))
    (T (append (flatten (car tree)) (flatten (cdr tree))))
  )
)

Voyons comment ça fonctionne avec un arbre simple mais significatif quand même.

(setq tree
       '(
	  (
	    ("*A1" . 1)
	  )
	  (
	    ("*A2" . 2)
	    (
	      ("*A1" . 3)
	    )
	    (
	      ("*A2" . 4)
	    )
	  )
	)
)

Description des évaluations dans la phase d'empilement des appels récursif (on évalue toujours le premier appel) :

;; 1 le premier élément est une branche
(flatten '((("*A1" . 1)) (("*A2" . 2) (("*A1" . 3)) (("*A2" . 4)))))
;; 2 le premier élément est une feuille
(append (flatten '(("*A1" . 1))) (flatten '((("*A2" . 2) (("*A1" . 3)) (("*A2" . 4))))))
;; 3 le premier élément est vide
(append (cons 1 (flatten nil)) (flatten '((("*A2" . 2) (("*A1" . 3)) (("*A2" . 4))))))
;; 4 le premier élément est une branche
(append (cons 1 nil) (flatten '((("*A2" . 2) (("*A1" . 3)) (("*A2" . 4))))))
;; 5 le premier élément est une feuille
(append (cons 1 nil) (append (flatten '(("*A2" . 2) (("*A1" . 3)) (("*A2" . 4))) (flatten nil))))
;; 6 le premier élément est une branche
(append (cons 1 nil) (append (cons 2 (flatten '((("*A1" . 3)) (("*A2" . 4))))) (flatten nil)))
;; 7 le premier élément est une feuille
(append (cons 1 nil) (append (cons 2 (append (flatten '(("*A1" . 3))) (flatten '((("*A2" . 4)))))) (flatten nil)))
;; 8 le premier élément est vide
(append (cons 1 nil) (append (cons 2 (append (cons 3 (flatten nil)) (flatten '((("*A2" . 4)))))) (flatten nil)))
;; 9 le premier élément est une branche
(append (cons 1 nil) (append (cons 2 (append (cons 3 nil) (flatten '((("*A2" . 4)))))) (flatten nil)))
;; 10 le premier élément est une feuille
(append (cons 1 nil) (append (cons 2 (append (cons 3 nil) (append (flatten '(("*A2" . 4))) (flatten nil)))) (flatten nil)))
;; 11 le premier élément est vide
(append (cons 1 nil) (append (cons 2 (append (cons 3 nil) (append (cons 4 (flatten nil)) (flatten nil)))) (flatten nil)))
;; 12 le premier élément est vide
(append (cons 1 nil) (append (cons 2 (append (cons 3 nil) (append (cons 4 nil) (flatten nil)))) (flatten nil)))
;; 13 le premier élément est vide
(append (cons 1 nil) (append (cons 2 (append (cons 3 nil) (append (cons 4 nil) nil))) (flatten nil)))
;; fin des appels récursifs, dépilement
(append (cons 1 nil) (append (cons 2 (append (cons 3 nil) (append (cons 4 nil) nil))) nil))

 

  • Like 1

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Lien vers le commentaire
Partager sur d’autres sites

Une autre façon, peut-être plus facile à appréender, pas sûr avec la cascade (apply 'append (mapcar '(lambda ...))).
Dans tous les cas, on n'échappe pas à la récursivité.

(defun traverse (tree)
  (apply
    'append
    (mapcar
      (function
	(lambda	(x)
	  (if (and (cdr x) (atom (cdr x)))
	    (list (cdr x))
	    (traverse x)
	  )
	)
      )
      tree
    )
  )
)

 

Gilles Chanteau - gileCAD -
Développements sur mesure pour AutoCAD
ADSK_Expert_Elite_Icon_S_Color_Blk_125.png

Lien vers le commentaire
Partager sur d’autres sites

Coucou,

Merci beaucoup @(gile) pour ces explications ! Je vais regarder tout cela d'un peu plus prêt lorsque j'aurais un peu de temps 😉
Mais je pense que cela va me permettre de m'entraîner avec une bonne base sur les programmes qui nécessitent de la récursivité

Bisous,
Luna

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é