Données étendues et dictionnaires
Jusqu'ici, nous avons créé, modifié et lu des entités avec leurs propriétés géométriques standard : points, rayons, calques, couleurs. Mais dans un programme réel, vous aurez souvent besoin d'attacher vos propres informations à une entité — un numéro de pièce, une référence fournisseur, un lien vers une autre entité. AutoLISP offre plusieurs mécanismes pour cela, du plus simple au plus puissant.
Les données étendues (xdata)
Les données étendues (extended data ou xdata) permettent d'attacher des informations personnalisées à n'importe quelle entité du dessin. Ces données sont invisibles pour l'utilisateur — elles ne s'affichent pas à l'écran — mais votre programme peut les lire et les modifier.
Enregistrer une application
Avant d'attacher des xdata, vous devez enregistrer un nom d'application avec regapp. Ce nom sert d'identifiant pour regrouper vos données :
(regapp "WIIP_TUYAUTERIE")
regapp retourne le nom de l'application si l'enregistrement réussit, ou nil si le nom est déjà enregistré (ce qui n'est pas une erreur). En pratique, on appelle regapp au début du programme sans se soucier de la valeur de retour.
Convention : choisissez un nom d'application unique qui identifie clairement votre programme. Un préfixe avec le nom de votre société évite les collisions avec d'autres développeurs.
Attacher des xdata à une entité
Les xdata sont ajoutées au groupe -3 de la liste DXF d'une entité. Chaque donnée a un code DXF spécifique :
| Code | Type de donnée | Exemple |
|---|---|---|
| 1000 | Chaîne de caractères | (1000 . "DN100") |
| 1001 | Nom d'application (début d'un groupe xdata) | (1001 . "WIIP_TUYAUTERIE") |
| 1005 | Référence de maintien (lien vers une autre entité) | (1005 . "1A3F") |
| 1010 | Point 3D | (1010 0.0 0.0 0.0) |
| 1040 | Nombre réel | (1040 . 114.3) |
| 1070 | Entier 16 bits, de -32 768 à 32 767 — typique pour les index de couleur, les flags | (1070 . 42) |
| 1071 | Entier long 32 bits, de -2 147 483 648 à 2 147 483 647 — pour les grandes valeurs | (1071 . 100000) |
Voici comment attacher des xdata à la dernière entité créée :
;; Enregistrer l'application
(regapp "WIIP_TUYAUTERIE")
;; Récupérer la dernière entité
(setq entite (entlast))
(setq donnees (entget entite))
;; Ajouter les xdata
(setq donnees
(append donnees
(list
(list -3
(list "WIIP_TUYAUTERIE"
(cons 1000 "DN100") ; Diamètre nominal
(cons 1040 114.3) ; Diamètre extérieur en mm
(cons 1070 10) ; Pression nominale (PN)
)
)
)
)
)
;; Appliquer la modification
(entmod donnees)
Le code -3 signale à AutoCAD que ce qui suit est un bloc de données étendues. À l'intérieur, les données sont groupées par nom d'application.
Lire les xdata d'une entité
Par défaut, entget ne retourne pas les xdata. Il faut explicitement demander les données d'une application :
;; Lire l'entité AVEC ses xdata
(setq donnees (entget (entlast) '("WIIP_TUYAUTERIE")))
;; Extraire le groupe xdata
(setq xdata (assoc -3 donnees))
Le résultat de (assoc -3 donnees) ressemble à :
(-3 ("WIIP_TUYAUTERIE"
(1000 . "DN100")
(1040 . 114.3)
(1070 . 10)
)
)
Pour extraire une valeur précise :
;; Récupérer les données de l'application
(setq donnees-appli (cdadr (assoc -3 donnees)))
;; Chercher le diamètre nominal
(cdr (assoc 1000 donnees-appli)) ; → "DN100"
;; Chercher le diamètre extérieur
(cdr (assoc 1040 donnees-appli)) ; → 114.3
Exemple complet : étiqueter des entités
Ce programme attache un identifiant unique à chaque entité sélectionnée, puis permet de le retrouver :
(defun c:etiqueter (/ jeu index entite donnees identifiant)
(regapp "WIIP_ID")
(setq jeu (ssget))
(if jeu
(progn
(setq index 0)
(repeat (sslength jeu)
(setq entite (ssname jeu index))
(setq identifiant (strcat "ID-" (itoa (1+ index))))
;; Lire l'entité
(setq donnees (entget entite))
;; Ajouter les xdata
(setq donnees
(append donnees
(list
(list -3
(list "WIIP_ID"
(cons 1000 identifiant)
)
)
)
)
)
(entmod donnees)
(setq index (1+ index))
)
(princ (strcat "\n" (itoa (sslength jeu)) " entité(s) étiquetée(s)."))
)
(princ "\nAucune sélection.")
)
(princ)
)
(defun c:lire-etiquette (/ selection entite donnees xdata)
(setq selection (entsel "\nSélectionnez une entité : "))
(if selection
(progn
(setq entite (car selection))
(setq donnees (entget entite '("WIIP_ID")))
(setq xdata (assoc -3 donnees))
(if xdata
(princ (strcat "\nIdentifiant : " (cdr (assoc 1000 (cdadr xdata)))))
(princ "\nCette entité n'a pas d'identifiant.")
)
)
(princ "\nAucune sélection.")
)
(princ)
)
Les dictionnaires d'extension
Les xdata sont parfaites pour attacher des données à une entité spécifique. Mais que faire si vous voulez stocker des informations au niveau du dessin lui-même — par exemple, la configuration de votre programme, un compteur global, ou une table de correspondance ? C'est le rôle des dictionnaires d'extension.
Le dictionnaire des objets nommés
Chaque dessin AutoCAD contient un dictionnaire des objets nommés (Named Object Dictionary ou NOD). C'est la racine de l'arborescence des dictionnaires. Vous y accédez avec la fonction namedobjdict :
(setq dictionnaire-racine (namedobjdict))
Cette fonction retourne le nom d'entité du dictionnaire racine. Vous pouvez ensuite y chercher ou y ajouter des entrées.
Chercher dans un dictionnaire
La fonction dictsearch cherche une entrée dans un dictionnaire par son nom :
;; Chercher un dictionnaire nommé "WIIP_CONFIG"
(setq resultat (dictsearch (namedobjdict) "WIIP_CONFIG"))
Si l'entrée existe, dictsearch retourne sa liste DXF. Sinon, elle retourne nil.
Stocker des données avec des xrecords
Un xrecord est un objet de la base de données qui peut contenir des données arbitraires. C'est l'équivalent d'un enregistrement dans une base de données. On le crée avec entmakex (variante d'entmake qui retourne le nom d'entité) :
;; Créer un xrecord
(setq xrecord
(entmakex
(list
'(0 . "XRECORD")
'(100 . "AcDbXrecord")
(cons 1 "Tuyauterie industrielle") ; Chaîne
(cons 70 42) ; Entier
(cons 40 3.14) ; Réel
)
)
)
Les codes DXF standard sont utilisés pour typer les données dans un xrecord :
| Code | Type |
|---|---|
| 1 | Chaîne de caractères |
| 10 | Point 3D |
| 40 | Nombre réel |
| 70 | Entier |
| 300-309 | Chaînes supplémentaires |
Ajouter un xrecord au dictionnaire
Une fois le xrecord créé, il faut l'attacher au dictionnaire des objets nommés avec dictadd :
(dictadd (namedobjdict) "WIIP_CONFIG" xrecord)
Exemple complet : configuration persistante
Ce programme stocke et lit une configuration dans le dessin :
(defun sauvegarder-configuration (nom-projet echelle / xrecord existant)
;; Vérifier si la configuration existe déjà
(setq existant (dictsearch (namedobjdict) "WIIP_CONFIG"))
(if existant
;; Supprimer l'ancien xrecord
(dictremove (namedobjdict) "WIIP_CONFIG")
)
;; Créer un nouveau xrecord
(setq xrecord
(entmakex
(list
'(0 . "XRECORD")
'(100 . "AcDbXrecord")
(cons 1 nom-projet)
(cons 40 echelle)
)
)
)
;; L'ajouter au dictionnaire
(dictadd (namedobjdict) "WIIP_CONFIG" xrecord)
(princ (strcat "\nConfiguration sauvegardée pour " nom-projet))
(princ)
)
(defun lire-configuration (/ resultat)
(setq resultat (dictsearch (namedobjdict) "WIIP_CONFIG"))
(if resultat
(progn
(princ (strcat "\nProjet : " (cdr (assoc 1 resultat))))
(princ (strcat "\nÉchelle : " (rtos (cdr (assoc 40 resultat)) 2 2)))
)
(princ "\nAucune configuration trouvée.")
)
(princ)
)
;; Utilisation
(defun c:sauver-config (/ nom echelle)
(setq nom (getstring T "\nNom du projet : "))
(setq echelle (getreal "\nÉchelle : "))
(sauvegarder-configuration nom echelle)
)
(defun c:lire-config ()
(lire-configuration)
)
Comme les xdata, les dictionnaires sont persistants : ils sont sauvegardés dans le fichier DWG et survivent aux sessions d'AutoCAD. Leur avantage décisif est qu'ils ne sont pas limités en taille (les xdata sont plafonnées à 16 Ko par application et par entité) et qu'ils permettent de stocker des données au niveau du dessin, indépendamment de toute entité.
Xdata ou dictionnaire : comment choisir ?
| Critère | Xdata | Dictionnaire d'extension |
|---|---|---|
| Portée | Attachées à une entité | Au niveau du dessin |
| Taille maximale | 16 Ko par application et par entité | Pas de limite pratique |
| Complexité | Simple | Plus complexe |
| Cas d'usage | Propriétés personnalisées d'une entité | Configuration globale, tables de données |
En règle générale : si la donnée est liée à une entité spécifique, utilisez les xdata. Si elle concerne le dessin dans son ensemble, utilisez un dictionnaire.
Lier des entités entre elles par les maintiens
Chaque entité du dessin possède un maintien (handle en anglais) — un identifiant unique sous forme de chaîne hexadécimale. Vous le trouvez dans le code DXF 5 :
(setq donnees (entget (entlast)))
(cdr (assoc 5 donnees)) ; → "1A3F" (par exemple)
Ce maintien reste stable : il ne change pas quand vous sauvegardez et rouvrez le dessin. C'est ce qui le rend idéal pour créer des liens entre entités.
Créer un lien entre deux entités
Imaginons que vous voulez lier un texte d'annotation à la ligne qu'il décrit. L'idée est de stocker le maintien de la ligne dans les xdata du texte :
(defun c:lier-annotation (/ selection-ligne ligne donnees-ligne handle-ligne
selection-texte texte donnees-texte)
(regapp "WIIP_LIEN")
;; Sélectionner la ligne
(setq selection-ligne (entsel "\nSélectionnez la ligne : "))
(if (null selection-ligne)
(progn (princ "\nAucune sélection.") (princ) (exit))
)
(setq ligne (car selection-ligne))
(setq donnees-ligne (entget ligne))
(setq handle-ligne (cdr (assoc 5 donnees-ligne)))
;; Sélectionner le texte
(setq selection-texte (entsel "\nSélectionnez le texte : "))
(if (null selection-texte)
(progn (princ "\nAucune sélection.") (princ) (exit))
)
(setq texte (car selection-texte))
(setq donnees-texte (entget texte))
;; Attacher le maintien de la ligne au texte via xdata
(setq donnees-texte
(append donnees-texte
(list
(list -3
(list "WIIP_LIEN"
(cons 1005 handle-ligne) ; Code 1005 = référence de maintien
)
)
)
)
)
(entmod donnees-texte)
(princ (strcat "\nLien créé vers le maintien " handle-ligne))
(princ)
)
Le code xdata 1005 est spécialement conçu pour stocker des références de maintiens. Ce n'est pas anodin — AutoCAD le traite différemment d'une simple chaîne (code 1000).
Retrouver l'entité liée
Pour retrouver une entité à partir de son maintien, utilisez handent :
(defun c:suivre-lien (/ selection entite donnees xdata handle-cible cible)
(setq selection (entsel "\nSélectionnez l'annotation : "))
(if (null selection)
(progn (princ "\nAucune sélection.") (princ) (exit))
)
(setq entite (car selection))
(setq donnees (entget entite '("WIIP_LIEN")))
(setq xdata (assoc -3 donnees))
(if xdata
(progn
(setq handle-cible (cdr (assoc 1005 (cdadr xdata))))
(setq cible (handent handle-cible))
(if cible
(progn
(princ (strcat "\nEntité liée trouvée : " handle-cible))
;; Mettre l'entité cible en surbrillance
(redraw cible 3)
)
(princ "\nL'entité liée n'existe plus dans le dessin.")
)
)
(princ "\nCette entité n'a pas de lien.")
)
(princ)
)
WBLOCK et la traduction des maintiens
C'est un point crucial à comprendre. Quand vous utilisez WBLOCK (écrire un bloc dans un fichier externe), AutoCAD traduit les maintiens : les entités reçoivent de nouveaux maintiens dans le fichier de destination. Et grâce au code 1005, AutoCAD sait que la valeur stockée est un maintien et met à jour la référence automatiquement. C'est pour cela qu'il ne faut pas utiliser le code 1000 (chaîne ordinaire) pour stocker un maintien — AutoCAD ne saurait pas qu'il doit le traduire.
En revanche, lors d'une copie interne (par exemple avec _COPY ou (command "_COPY" ...)), il n'y a pas de traduction de maintien. La copie conserve les mêmes valeurs xdata que l'original, y compris les références de maintiens. Les deux entités pointeront donc vers la même cible. C'est un comportement à garder en tête : après une copie, il faudra peut-être mettre à jour les liens manuellement.
| Opération | Traduction des maintiens (code 1005) |
|---|---|
| WBLOCK (export vers fichier externe) | Oui — les références sont mises à jour |
| INSERT (import d'un fichier externe) | Oui — les références sont mises à jour |
COPIE interne (_COPY) |
Non — les références restent identiques |
| COPYCLIP / PASTECLIP | Oui — traitement similaire à WBLOCK/INSERT |
Résumé
| Concept | Fonction | Description |
|---|---|---|
| Enregistrer une application | regapp |
Déclare un nom d'application pour les xdata |
| Lire les xdata | (entget ename '("APP")) |
Récupère les données étendues d'une entité |
| Dictionnaire racine | (namedobjdict) |
Accède au dictionnaire des objets nommés |
| Chercher dans un dictionnaire | (dictsearch dict "nom") |
Recherche une entrée par nom |
| Ajouter au dictionnaire | (dictadd dict "nom" xrec) |
Attache un xrecord au dictionnaire |
| Maintien d'une entité | (cdr (assoc 5 donnees)) |
Identifiant unique et stable |
| Entité depuis un maintien | (handent "1A3F") |
Retrouve une entité par son maintien |
Dans le prochain chapitre, nous verrons comment réagir automatiquement aux modifications du dessin grâce aux reactors.
Besoin d'un développement AutoCAD (AutoLISP, ObjectARX, .NET, VBA) ? Contactez-moi pour un devis gratuit.