xBIM 基本的模型操作

本次案例我們主要查看xBIM 一些簡單的基本操作,我們將介紹被稱為CRUD(創建,檢索,更新和刪除)的持久性存儲的四個基本功能 。以下示例通常適用於IFC4,但您也可以對IFC2x3執行相同的操作。實際上,大部分代碼都是IFC版本不可知的,因為它使用IFC4接口,它也適用於IFC2x3。用於開發這些示例的示例數據可以在這裡[http://docs.xbim.net/data/SampleHouse.zip]

下載 。

一、創建

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

<code>var editor = new XbimEditorCredentials
{
ApplicationDevelopersName = "xBIM Team",
ApplicationFullName = "xBIM Toolkit",
ApplicationIdentifier = "xBIM",
ApplicationVersion = "4.0",
EditorsFamilyName = "Santini Aichel",
EditorsGivenName = "Johann Blasius",
EditorsOrganisationName = "Independent Architecture"
};/<code>

IModel 在xBIM中的所有實現都是IDisposable這樣的,建議在開發時應用 using:

<code>using (var model = IfcStore.Create(editor, IfcSchemaVersion.Ifc4, XbimStoreType.InMemoryModel))
{
//...do something with the model
}/<code>

如果要在模型中創建或修改任何內容,則必須使用事務。這些也應該在using語句中使用,以便在事件發生的時候有適當的回滾操作範圍。您必須明確提交事務以保持更改。事務不能嵌套,所以當時總是隻有一個事務。

<code>using (var txn = model.BeginTransaction("Hello Wall"))
{
//....do something in the scope of this transaction
txn.Commit()
}/<code>

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

<code>var newWall = mode.Instances.New<ifcwall>();/<ifcwall>/<code>

除了使用這個函數之外,不可能以任何其他方式創建新的實體。你會在上面的代碼中看到,這個函數使用可選的類型化對象初始化器來設置對象的值。沒有必要使用它們,但我個人喜歡它,因為我可以看到結果實體的結構。使用所有這些基本的部分,我們可以建造第一堵牆。這面牆沒有任何幾何圖形,所以IFC的大部分觀眾不會告訴你任何東西。但這只是一個基本的例子。這裡是完整的代碼:

<code>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.Create(editor, IfcSchemaVersion.Ifc4, XbimStoreType.InMemoryModel))
{
using (var txn = model.BeginTransaction("Hello Wall"))
{
//創建模型前應該先創建項目
var project = model.Instances.New<ifcproject>(p => p.Name = "Basic Creation");
//定義基本的單位 SIUnitsUK 為英制單位
project.Initialize(ProjectUnits.SIUnitsUK);

//創建簡單的對象並使用lambda初始值設定名稱
var wall = model.Instances.New<ifcwall>(w => w.Name = "The very first wall");

//設置一些基本的屬性
model.Instances.New<ifcreldefinesbyproperties>(rel => {
rel.RelatedObjects.Add(wall);
rel.RelatingPropertyDefinition = model.Instances.New<ifcpropertyset>(pset => {
pset.Name = "Basic set of properties";
pset.HasProperties.AddRange(new[] {
model.Instances.New<ifcpropertysinglevalue>(p =>
{
p.Name = "Text property";
p.NominalValue = new IfcText("Any arbitrary text you like");
}),
model.Instances.New<ifcpropertysinglevalue>(p =>
{
p.Name = "Length property";
p.NominalValue = new IfcLengthMeasure(56.0);
}),
model.Instances.New<ifcpropertysinglevalue>(p =>
{
p.Name = "Number property";
p.NominalValue = new IfcNumericMeasure(789.2);
}),
model.Instances.New<ifcpropertysinglevalue>(p =>
{

p.Name = "Logical property";
p.NominalValue = new IfcLogical(true);
})
});
});
});

txn.Commit();
}
model.SaveAs("BasicWall.ifc");
}/<ifcpropertysinglevalue>/<ifcpropertysinglevalue>/<ifcpropertysinglevalue>/<ifcpropertysinglevalue>/<ifcpropertyset>/<ifcreldefinesbyproperties>/<ifcwall>/<ifcproject>/<code>

IFC 文件格式如下

<code>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;/<code>

二、查詢

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

<code>var firstWall = mode.Instances.FirtsOrDefault<ifcwall>();
var allWalls = model.Instances.OfType<ifcwall>();
var specificWall = model.Instances.Where<ifcwall>(w => w.Name == "Brick wall");/<ifcwall>/<ifcwall>/<ifcwall>/<code>

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

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

<code>using System;
using System.Linq;
using Xbim.Ifc;
using Xbim.Ifc4.Interfaces;/<code>

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

<code>const string fileName = "SampleHouse.ifc";
using (var model = IfcStore.Open(fileName))
{
// 獲得IFC 文件中的所有門(使用IfcDoor的IFC4接口,這將對IFC2x3和IFC4都有效)
var allDoors = model.Instances.OfType<iifcdoor>();
//只獲得具有定義的IIfcTypeObject的門
var someDoors = model.Instances.Where<iifcdoor>(d => d.IsTypedBy.Any());
//獲取單個門 以Id 查詢
var id = "2AswZfru1AdAiKfEdrNPnu";
var theDoor = model.Instances.FirstOrDefault<iifcdoor>(d => d.GlobalId == id);
Console.WriteLine($"Door ID: {theDoor.GlobalId}, Name: {theDoor.Name}");
//獲取這個門的所有屬性
var properties = theDoor.IsDefinedBy
.Where(r => r.RelatingPropertyDefinition is IIfcPropertySet)
.SelectMany(r => ((IIfcPropertySet)r.RelatingPropertyDefinition).HasProperties)
.OfType<iifcpropertysinglevalue>();
foreach (var property in properties)
Console.WriteLine($"Property: {property.Name}, Value: {property.NominalValue}");
}/<iifcpropertysinglevalue>/<iifcdoor>/<iifcdoor>/<iifcdoor>/<code>

控制檯輸出屬性信息

<code>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/<code>

三、修改

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

<code>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();
}
}/<ifcpropertysinglevalue>/<ifcpropertysinglevalue>/<ifcpropertyset>/<ifcreldefinesbyproperties>/<ifcdoor>/<code>

四、刪除

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

<code>using (var model = IfcStore.Open(fileName))
{
//獲取模型中得一個門
var id = "3cUkl32yn9qRSPvBJVyWYp"; //使用模型ID
var theDoor = model.Instances.FirstOrDefault<iifcdoor>(d => d.GlobalId == id);
//打開事務
using (var txn = model.BeginTransaction("Delete the door"))
{
//刪除門
model.Delete(theDoor);
//提交修改
txn.Commit();
}
} /<iifcdoor>/<code>


分享到:


相關文章: