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 }

代码下载地址:https://pan.baidu.com/s/1M6sIOJqCl_UoAlq6B9ddCw   提取码:e1jf

posted @ 2019-06-12 21:11  张传宁  阅读(2027)  评论(3编辑  收藏  举报
页脚 HTML 代码