mryapados Posté(e) le 7 avril 2012 Posté(e) le 7 avril 2012 Bonjour Je dois concevoir une application capable de récupérer les informations (attributs) contenues dans les blocs insérés dans le dessin Autocad (je ne suis pas utilisateur d'Autocad à la base). Je suis sous Autocad 2011 et Visual studio 2010, je ne peux pas installer ObjectARX, donc pour tester mon appli je dois la compiler puis la charger dans Autocad à chaque fois donc pas évident à débuguer. J'ai beaucoup de mal à comprendre la hiérarchie des blocs (BlockTable, BlockTableRecord, BlockReference) et leur mode de construction. J'ai malgré tout réussi à extraire les références de bloc avec le code suivant (récupéré sur ce forum) : Private Function GetBlockReference(ByVal db As Database, ByVal ed As Editor) As ObjectIdCollection Dim result As New ObjectIdCollection Using tr As Transaction = db.TransactionManager.StartTransaction() Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead), BlockTable) For Each id As ObjectId In bt Dim btrA As BlockTableRecord = DirectCast(id.GetObject(OpenMode.ForRead), BlockTableRecord) Dim btr As BlockTableRecord = DirectCast(tr.GetObject(bt(btrA.Name), OpenMode.ForRead), BlockTableRecord) GetRefs(btr, result, ed) For Each anonId As ObjectId In btr.GetAnonymousBlockIds() Dim anonBtr As BlockTableRecord = DirectCast(tr.GetObject(anonId, OpenMode.ForRead), BlockTableRecord) GetRefs(anonBtr, result, ed) Next Next End Using Return result End Function Private Sub GetRefs(ByVal btr As BlockTableRecord, ByVal ids As ObjectIdCollection, ByVal ed As Editor) For Each id As ObjectId In btr.GetBlockReferenceIds(True, False) Dim br As BlockReference = DirectCast(id.GetObject(OpenMode.ForRead), BlockReference) Dim owner As BlockTableRecord = DirectCast(br.OwnerId.GetObject(OpenMode.ForRead), BlockTableRecord) If owner.IsLayout Then ids.Add(br.Id) ed.WriteMessage(" Ref = " + br.Name + " " + owner.Name + " " + vbCrLf) End If Next End Sub Ce qui sort pour le dessin testé : Début de l'extraction Ref = TRIPODE *Paper_Space Ref = EDTOLE *Model_Space Ref = EDTOLE *Model_Space Ref = EDTOLE *Model_Space Ref = ESTOLE *Model_Space Ref = _Cartouche *Model_Space Ref = EDCASE *Model_Space Succès de l'extraction Questions : le bout de code ci-dessus est-il bien indiqués si l'on veut récupérer toutes les références de blocs insérés dans le dessin ?Comment accéder aux informations contenues dans les attributs ? Pour infos, les blocs insérés peuvent être des blocs dynamiques. Merci
(gile) Posté(e) le 7 avril 2012 Posté(e) le 7 avril 2012 Salut, la table des blocs (BlockTable) est la collection qui contient tous les objets BlockTableRecord du dessin, à savoir l'espace objet, les espaces papier, les définitions de bloc et les références externes. Un objet BlockReference est une référence à une définition de bloc insérée dans une BlockTableRecord (qui peut être un espace ou une définition de bloc).Les définitions de blocs peuvent contenir des définitions d'attribut (AttributeDefinition). Quand c'est le cas, les références de ces blocs contiennent autant de référence d'attributs (AttributeReference) qui ont chacune une propriété Tag pour l'étiquette de l'attribut et une propriété TextString pour la valeur de l'attribut 1. Oui le code retourne bien toutes les références mais on peut faire plus simple (ce code était prévue pour récupérer les références de bloc suivant un nom. 2. Les objets BlockReference ont une propriété AttributeCollection qui contient les ObjectId des attributs de cette référence de bloc. Un exemple simple qui utilise une classe BlockAttribute avec deux propriétés: Name pour le nom du bloc (de type String) et Attributes pour les attributs (de type Dictionary). using System.Collections.Generic; using System.Linq; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; using AcAp = Autodesk.AutoCAD.ApplicationServices.Application; namespace GetAttributesSample { public class Commands { [CommandMethod("Test")] public void Test() { Document doc = AcAp.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; foreach (BlockAttribute blkAtt in GetBlockAttributes(db)) { ed.WriteMessage("\n" + blkAtt.ToString()); } } private List<BlockAttribute> GetBlockAttributes(Database db) { List<BlockAttribute> result = new List<BlockAttribute>(); using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); foreach (ObjectId id in bt) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead); if (!(btr.IsAProxy || btr.IsFromExternalReference || btr.IsLayout)) { foreach (ObjectId brId in btr.GetBlockReferenceIds(true, false)) { BlockReference br = (BlockReference)brId.GetObject(OpenMode.ForRead); BlockTableRecord owner = (BlockTableRecord)br.OwnerId.GetObject(OpenMode.ForRead); if (owner.IsLayout) result.Add(new BlockAttribute(br)); } } } } return result; } } public class BlockAttribute { private string _name; private Dictionary<string, string> _atts; private Transaction _tr; public string Name { get { return _name; } } public Dictionary<string, string> Attributes { get { return _atts; } } public string this[string key] { get { return _atts[key.ToUpper()]; } } public BlockAttribute(BlockReference br) { Document doc = AcAp.DocumentManager.MdiActiveDocument; using (_tr = doc.TransactionManager.StartTransaction()) { SetProperties(br); } } public BlockAttribute(ObjectId id) { Document doc = AcAp.DocumentManager.MdiActiveDocument; using (_tr = doc.TransactionManager.StartTransaction()) { SetProperties(_tr.GetObject(id, OpenMode.ForRead) as BlockReference); } } public override string ToString() { if (_atts != null && _atts.Count > 0) return string.Format("{0}: {1}", _name, _atts.Select(a => string.Format("{0}={1}", a.Key, a.Value)) .Aggregate((a, B) => string.Format("{0}; {1}", a, B))); return _name; } private void SetProperties(BlockReference br) { if (br == null) return; if (br.IsDynamicBlock) { BlockTableRecord btr = (BlockTableRecord)_tr.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead); _name = btr.Name; } else _name = br.Name; _atts = new Dictionary<string, string>(); foreach (ObjectId id in br.AttributeCollection) { AttributeReference att = (AttributeReference)_tr.GetObject(id, OpenMode.ForRead); _atts.Add(att.Tag.ToUpper(), att.TextString); } } } } Tu trouveras un exemple plus complet pour une extraction d'attributs utilisant un DataTable où les blocs sont regroupés par noms et valeurs d'attributs identiques ici. Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
mryapados Posté(e) le 10 avril 2012 Auteur Posté(e) le 10 avril 2012 L'extraction des blocs et de leur attributs fonctionne bien, merci. j'ai une nouvelle question peut-être simple mais je n'ai pas trouvé de solution. Est-il possible de récupérer les dimensions d'une référence de block ? tel que : http://img15.hostingpics.net/pics/657125dim.png Merci
(gile) Posté(e) le 10 avril 2012 Posté(e) le 10 avril 2012 Salut, Oui, si ce que tu cherches correspond à l'emprise rectangulaire de bloc suivant les axes X et Y (BoundingBox).Ces dimension peuvent être différentes pour des références d'un même bloc suivant qu'elles ont subit une rotation ou des changement d'échelle. using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; namespace BoundingBoxSample { public class Commands { [CommandMethod("Test")] public void Test() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; PromptEntityOptions peo = new PromptEntityOptions("\nSélectionnez un bloc: "); peo.SetRejectMessage("Objet non valide."); peo.AddAllowedClass(typeof(BlockReference), true); PromptEntityResult per = ed.GetEntity(peo); if (per.Status != PromptStatus.OK) return; double width, height; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockReference br = (BlockReference)tr.GetObject(per.ObjectId, OpenMode.ForRead); GetExtentsDimensions(br, out width, out height); tr.Commit(); } ed.WriteMessage("\nLargeur = {0}\nHauteur = {1}", width, height); } private void GetExtentsDimensions(BlockReference br, out double width, out double height) { Extents3d ext = br.GeometricExtents; width = ext.MaxPoint.X - ext.MinPoint.X; height = ext.MaxPoint.Y - ext.MinPoint.Y; } } } Gilles Chanteau - gileCAD - GitHub Développements sur mesure pour AutoCAD
Messages recommandés
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 compteSe connecter
Vous avez déjà un compte ? Connectez-vous ici.
Connectez-vous maintenant