xBIM 高級02 插入複製功能

  • 2019 年 10 月 4 日
  • 筆記

  IFC 模型中的合併和刪除實體是一個非常重要的任務,因為 IFC 不是一個分層結構。它是一個複雜的結構,具有潛在的循環關係,是一個雙嚮導航。在單個實體上執行這些任務並不是問題(您可以將其想像為STEP21文件中的一行)。

#144= IFCBUILDINGSTOREY('026ajlHVj1HBm_osQm7IDT',#47,'Lower Roof - Slab Level',$,$,#143,$,                          'Lower Roof - Slab Level',.ELEMENT.,3199.99999999704);

如果您希望隔離定義實體的完整數據孤島,並且希望刪除該實體而不對數據孤島之外的其他實體產生副作用,或者希望合併該實體以使其與現有數據混合而不產生重複性和不一致性,則會變得越來越困難。出於這些原因,我們更喜歡第三種選擇,即選擇您想要的,並將其複製到一個空模型中。這顯然是一項潛在的複雜任務,但至少在你的控制之下更容易。IModel 介面中的核心函數是 InsertCopy():

T InsertCopy<T>(T toCopy, XbimInstanceHandleMap mappings, PropertyTranformDelegate propTransform,                  bool includeInverses, bool keepLabels);

正如對所有參數的簡要描述一樣:

  • toCopy:要複製的實體
  • mappings:以前插入的映射。對於兩個模型之間的所有插入, 應該始終只有一個實例。
  • propTransform:可選的委託, 您可以使用它來篩選將在複製之前獲得 coppied 或轉換它的內容。這是非常棒的一個功能。
  • includeInverses:選項引入所有反轉實體。這是潛在的危險, 因為如果不受 propTransform 委託的限制, 它可能會輕易地帶來幾乎整個模型。
  • keepLabels:選項以使實體標籤保持不變。有時保持標籤相同可能會很有用。如果目標模型不是新模型或從多個模型中插入對象, 則永遠不要使用此選項。

從所有這些 PropertyTranformDelegate 委託中看起來似乎有點神秘。但它是上述方法的基本部分,因為它允許控制複製數據的範圍。如果您允許反向,並且不提供任何額外的過濾,那麼您最終可能會得到包含98%的原始模型,即使您只是嘗試在單個牆上複製。要正確使用它,你需要非常好地理解IFC的結構。下面是一個強大的轉換的簡單示例,它將忽略所有的幾何圖形和位置,只允許描述產品類型及其屬性的逆關係。幾何圖形通常占文件的90%左右,因此如果您對基於幾何圖形的圖形或分析不感興趣,可以使用它創建僅包含描述性數據的非常小的IFC文件。

PropertyTranformDelegate semanticFilter = (property, parentObject) =>  {      // 省略幾何圖形和位置      if (parentObject is IIfcProduct &&          (property.PropertyInfo.Name == nameof(IIfcProduct.Representation) ||          property.PropertyInfo.Name == nameof(IIfcProduct.ObjectPlacement)))          return null;        // 省略映射的幾何圖形      if (parentObject is IIfcTypeProduct &&          property.PropertyInfo.Name == nameof(IIfcTypeProduct.RepresentationMaps))          return null;        // 僅通過反向關係(它將接管所有屬性和類型)實現 isDefinedby 和 istypedby          property.PropertyInfo.Name == nameof(IIfcProduct.IsDefinedBy) ||          property.PropertyInfo.Name == nameof(IIfcProduct.IsTypedBy)          ))          return null;        return property.PropertyInfo.GetValue(parentObject, null);  };

PropertyTranformDelegate 採用兩個參數, 其中第一個是 ExpressMetaProperty, 另一個是 IPersistEntity 的對象。ExpressMetaProperty 是一個快取對象,它是我們自己反射元模型的一部分,我們用於某些數據操作。該委託在其他程式碼中使用,這些程式碼使用C#反射來檢查數據並複製值。如果不指定委託insertcopy(),則將使用實體中的所有屬性並複製它們。

using Xbim.Common;  using Xbim.Ifc;  using Xbim.Ifc4.Interfaces;    namespace BasicExamples  {      class InsertCopy      {          public void CopyWallsOver()          {              const string original = "SampleHouse.ifc";              const string inserted = "SampleHouseWalls.ifc";                PropertyTranformDelegate semanticFilter = (property, parentObject) =>              {                  // 省略幾何圖形和位置                  if (parentObject is IIfcProduct &&                      (property.PropertyInfo.Name == nameof(IIfcProduct.Representation) ||                      property.PropertyInfo.Name == nameof(IIfcProduct.ObjectPlacement)))                      return null;                   // 省略映射的幾何圖形                 if (parentObject is IIfcTypeProduct &&                      property.PropertyInfo.Name == nameof(IIfcTypeProduct.RepresentationMaps))                      return null;                    // 僅通過反向關係(它將接管所有屬性和類型)實現 isDefinedby 和 istypedby                  if (property.EntityAttribute.Order < 0 && !(                      property.PropertyInfo.Name == nameof(IIfcProduct.IsDefinedBy) ||                      property.PropertyInfo.Name == nameof(IIfcProduct.IsTypedBy)                      ))                      return null;                    return property.PropertyInfo.GetValue(parentObject, null);              };                using (var model = IfcStore.Open(original))              {                  var walls = model.Instances.OfType<IIfcWall>();                  using (var iModel = IfcStore.Create(model.IfcSchemaVersion, XbimStoreType.InMemoryModel))                  {                      using (var txn = iModel.BeginTransaction("Insert copy"))                      {                          //兩個模型之間的所有插入都應使用單一圖                          var map = new XbimInstanceHandleMap(model, iModel);                          foreach (var wall in walls)                          {                              iModel.InsertCopy(wall, map, semanticFilter, true, false);                          }                            txn.Commit();                      }                        iModel.SaveAs(inserted);                  }              }          }      }