xBIM 應用與學習 (一)html
xBIM 基本的模型操做編輯器
xBIM 日誌操做ide
xBIM 多個IFC文件合併code
本示例將展現從IFC文件讀取數據所需的一些概念。它使用IFC4 接口,能夠同時用於IFC2x3和IFC4版本。建立EXCEL文件,咱們使用開源的組件NPOI。這個例子只須要xBIM Essentials。
引用命名空間:
using NPOI.SS.UserModel; // EXCEL 組件 using NPOI.XSSF.UserModel; using System.Diagnostics; using System.IO; using System.Linq; using Xbim.Ifc; using Xbim.Ifc4.Interfaces;
主要的功能以下所示:
//從模板初始化NPOI工做簿 var workbook = new XSSFWorkbook("template.xlsx"); var sheet = workbook.GetSheet("Spaces");//用單位建立漂亮的數字格式。 現實中須要更多的關心的是單位。 //咱們只知道咱們如今的模型有空間面積以立方米和空間體積爲單位 //請注意從Revit導出的原始數據是錯誤的,由於數據量比應該大1000倍。 //在這個例子中,數據是使用xBIM修復的。 var areaFormat = workbook.CreateDataFormat(); var areaFormatId = areaFormat.GetFormat("# ##0.00 [$m²]"); var areaStyle = workbook.CreateCellStyle(); areaStyle.DataFormat = areaFormatId; var volumeFormat = workbook.CreateDataFormat(); var volumeFormatId = volumeFormat.GetFormat("# ##0.00 [$m³]"); var volumeStyle = workbook.CreateCellStyle(); volumeStyle.DataFormat = volumeFormatId; //打開IFC模型。 不會改變模型中的任何東西,因此咱們能夠把編輯器的信息保留下來。 using (var model = IfcStore.Open("SampleHouse.ifc")) { //獲取模型中的全部空間. //須要 ToList() 方便使用 Foreach var spaces = model.Instances.OfType<IIfcSpace>().ToList(); //設置報表標題 sheet.GetRow(0).GetCell(0) .SetCellValue($"Space Report ({spaces.Count} spaces)"); foreach (var space in spaces) { //寫報表數據 WriteSpaceRow(space, sheet, areaStyle, volumeStyle); } } //保存 報表 using (var stream = File.Create("spaces.xlsx")) { workbook.Write(stream); stream.Close(); } //打開保存的EXCEL 文件 Process.Start("spaces.xlsx");
從IFC 讀取數據,併爲每一個空間寫一行
private static void WriteSpaceRow(IIfcSpace space, ISheet sheet, ICellStyle areaStyle, ICellStyle volumeStyle) { var row = sheet.CreateRow(sheet.LastRowNum + 1); var name = space.Name; row.CreateCell(0).SetCellValue(name); var floor = GetFloor(space); row.CreateCell(1).SetCellValue(floor?.Name); var area = GetArea(space); if (area != null) { var cell = row.CreateCell(2); cell.CellStyle = areaStyle; //若是來自於其餘的類型 不保證是數字 (如財產 等) if (area.UnderlyingSystemType == typeof(double)) cell.SetCellValue((double)(area.Value)); else cell.SetCellValue(area.ToString()); } var volume = GetVolume(space); if (volume != null) { var cell = row.CreateCell(3); cell.CellStyle = volumeStyle; if (volume.UnderlyingSystemType == typeof(double)) cell.SetCellValue((double)(volume.Value)); else cell.SetCellValue(volume.ToString()); } }
如何獲取包含空間的地板,須要執行如下操做
private static IIfcBuildingStorey GetFloor(IIfcSpace space) { return //獲得這個模型空間全部關係 space.Decomposes //選擇分解對象 (這些多是其餘空間或建築層) .Select(r => r.RelatingObject) //建築樓層 .OfType<IIfcBuildingStorey>() .FirstOrDefault(); //獲取第一個 }
IFC 包含數據基礎架構, 用於存儲與產品及其類型相關的任意數據。此基礎結構至關複雜。存儲數據的兩種主要方法是做爲數量或做爲屬性。數量對於它們所包含的值的類型是明確的, 其中屬性能夠包含許多不一樣的數據類型做爲值。對於面積和體積, 最好從數量中獲得值, 若是它們被定義。在這種狀況下, 屬性是回退。
private static IIfcValue GetArea(IIfcProduct product) { //嘗試先從數量中獲取 var area = //獲取能夠定義屬性和數量集的全部關係 product.IsDefinedBy //在全部屬性和數量集之間搜索。 //您可能還但願按名稱搜索特定數量 .SelectMany(r => r.RelatingPropertyDefinition.PropertySetDefinitions) //數量集合 .OfType<IIfcElementQuantity>() //從數量集獲取全部數量 .SelectMany(qset => qset.Quantities) //咱們只對面積感興趣 .OfType<IIfcQuantityArea>() //咱們將採起第一個。顯然有一個以上的面積屬性 //因此, 要檢查的名稱。可是,咱們將保持它簡單的這個例子。 .FirstOrDefault()? .AreaValue; if (area != null) return area; //從屬性中獲取值 return GetProperty(product, "Area"); } private static IIfcValue GetVolume(IIfcProduct product) { var volume = product.IsDefinedBy .SelectMany(r => r.RelatingPropertyDefinition.PropertySetDefinitions) .OfType<IIfcElementQuantity>() .SelectMany(qset => qset.Quantities) .OfType<IIfcQuantityVolume>() .FirstOrDefault()?.VolumeValue; if (volume != null) return volume; return GetProperty(product, "Volume"); }
更常見的屬性在屬性集中搜索
private static IIfcValue GetProperty(IIfcProduct product, string name) { return //獲取能夠定義屬性和數量集的全部關係 product.IsDefinedBy //在全部屬性和數量集之間搜索。您可能還但願在特定屬性集中搜索 .SelectMany(r => r.RelatingPropertyDefinition.PropertySetDefinitions) //在這種狀況下, 只考慮屬性集。 .OfType<IIfcPropertySet>() //從全部屬性集中獲取全部屬性 .SelectMany(pset => pset.HasProperties) //只容許考慮單個值屬性。還有枚舉屬性, //表屬性、引用屬性、複雜屬性和其餘 .OfType<IIfcPropertySingleValue>() .Where(p => string.Equals(p.Name, name, System.StringComparison.OrdinalIgnoreCase) || p.Name.ToString().ToLower().Contains(name.ToLower())) .FirstOrDefault()?.NominalValue; }
最終結果以下