Aller au contenu

Sélectionner des blocks et retirer le nom du block


Messages recommandés

Ah bien sur.

 

Dans un sens je veux comprendre la documentation d'autoCAD.

 

Comprend la difference entre BlockTable, BlocktableRecord et BlockReference.

 

pour comprend comment m'enligner avec mon code.

 

Voila j'espère que c'est plus claire.

 

J'ai ce bout code que j'ai ecrit :

 

private List<string> GetBlockNames(Database database, SelectionSet selectionSet)
       {
           List<string> blockList = new List<string>();
           try
           {
               using (Transaction transaction = database.TransactionManager.StartTransaction())
               {
                   var blockTable = (BlockTable)transaction.GetObject(database.BlockTableId, OpenMode.ForRead);

                   foreach (ObjectId selectedObject in selectionSet.GetObjectIds())
                   {
                       var blockTR = (BlockReference)transaction.GetObject(selectedObject, OpenMode.ForRead);

                       if (blockTR.IsDynamicBlock == true)
                       {
                           if (!blockList.Contains(blockTR.Name))
                           {
                               blockList.Add(blockTR.Name);
                           }
                       }
                   }
               }

           }
           catch (System.Exception ex)
           {
               Active.WriteMessage(ex.Message);
           }
           return blockList;
       }

 

Lien vers le commentaire
Partager sur d’autres sites

Je crains de ne toujours pas comprendre ce que tu cherches à faire.

 

Brièvement.

 

BlockTable : table des blocs, sommairement la collections des définitions de blocs (BlockTableRecord) du dessin (comme LayerTable est la collection des calques du dessin). Il y a obligatoirement une et une seule table des blocs par dessin (tout comme pour les autres "tables").

 

BlockTableRecord : définition de bloc ou espace (l'espace objet et tous les espaces papier sont le type BlockTableRecord), sommairement une collection d'entité (objet non graphique). Les objets de type BlockTableRecord appartiennent tous à la table des blocs du dessin.

 

BlockReference : référence de bloc, une entité graphique (comme les lignes, cercles, polylignes, etc.) insérée dans un objet de type BlockTableRecord (espace objet, espace papier ou définition de bloc). Une référence de bloc est une représentation géométrique des entités contenues dans la définition de bloc.

 

Donc, dans un jeu de sélection (SelectionSet), il ne peut y avoir que des références de bloc (objets de type BlockReference) qui sont des références à une définition de bloc (objet de type BlockTableRecord) qui est obligatoirement contenue dans la table des blocs (objet de type BlockTable).

 

        private List<string> GetBlockNames(Database database, SelectionSet selectionSet)
       {
           List<string> blockList = new List<string>();
           try
           {
               using (Transaction transaction = database.TransactionManager.StartTransaction())
               {
                   foreach (ObjectId selectedObject in selectionSet.GetObjectIds())
                   {
                       var blockReference = (BlockReference)transaction.GetObject(selectedObject, OpenMode.ForRead);
                       var blockName = blockReference.Name;
                       if (blockReference.IsDynamicBlock)
                       {
                           var blockRecord = (BlockTableRecord)transaction.GetObject(blockReference.DynamicBlockTableRecord, OpenMode.ForRead);
                           blockName += $" ({blockRecord.Name})";
                       }
                       if (!blockList.Contains(blockName))
                       {
                           blockList.Add(blockName);
                       }
                   }
               }
           }
           catch (System.Exception ex)
           {
               Active.WriteMessage(ex.Message);
           }
           return blockList;
       }

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

Parfait aucun problème, je vais expliquer d'avantage.

 

L'emploi ou je travail en ce moment nous utilisons beaucoup de block dynamic.Nous devons souvent faire une liste de matériel à l'aide de ces block.

 

Alors je vexu faire une application qui sortira la liste de matériel sur une feuille excel.

 

Voila ce qui en est.

 

Par contre, j'essaie de comprend la documentation du guide de développement d'autocad et l'information n'est que publié en anglais. Cela m'incomode un peu car ma langue premier est le français et je crois ne pas toujours bien saisr ce qu'elle dit en anglais.

 

Je trouve aussi qu'il manque beaucoup d'information sur la manipulation des blocs :D Mais bon c'est mon opinion.

 

Si il y aurait de la documentation en francais cela maiderais surment plus.

 

Cordialement Francois,

Lien vers le commentaire
Partager sur d’autres sites

ah .... d'où le fait de bien savoir s'exprimer huh.gif

 

ce que tu veux faire, c'est de l'extraction de données ... il y a des lisp existants pour cela. ;)

