xBIM 实战03 使用WPF技术实现IFC模型的加载与浏览
因为 DirectX 能理解可由显卡直接渲染的高层元素,如纹理和渐变,所以 DirectX 效率更高。而 GDI/GDI+不理解这些高层元素,因此必须将他们转换成逐像素指令,而通过现代显卡渲染这些指令更慢。

主要业务逻辑如下:
/// <summary>
/// 加载模型文件
/// </summary>
/// <param name="modelFileName"></param>
public void LoadAnyModel(string modelFileName)
{
var fInfo = new FileInfo(modelFileName);
if (!fInfo.Exists)
return; if (fInfo.FullName.ToLower() == GetOpenedModelFileName())
return; // 没有撤回功能;如果在这一点之后失败,那么应该关闭当前文件。
CloseAndDeleteTemporaryFiles();
SetOpenedModelFileName(modelFileName.ToLower());
ProgressStatusBar.Visibility = Visibility.Visible;
SetWorkerForFileLoad(); var ext = fInfo.Extension.ToLower();
switch (ext)
{
case ".ifc": // Ifc 文件
case ".ifcxml": // IfcXml 文件
case ".ifczip": // zip 文件,包含 xbim 或者 ifc 文件
case ".zip": // zip 文件,包含 xbim 或者 ifc 文件
case ".xbimf":
case ".xbim":
_loadFileBackgroundWorker.RunWorkerAsync(modelFileName);
break;
default:
Logger.LogWarning("Extension '{extension}' has not been recognised.", ext);
break;
}
}
其中调用的主要方法如下:
/// <summary>
/// 整理所有打开的文件并关闭所有打开的模型
/// </summary>
private void CloseAndDeleteTemporaryFiles()
{
try
{
if (_loadFileBackgroundWorker != null && _loadFileBackgroundWorker.IsBusy)
{
_loadFileBackgroundWorker.CancelAsync(); //通知线程取消操作
} SetOpenedModelFileName(null);
if (Model != null)
{
Model.Dispose();
ModelProvider.ObjectInstance = null;
ModelProvider.Refresh();
} if (!(DrawingControl.DefaultLayerStyler is SurfaceLayerStyler))
{
SetDefaultModeStyler(null, null);
}
}
finally
{
if (!(_loadFileBackgroundWorker != null && _loadFileBackgroundWorker.IsBusy && _loadFileBackgroundWorker.CancellationPending)) //它仍然在运行,但已经取消了
{
if (!string.IsNullOrWhiteSpace(_temporaryXbimFileName) && File.Exists(_temporaryXbimFileName))
{
File.Delete(_temporaryXbimFileName);
}
_temporaryXbimFileName = null;
}
else
{
//它将在工作线程中清除
}
}
}
private void SetOpenedModelFileName(string ifcFilename)
{
_openedModelFileName = ifcFilename;
// 尝试通过用于多线程的委托更新窗口标题
Dispatcher.BeginInvoke(new Action(delegate
{
Title = string.IsNullOrEmpty(ifcFilename)
? "Xbim Xplorer"
: "Xbim Xplorer - [" + ifcFilename + "]";
}));
}
private void SetWorkerForFileLoad()
{
_loadFileBackgroundWorker = new BackgroundWorker
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
_loadFileBackgroundWorker.ProgressChanged += OnProgressChanged;
_loadFileBackgroundWorker.DoWork += OpenAcceptableExtension;
_loadFileBackgroundWorker.RunWorkerCompleted += FileLoadCompleted;
}
private void OnProgressChanged(object s, ProgressChangedEventArgs args)
{
if (args.ProgressPercentage < || args.ProgressPercentage > )
return; Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Send,
new Action(() =>
{
ProgressBar.Value = args.ProgressPercentage;
StatusMsg.Text = (string)args.UserState;
})); }
private void OpenAcceptableExtension(object s, DoWorkEventArgs args)
{
var worker = s as BackgroundWorker;
var selectedFilename = args.Argument as string; try
{
if (worker == null)
throw new Exception("Background thread could not be accessed");
_temporaryXbimFileName = Path.GetTempFileName();
SetOpenedModelFileName(selectedFilename);
var model = IfcStore.Open(selectedFilename, null, null, worker.ReportProgress, FileAccessMode);
if (_meshModel)
{
// 匹配直接模型
if (model.GeometryStore.IsEmpty)
{
try
{
var context = new Xbim3DModelContext(model); if (!_multiThreading)
context.MaxThreads = ;
#if FastExtrusion
context.UseSimplifiedFastExtruder = _simpleFastExtrusion;
#endif
SetDeflection(model);
// 升级到新的几何图形表示,使用默认的三维模型
context.CreateContext(worker.ReportProgress, App.ContextWcsAdjustment);
}
catch (Exception geomEx)
{
var sb = new StringBuilder();
sb.AppendLine($"Error creating geometry context of '{selectedFilename}' {geomEx.StackTrace}.");
var newException = new Exception(sb.ToString(), geomEx);
Logger.LogError(, newException, "Error creating geometry context of {filename}", selectedFilename);
}
} // 匹配引用
foreach (var modelReference in model.ReferencedModels)
{
// 根据需要创建联合几何体上下文
Debug.WriteLine(modelReference.Name);
if (modelReference.Model == null)
continue;
if (!modelReference.Model.GeometryStore.IsEmpty)
continue;
var context = new Xbim3DModelContext(modelReference.Model);
if (!_multiThreading)
context.MaxThreads = ;
#if FastExtrusion
context.UseSimplifiedFastExtruder = _simpleFastExtrusion;
#endif
SetDeflection(modelReference.Model);
// 升级到新的几何图形表示,使用默认的三维模型
context.CreateContext(worker.ReportProgress, App.ContextWcsAdjustment);
}
if (worker.CancellationPending)
// 如果已请求取消,则不要打开结果文件
{
try
{
model.Close();
if (File.Exists(_temporaryXbimFileName))
{
File.Delete(_temporaryXbimFileName);
} _temporaryXbimFileName = null;
SetOpenedModelFileName(null);
}
catch (Exception ex)
{
Logger.LogError(, ex, "Failed to cancel open of model {filename}", selectedFilename);
}
return;
}
}
else
{
Logger.LogWarning("Settings prevent mesh creation.");
}
args.Result = model;
}
catch (Exception ex)
{
var sb = new StringBuilder();
sb.AppendLine($"Error opening '{selectedFilename}' {ex.StackTrace}.");
var newException = new Exception(sb.ToString(), ex);
Logger.LogError(, ex, "Error opening {filename}", selectedFilename);
args.Result = newException;
}
}
private void FileLoadCompleted(object s, RunWorkerCompletedEventArgs args)
{
if (args.Result is IfcStore)
{
// 这将触发将模型加载到视图中的事件
ModelProvider.ObjectInstance = args.Result;
ModelProvider.Refresh();
ProgressBar.Value = ;
StatusMsg.Text = "Ready";
AddRecentFile();
}
else
{
var errMsg = args.Result as string;
if (!string.IsNullOrEmpty(errMsg))
{
MessageBox.Show(this, errMsg, "Error Opening File", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.None, MessageBoxOptions.None);
} var exception = args.Result as Exception;
if (exception != null)
{
var sb = new StringBuilder(); var indent = "";
while (exception != null)
{
sb.AppendFormat("{0}{1}\n", indent, exception.Message);
exception = exception.InnerException;
indent += "\t";
}
MessageBox.Show(this, sb.ToString(), "Error Opening Ifc File", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.None, MessageBoxOptions.None);
}
ProgressBar.Value = ;
StatusMsg.Text = "Error/Ready";
SetOpenedModelFileName("");
}
FireLoadingComplete(s, args);
}
/// <summary>
/// 模型文件加载完成事件
/// </summary>
public event LoadingCompleteEventHandler LoadingComplete; private void FireLoadingComplete(object s, RunWorkerCompletedEventArgs args)
{
if (LoadingComplete != null)
{
LoadingComplete(s, args);
}
}
xBIM 实战03 使用WPF技术实现IFC模型的加载与浏览的更多相关文章
- xBIM 实战04 在WinForm窗体中实现IFC模型的加载与浏览
系列目录 [已更新最新开发文章,点击查看详细] WPF底层使用 DirectX 进行图形渲染.DirectX 能理解可由显卡直接渲染的高层元素,如纹理和渐变,所以 DirectX 效率更高. ...
- WPF防止界面卡死并显示加载中效果
原文:WPF防止界面卡死并显示加载中效果 网上貌似没有完整的WPF正在加载的例子,所以自己写了一个,希望能帮到有需要的同学 前台: <Window x:Class="WpfApplic ...
- [WPF自定义控件库] 让Form在加载后自动获得焦点
原文:[WPF自定义控件库] 让Form在加载后自动获得焦点 1. 需求 加载后让第一个输入框或者焦点是个很基本的功能,典型的如"登录"对话框.一般来说"登录" ...
- 【Android编程实战】源码级免杀_Dex动态加载技术_Metasploit安卓载荷傀儡机代码复现
/文章作者:MG193.7 CNBLOG博客ID:ALDYS4 QQ:3496925334/ 在读者阅读本文章前,建议先阅读笔者之前写的一篇对安卓载荷的分析文章 [逆向&编程实战]Metasp ...
- 【WPF学习】第四章 加载和编译XAML
前面已经介绍过,尽管XAML和WPF这两种技术具有相互补充的作用,但他们也是相互独立的.因此,完全可以创建不使用XAML和WPF应用程序. 总之,可使用三种不同的编码方式来创建WPF应用程序: 只使用 ...
- HTML5的页面资源预加载技术(Link prefetch)加速页面加载
不管是浏览器的开发者还是普通web应用的开发者,他们都在做一个共同的努力:让Web浏览有更快的速度感觉.有很多已知的技术都可以让你的网站速度变得更快:使用CSS sprites,使用图片优化工具,使用 ...
- 那些H5用到的技术(1)——素材加载
编码环境前言什么时候用到素材加载?loading提示,让用户等待图片的加载音频的加载利用神器PreloadJS总结 编码环境 Sublime Text 3 插件包括: Autoprefixer 自动补 ...
- wpf prism4 出现问题:无法加载一个或多个请求的类型。有关更多信息,请检索 LoaderExceptions 属性。
WPF Prism 框架 程序 出现 问题: 无法加载一个或多个请求的类型.有关更多信息,请检索 LoaderExceptions 属性. 1.开始以为是配置的问题,找了半天,最后原来是有个依赖类库没 ...
- tvtk管线技术、数据集与数据加载
管线技术也称流水线技术(Pipeline)每个对象只实现相对简单的任务,整个管线进行复杂的可视化处理在tvtk中分为可视化管线和图形管线 可视化管线(Visualization Pipeline):将 ...
随机推荐
- PHP的错误处理和异常处理
由于教程是围绕着文件打开做的错误处理,所以先记录几个用于文件处理的一些函数,fopen 用于打开一个文件:file_exists 用于检查目录是否存在:fclose( $变量 )用于指定关闭打开的文件 ...
- CSS实现栅格布局
CSS实现栅格布局 设置容器container: .grid-container { width: 100%; max-width: 1200px; } 清除浮动: .row:before, .row ...
- Android和Html的简单交互
---恢复内容开始--- 1.通过WebView加载Html界面.在android studio中html放在assets中. 但是默认的并不存在这个文件夹,创建过程是 2.创建后简单实现下,js调用 ...
- performSelector与objc_msgSend
- perform:(SEL)aSelector { if (aSelector) return objc_msgSend(self, aSelector); else return [self er ...
- 基于vue项目的js工具方法汇总
以下是个人过去一年在vue项目的开发过程中经常会用到的一些公共方法,在此进行汇总,方便以后及有需要的朋友查看~ let util = {}; /** * @description 日期格式化 * @p ...
- https://blog.csdn.net/sxf359/article/details/71082404
https://blog.csdn.net/sxf359/article/details/71082404
- 设置mySql的编码方式为utf-8
检查命令: mysql> show variables like '%char%'; 期望结果: 使用mysql命令设置: 如果仍有编码不是utf8的,请检查配置文件,也可使用mysql命令设置 ...
- 操作mysql操作数据库
操作数据库 查询数据库:show databases: 增加数据库:create database student default character set uft-8:(设置默认字符集) 删除数据 ...
- Eclipse中使用GIT提交文件至本地
GIT提交文件至本地: 1. 右击项目——Team——Commit…: 2.在弹出的Commit Changes框中——选择要提交的文件——填写提交说明——点击Commit,即可提交至本地.
- C# 基础复习 四 多线程
单线程和多线程的区别 单线程: 只用主线程处理,如果一个操作在占用主线程,那么其他操作则无法执行 多线程: 除了主线程外,还开启了子线程来执行操作,子线 ...