系列目录 【已更新最新开发文章,点击查看详细】

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)
 3             InitializeComponent();
 5             Logger = logger ?? new LoggerFactory().CreateLogger<FormExample>();
 7             IfcStore.ModelProviderFactory.UseHeuristicModelProvider();
 9             _wpfControl = new WinformsAccessibleControl();
10             _wpfControl.SelectionChanged += _wpfControl_SelectionChanged;
12             controlHost.Child = _wpfControl;

运行效果如下:

完整的示例代码如下:

  1 using System;
  2 using System.Linq;
  3 using System.Windows.Forms;
  5 using Microsoft.Extensions.Logging;
  7 using Xbim.Common;
  8 using Xbim.Ifc;
  9 using Xbim.Ifc4.Interfaces;
 10 using Xbim.ModelGeometry.Scene;
 12 namespace Xbim.WinformsSample
 13 {
 14     public partial class FormExample : Form
 15     {
 16         private WinformsAccessibleControl _wpfControl;
 18         int starting = -1;
 20         protected ILogger Logger { get; private set; }
 22         public FormExample(ILogger logger = null)
 23         {
 24             InitializeComponent();
 26             Logger = logger ?? new LoggerFactory().CreateLogger<FormExample>();
 28             IfcStore.ModelProviderFactory.UseHeuristicModelProvider();
 30             _wpfControl = new WinformsAccessibleControl();
 31             _wpfControl.SelectionChanged += _wpfControl_SelectionChanged;
 33             controlHost.Child = _wpfControl;
 34         }
 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         }
 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         }
 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;
 69             var found = mod.Instances.OfType<IIfcProduct>().FirstOrDefault(x => x.EntityLabel > starting);
 70             _wpfControl.SelectedElement = found;
 72             if(found != null)
 73             {
 74                 starting = found.EntityLabel;
 75             }
 76             else
 77             {
 78                 starting = -1;
 79             }
 80         }
 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             //  如果加载的模型文件较大,耗时可能较长,建议使用后要程序处理,给用户一个好的使用体验。
 91             Clear();
 93             var model = IfcStore.Open(dlgFileName);
 94             if (model.GeometryStore.IsEmpty)
 95             {
 96                 // 使用 xBIM 几何引擎创建 GeometryEngine 对象
 97                 try
 98                 {
 99                     var context = new Xbim3DModelContext(model);
101                     context.CreateContext();
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         }
113         public void Clear()
114         {
115             if (_wpfControl.ModelProvider != null)
116             {
117                 var currentIfcStore = _wpfControl.ModelProvider.ObjectInstance as IfcStore;
118                 currentIfcStore?.Dispose();
120                 _wpfControl.ModelProvider.ObjectInstance = null;
121             }
122         }
123     }
124 }

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

成在管理,败在经验;嬴在选择,输在不学!  贵在坚持!

    BIMFace.SDK.NET

     开源地址:https://gitee.com/NAlps/BIMFace.SDK

     系列博客:https://www.cnblogs.com/SavionZhang/p/11424431.html

     系列视频:https://www.cnblogs.com/SavionZhang/p/14258393.html

 1、Visual Studio、.NET Core/.NET、MVC、Web API、RESTful API、gRPC、SignalR、Java、Python

 2、jQuery、Vue.js、Bootstrap、ElementUI

 3、数据库:分库分表、读写分离、SQLServer、MySQL、PostgreSQL、Redis、MongoDB、ElasticSearch、达梦DM

 4、架构:DDD、ABP、SpringBoot、jFinal

 5、环境:跨平台、Windows、Linux、Nginx

 6、移动App:Android、IOS、HarmonyOS、微信小程序、钉钉、uni-app、MAUI

 分布式、高并发、云原生、微服务、Docker、CI/CD、DevOps、K8S;Dapr、RabbitMQ、Kafka、RPC、Elasticsearch。

欢迎关注作者头条号 张传宁IT讲堂,获取更多IT文章、视频等优质内容。

出处:www.cnblogs.com/SavionZhang

作者:张传宁   技术顾问、培训讲师、微软MCP、系统架构设计师、系统集成项目管理工程师、科技部创新工程师。

          专注于企业级通用开发平台、工作流引擎、自动化项目(代码)生成器、SOA 、DDD、 云原生(Docker、微服务、DevOps、CI/CD);PDF、CAD、BIM 审图等研究与应用。

          多次参与电子政务、图书教育、生产制造等企业级大型项目研发与管理工作。

          熟悉中小企业软件开发过程:可行调研、需求分析、架构设计、编码测试、实施部署、项目管理。通过技术与管理帮助中小企业实现互联网转型升级全流程解决方案。

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

如有问题,可以通过邮件905442693@qq.com联系。共同交流、互相学习。

如果您觉得文章对您有帮助,请点击文章右下角【推荐】。您的鼓励是作者持续创作的最大动力!