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