.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Custom implementation of select similar

4 REPLIES 4
Reply
Message 1 of 5
Anonymous
652 Views, 4 Replies

Custom implementation of select similar

Can any one guide how to implement select similar functionality using .net interface.

 

Issue facing: Am trying to get all the entities in drawing by block reference name ..But only one element is coming as result set ..But if right click and use select similar command all the similar block references are getting selected.

 

I am clueless what am i missing in this case?

 

4 REPLIES 4
Message 2 of 5
_gile
in reply to: Anonymous

Hi,

 

Here's a little example:

 

        [CommandMethod("SELECTBLOCKBYNAME")]
        public static void SelectBlockByName()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            var peo = new PromptEntityOptions("\nSelect a block: ");
            peo.SetRejectMessage("\nselected object is not a block reference.");
            peo.AddAllowedClass(typeof(BlockReference), true);
            var per = ed.GetEntity(peo);
            if (per.Status == PromptStatus.OK)
            {
                ObjectId[] ids;
                using (var tr = db.TransactionManager.StartOpenCloseTransaction())
                {
                    string GetEffectiveName(BlockReference br) =>
                        br.IsDynamicBlock ?
                        ((BlockTableRecord)tr.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead)).Name :
                        br.Name;

                    var source = (BlockReference)tr.GetObject(per.ObjectId, OpenMode.ForRead);
                    var name = GetEffectiveName(source);
                    ids = ((BlockTableRecord)tr.GetObject(source.OwnerId, OpenMode.ForRead))
                        .Cast<ObjectId>()
                        .Where(id => id.ObjectClass.DxfName == "INSERT")
                        .Select(id => (BlockReference)tr.GetObject(id, OpenMode.ForRead))
                        .Where(br => GetEffectiveName(br) == name)
                        .Select(br => br.ObjectId)
                        .ToArray();
                }
                ed.SetImpliedSelection(ids);
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 5
Anonymous
in reply to: _gile

Hi @_gile 

 

Thanks for the instant reply. But how to change this particular code

 

 ids = ((BlockTableRecord)tr.GetObject(source.OwnerId, OpenMode.ForRead))
                        .Cast<ObjectId>()
                        .Where(id => id.ObjectClass.DxfName == "INSERT")
                        .Select(id => (BlockReference)tr.GetObject(id, OpenMode.ForRead))
                        .Where(br => GetEffectiveName(br) == name)
                        .Select(br => br.ObjectId)
                        .ToArray();

 In  the above code snippet 

((BlockTableRecord)tr.GetObject(source.OwnerId, OpenMode.ForRead))
                        .Cast<ObjectId>()
How to avoid the above if i have only block name and not prompting 
user to select a type from the user interface

 Previously was using a function like this 

 

static private ObjectIdCollection GetAllBlockReferenceByName(string name, Database db)
{
ObjectIdCollection ids_temp = null, ids = new ObjectIdCollection();
Transaction tr = db.TransactionManager.StartTransaction();
try
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[name], OpenMode.ForRead);
BlockTableRecord btr_model = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
ObjectId id_model = btr_model.ObjectId;
ids_temp = btr.GetBlockReferenceIds(true, true);
foreach (ObjectId id in ids_temp)
{
DBObject obj = (DBObject)tr.GetObject(id, OpenMode.ForWrite);
if (obj.OwnerId == id_model)
{
ids.Add(id);
}
}
tr.Commit();
}
finally
{
tr.Dispose();
}

return ids;
}

Message 4 of 5
_gile
in reply to: Anonymous

Assuming the block is not a dynamic block, you can try this:

 

        private static ObjectId[] GetAllBlockReferenceByName(string name, Database db)
        {
            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (!bt.Has(name))
                    return null;
                var msId = SymbolUtilityServices.GetBlockModelSpaceId(db);
                var btr = (BlockTableRecord)tr.GetObject(bt[name], OpenMode.ForRead);
                return btr.GetBlockReferenceIds(true, true)
                    .Cast<ObjectId>()
                    .Where(id => tr.GetObject(id, OpenMode.ForRead).OwnerId == msId)
                    .ToArray();
            }
        }

 

Testing command:

 

        [CommandMethod("TEST")]
        public static void Test()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            var pr = ed.GetString("\nBlock Name: ");
            if (pr.Status != PromptStatus.OK)
                return;
            var ids = GetAllBlockReferenceByName(pr.StringResult, db);
            if (ids == null)
                ed.WriteMessage($"\nBloc '{pr.StringResult}' not found.");
            else
                ed.SetImpliedSelection(ids);
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 5 of 5
_gile
in reply to: _gile

This one will also work with dynamic blocks

 

        private static ObjectId[] GetAllBlockReferenceByName(string name, Database db)
        {
            using (var tr = db.TransactionManager.StartOpenCloseTransaction())
            {
                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                if (!bt.Has(name))
                    return null;
                var msId = SymbolUtilityServices.GetBlockModelSpaceId(db);
                var btr = (BlockTableRecord)tr.GetObject(bt[name], OpenMode.ForRead);
                return btr.GetBlockReferenceIds(true, true)
                    .Cast<ObjectId>()
                    .Concat(btr.GetAnonymousBlockIds()
                            .Cast<ObjectId>()
                            .SelectMany(anonId => ((BlockTableRecord)tr.GetObject(anonId, OpenMode.ForRead))
                                                    .GetBlockReferenceIds(true, true)
                                                    .Cast<ObjectId>()))
                    .Where(id => tr.GetObject(id, OpenMode.ForRead).OwnerId == msId)
                    .ToArray();
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Technology Administrators


Autodesk Design & Make Report