Aller au contenu

Block Dynamic - compteur selon visibilité


Messages recommandés

Salut,

 

Si j'ai bien compris la question

 

        /// <summary>
       /// Compte les blocs dynamiques groupés par valeur de la propriété spécifiée.
       /// </summary>
       /// <param name="db">Base de données du dessin dans lequel s'appliquela méthode.</param>
       /// <param name="blockName">Nom du bloc.</param>
       /// <param name="propertyName">Nom de la propriété.</param>
       /// <returns>Un dictionnaire de paires clé/valeur : valeur de la propriété/nombre d'occurences.</returns>
       private Dictionary<object, int> CountByDynamicPropertyValue(Database db, string blockName, string propertyName)
       {
           using (var tr = db.TransactionManager.StartOpenCloseTransaction())
           {
               var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);

               if (!bt.Has(blockName))
                   throw new ArgumentException($"Le bloc '{blockName}' est introuvable.");

               var btr = (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
               if (!btr.IsDynamicBlock)
                   throw new InvalidOperationException($"Le bloc '{blockName} n'est pas un bloc dynamique.");

               var blockRefs = new List<BlockReference>();
               foreach (ObjectId brId in btr.GetBlockReferenceIds(true, false))
               {
                   blockRefs.Add((BlockReference)tr.GetObject(brId, OpenMode.ForRead));
               }
               foreach (ObjectId anonymBtrId in btr.GetAnonymousBlockIds())
               {
                   var anonymBtr = (BlockTableRecord)tr.GetObject(anonymBtrId, OpenMode.ForRead);
                   foreach (ObjectId brId in anonymBtr.GetBlockReferenceIds(true, false))
                   {
                       blockRefs.Add((BlockReference)tr.GetObject(brId, OpenMode.ForRead));
                   }
               }

               return blockRefs
                   .SelectMany(br => 
                       br.DynamicBlockReferencePropertyCollection
                       .Cast<DynamicBlockReferenceProperty>()
                       .Where(prop => prop.PropertyName == propertyName))
                   .ToLookup(prop => prop.Value)
                   .ToDictionary(grp => grp.Key, grp => grp.Count());
           }
       }

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Bonjour Gile,

 

Je crois que tu as surment bien compris la question. Par contre, il me faudrait p-e quelque explication sur comment utiliser ton code.

 

Ce que je veux vraiment faire est selection mes items dans un dessin CAD et ensuite créer une liste des ces élément.

 

[CommandMethod("DBP")]
       static public void DynamicBlockProps()
       {
           Document doc =
             Application.DocumentManager.MdiActiveDocument;
           Database db = doc.Database;
           Editor ed = doc.Editor;

           PromptStringOptions pso =
             new PromptStringOptions(
               "\nEnter dynamic block name or enter to select: "
             );

           pso.AllowSpaces = true;
           PromptResult pr = ed.GetString(pso);

           if (pr.Status != PromptStatus.OK)
               return;

           Transaction tr =
             db.TransactionManager.StartTransaction();
           using (tr)
           {
               BlockReference br = null;

               // If a null string was entered allow entity selection

               if (pr.StringResult == "")
               {
                   // Select a block reference

                   PromptEntityOptions peo =
                     new PromptEntityOptions(
                       "\nSelect dynamic block reference: "
                     );

                   peo.SetRejectMessage("\nEntity is not a block.");
                   peo.AddAllowedClass(typeof(BlockReference), false);

                   PromptEntityResult per =
                     ed.GetEntity(peo);

                   if (per.Status != PromptStatus.OK)
                       return;

                   // Access the selected block reference

                   br =
                     tr.GetObject(
                       per.ObjectId,
                       OpenMode.ForRead
                     ) as BlockReference;
               }
               else
               {
                   // Otherwise we look up the block by name

                   BlockTable bt =
                     tr.GetObject(
                       db.BlockTableId,
                       OpenMode.ForRead) as BlockTable;

                   if (!bt.Has(pr.StringResult))
                   {
                       ed.WriteMessage(
                         "\nBlock \"" + pr.StringResult + "\" does not exist."
                       );
                       return;
                   }

                   // Create a new block reference referring to the block

                   br =
                     new BlockReference(
                       new Point3d(),
                       bt[pr.StringResult]
                     );
               }

               BlockTableRecord btr =
                 (BlockTableRecord)tr.GetObject(
                   br.DynamicBlockTableRecord,
                   OpenMode.ForRead
                 );

               // Call our function to display the block properties

               DisplayDynBlockProperties(ed, br, btr.Name);

               // Committing is cheaper than aborting

               tr.Commit();
           }
       }

       private static void DisplayDynBlockProperties(
         Editor ed, BlockReference br, string name
       )
       {
           // Only continue is we have a valid dynamic block

           if (br != null && br.IsDynamicBlock)
           {
               ed.WriteMessage(
                 "\nDynamic properties for \"{0}\"\n",
                 name
               );

               // Get the dynamic block's property collection


               DynamicBlockReferencePropertyCollection pc =
                 br.DynamicBlockReferencePropertyCollection;



               // Loop through, getting the info for each property

               foreach (DynamicBlockReferenceProperty prop in pc)
               {
                   // Start with the property name, type and description
                  
                   if (prop.PropertyName == "Choisir")
                   {
                       ed.WriteMessage("\nProperty Type Code : " + prop.PropertyTypeCode.ToString());
                       ed.WriteMessage("\nProperty Value : " + prop.Value.ToString());
                       ed.WriteMessage("\nProperty UnitsType : " + prop.UnitsType.ToString());
                   }
               }
           }
       }

 

