xBIM 基礎03 基本模型操作

  • 2019 年 10 月 4 日
  • 筆記

  本篇將使用基本的程式碼示例來表示如何使用xBIM。我們將介紹持久存儲的四個基本功能,即 CRUD(創建,檢索,更新和刪除)。以下示例通常適用於IFC4,但您也可以使用IFC2x3。實際上大多數程式碼都是IFC版本不可知的,因為它使用的IFC4介面也適用於IFC2x3。用於開發這些示例的示例數據可以在此處下載 。

一、創建

  以下示例將創建沒有任何幾何體的簡單IFC模型。如您所見,IfcStore需要一個XbimEditorCredentials表示當前應用程式和用戶的配置對象,並使用它來維護OwnerHistory根實體。這是一項要求,可以更輕鬆地處理創建合規IFC模型所需的眾多方面之一。此IFC未定義任何模型視圖定義(MVD), 因此除了WHERE規則和所需屬性之外沒有其他限制。您應始終設置編輯器憑據並使用應用程式的首字母和當前用戶填寫它。

 1  XbimEditorCredentials editor = new XbimEditorCredentials   2  {   3     ApplicationDevelopersName = "NJQY",                             //應用開發商名稱   4     ApplicationFullName = "SparkDigitalReview",                     //應用程式名稱   5     ApplicationIdentifier = "NJQYf43a-faa7-4a49-b06d-4cb21f81d220", //應用程式標示符,通過Guid來表示   6     ApplicationVersion = "4.0",   7   8     //個人資訊   9     EditorsFamilyName = "Zhang",  10     EditorsGivenName = "ChuanNing",  11     EditorsOrganisationName = "bim"  12 };

IModel xBIM中的所有實現都是 IDisposable 這樣的,你應該總是在這樣的 using 語句中使用它們

1 using (var model = IfcStore.Create(editor, IfcSchemaVersion.Ifc4, XbimStoreType.InMemoryModel))  2 {  3     //...do something with the model  4 }

如果要在模型中創建或修改任何內容,則必須使用事務。這些也應該在 using 語句中使用,因此它們具有適當的範圍,以便在發生某些情況時進行最終回滾操作。您必須明確提交事務以保留更改。事務不能嵌套,因此當時總是只有一個事務。

1 using (var txn = model.BeginTransaction("Hello Wall"))  2 {  3     //....do something in the scope of this transaction  4     txn.Commit()  5 }

所有與實體相關的操作都可通過IModel.Instances。這是您在模型中獲取,更改和創建新實體的訪問點。要創建任何新對象,請使用此模板化函數。您始終必須指定要創建的非抽象類型。這是在xBIM中構建的,如果不這樣,就會出現編譯時錯誤。每個模型都是特定於模式的,因此它是IFC2x3或IFC4或其他特定模式。IfcStore使它更容易,因為它可以打開兩個IFC版本,並會告訴你它是什麼,但是當你想要創建數據時,請確保你不要搞砸你的using陳述。如果您嘗試使用初始化為IFC2x3的模型創建IFC4實體,則會拋出運行時異常。

1 var newWall = mode.Instances.New<IfcWall>();

除了使用此功能之外,無法以任何其他方式創建新實體。您將在上面的程式碼中看到,此函數使用可選的類型化對象初始值設定項來設置對象的值。沒有必要使用它們,但我個人喜歡它,因為我可以看到結果實體的結構。

使用所有這些基本部件,我們可以建造第一面牆。這面牆沒有任何幾何形狀,因此大多數IFC觀眾都不會向您展示任何東西。但這只是一個基本的例子。這是完整的程式碼:

 1 var editor = new XbimEditorCredentials   2 {   3     ApplicationDevelopersName = "xBIM Team",   4     ApplicationFullName = "xBIM Toolkit",   5     ApplicationIdentifier = "xBIM",   6     ApplicationVersion = "4.0",   7     EditorsFamilyName = "Santini Aichel",   8     EditorsGivenName = "Johann Blasius",   9     EditorsOrganisationName = "Independent Architecture"  10 };  11 using (var model = IfcStore.Create(editor, IfcSchemaVersion.Ifc4, XbimStoreType.InMemoryModel))  12 {  13     using (var txn = model.BeginTransaction("Hello Wall"))  14     {  15         // 創建模型前應該先創建項目  16         var project = model.Instances.New<IfcProject>(p => p.Name = "Basic Creation");  17         // 定義基本的單位  SIUnitsUK 為英制單位  18         project.Initialize(ProjectUnits.SIUnitsUK);  19  20         // 創建簡單的對象並使用lambda初始值設定名稱  21         var wall = model.Instances.New<IfcWall>(w => w.Name = "The very first wall");  22  23         // 設置一些基本的屬性  24         model.Instances.New<IfcRelDefinesByProperties>(rel => {  25             rel.RelatedObjects.Add(wall);  26             rel.RelatingPropertyDefinition = model.Instances.New<IfcPropertySet>(pset => {  27                 pset.Name = "Basic set of properties";  28                 pset.HasProperties.AddRange(new[] {  29                     model.Instances.New<IfcPropertySingleValue>(p =>  30                     {  31                         p.Name = "Text property";  32                         p.NominalValue = new IfcText("Any arbitrary text you like");  33                     }),  34                     model.Instances.New<IfcPropertySingleValue>(p =>  35                     {  36                         p.Name = "Length property";  37                         p.NominalValue = new IfcLengthMeasure(56.0);  38                     }),  39                     model.Instances.New<IfcPropertySingleValue>(p =>  40                     {  41                         p.Name = "Number property";  42                         p.NominalValue = new IfcNumericMeasure(789.2);  43                     }),  44                     model.Instances.New<IfcPropertySingleValue>(p =>  45                     {  46                         p.Name = "Logical property";  47                         p.NominalValue = new IfcLogical(true);  48                     })  49                 });  50             });  51         });  52  53         txn.Commit();  54     }  55     model.SaveAs("BasicWall.ifc");  56 }

IFC 文件格式如下(Revit 自帶示例轉換 rac_advanced_sample_project.ifc)

ISO-10303-21;  HEADER;  FILE_DESCRIPTION ((''), '2;1');  FILE_NAME ('', '2016-10-27T13:14:43', (''), (''), 'Xbim File Processor version 3.2.0.0', 'Xbim version 3.2.0.0', '');  FILE_SCHEMA (('IFC4'));  ENDSEC;  DATA;  #1=IFCPROJECT('2t0OftVsP8UBH3rtAB$yJv',#2,'Basic Creation',$,$,$,$,(#20,#23),#8);  #2=IFCOWNERHISTORY(#5,#6,$,.ADDED.,$,$,$,0);  #3=IFCPERSON($,'Santini Aichel','Johann Blasius',$,$,$,$,$);  #4=IFCORGANIZATION($,'Independent Architecture',$,$,$);  #5=IFCPERSONANDORGANIZATION(#3,#4,$);  #7=IFCORGANIZATION($,'xBIM Team',$,$,$);  #6=IFCAPPLICATION(#7,$,'xBIM Toolkit','xBIM');  #8=IFCUNITASSIGNMENT((#9,#10,#11,#12,#13,#14,#15,#16,#17));  #9=IFCSIUNIT(*,.LENGTHUNIT.,.MILLI.,.METRE.);  #10=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);  #11=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);  #12=IFCSIUNIT(*,.SOLIDANGLEUNIT.,$,.STERADIAN.);  #13=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);  #14=IFCSIUNIT(*,.MASSUNIT.,$,.GRAM.);  #15=IFCSIUNIT(*,.TIMEUNIT.,$,.SECOND.);  #16=IFCSIUNIT(*,.THERMODYNAMICTEMPERATUREUNIT.,$,.DEGREE_CELSIUS.);  #17=IFCSIUNIT(*,.LUMINOUSINTENSITYUNIT.,$,.LUMEN.);  #18=IFCCARTESIANPOINT((0.,0.,0.));  #19=IFCAXIS2PLACEMENT3D(#18,$,$);  #20=IFCGEOMETRICREPRESENTATIONCONTEXT('Building Model','Model',3,1.E-05,#19,$);  #21=IFCCARTESIANPOINT((0.,0.));  #22=IFCAXIS2PLACEMENT2D(#21,$);  #23=IFCGEOMETRICREPRESENTATIONCONTEXT('Building Plan View','Plan',2,1.E-05,#22,$);  #24=IFCWALL('1YTVCro6L0$OJQL2X7wICY',#2,'The very first wall',$,$,$,$,$,$);  #27=IFCPROPERTYSINGLEVALUE('Text property',$,IFCTEXT('Any arbitrary text you like'),$);  #28=IFCPROPERTYSINGLEVALUE('Length property',$,IFCLENGTHMEASURE(56.),$);  #29=IFCPROPERTYSINGLEVALUE('Number property',$,IFCNUMERICMEASURE(789.2),$);  #30=IFCPROPERTYSINGLEVALUE('Logical property',$,IFCLOGICAL(.T.),$);  #26=IFCPROPERTYSET('2u_olyjv13oRt0GvSVSxHS',#2,'Basic set of properties',$,(#27,#28,#29,#30));  #25=IFCRELDEFINESBYPROPERTIES('3I5GuvWn95PRXcxoFGfJAL',#2,$,$,(#24),#26);  ENDSEC;  END-ISO-10303-21;

二、查詢

從模型中檢索數據非常簡單,它 IModel.Instances 再次用於訪問我們需要的所有實體。

1 var firstWall = mode.Instances.FirtsOrDefault<IfcWall>();  2 var allWalls = model.Instances.OfType<IfcWall>();  3 var specificWall = model.Instances.Where<IfcWall>(w => w.Name == "Brick wall");

您可以看到,所有這些函數都是模板化的,所以它們使用對象的類型作為第一級過濾器。如果你知道你想要的類型,你應該總是指定它來提高性能。對於所有的搜索查詢,您也可以使用介面來檢索實體。我們在IFC2x3實體上實現了IFC4介面,這意味著您可以用一個程式碼庫查詢IFC2x3和IFC4 。

以下示例只需要這些使用:

using System;  using System.Linq;  using Xbim.Ifc;  using Xbim.Ifc4.Interfaces;

如果您對實體的結構感興趣,建議瀏覽 buildingSMART ,它的前身是國際數據互用聯盟(IAI-International Alliance of Interoperability) 教程網站。

 1 const string fileName = "SampleHouse.ifc";   2 using (var model = IfcStore.Open(fileName))   3 {   4     // 獲得IFC 文件中的所有門(使用IfcDoor的IFC4介面,這將對IFC2x3和IFC4都有效)   5     var allDoors = model.Instances.OfType<IIfcDoor>();   6     // 只獲得具有定義的IIfcTypeObject的門   7     var someDoors = model.Instances.Where<IIfcDoor>(d => d.IsTypedBy.Any());   8     // 獲取單個門 以Id 查詢   9     var id = "2AswZfru1AdAiKfEdrNPnu";  10     var theDoor = model.Instances.FirstOrDefault<IIfcDoor>(d => d.GlobalId == id);  11     Console.WriteLine($"Door ID: {theDoor.GlobalId}, Name: {theDoor.Name}");  12     // 獲取這個門的所有屬性  13     var properties = theDoor.IsDefinedBy  14         .Where(r => r.RelatingPropertyDefinition is IIfcPropertySet)  15         .SelectMany(r => ((IIfcPropertySet)r.RelatingPropertyDefinition).HasProperties)  16         .OfType<IIfcPropertySingleValue>();  17     foreach (var property in properties)  18         Console.WriteLine($"Property: {property.Name}, Value: {property.NominalValue}");  19 }

控制台輸出屬性資訊

Door ID: 3cUkl32yn9qRSPvBJVyWYp, Name: Doors_ExtDbl_Flush:1810x2110mm:285860  Property: IsExternal, Value: true  Property: Reference, Value: 1810x2110mm  Property: Level, Value: Level: Ground Floor  Property: Sill Height, Value: 0  Property: Area, Value: 4.9462127188431  Property: Volume, Value: 0.193819981582386  Property: Mark, Value: 1  Property: Category, Value: Doors  Property: Family, Value: Doors_ExtDbl_Flush: 1810x2110mm  Property: Family and Type, Value: Doors_ExtDbl_Flush: 1810x2110mm  Property: Head Height, Value: 2110  Property: Host Id, Value: Basic Wall: Wall-Ext_102Bwk-75Ins-100LBlk-12P  Property: Type, Value: Doors_ExtDbl_Flush: 1810x2110mm  Property: Type Id, Value: Doors_ExtDbl_Flush: 1810x2110mm  Property: Phase Created, Value: New Construction

三、修改

修改與新增、查詢比較類似。注意事務必須是開放的,並且應該被包含在using語句中,否則模型將在您創建或更改任何對象時拋出異常。

const string fileName = "SampleHouse.ifc";  var editor = new XbimEditorCredentials  {      ApplicationDevelopersName = "xBIM Team",      ApplicationFullName = "xBIM Toolkit",      ApplicationIdentifier = "xBIM",      ApplicationVersion = "4.0",      EditorsFamilyName = "Santini Aichel",      EditorsGivenName = "Johann Blasius",      EditorsOrganisationName = "Independent Architecture"  };    using (var model = IfcStore.Open(fileName, editor, true))  {      // 根據ID 在模型中查詢對應的門      var id = "3cUkl32yn9qRSPvBJVyWYp";      var theDoor = model.Instances.FirstOrDefault<IfcDoor>(d => d.GlobalId == id);      // 修改事務      using (var txn = model.BeginTransaction("Doors modification"))      {          // 創建具有兩個屬性的新屬性集          var pSetRel = model.Instances.New<IfcRelDefinesByProperties>(r =>          {              r.GlobalId = Guid.NewGuid();              r.RelatingPropertyDefinition = model.Instances.New<IfcPropertySet>(pSet =>              {                  pSet.Name = "New property set";                  // 所有的集合被初始化                  pSet.HasProperties.Add(model.Instances.New<IfcPropertySingleValue>(p =>                  {                      p.Name = "First property";                      p.NominalValue = new IfcLabel("First value");                  }));                  pSet.HasProperties.Add(model.Instances.New<IfcPropertySingleValue>(p =>                  {                      p.Name = "Second property";                      p.NominalValue = new IfcLengthMeasure(156.5);                  }));              });          });            // 修改門的名稱          theDoor.Name += "_checked";            // 添加屬性          pSetRel.RelatedObjects.Add(theDoor);            // 提交修改事務          txn.Commit();      }  }

四、刪除

  刪除是模型中最複雜的操作,首先要知道的是,它只能在MemoryModel (記憶體模式)(2016年10月)中完全實現。之所以這麼複雜,是因為IFC 格式的數據模型非常複雜,並不是層次結構或方向圖。所以我們的delete實現只能確保模型中沒有對象引用你刪除的對象,所以模型保持一致。但它不會自動刪除任何引用它的對象或引用它。有程式設計師或用戶可以選擇。但是,用於刪除的底層基礎設施可以非常簡單地使用:

 1 using (var model = IfcStore.Open(fileName))   2 {   3     // 獲取模型中得一個門   4     var id = "3cUkl32yn9qRSPvBJVyWYp";  // 使用模型ID   5     var theDoor = model.Instances.FirstOrDefault<IIfcDoor>(d => d.GlobalId == id);   6     // 打開事務   7     using (var txn = model.BeginTransaction("Delete the door"))   8     {   9         //刪除門  10         model.Delete(theDoor);  11         //提交修改  12         txn.Commit();  13     }  14 }