Programmer des blocs et des attributs dans AutoCAD .NET

CAD-Programm mit dem Symbol eines Ventils und seinen Eigenschaften wie Name, Druck und Temperatur

CAO

D'un clic, votre add-in place le cartouche dans chaque présentation. Le bloc a bonne allure – mais le numéro de dessin, la date et le nom du dessinateur manquent. Ou bien la nomenclature compte moins de portes qu'il n'y en a sur le plan. Les deux ont une cause simple.

Le tampon et son empreinte

Une définition de bloc est comme un tampon d'entreprise : elle décrit une fois pour toutes de quoi se compose le bloc. Chaque référence de bloc est une empreinte qui indique seulement où se trouve le bloc, comment il est orienté et quelle est sa taille. Contrairement au bureau, dans AutoCAD toutes les empreintes changent lorsqu'on retaille le tampon – car la référence ne fait que pointer vers la définition. Le même principe s'applique aux attributs :

QuoiDéfinition (une fois)Référence (autant de fois que souhaité)
Bloc BlockTableRecord dans la BlockTable BlockReference
Attribut AttributeDefinition dans la définition de bloc AttributeReference sur la référence de bloc

Attention : BlockReference.BlockTableRecord est un ObjectId, pas un objet.

Créer une définition de bloc

Une définition est un BlockTableRecord comme l'espace objet, sauf qu'elle n'est pas dessinée elle-même. Trois règles évitent bien des ennuis :

  • Ordre : d'abord, la définition est ajoutée à la BlockTable avec Add et à la transaction avec AddNewlyCreatedDBObject, puis viennent les éléments. Dans l'ordre inverse, on obtient ErrorStatus.NotInDatabase.
  • Calque 0 : même dans un bloc, les éléments sans indication de calque se retrouvent sur le calque courant. Définissez LayerId = db.LayerZero pour que le bloc suive le calque de la référence. Avec la couleur DUBLOC (ColorIndex = 0), un élément suit la couleur de la référence.
  • Point de base : dessinez les éléments autour de l'origine. Origin reste alors (0,0,0), comme le fait aussi la commande _BLOCK.

Créer soi-même les attributs lors de l'insertion

C'est ici que se trouve l'erreur la plus fréquente. Lorsque l'utilisateur insère un bloc avec _INSERT, AutoCAD crée un attribut sur la référence pour chaque définition d'attribut. Qui insère une BlockReference par code n'obtient que la référence. Il doit créer lui-même les attributs :

// Insérer une référence de bloc et – comme _INSERT – créer soi-même les attributs

public static ObjectId FügeEinMitAttributen(Transaction tr, BlockTableRecord besitzer,

    ObjectId blockId, Point3d position, IDictionary<string, string> werte)

{

    var referenz = new BlockReference(position, blockId);

    var ergebnis = besitzer.AppendEntity(referenz);

    tr.AddNewlyCreatedDBObject(referenz, true);



    var definition = (BlockTableRecord)tr.GetObject(blockId, OpenMode.ForRead);

    foreach (ObjectId elementId in definition)

    {

        // Les attributs constants restent dans la définition, la référence n'en reçoit aucun

        if (tr.GetObject(elementId, OpenMode.ForRead) is AttributeDefinition attDef

            && !attDef.Constant)

        {

            var attribut = new AttributeReference();

            // Reprend l'étiquette, la valeur par défaut, le style et la position – convertis dans le dessin

            attribut.SetAttributeFromBlock(attDef, referenz.BlockTransform);

            if (werte.TryGetValue(attDef.Tag, out var wert))

            {

                attribut.TextString = wert;

            }

            referenz.AttributeCollection.AppendAttribute(attribut);

            tr.AddNewlyCreatedDBObject(attribut, true);

        }

    }

    return ergebnis;

}

SetAttributeFromBlock reprend de la définition l'étiquette, la valeur par défaut, la hauteur de texte, le style et le calque. La méthode a besoin de la BlockTransform de la référence pour la position : la définition est en coordonnées de bloc, l'attribut sur la référence en coordonnées générales. Avec une mauvaise matrice, les attributs se retrouveraient autour de l'origine du dessin. Créez le dictionnaire avec StringComparer.OrdinalIgnoreCase, car les étiquettes sont souvent écrites de manières différentes.