Raph.

Celui qui pose une question est bête 5 minutes, celui qui n'en pose pas l'est toute sa vie !

Lien vers le commentaire
Partager sur d’autres sites

  • 2 mois après...

BlockTable : table des blocs, sommairement la collections des définitions de blocs (BlockTableRecord) du dessin (comme LayerTable est la collection des calques du dessin). Il y a obligatoirement une et une seule table des blocs par dessin (tout comme pour les autres "tables").

 

BlockTableRecord : définition de bloc ou espace (l'espace objet et tous les espaces papier sont le type BlockTableRecord), sommairement une collection d'entité (objet non graphique). Les objets de type BlockTableRecord appartiennent tous à la table des blocs du dessin.

 

BlockReference : référence de bloc, une entité graphique (comme les lignes, cercles, polylignes, etc.) insérée dans un objet de type BlockTableRecord (espace objet, espace papier ou définition de bloc). Une référence de bloc est une représentation géométrique des entités contenues dans la définition de bloc.

 

Donc, dans un jeu de sélection (SelectionSet), il ne peut y avoir que des références de bloc (objets de type BlockReference) qui sont des références à une définition de bloc (objet de type BlockTableRecord) qui est obligatoirement contenue dans la table des blocs (objet de type BlockTable).

 

 

Donc, si je comprend bien, BlockTable contient tout les blocs auquel je peux insérer dans mon dessin, avec la command Insert?

 

BlockTableRecord associe l'espace papier ou se situe le block et BlockReference est tout ce que le bloc contient incluant les attributs?

Lien vers le commentaire
Partager sur d’autres sites

Alors je vexu faire une application qui sortira la liste de matériel sur une feuille excel.

 

Bonjour,

 

Pourquoi ne pas passer directement par l'extraction de données d'AutoCAD?

 

Commande: _dataextraction

ou

Commande:_table

Steven________________________________________

Pour le taf; Windows (et ses emmerdes) sinon pas d'AutoCAD.

Pour le perso Linux Mint et pas de problèmes. Mais pas d'AutoCAD.

En rêve; AutoCAD sous Linux.

Lien vers le commentaire
Partager sur d’autres sites

Donc, si je comprend bien, BlockTable contient tout les blocs auquel je peux insérer dans mon dessin, avec la command Insert?

 

BlockTableRecord associe l'espace papier ou se situe le block et BlockReference est tout ce que le bloc contient incluant les attributs?

 

1. Oui, BlockTable contient tous les blocs que tu peux insérer directement dans ton dessin avec la commande INSERT. Quand tu choisis l'option "Parcourir" de la commande INSERT et que tu choisis un fichier DWG, AutoCAD crée une nouvelle définition de bloc (BlockTableRecord) dans la table des blocs du dessin (BlockTable) avec le contenu de l'espace objet du fichier sélectionné et, si la commande aboutit, insère une référence à cette nouvelle définition (si on fait Echap au lieu de spécifier le point d'insertion, la définition est ajoutée à la table mais aucune référence n'est insérée).

 

2. L'espace papier est de type BlockTableRecord et peut contenir des entités graphiques (Entity) comme des lignes (Line), des polylignes (Polyline), etc. ainsi que des références de bloc (BlockReference).

Les objets de type BlockReference ne "contiennent" pas d'entités stricto sensu, ce sont juste des références à une définition qui, elle, contient ces entités.

Pour les attributs, c'est un peu particulier. La définition de bloc peut contenir des définitions d'attribut (entités de type AttributeDefinition). Ces définitions d'attributs sont, en quelque sorte, des modèles ou gabarits qui sont utilisés pour la création de références d'attributs (AttributeReference)*. Ce sont ces références d'attribut qui sont liées à une référence de bloc et qu'on retrouve grâce à la propriété AttributeCollection de la référence de bloc.

 

 

* Avec .NET, comme avec AutoLISP et la fonction entmake, quand on insère une nouvelle référence de bloc qui a des attributs, il faut explicitement créer les références d'attribut et les ajouter à la collection d'attributs de la nouvelle référence. La commande INSERT comme la méthode COM/ActiveX InsertBlock() font ça implicitement et masquent donc tout ce processus à l'utilisateur.

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

1. Oui, BlockTable contient tous les blocs que tu peux insérer directement dans ton dessin avec la commande INSERT. Quand tu choisis l'option "Parcourir" de la commande INSERT et que tu choisis un fichier DWG, AutoCAD crée une nouvelle définition de bloc (BlockTableRecord) dans la table des blocs du dessin (BlockTable) avec le contenu de l'espace objet du fichier sélectionné.

 

2. L'espace papier est de type BlockTableRecord et peut contenir des entités graphiques (Entity) comme des lignes (Line), des polylignes (Polyline), dés références de block (BlockReference). Les objets de type BlockReference en "contiennent" pas d'entités stricto sensu, ce sont juste des références à une définition qui contient ces entités. Pour les attributs, c'est un peu particulier. La définition de bloc peut contenir des définitions d'attribut (entité de type AttributeDefinition). Ces définitions d'attributs sont, en quelque sorte, des modèles ou gabarits qui sont utilisés pour la création de références d'attributs (AttributeReference)*. Ce sont ces références d'attribut qui sont liées aux références de bloc et qu'on retrouve grâce à la propriété AttributeCollection des références de bloc.

 

 

* Avec .NET, comme avec AutoLISP et la fonction entmake, quand on insère une nouvelle référence de bloc qui a des attributs, il faut explicitement créer les référence d'attributs et les ajouter à la collection d'attributs de la nouvelle référence. La commande INSERT comme la méthode COM/ActiveX InsertBlock() font ça implicitement masquant ce processus à l'utilisateur.

 

Alors si je veux identifier un bloc sur un espace papier. Avec quel élément est-ce que je peux identifier le layout id?

 

J'essaie vraiment de comprend comment leur API fonctionne :S

 

 

 

 

 

 

 

 

 

Lien vers le commentaire
Partager sur d’autres sites

Les "espaces" sont en fait constitués de deux objets liés :

  • un objet de type Layout qui correspond à la configuration de traçage. Les objets de type Layout sont des entrées du dictionnaire "ACAD_LAYOUT" ;
  • un objet de type BlockTableRecord qui contient les entités graphiques.

 

On retrouve l'objet BlockTableRecord d'un Layout grâce à sa propriété BlockTableRecordId, inversement, on retrouve le Layout associé à un BlockTableRecord (dont la propriété IsLayout == true) via sa propriété LayoutId.

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

Les "espaces" sont en fait constitués de deux objets liés :

  • un objet de type Layout qui correspond à la configuration de traçage. Les objets de type Layout sont des entrées du dictionnaire "ACAD_LAYOUT" ;
  • un objet de type BlockTableRecord qui contient les entités graphiques.

On retrouve l'objet BlockTableRecord d'un Layout grâce à sa propriété BlockTableRecordId, inversement, on retrouve le Layout associé à un BlockTableRecord (dont la propriété IsLayout == true) via sa propriété LayoutId.

 

        [CommandMethod("Test")]
       public static void Test()
       {
           var database = Active.Database;

            using (Transaction transaction = Active.Database.TransactionManager.StartTransaction())
           {
               DBDictionary layoutIds = transaction.GetObject(Active.Database.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
               
               int count = 0;
               //int layoutCount = layoutIds.Count - 1;
               foreach (DBDictionaryEntry entry in layoutIds)
               {
                   
                   using (Transaction transLayout = Active.Database.TransactionManager.StartTransaction())
                   {
                       ObjectIdCollection ids = new ObjectIdCollection();
                       BlockTable blockTable = transLayout.GetObject(database.BlockTableId, OpenMode.ForRead) as BlockTable;
                       Layout layout = transLayout.GetObject(entry.Value, OpenMode.ForRead) as Layout;

                       BlockTableRecord btr = blockTable["CARTOUCHE LU"].GetObject(OpenMode.ForRead) as BlockTableRecord;

                       foreach (ObjectId brId in btr.GetBlockReferenceIds(true, true))
                       {
                           if (!ids.Contains(brId))
                           {
                               ids.Add(brId);
                           }
                       }

                       // si le bloc est dynamique on cherche aussi les reférence des blocks anonymes
                       if (btr.IsDynamicBlock)
                       {
                           foreach (ObjectId btrId in btr.GetAnonymousBlockIds())
                           {
                               var anonymousBtr = (BlockTableRecord)transLayout.GetObject(btrId, OpenMode.ForRead);
                               foreach (ObjectId brId in anonymousBtr.GetBlockReferenceIds(true, true))
                               {
                                   if (!ids.Contains(brId))
                                   {
                                       ids.Add(brId);
                                   }
                               }
                           }
                       }
                       
                       setTextString(transLayout, ids, "PAGE", count.ToString());
                       setTextString(transLayout, ids, "#PAGE", (layoutIds.Count - 1).ToString());
                       transLayout.Commit();
                   }                 
                   
                   count++;
               }
               transaction.Commit();
           }        }

 

 

Bon voici le code que j'ai généré avec ton aide Gile.

 

Par contre, en ce moment il affect que les dernier valeur retenu.

 

Voici le dwg avec le bloc. Si tu as besoin de tester.

 

Je veux que le nombre de page soit en fonction du layout. En ce qui concerne du reste, il reste identique.

 

J'aimerai que des explications et nom le code pour le faire si possible.

Lien vers le commentaire
Partager sur d’autres sites

Si tu veux de l'aide, commence par essayer de présenter un code un peu plus épuré / optimisé, il sera plus lisible (pour ceux qui te lisent comme pour toi) :

  • Puisque tu initialises une variable database, utilise cette variable dans la suite du code à chaque fois que tu peux.
  • Tu n'as pas besoin de démarrer une nouvelle transaction à chaque itération, utilise simplement la transaction dans laquelle tu es déjà.
  • De même, tu n'as pas besoin de créer une instance BlockTable et du BlockTableRecord "CARTOUCHE LU" à chaque itération.

 

Sinon, du point de vue de la méthode, il semble que tu n'aies pas compris la manière de chercher les références de blocs et que tu mélanges deux approches complètement différentes.

 

Soit tu pars de la définition du bloc "CARTOUCHE LU" et tu obtiens toutes les références insérées dans la dessin avec la méthode GetBlockReferenceIds() que tu devras ensuite trier par Layout en retrouvant le BlockTableRecord propriétaire de chaque référence de bloc avec OwnerId, puis le Layout correspondant à ce BlockTableRecord.

 

Soit tu parcours tous les Layouts depuis le dictionnaire "ACAD_LAYOUT" et, pour chaque Layout, tu ouvres le BlockTableRecord correspondant que tu parcours à son tour pour retrouver les références du bloc "CARTOUCHE LU" qu'il contient.

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

Désolé pour le code.

 

Je sais que quelque chose manque dans ma compréhension.

 

Désolé si je ne saisit pas tout en ce moment.

 

Si tu as des références que je peux lire pour m'aider ça serait grandement apprécier.

 

Cordialement,

 

 

 

 

Lien vers le commentaire
Partager sur d’autres sites



Soit tu parcours tous les Layouts depuis le dictionnaire "ACAD_LAYOUT" et, pour chaque Layout, tu ouvres le BlockTableRecord correspondant que tu parcours à son tour pour retrouver les références du bloc "CARTOUCHE LU" qu'il contient.


Active est une class appart.

public static class Active
   {
       /// <summary>
       /// Returns the active Editor object.
       /// </summary>
       public static Document Document
       {
           get { return Application.DocumentManager.MdiActiveDocument; }
       }

       /// <summary>
       /// Returns the active Database object.
       /// </summary>
       public static Database Database
       {
           get { return Document.Database; }
       }

       /// <summary>
       /// Returns the active Editor object.
       /// </summary>
       public static Editor Editor
       {
           get { return Document.Editor; }
       }

       /// <summary>
       /// Sends a string to the command line in the active Editor
       /// </summary>
       /// <param name="message">The message to send.</param>
       public static void WriteMessage(string message)
       {
           Editor.WriteMessage(message);
       }

       /// <summary>
       /// Sends a string to the command line in the active Editor using String.Format.
       /// </summary>
       /// <param name="message">The message containing format specifications.</param>
       /// <param name="parameter">The variables to substitute into the format string.</param>
       public static void WriteMessage(string message, params object[] parameter)
       {
           Editor.WriteMessage(message, parameter);
       }
   }

 

 

using (Transaction transaction = Active.Database.TransactionManager.StartTransaction())
                   {
                       DBDictionary layoutIds = transaction.GetObject(Active.Database.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
                       foreach (DBDictionaryEntry entry in layoutIds)
                       {

                           ObjectIdCollection ids = new ObjectIdCollection();
                           Layout layout = transaction.GetObject(entry.Value, OpenMode.ForRead) as Layout;
                           // Code.

                           transaction.Commit();
                       }

 

 

Est ce que c'est cela tu veux dire par parcourir les Layout avec ACAD_LAYOUT?

Lien vers le commentaire
Partager sur d’autres sites

using (Transaction transaction = Active.Database.TransactionManager.StartTransaction())
                   {
                       DBDictionary layoutIds = transaction.GetObject(Active.Database.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
                       foreach (DBDictionaryEntry entry in layoutIds)
                       {

                           ObjectIdCollection ids = new ObjectIdCollection();
                           Layout layout = transaction.GetObject(entry.Value, OpenMode.ForRead) as Layout;
                           // Code.

                           transaction.Commit();
                       }

 

 

Est ce que c'est cela tu veux dire par parcourir les Layout avec ACAD_LAYOUT?

 

Oui,ensuite tu ouvres le BlockTableRecord du Layout (layout.BlockTableRecordId), puis tu parcours les entités contenues dans ce BlockTableRecord (toujours avec foreach) à la recherche des références de bloc nommées "CARTOUCHE LU".

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

J'obtiens toujours un erreur fatal. Pourquoi?

 

using (Transaction transaction = Active.Database.TransactionManager.StartTransaction())
           {
               DBDictionary layoutIds = transaction.GetObject(Active.Database.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;

               int count = 0;

               foreach (DBDictionaryEntry entry in layoutIds)
               {
                   ObjectIdCollection ids = new ObjectIdCollection();

                   Layout layout = transaction.GetObject(entry.Value, OpenMode.ForRead) as Layout;

                   BlockTableRecord btr = transaction.GetObject(layout.BlockTableRecordId, OpenMode.ForRead) as BlockTableRecord;
                   if (btr.Name != "*Model_Space")
                   {
                       foreach (ObjectId id in btr)
                       {                            
                           BlockReference br = transaction.GetObject(id, OpenMode.ForRead) as BlockReference;
                           
                               Active.WriteMessage("\n" + br.BlockName);
                               Active.WriteMessage("\n" + br.Name);
                           
                       }
                   }
               }
               count++;
               transaction.Commit();
           }

 

Sa fait mal a tete :(

 

Si je le met dans un try c'a me sort "Object reference not set to an instance of an object".

Lien vers le commentaire
Partager sur d’autres sites

BlockReference br = transaction.GetObject(id, OpenMode.ForRead) as BlockReference;

retourne null si id n'est pas l'identifiant d'une référence de bloc, ce qui adviendra inévitablement si la présentation contient d'autres entités que des blocs (une fenêtre flottante ou Viewport, par exemple).

Ceci provoque immanquablement une erreur de type "La référence d'objet n'est pas définie à une instance d'objet", erreur fatale pour AutoCAD.

Tu dois donc faire un test pour voir si br est null avant d'appeler br.BlockName, br.Name, ou mieux, tester le type de id.ObjectClass avant d'ouvrir l'entité.

Tu peux aussi tester directement si le Layout pour savoir si c'est l'espace objet (entry.Key == "Model") ce qui évite d'ouvrir le Layout et le BlockTableRecord pour rien.

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

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é