2012-12-26 162 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

相關問題