Comment récupérer la position de la valeur dimensionnelle par échelle

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 objet AcDbObjectContextData (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 AcDbObjectContextData que 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 fonction acdbEntGetX.

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 :

  1. Utiliser une fonction d’extraction DXF comme acdbEntGetX sur l’ID de l’objet AcDbObjectContextData.
  2. Parcourir la liste des données DXF retournées.
  3. 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 DxfEntry et DxfDataContainer : 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 un AcDbObjectId en entrée, appelle acdbEntGetX et retourne les données DXF dans un DxfDataContainer.
  • Fonction walkExtensionDictionary : C’est une fonction récursive qui parcourt le dictionnaire d’extension. Elle identifie spécifiquement les objets dont la classe contient CONTEXT_DATA et 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.