WPF底層使用 DirectX 進行圖形渲染。DirectX 能理解可由顯卡直接渲染的高層元素,如紋理和漸變,因此 DirectX 效率更高。而 GDI/GDI+不理解這些高層元素,所以必須將他們轉換成逐像素指令,而經過現代顯卡渲染這些指令更慢。WinForm 的繪圖技術使用的就是GDI/GDI+技術。可是xBIM並無提供專門針對傳統 WinForm 技術的的模型查看器。若是確實須要在傳統的 WinForm 窗體中也要加載並顯示BIM(.ifc格式)模型文件該如何處理呢?html
因爲WinForm與WPF技術能夠互通互用,因此本文介紹一種取巧的方式,在WinForm窗體中加載WPF控件,WPF控件中渲染BIM(.ifc格式)模型文件。具體操做步驟以下詳細介紹。express
添加引用後,自動添加了下列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官方提供的 模型瀏覽器組件。顯示效果以下:函數
添加一個WinForm窗體。左側Panel中是 按鈕區域,右側Panel填充窗體剩餘的全部區域。工具
後臺邏輯:在第四步驟中建立了一個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 }