Avec ce bout de code je peut trouver les propriété, par contre l'indexation de chaque propriéter change a chaque block.

 

Donc, il mes impossible de pouvoir faire une liste avec ce bout de code. :(

 

Par contre, je crois bien que ton code me pointe dans la bonne direction.

Lien vers le commentaire
Partager sur d’autres sites

Salut,

 

Le code que j'ai posté est une méthode qui collecte tous les blocs du dessin dont le nom correspond à l'argument blockName, les regroupe par valeur égale pour la propriété correspond à l'argument propName et retourne un dictionnaire avec une entrée par groupe dont la valeur est le nombre d’occurrences de blocs ayant cette valeur pour cette propriété.

 

Un exemple de commande qui appelle cette méthode.

 

        [CommandMethod("TEST", CommandFlags.UsePickSet)]
       public void Test()
       {
           var doc = Application.DocumentManager.MdiActiveDocument;
           var db = doc.Database;
           var ed = doc.Editor;

           var options = new PromptStringOptions("\nEntrez le nom du bloc: ");
           options.AllowSpaces = true;
           var result = ed.GetString(options);
           if (result.Status != PromptStatus.OK) return;
           var blockName = result.StringResult;

           options.Message = "\nEntrez le nom de la propriété: ";
           result = ed.GetString(options);
           if (result.Status != PromptStatus.OK) return;
           var propName = result.StringResult;

           try
           {
               foreach (var item in CountByDynamicPropertyValue(db, blockName, propName))
               {
                   ed.WriteMessage($"\n{item.Key} : {item.Value}");
               }
           }
           catch(System.Exception ex)
           {
               ed.WriteMessage($"\nErreur: {ex.Message}");
           }
       }

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

Donc en ce moment, il n'y a rien comme méthode qui détermine que la propriété est la visibilité? Par contre, en AutoLisp cela est possible..

 

Si, la classe .NET DynamicBlockReferenceProperty a une propriété PropertyTypeCode qui vaut 5 pour un paramètre de visiblité.

 

        [CommandMethod("CountByVis")]
       public void CountByVis()
       {
           var doc = Application.DocumentManager.MdiActiveDocument;
           var db = doc.Database;
           var ed = doc.Editor;

           var options = new PromptStringOptions("\nEntrez le nom du bloc: ");
           options.AllowSpaces = true;
           var result = ed.GetString(options);
           if (result.Status != PromptStatus.OK) return;
           var blockName = result.StringResult;

           try
           {
               var visibilities = CountByVisibilityState(db, blockName);
               if (visibilities.Count == 0)
                   ed.WriteMessage($"\nLe bloc '{blockName}' n'a pas d'états de visibilité.");
               else
                   foreach (var item in visibilities)
                   {
                       ed.WriteMessage($"\n{item.Key} : {item.Value}");
                   }
           }
           catch (System.Exception ex)
           {
               ed.WriteMessage($"\nErreur: {ex.Message}");
           }
       }

       private Dictionary<string, int> CountByVisibilityState(Database db, string blockName)
       {
           using (var tr = db.TransactionManager.StartOpenCloseTransaction())
           {
               var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);

               if (!bt.Has(blockName))
                   throw new ArgumentException($"Le bloc '{blockName}' est introuvable.");

               var btr = (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForRead);
               if (!btr.IsDynamicBlock)
                   throw new InvalidOperationException($"Le bloc '{blockName} n'est pas un bloc dynamique.");

               var blockRefs = new List<BlockReference>();
               foreach (ObjectId brId in btr.GetBlockReferenceIds(true, false))
               {
                   blockRefs.Add((BlockReference)tr.GetObject(brId, OpenMode.ForRead));
               }
               foreach (ObjectId anonymBtrId in btr.GetAnonymousBlockIds())
               {
                   var anonymBtr = (BlockTableRecord)tr.GetObject(anonymBtrId, OpenMode.ForRead);
                   foreach (ObjectId brId in anonymBtr.GetBlockReferenceIds(true, false))
                   {
                       blockRefs.Add((BlockReference)tr.GetObject(brId, OpenMode.ForRead));
                   }
               }

               return blockRefs
                   .SelectMany(br =>
                       br.DynamicBlockReferencePropertyCollection
                       .Cast<DynamicBlockReferenceProperty>()
                       .Where(prop => prop.PropertyTypeCode == 5)) // <- filtre la propriété "état de visibilité"
                   .ToLookup(prop => (string)prop.Value)
                   .ToDictionary(grp => grp.Key, grp => grp.Count());
           }
       }

 

Par contre, en LISP (ActiveX) il me semble qu'il n'existe pas d'équivalent (voir ici).

Gilles Chanteau - gileCAD - GitHub
Développements sur mesure pour AutoCAD

Lien vers le commentaire
Partager sur d’autres sites

J'ai testé ton code.

 

J'ai une petite question, Est ce que l'état de visibilité correspond a des lookup?

 

Car j'ai toujours plus qu'un élément qui sort dans la ligne de command.

 

J'aimerais avoir si possible l'information relative au class .net d'autoCAD? svp ou bien m'indiquer ou je peux la trouver.

 

Désolé si j'ai du délai sur mes questions j'habitte au Québec :D

 

Merci.

Lien vers le commentaire
Partager sur d’autres sites

Par contre si on voudrais faire une liste de toute les blocks dans un dessin CAD il me faudrais mettre le meme nom d'état de visibilité.

 

Pour être sur que seulement c'est block son choisi.

 

Je vais donc devoir repenser a comment je fais mes blocks pour m'assurer que je choisi le paramettre voulu.

 

Merci encore

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é