Custom implementation of select similar

Custom implementation of select similar

Anonymous
Not applicable
943 Views
4 Replies
Message 1 of 5

Custom implementation of select similar

Anonymous
Not applicable

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?

 

0 Likes
944 Views
4 Replies
Replies (4)
Message 2 of 5

_gile
Consultant
Consultant

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

0 Likes
Message 3 of 5

Anonymous
Not applicable

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;
}

0 Likes
Message 4 of 5

_gile
Consultant
Consultant

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

0 Likes
Message 5 of 5

_gile
Consultant
Consultant

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

0 Likes