2012-12-26 116 views
2

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

我可以遍历图中的对象并获取所有对象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. 
} 
+0

请发表您目前拥有的代码。 –

+0

你是否试图找到'Base'属性值等于'Pipe'的所有块引用? – vinayan

+0

是@vinayan,这是我正在尝试做一个可以接受的表现。 – Demir

回答

1

如果有人需要,这里是解决我的问题的代码。诀窍是Iterate方法。这是基于Philippe Leefsma的this article。我在此方法中添加的是发现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; } 
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,你只需要迭代一个非常小的集合。

+0

谢谢你的建议@vinayan。如果选择对象,则使用选择过滤器。在我的情况下,我不应该选择任何对象,只是循环通过绘图数据库。 – Demir

+0

@Demir - 很高兴你自己制定出来!稍作修改以避免用户交互:) – vinayan

相关问题