1. 程式人生 > >xBIM 實戰04 在WinForm窗體中實現IFC模型的載入與瀏覽

xBIM 實戰04 在WinForm窗體中實現IFC模型的載入與瀏覽

系列目錄    【已更新最新開發文章,點選檢視詳細】 

  WPF底層使用 DirectX 進行圖形渲染。DirectX  能理解可由顯示卡直接渲染的高層元素,如紋理和漸變,所以 DirectX 效率更高。而 GDI/GDI+不理解這些高層元素,因此必須將他們轉換成逐畫素指令,而通過現代顯示卡渲染這些指令更慢。WinForm 的繪圖技術使用的就是GDI/GDI+技術。但是xBIM並沒有提供專門針對傳統 WinForm 技術的的模型檢視器。如果確實需要在傳統的 WinForm 窗體中也要載入並顯示BIM(.ifc格式)模型檔案該如何處理呢?

  由於WinForm與WPF技術可以互通互用,所以本文介紹一種取巧的方式,在WinForm窗體中載入WPF控制元件,WPF控制元件中渲染BIM(.ifc格式)模型檔案。具體操作步驟如下詳細介紹。

一、新建WinForm專案    新建WinForm專案,.NET Framework 選擇4.7版本,因為需要引用最新的 XBIM相關DLL(依賴 .NET Framework 4.7)。  二、新增xBIM相關DLL引用   通過NuGet程式包管理器新增xBIM相關的DLL引用  需要應用下列DLL 三、新增WPF相關DLL引用   通過NuGet程式包管理器新增WPF相關的DLL引用。其中 HelixToolkit 是開發wpf3D應用的開源庫,比較好用。

新增引用後,自動添加了下列WPF的基礎庫。

四、在Winform專案中新增WPF使用者控制元件

編寫XAML程式碼如下:

 1 <UserControl x:Class="Xbim.WinformsSample.WinformsAccessibleControl"
 2              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 5              xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 6              xmlns:presentation="http://schemas.Xbim.com/Presentation"
 7              mc:Ignorable="d" 
 8              d:DesignHeight="600" d:DesignWidth="800"
 9              x:Name="MainWindow"
10              DataContext="{Binding RelativeSource={RelativeSource Self}}">
11     <Grid Name="MainFrame">
12         <presentation:DrawingControl3D x:Name="DrawingControl" 
13                                        x:FieldModifier="public"  
14                                        Model ="{Binding ModelProvider.ObjectInstance}" 
15                                        Focusable="True" 
16                                        Width="Auto" 
17                                        Height="Auto"
18                                        SelectedEntityChanged="DrawingControl_SelectedEntityChanged"
19                                        ModelOpacity="1">
20         </presentation:DrawingControl3D>
21     </Grid>
22 </UserControl>

其中第12行,引用了 xBIM官方提供的 模型瀏覽器元件。顯示效果如下:

五、在WinForm窗體中呼叫WPF檢視器

  新增一個WinForm窗體。左側Panel中是 按鈕區域,右側Panel填充窗體剩餘的所有區域。

  開啟VS的工具箱,可以看到如下欄目   WPF互操作性,將 “ElementHost”控制元件拖拽到右側Panel中,命名為controlHost,並設定 Dock 屬性為 Fill。

 

後臺邏輯:在第四步驟中建立了一個WPF使用者控制元件,在此處例項化一個物件

private WinformsAccessibleControl _wpfControl;

在建構函式中初始化該物件並將物件新增到 controlHost 中

 1  public FormExample(ILogger logger = null)
 2         {
 3             InitializeComponent();
 4 
 5             Logger = logger ?? new LoggerFactory().CreateLogger<FormExample>();
 6             
 7             IfcStore.ModelProviderFactory.UseHeuristicModelProvider();
 8 
 9             _wpfControl = new WinformsAccessibleControl();
10             _wpfControl.SelectionChanged += _wpfControl_SelectionChanged;
11 
12             controlHost.Child = _wpfControl;
13         }

