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

时间:2012-12-26 12:55:34

标签: c# autocad-plugin

我在Autocad绘图中有对象,其属性名为Base。我试图找到该图形中的所有对象Base属性具有特定的字符串值,例如“Pipe”。

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

迭代性能不够好。有没有办法直接获取具有名为Base = "Pipe"

属性的对象ID

以下是我遍历所有对象的方法:

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

2 个答案:

答案 0 :(得分:1)

这里的慢性能是因为它试图读取所有对象并检查它是否包含任何属性。据我所知,这些属性仅适用于块引用(插入)。因此,如果使用selection filters,我们可以根据过滤条件直接访问这些记录。

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

复制该代码的一部分以供参考。这仅选择块引用。你可以从这里迭代。

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

}

如果可以add complexities to your filter,则只需要迭代一小组。

答案 1 :(得分:1)

如果有人需要,这里的代码可以解决我的问题。诀窍是Iterate方法。这是基于Philippe Leefsma的this article。我添加到此方法的是已找到的ObjectClass个实例的ObjectId属性列表。我的样本dawing大约有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; }