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

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

  因爲WinForm與WPF技術能夠互通互用,因此本文介紹一種取巧的方式,在WinForm窗體中加載WPF控件,WPF控件中渲染BIM(.ifc格式)模型文件。具體操做步驟以下詳細介紹。express

1、新建WinForm項目
    新建WinForm項目,.NET Framework 選擇4.7版本,由於須要引用最新的 XBIM相關DLL(依賴 .NET Framework 4.7)。 
2、添加xBIM相關DLL引用
   經過NuGet程序包管理器添加xBIM相關的DLL引用
  須要應用下列DLL
3、添加WPF相關DLL引用
   經過NuGet程序包管理器添加WPF相關的DLL引用。 其中 HelixToolkit 是開發wpf3D應用的開源庫,比較好用。

添加引用後,自動添加了下列WPF的基礎庫。瀏覽器

4、在Winform項目中添加WPF用戶控件

編寫XAML代碼以下:ide

 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官方提供的 模型瀏覽器組件。顯示效果以下:函數

5、在WinForm窗體中調用WPF查看器

  添加一個WinForm窗體。左側Panel中是 按鈕區域,右側Panel填充窗體剩餘的全部區域。工具

 
打開VS的工具箱,能夠看到以下欄目
 
WPF互操做性,將 「ElementHost」控件拖拽到右側Panel中,命名爲controlHost,並設置 Dock 屬性爲 Fill。

 後臺邏輯:在第四步驟中建立了一個WPF用戶控件,在此處實例化一個對象this

private WinformsAccessibleControl _wpfControl;

在構造函數中初始化該對象並將對象添加到 controlHost 中spa

 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         }

運行效果以下:code

完整的示例代碼以下:orm

  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 }
 
相關文章
相關標籤/搜索