查找Autocad绘图中特定属性中具有特定值的对象

本文关键字:对象 Autocad 查找 属性 绘图 | 更新日期: 2023-09-27 17:49:29

我在Autocad绘图对象的属性命名为Base。我试图找到与Base属性的绘图中的所有对象具有特定的字符串值,如"Pipe"。

我可以在绘图中迭代对象并获得所有对象id。然后我获得具有该Id的对象的所有属性,并检查属性是否命名为Base = "Pipe"

迭代性能不够好。是否有任何方法直接获得对象id的属性命名为Base = "Pipe" ?

下面是遍历所有对象的方法:
    List<ObjectId> ObjectIds = new List<ObjectId>();
    foreach (Document Document in Documents)
    {
        Database Database = Document.Database;
        using (Transaction Transaction = Database.TransactionManager.StartTransaction())
        {
            for (long i = Database.BlockTableId.Handle.Value; i < Database.Handseed.Value; i++)
            {
                ObjectId Id;
                if (Database.TryGetObjectId(new Handle(i), out Id))
                {
                        ObjectIds.Add(Id);
                }
            }
            Transaction.Commit();
        }
    }

下面是我如何获得ObjectIds集合中所有对象的属性。

public static DataLinksManager DataLinks
{
    get
    {
        if (null == _DataLinks)
        {
            StringCollection Coll = Autodesk.ProcessPower.DataLinks.DataLinksManager.GetLinkManagerNames();
            if (Coll.Count > 0)
            {
                if (Coll[0] != string.Empty)
                {
                    _DataLinks = Autodesk.ProcessPower.DataLinks.DataLinksManager.GetManager(Coll[0]);
                }
            }
        }
        return _DataLinks;
    }
}
private static DataLinksManager _DataLinks;
foreach(var Id in ObjectIds)
{
    List<KeyValuePair<string, string>> Properties = DataLinks.GetAllProperties(Id, true);
    // I check existence of my property and if so its value.
}

查找Autocad绘图中特定属性中具有特定值的对象

如果有人需要,这里是解决我的问题的代码。诀窍是Iterate方法。这是基于Philippe Leefsma的文章。我添加到此方法的是找到ObjectId实例的ObjectClass属性列表。我的样品绘图大约有8500个ObjectIds。然而,我感兴趣的是具有基类acppassetacppdynamicasset的对象,此类对象的计数为90。

using Autodesk.AutoCAD.ApplicationServices;
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
public static void GetObjects()
{
    List<KeyValuePair<string, ObjectId>> ObjectIds = new List<KeyValuePair<string, ObjectId>>();
    List<string> Filter = new List<string>() { "acppasset", "acppdynamicasset" };
    foreach (Document Document in this.Documents)
    {
        ObjectIdCollection Ids = this.Iterate(Document, Filter);
        if (null != Ids) foreach (var Id in Ids.OfType<ObjectId>()) ObjectIds.Add(new KeyValuePair<string, ObjectId>(System.IO.Path.GetFileNameWithoutExtension(Document.Name), Id));
    }
    this.Results = new Dictionary<string, List<List<KeyValuePair<string, string>>>>();
    foreach (var Id in ObjectIds)
    {
        try
        {
            var Properties = this.GetObject(Id.Value);
            if (null == Properties) continue;
            var Base = Properties.Where(x => x.Key == "Base").FirstOrDefault();
            if (string.IsNullOrWhiteSpace(Base.Value)) continue;
            if (!this.Results.ContainsKey(Base.Value)) this.Results.Add(Base.Value, new List<List<KeyValuePair<string, string>>>());
            this.Results[Base.Value].Add(Properties);
        }   catch { }
    }
}
 public ObservableCollection<Document> Documents { get; set; }
 public ObjectIdCollection Iterate(Document Document, List<string> Filter = null)
        {
            ads_name Instance = new ads_name();
            Database Database = Document.Database;
            ObjectIdCollection ValidIds = new ObjectIdCollection();
            // Get the last handle in the Database
            Handle Handseed = Database.Handseed;
            // Copy the handseed total into an efficient raw datatype
            long HandseedTotal = Handseed.Value;
            for (long i = 1; i < HandseedTotal; ++i)
            {
                string Handle = Convert.ToString(i, 16);
                int Result = acdbHandEnt(Handle, ref Instance);
                if (Result != 5100) continue; // RTNORM
                ObjectId Id = new ObjectId(Instance.a);
                if (!Id.IsValid) continue;
                try
                {
                    if (null != Filter)
                    {
                        if (!Filter.Contains(Id.ObjectClass.Name.ToLower())) continue;
                    }
                    using (DBObject DBObject = Id.Open(OpenMode.ForRead, false))
                    {
                        ValidIds.Add(Id);
                        DBObject.Dispose();
                    }
                }   catch { }
            }
            return ValidIds;
    }
    public List<KeyValuePair<string, string>> GetObject(ObjectId Id)
    {
        if (Command.DataLinks != null) try { return Command.DataLinks.GetAllProperties(Id, true); } catch { return null; }
        return null;
    }
public static DataLinksManager DataLinks
{
    get
    {
        if (null == _DataLinks)
        {
            StringCollection Coll = Autodesk.ProcessPower.DataLinks.DataLinksManager.GetLinkManagerNames();
            if (Coll.Count > 0)
            {
                if (Coll[0] != string.Empty)
                {
                    _DataLinks = Autodesk.ProcessPower.DataLinks.DataLinksManager.GetManager(Coll[0]);
                }
            }
        }
            return _DataLinks;
        }
    }
private static DataLinksManager _DataLinks;
public Dictionary<string, List<List<KeyValuePair<string, string>>>> Results { get; set; }

这里的性能较慢是因为它试图读取所有对象并检查它是否包含任何属性。据我所知,属性只存在于块引用(插入)中。因此,如果使用选择过滤器,我们可以直接访问基于过滤条件的记录。

我在这里找到了一个非常简单的例子,使用选择过滤器选择具有特定名称的所有块。

复制部分代码以供参考。这只选择块引用。你可以从这里开始迭代。

TypedValue[] filterlist = new TypedValue[1];
filterlist[0] = new TypedValue(0, "INSERT");
SelectionFilter filter =  new SelectionFilter(filterlist);
PromptSelectionResult selRes =  ed.SelectAll(filter);
if (selRes.Value.Count != 0)
{
    SelectionSet set = selRes.Value;
    foreach (ObjectId id in set.GetObjectIds())
    {
        BlockReference oEnt = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
        //do something with oEnt..;
    }
}

如果你可以增加你的过滤器的复杂性,你将只需要迭代一个非常小的集合。