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 实战04 在WinForm窗体中实现IFC模型的加载与浏览
二、添加xBIM相关DLL引用
  通过NuGet程序包管理器添加xBIM相关的DLL引用
xBIM 实战04 在WinForm窗体中实现IFC模型的加载与浏览
 需要应用下列DLL
xBIM 实战04 在WinForm窗体中实现IFC模型的加载与浏览
三、添加WPF相关DLL引用
  通过NuGet程序包管理器添加WPF相关的DLL引用。其中 HelixToolkit 是开发wpf3D应用的开源库,比较好用。
xBIM 实战04 在WinForm窗体中实现IFC模型的加载与浏览

添加引用后,自动添加了下列WPF的基础库。

xBIM 实战04 在WinForm窗体中实现IFC模型的加载与浏览

四、在Winform项目中添加WPF用户控件
xBIM 实战04 在WinForm窗体中实现IFC模型的加载与浏览

编写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官方提供的 模型浏览器组件。显示效果如下:

xBIM 实战04 在WinForm窗体中实现IFC模型的加载与浏览

五、在WinForm窗体中调用WPF查看器

  添加一个WinForm窗体。左侧Panel中是 按钮区域,右侧Panel填充窗体剩余的所有区域。

 xBIM 实战04 在WinForm窗体中实现IFC模型的加载与浏览
打开VS的工具箱,可以看到如下栏目
xBIM 实战04 在WinForm窗体中实现IFC模型的加载与浏览 
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 }
 

xBIM 实战04 在WinForm窗体中实现IFC模型的加载与浏览

上一篇:小米2S电池电量用尽充电无法开机解决方法


下一篇:《第一行代码——Android》封面诞生记