Lire et modifier les valeurs

L'AttributeCollection d'une référence ne contient pas les attributs, mais leurs ObjectIds. Vous ouvrez chaque attribut via la transaction, le trouvez par son étiquette – sans tenir compte des majuscules et minuscules – et l'ouvrez en écriture avec UpgradeOpen. Pour les attributs centrés ou alignés à droite, appelez la méthode AdjustAlignment après avoir défini TextString, afin que la position soit recalculée. Deux particularités :

  • Les attributs constants n'ont pas d'AttributeReference. Leur valeur ne figure que dans la définition. Qui veut lister tous les attributs d'une référence doit aussi regarder là.
  • Les nouvelles définitions d'attributs n'atteignent pas d'elles-mêmes les références existantes. Seule la synchronisation les aligne, avec _ATTSYNC ou un code propre. Qui synchronise par l'étiquette perd la valeur si une étiquette a été renommée.

Blocs dynamiques : le nom est trompeur

Lorsque l'utilisateur modifie une propriété d'un bloc dynamique, par exemple la largeur d'une porte, AutoCAD crée un bloc anonyme – une copie avec la géométrie modifiée – et fait pointer la référence dessus. Son nom est alors par exemple *U12. Le nom que voit l'utilisateur est fourni par DynamicBlockTableRecord. Et GetBlockReferenceIds ne trouve que les références avec les valeurs par défaut – c'est ainsi que naît la liste de portes trop courte. Vous trouvez toutes les références via les blocs anonymes :

// Toutes les références d'un bloc dynamique – y compris les modifiées (*U…)

var definition = (BlockTableRecord)tr.GetObject(definitionId, OpenMode.ForRead);

var alle = definition.GetBlockReferenceIds(true, false).Cast<ObjectId>().ToList();

foreach (ObjectId anonymId in definition.GetAnonymousBlockIds())

{

    var anonym = (BlockTableRecord)tr.GetObject(anonymId, OpenMode.ForRead);

    alle.AddRange(anonym.GetBlockReferenceIds(true, false).Cast<ObjectId>());

}

Les propriétés dynamiques ne se trouvent pas dans l'AttributeCollection, mais dans la DynamicBlockReferencePropertyCollection. Une valeur se définit avec exactement le type qu'elle a : Double, Int16 ou String, les angles en radians. Un bloc dynamique ne peut pas être créé via .NET ; l'add-in le récupère dans un dessin de bibliothèque avec WblockCloneObjects.

Erreurs typiques

  • Insérer une référence par code et oublier les attributs.
  • Appeler SetAttributeFromBlock avec Matrix3d.Identity au lieu de la BlockTransform.
  • Créer des éléments de la définition sans calque – ils se retrouvent sur le calque courant.
  • Compter les blocs par leur nom et négliger les blocs anonymes des blocs dynamiques.
  • Modifier un élément de la définition de bloc en croyant qu'une seule référence est concernée.

Comment nous vous aidons

  • Formation : lors de la formation « AutoCAD .NET API avec C# », vous programmez des blocs, des attributs et des blocs dynamiques avec AutoCAD 2027.
  • Diagnostic d'add-in : nous examinons votre add-in au regard de ces pièges et d'AutoCAD 2027 – sous forme de forfait de démarrage à prix fixe.
  • Développement : nomenclatures, cartouches, bibliothèques de blocs – contactez-nous.
  • Le livre : tout est expliqué en détail dans l'ouvrage spécialisé d'Ebi F. Eilber « AutoCAD .NET API », dont la parution est prévue en 2027.

Source : Ebi F. Eilber, AutoCAD .NET API (ouvrage spécialisé, parution prévue en 2027), chapitres « Blocs », « Attributs » et « Blocs dynamiques »

CONTACT

Sélectionnez votre langue

Premier entretienprendre rendez-vousPremier entretienprendre rendez-vous