Article de blog de développeurs Autodesk® qui répond à une requête technique complexe concernant les objets annotatifs dans AutoCAD®. Le problème central abordé est de déterminer la position exacte des coordonnées de la valeur d’une dimension lorsque celle-ci a été ajustée pour différentes échelles d’annotation dans le dessin.
L’article explique que cette donnée spécifique à l’échelle n’est pas stockée directement sur l’entité de dimension principale, mais se trouve dans son dictionnaire d’extension . La méthode de récupération, utilisant l’API ObjectARX, nécessite un processus de recherche en trois étapes pour trouver l’échelle cible. Il faut ensuite localiser un objet compagnon spécialisé appelé AcDbObjectContextData qui contient les informations d’écrasement. Finalement, les coordonnées du texte sont extraites des propriétés de l’objet de contexte, typiquement en recherchant le DXF code 10 , révélant la position unique pour chaque échelle configurée.
Note Technique : Extraction de la Position de Texte de Cote par Échelle d’Annotation
Introduction
L’un des défis techniques récurrents lors de la manipulation par programme des objets annotatifs dans AutoCAD® réside dans l’extraction des propriétés spécifiques à une échelle. En particulier, il est impossible d’obtenir directement les coordonnées de position du texte d’une cote lorsque cette position a été manuellement remplacée pour des échelles d’annotation distinctes. Cette note technique fournit une méthode de programmation détaillée et fiable pour résoudre ce problème en utilisant l’API ObjectARX, en explorant l’architecture de stockage sous-jacente des données de remplacement.
1. Principe Fondamental : Le Stockage des Données de Remplacement
Pour développer des solutions robustes, il est stratégique de comprendre comment AutoCAD® stocke les données des objets annotatifs. La complexité provient du fait que les propriétés de remplacement, comme la position du texte de cote pour une échelle spécifique, ne sont pas stockées sur l’entité de cote principale (AcDbDimension). Cette information est déportée dans un objet compagnon, ce qui nécessite une approche d’extraction indirecte. Le mécanisme de stockage repose sur trois composants architecturaux clés. L’accès à la position du texte de cote remplacée se fait en naviguant à travers cette hiérarchie :
- Dictionnaire d’Extension (
Extension Dictionary) : Il s’agit d’un conteneur (AcDbDictionary) qui appartient à l’entité de cote. Il sert de point d’entrée pour accéder à toutes les données étendues associées à cette cote, y compris les informations de contexte d’échelle. - Données de Contexte (
AcDbObjectContextData) : À l’intérieur du dictionnaire d’extension, AutoCAD® stocke un objetAcDbObjectContextData(ou une classe dérivée) pour chaque échelle d’annotation qui possède au moins une propriété de remplacement. Chaque objet de ce type est associé à une échelle unique. - Stockage des Propriétés : C’est finalement à l’intérieur de l’objet
AcDbObjectContextDataque la position du texte de cote remplacée est effectivement stockée. Cette information n’est pas accessible via une propriété directe, mais doit être extraite en analysant les données DXF brutes de l’objet, par exemple avec la fonctionacdbEntGetX.
Cette architecture de données spécifique dicte la procédure à suivre pour localiser et extraire les coordonnées recherchées, comme détaillé dans la section suivante.
2. Procédure d’Extraction en Trois Étapes
Cette section constitue le cœur procédural de la note. La solution consiste en une recherche structurée qui permet de localiser et d’extraire les coordonnées de position du texte en suivant trois étapes logiques.
2.1. Étape 1 : Identifier l’Échelle d’Annotation Cible
Avant toute chose, il est nécessaire d’obtenir une référence à l’objet AcDbAnnotationScale correspondant à l’échelle d’annotation pour laquelle on souhaite extraire la position. Cet objet représente une échelle définie dans le dessin (par exemple, « 1:5 » ou « 1:30 »). Dans le contexte d’une commande interactive ou d’un processus automatisé, cela correspond souvent à l’échelle courante, accessible via l’équivalent de la variable système CANNONSCALE.
2.2. Étape 2 : Parcourir le Dictionnaire d’Extension de la Cote
Une fois l’échelle cible identifiée, l’étape suivante consiste à accéder au dictionnaire d’extension de l’entité de cote (AcDbDimension). La logique de recherche implique de parcourir le dictionnaire nommé ACDB_ANNOTATIONSCALES à l’intérieur du dictionnaire d’extension. Bien que le Handle de l’objet AcDbAnnotationScale serve à l’identification, la recherche ne se fait pas par une lecture directe utilisant ce Handle comme clé. Il faut plutôt itérer sur les entrées de ce dictionnaire, dont les clés sont des chaînes de caractères (par exemple, *A1, *A2), pour trouver l’objet AcDbObjectContextData qui correspond à l’échelle d’annotation cible.
2.3. Étape 3 : Extraire la Position à partir des Données de Contexte
L’objet identifié à l’étape 2 est de type AcDbObjectContextData. La dernière étape consiste à extraire les données DXF de cet objet. La position du texte est stockée sous la forme d’un point 3D. Pour l’obtenir, il faut :
- Utiliser une fonction d’extraction DXF comme
acdbEntGetXsur l’ID de l’objetAcDbObjectContextData. - Parcourir la liste des données DXF retournées.
- Rechercher spécifiquement le code de groupe DXF 10, qui contient généralement les coordonnées de la position du texte.
Cette approche est directement implémentée dans la boucle finale de la fonction run2 présentée ci-après, qui filtre les données DXF extraites pour isoler cette coordonnée.
Note importante : La structure interne des objets de contexte peut varier. La position du texte est généralement stockée avec un code de point standard (plage 10-17) ou un code de point XDATA personnalisé (plage 1010-1017). Il est recommandé d’inspecter les données DXF d’un objet de test pour confirmer le code exact utilisé.
La section suivante présente une implémentation complète de cette procédure avec un exemple de code ObjectARX.
3. Exemple d’Implémentation et Validation
Cette section fournit une démonstration pratique de la théorie et de la procédure décrites précédemment. Elle présente un exemple de code ObjectARX fonctionnel ainsi que le résultat attendu, validant l’approche proposée.
3.1. Logique Principale d’Exécution
La fonction run2 ci-dessous orchestre le processus complet : sélection de l’entité, parcours récursif de son dictionnaire d’extension et, enfin, extraction et affichage des données DXF pertinentes à partir des objets de contexte trouvés.
void run2() {
AcDbDatabase* pDb = acdbHostApplicationServices()->workingDatabase();
if (pDb == nullptr) {
return;
}
// --- Afficher l'échelle d'annotation courante ---
AcDbAnnotationScale* curAnnoScale = pDb->cannoscale();
if (curAnnoScale != nullptr) {
AcString scaleName;
curAnnoScale->getName(scaleName);
acutPrintf(_T("\nCurrent annotation scale is %s."), scaleName.c_str());
}
// --- Sélection de l'entité ---
AcDbEntity* pEnt = nullptr;
ads_name ename = {};
ads_point ePt = {};
if (acedEntSel(_T("\nSelect an entity to inspect its dictionary: "), ename, ePt) != RTNORM) {
acutPrintf(_T("\nSelection cancelled or error."));
return;
}
// --- Ouvrir l'entité en lecture ---
AcDbObjectId entId;
acdbGetObjectId(entId, ename);
acdbOpenObject(pEnt, entId, AcDb::kForRead);
// --- Parcourir le dictionnaire et afficher ---
acutPrintf(_T("\n\n--- Extension Dictionary Tree ---"));
Node rootNode;
rootNode.name = _T("Selected Entity Dictionary");
// Lancer le parcours récursif
walkExtensionDictionary(pEnt->extensionDictionary(), rootNode);
printNodeRecursive(rootNode);
// --- Extraire et afficher la position à partir des données de contexte ---
for (const auto& contextId : g_ContextDataIds) {
acutPrintf(_T("\n\n--- DXF Data for ContextData Id: %lld ---"), contextId.asOldId());
DxfDataContainer contextDxfData = getDxfDataFromId(contextId);
for (const auto& entry : contextDxfData) {
// Rechercher spécifiquement le code DXF 10
if (entry.code == 10)
acutPrintf(_T("\n Dimension Text Value Position %d: %s"), entry.code, entry.value.c_str());
}
}
// --- Nettoyage ---
pEnt->close();
acutPrintf(_T("\n--- End of Dictionary Tree ---\n"));
}
3.2. Fonctions Utilitaires et Structures de Données
Le code s’appuie sur plusieurs structures et fonctions de support pour gérer les données DXF et la navigation dans le dictionnaire.
- Structures
DxfEntryetDxfDataContainer: Ces structures permettent de stocker de manière organisée les paires code/valeur extraites des données DXF d’un objet. - Fonction
getDxfDataFromId: Cette fonction utilitaire prend unAcDbObjectIden entrée, appelleacdbEntGetXet retourne les données DXF dans unDxfDataContainer. - Fonction
walkExtensionDictionary: C’est une fonction récursive qui parcourt le dictionnaire d’extension. Elle identifie spécifiquement les objets dont la classe contientCONTEXT_DATAet stocke leur ID pour une analyse ultérieure.
3.3. Résultat Attendu
L’exécution de la commande associée à la fonction run2 sur une cote annotative avec des positions de texte remplacées produit la sortie suivante. Cette sortie valide le succès de l’opération en affichant clairement les coordonnées de la Dimension Text Value Position (Code DXF 10) pour chaque contexte d’échelle trouvé.
Command: ANSCALE
Current annotation scale is 1:30.
Select an entity to inspect its dictionary:
--- Extension Dictionary Tree ---
-- Context Data Found: *A1 --
-- Context Data Found: *A2 --
- Name: Selected Entity Dictionary | Handle: 0
- Name: AcDbContextDataManager | Handle: 4189C
- Name: ACDB_ANNOTATIONSCALES | Handle: 4189D
- Name: *A1 | Handle: 4189E
- Name: *A2 | Handle: 418AB
--- DXF Data for ContextData Id: 4189E ---
Dimension Text Value Position 10: (677605.0297795322, 185202.7687388095, 0.000000000000000)
Dimension Line Position (End Point 1) 11: (678850.0310509118, 185135.2687388095, 0.000000000000000)
--- DXF Data for ContextData Id: 418AB ---
Dimension Text Value Position 10: (676580.7945011582, 186752.3620226077, 0.000000000000000)
Dimension Line Position (End Point 1) 11: (678850.0310509118, 186741.1120226077, 0.000000000000000)
--- End of Dictionary Tree ---
Cet exemple complet fournit un modèle robuste pour intégrer cette fonctionnalité dans des applications personnalisées nécessitant une interaction fine avec les objets annotatifs.
4. Synthèse et Points Clés
Le point critique à retenir de cette analyse est que pour accéder par programme aux positions de texte de cote qui ont été remplacées pour des échelles d’annotation spécifiques, un développeur doit impérativement cibler l’objet AcDbObjectContextData approprié, localisé dans le dictionnaire d’extension de la cote. Cette information n’existe pas directement sur l’entité AcDbDimension elle-même. La compréhension de cette architecture de données déportée est la clé pour maîtriser la manipulation programmatique des propriétés des objets annotatifs et développer des outils fiables et précis.