2

我在 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.
}
4

2 回答 2

1

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

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

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

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

}

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

于 2012-12-28T19:44:15.583 回答
1

如果有人需要,这里是解决我的问题的代码。诀窍在于Iterate方法。这是基于Philippe Leefsma 的这篇文章。我添加到此方法的是已找到实例的ObjectClass属性列表。ObjectId我的样品 dawing 大约有 8500 ObjectIds。但是,我感兴趣的是具有基类的对象,acppasset并且acppdynamicasset此类对象的数量为 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; }
于 2013-01-02T12:28:46.363 回答