完整的示例程式碼如下:

  1 using System;
  2 using System.Linq;
  3 using System.Windows.Forms;
  4 
  5 using Microsoft.Extensions.Logging;
  6 
  7 using Xbim.Common;
  8 using Xbim.Ifc;
  9 using Xbim.Ifc4.Interfaces;
 10 using Xbim.ModelGeometry.Scene;
 11 
 12 namespace Xbim.WinformsSample
 13 {
 14     public partial class FormExample : Form
 15     {
 16         private WinformsAccessibleControl _wpfControl;
 17 
 18         int starting = -1;
 19 
 20         protected ILogger Logger { get; private set; }
 21 
 22         public FormExample(ILogger logger = null)
 23         {
 24             InitializeComponent();
 25 
 26             Logger = logger ?? new LoggerFactory().CreateLogger<FormExample>();
 27             
 28             IfcStore.ModelProviderFactory.UseHeuristicModelProvider();
 29 
 30             _wpfControl = new WinformsAccessibleControl();
 31             _wpfControl.SelectionChanged += _wpfControl_SelectionChanged;
 32 
 33             controlHost.Child = _wpfControl;
 34         }
 35 
 36         private void _wpfControl_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
 37         {
 38             var ent = e.AddedItems[0] as IPersistEntity;
 39             txtEntityLabel.Text = ent == null ? "" : ent.EntityLabel.ToString();
 40         }
 41 
 42         /// <summary>
 43         /// 開啟BIM(.ifc格式)檔案
 44         /// </summary>
 45         /// <param name="sender"></param>
 46         /// <param name="e"></param>
 47         private void BtnLoadBimFile_Click(object sender, EventArgs e)
 48         {
 49             var dlg = new OpenFileDialog();
 50             dlg.Filter = @"IFC Files|*.ifc;*.ifczip;*.ifcxml|Xbim Files|*.xbim";
 51             dlg.FileOk += (s, args) =>
 52                           {
 53                               LoadXbimFile(dlg.FileName);
 54                           };
 55             dlg.ShowDialog(this);
 56         }
 57 
 58         /// <summary>
 59         ///  檢視模型實體標籤
 60         /// </summary>
 61         /// <param name="sender"></param>
 62         /// <param name="e"></param>
 63         private void BtnNext_Click(object sender, EventArgs e)
 64         {
 65             var mod = _wpfControl.ModelProvider.ObjectInstance as IfcStore;
 66             if (mod == null)
 67                 return;
 68 
 69             var found = mod.Instances.OfType<IIfcProduct>().FirstOrDefault(x => x.EntityLabel > starting);
 70             _wpfControl.SelectedElement = found;
 71 
 72             if(found != null)
 73             {
 74                 starting = found.EntityLabel;
 75             }
 76             else
 77             {
 78                 starting = -1;
 79             }
 80         }
 81 
 82         /// <summary>
 83         ///  載入BIM(.ifc格式)檔案
 84         /// </summary>
 85         /// <param name="dlgFileName"></param>
 86         private void LoadXbimFile(string dlgFileName)
 87         {
 88             // TODO: should do the load on a worker thread so as not to lock the UI. 
 89             //  如果載入的模型檔案較大,耗時可能較長,建議使用後要程式處理,給使用者一個好的使用體驗。
 90 
 91             Clear();
 92 
 93             var model = IfcStore.Open(dlgFileName);
 94             if (model.GeometryStore.IsEmpty)
 95             {
 96                 // 使用 xBIM 幾何引擎建立 GeometryEngine 物件
 97                 try
 98                 {
 99                     var context = new Xbim3DModelContext(model);
100 
101                     context.CreateContext();
102 
103                     // TODO: SaveAs(xbimFile); // so we don't re-process every time
104                 }
105                 catch (Exception geomEx)
106                 {
107                     Logger.LogError(0, geomEx, "Failed to create geometry for {filename}", dlgFileName);
108                 }
109             }
110             _wpfControl.ModelProvider.ObjectInstance = model;
111         }
112 
113         public void Clear()
114         {
115             if (_wpfControl.ModelProvider != null)
116             {
117                 var currentIfcStore = _wpfControl.ModelProvider.ObjectInstance as IfcStore;
118                 currentIfcStore?.Dispose();
119 
120                 _wpfControl.ModelProvider.ObjectInstance = null;
121             }
122         }
123     }
124 }
  系列目錄    【已更新最新開發文章,點選檢視詳細】&nbs