• xBIM 实战03 使用WPF技术实现IFC模型的加载与浏览


      WPF应用程序在底层使用 DirectX ,无论设计复杂的3D图形(这是 DirectX 的特长所在)还是绘制简单的按钮与文本,所有绘图工作都是通过 DirectX 管线完成的。在硬件加速方面也带来了好处,DirectX 在渲染图形时会将尽可能多的工作递交给图形处理单元(GPU)去处理,GPU是显卡的专用处理器。

    因为 DirectX 能理解可由显卡直接渲染的高层元素,如纹理和渐变,所以 DirectX 效率更高。而 GDI/GDI+不理解这些高层元素,因此必须将他们转换成逐像素指令,而通过现代显卡渲染这些指令更慢。

      WPF凭借着出色的3D渲染能力,使其成为在客户端加载渲染3D模型不二的选择。在3D模型查看器中加载BIM文件(.ifc格式),显示效果如下图所示:

     主要业务逻辑如下:

     1         /// <summary>
     2         ///  加载模型文件
     3         /// </summary>
     4         /// <param name="modelFileName"></param>
     5         public void LoadAnyModel(string modelFileName)
     6         {
     7             var fInfo = new FileInfo(modelFileName);
     8             if (!fInfo.Exists)
     9                 return;
    10 
    11             if (fInfo.FullName.ToLower() == GetOpenedModelFileName())
    12                 return;
    13 
    14             // 没有撤回功能;如果在这一点之后失败,那么应该关闭当前文件。
    15             CloseAndDeleteTemporaryFiles();
    16             SetOpenedModelFileName(modelFileName.ToLower());
    17             ProgressStatusBar.Visibility = Visibility.Visible;
    18             SetWorkerForFileLoad();
    19 
    20             var ext = fInfo.Extension.ToLower();
    21             switch (ext)
    22             {
    23                 case ".ifc":    // Ifc 文件
    24                 case ".ifcxml": // IfcXml 文件
    25                 case ".ifczip": // zip 文件,包含  xbim 或者 ifc 文件
    26                 case ".zip":    // zip 文件,包含  xbim 或者 ifc 文件
    27                 case ".xbimf":
    28                 case ".xbim":
    29                     _loadFileBackgroundWorker.RunWorkerAsync(modelFileName);
    30                     break;
    31                 default:
    32                     Logger.LogWarning("Extension '{extension}' has not been recognised.", ext);
    33                     break;
    34             }
    35         }

    其中调用的主要方法如下:

     1         /// <summary>
     2         ///  整理所有打开的文件并关闭所有打开的模型
     3         /// </summary>
     4         private void CloseAndDeleteTemporaryFiles()
     5         {
     6             try
     7             {
     8                 if (_loadFileBackgroundWorker != null && _loadFileBackgroundWorker.IsBusy)
     9                 {
    10                     _loadFileBackgroundWorker.CancelAsync(); //通知线程取消操作
    11                 }
    12 
    13                 SetOpenedModelFileName(null);
    14                 if (Model != null)
    15                 {
    16                     Model.Dispose();
    17                     ModelProvider.ObjectInstance = null;
    18                     ModelProvider.Refresh();
    19                 }
    20 
    21                 if (!(DrawingControl.DefaultLayerStyler is SurfaceLayerStyler))
    22                 {
    23                     SetDefaultModeStyler(null, null);
    24                 }
    25             }
    26             finally
    27             {
    28                 if (!(_loadFileBackgroundWorker != null && _loadFileBackgroundWorker.IsBusy && _loadFileBackgroundWorker.CancellationPending)) //它仍然在运行,但已经取消了
    29                 {
    30                     if (!string.IsNullOrWhiteSpace(_temporaryXbimFileName) && File.Exists(_temporaryXbimFileName))
    31                     {
    32                         File.Delete(_temporaryXbimFileName);
    33                     }
    34                     _temporaryXbimFileName = null;
    35                 }
    36                 else
    37                 {
    38                     //它将在工作线程中清除
    39                 }
    40             }
    41         }
     1         private void SetOpenedModelFileName(string ifcFilename)
     2         {
     3             _openedModelFileName = ifcFilename;
     4             // 尝试通过用于多线程的委托更新窗口标题
     5             Dispatcher.BeginInvoke(new Action(delegate
     6             {
     7                 Title = string.IsNullOrEmpty(ifcFilename)
     8                     ? "Xbim Xplorer"
     9                     : "Xbim Xplorer - [" + ifcFilename + "]";
    10             }));
    11         }
     1         private void SetWorkerForFileLoad()
     2         {
     3             _loadFileBackgroundWorker = new BackgroundWorker
     4             {
     5                 WorkerReportsProgress = true,
     6                 WorkerSupportsCancellation = true
     7             };
     8             _loadFileBackgroundWorker.ProgressChanged += OnProgressChanged;
     9             _loadFileBackgroundWorker.DoWork += OpenAcceptableExtension;
    10             _loadFileBackgroundWorker.RunWorkerCompleted += FileLoadCompleted;
    11         }
     1        private void OnProgressChanged(object s, ProgressChangedEventArgs args)
     2         {
     3             if (args.ProgressPercentage < 0 || args.ProgressPercentage > 100)
     4                 return;
     5 
     6             Application.Current.Dispatcher.BeginInvoke(
     7                 DispatcherPriority.Send,
     8                 new Action(() =>
     9                 {
    10                     ProgressBar.Value = args.ProgressPercentage;
    11                     StatusMsg.Text = (string)args.UserState;
    12                 }));
    13 
    14         }
     1        private void OpenAcceptableExtension(object s, DoWorkEventArgs args)
     2         {
     3             var worker = s as BackgroundWorker;
     4             var selectedFilename = args.Argument as string;
     5 
     6             try
     7             {
     8                 if (worker == null)
     9                     throw new Exception("Background thread could not be accessed");
    10                 _temporaryXbimFileName = Path.GetTempFileName();
    11                 SetOpenedModelFileName(selectedFilename);
    12                 var model = IfcStore.Open(selectedFilename, null, null, worker.ReportProgress, FileAccessMode);
    13                 if (_meshModel)
    14                 {
    15                     // 匹配直接模型
    16                     if (model.GeometryStore.IsEmpty)
    17                     {
    18                         try
    19                         {
    20                             var context = new Xbim3DModelContext(model);
    21 
    22                             if (!_multiThreading)
    23                                 context.MaxThreads = 1;
    24 #if FastExtrusion
    25                             context.UseSimplifiedFastExtruder = _simpleFastExtrusion;
    26 #endif
    27                             SetDeflection(model);
    28                             // 升级到新的几何图形表示,使用默认的三维模型
    29                             context.CreateContext(worker.ReportProgress, App.ContextWcsAdjustment);
    30                         }
    31                         catch (Exception geomEx)
    32                         {
    33                             var sb = new StringBuilder();
    34                             sb.AppendLine($"Error creating geometry context of '{selectedFilename}' {geomEx.StackTrace}.");
    35                             var newException = new Exception(sb.ToString(), geomEx);
    36                             Logger.LogError(0, newException, "Error creating geometry context of {filename}", selectedFilename);
    37                         }
    38                     }
    39 
    40                     // 匹配引用
    41                     foreach (var modelReference in model.ReferencedModels)
    42                     {
    43                         // 根据需要创建联合几何体上下文
    44                         Debug.WriteLine(modelReference.Name);
    45                         if (modelReference.Model == null)
    46                             continue;
    47                         if (!modelReference.Model.GeometryStore.IsEmpty)
    48                             continue;
    49                         var context = new Xbim3DModelContext(modelReference.Model);
    50                         if (!_multiThreading)
    51                             context.MaxThreads = 1;
    52 #if FastExtrusion
    53                         context.UseSimplifiedFastExtruder = _simpleFastExtrusion;
    54 #endif
    55                         SetDeflection(modelReference.Model);
    56                         // 升级到新的几何图形表示,使用默认的三维模型
    57                         context.CreateContext(worker.ReportProgress, App.ContextWcsAdjustment);
    58                     }
    59                     if (worker.CancellationPending)
    60                     // 如果已请求取消,则不要打开结果文件
    61                     {
    62                         try
    63                         {
    64                             model.Close();
    65                             if (File.Exists(_temporaryXbimFileName))
    66                             {
    67                                 File.Delete(_temporaryXbimFileName);
    68                             }
    69 
    70                             _temporaryXbimFileName = null;
    71                             SetOpenedModelFileName(null);
    72                         }
    73                         catch (Exception ex)
    74                         {
    75                             Logger.LogError(0, ex, "Failed to cancel open of model {filename}", selectedFilename);
    76                         }
    77                         return;
    78                     }
    79                 }
    80                 else
    81                 {
    82                     Logger.LogWarning("Settings prevent mesh creation.");
    83                 }
    84                 args.Result = model;
    85             }
    86             catch (Exception ex)
    87             {
    88                 var sb = new StringBuilder();
    89                 sb.AppendLine($"Error opening '{selectedFilename}' {ex.StackTrace}.");
    90                 var newException = new Exception(sb.ToString(), ex);
    91                 Logger.LogError(0, ex, "Error opening {filename}", selectedFilename);
    92                 args.Result = newException;
    93             }
    94         }
     1        private void FileLoadCompleted(object s, RunWorkerCompletedEventArgs args)
     2         {
     3             if (args.Result is IfcStore)
     4             {
     5                 // 这将触发将模型加载到视图中的事件
     6                 ModelProvider.ObjectInstance = args.Result;
     7                 ModelProvider.Refresh();
     8                 ProgressBar.Value = 0;
     9                 StatusMsg.Text = "Ready";
    10                 AddRecentFile();
    11             }
    12             else
    13             {
    14                 var errMsg = args.Result as string;
    15                 if (!string.IsNullOrEmpty(errMsg))
    16                 {
    17                     MessageBox.Show(this, errMsg, "Error Opening File", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.None, MessageBoxOptions.None);
    18                 }
    19 
    20                 var exception = args.Result as Exception;
    21                 if (exception != null)
    22                 {
    23                     var sb = new StringBuilder();
    24 
    25                     var indent = "";
    26                     while (exception != null)
    27                     {
    28                         sb.AppendFormat("{0}{1}
    ", indent, exception.Message);
    29                         exception = exception.InnerException;
    30                         indent += "	";
    31                     }
    32                     MessageBox.Show(this, sb.ToString(), "Error Opening Ifc File", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.None, MessageBoxOptions.None);
    33                 }
    34                 ProgressBar.Value = 0;
    35                 StatusMsg.Text = "Error/Ready";
    36                 SetOpenedModelFileName("");
    37             }
    38             FireLoadingComplete(s, args);
    39         }
     1         /// <summary>
     2         ///  模型文件加载完成事件
     3         /// </summary>
     4         public event LoadingCompleteEventHandler LoadingComplete;
     5 
     6         private void FireLoadingComplete(object s, RunWorkerCompletedEventArgs args)
     7         {
     8             if (LoadingComplete != null)
     9             {
    10                 LoadingComplete(s, args);
    11             }
    12         }
     
  • 相关阅读:
    Ubuntu中设置永久的DNS
    Ubuntu上OpenStack DashBoard主题修改的方案
    OpenStack 控制台不能不能访问的问题
    树莓派2试玩
    SharpMap V1.1 For Web教程系列之——地图展示
    剑指offer12 矩阵中的路径
    flex布局中关键词整理
    浏览器缓存 强缓存 协商缓存整理
    二叉搜索树中第K小的元素
    leetcode cs-notes-树(一)【js】
  • 原文地址:https://www.cnblogs.com/SavionZhang/p/11010495.html
Copyright © 2020-2023  润新知