目前,见到使用的三维预览,是以二维平面生成的线段,类似如:
那么如何做到真正的三维效果呢?我们知道,要在winform中生成三维,那一般得需要有3d引擎。但我们不太可能为了某一个功能,跑去开发一个3d引擎,如果真能开发出3d引擎,那么你自己就可以开一家公司了,光3d引擎技术就够你吃香的喝辣的了。
言归正传,本文是使用Revit的三维效果,嵌入到winfrom中实现的。
正文开始之前,先看下最终效果:
请注意,此三维预览,是在winform中先预览,然后才去Revit中,生成你的实际效果。而不是将Revit的建筑预览到Winform中。
一、首先我们先实现IExternalCommand接口,制作一个插件
using Autodesk.Revit.DB;using Autodesk.Revit.DB.Architecture;using Autodesk.Revit.DB.Structure;using Autodesk.Revit.UI;using Autodesk.Revit.UI.Selection;using Previewer;using Previewer.Extensions;using Previewer.Runtime;using System;using System.Collections.Generic;using System.Diagnostics;using System.Linq;using System.Runtime.CompilerServices;using System.Text;using System.Windows.Forms;namespace Rotation{ /// /// Revit预览 /// /// marc [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] [Autodesk.Revit.Attributes.Journaling(Autodesk.Revit.Attributes.JournalingMode.NoCommandData)] public class DefaultCommand : IExternalCommand { /// /// 执行指令 /// /// /// /// /// public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { var activeDocument = commandData.Application.ActiveUIDocument; var document = activeDocument.Document; IDataContext context = new DataContext(commandData); RevitRuntime.SetDataContext(context); Result result; Transaction tran = new Transaction(document, Guid.NewGuid().ToString()); try { tran.Start(); IWork work = new PreviewWork(); result = work.Run(); tran.Commit(); } catch (System.Exception exp) { tran.RollBack(); result = Result.Failed; Debug.WriteLine(exp.Message); } finally { tran.Dispose(); } return result; } }}
上述接口实现,里面就一句核心代码:IWork.Run(),也就是说业务逻辑的代码,已经放在了Run方法中,那么我们看下IWork接口
二、定义IWork业务逻辑接口
using Autodesk.Revit.UI;namespace Previewer{ /// /// 逻辑作业接口 /// /// marc public interface IWork { /// /// 运行 /// /// Result Run(); }}
三、实现IWork方法
using Autodesk.Revit.DB;using Autodesk.Revit.UI;using Previewer.UI;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;namespace Previewer{ /// /// Revit预览的具体逻辑 /// /// marc public class PreviewWork : IWork { /// /// 运行 /// /// public virtual Result Run() { this.ShowForm(); return Result.Succeeded; } /// /// 显示窗体 /// private void ShowForm() { var document = PreviewConfigure.GetOrCreateDocument(PreviewRealtime.ProjectName); using (Transaction tran = new Transaction(document, Guid.NewGuid().ToString())) { tran.Start(); var form = new PreviewForm(); DialogResult result = form.ShowDialog(); if (result != DialogResult.OK) { tran.RollBack(); return; } tran.Commit(); } } }}
如上述,我们的具体实现,只是显示了一个Winform窗体。
四、我们在显示Winform窗体之前,先创建一个自定义的Winform控件
自定义Winform控件的界面如下:
五、下面创建一个Winform窗体,并载入上面的自定义控件,界面如下:
右侧看不见的区域,就是自定义控件的东西。用来显示三维预览的。
六、看下Winform窗体的代码,讲解下:
using Autodesk.Revit.DB;using Autodesk.Revit.DB.Structure;using Previewer.Core;using Previewer.CustomControls;using Previewer.Runtime;using Previewer.UI;using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;namespace Previewer{ /// /// 预览窗体 /// /// marc public partial class PreviewForm : FormBase { /// /// 实时预览对象 /// private readonly IPreviewRealtime _previewRealtime; private Preview _preview; /// /// 构造函数 /// public PreviewForm() { InitializeComponent(); this._previewRealtime = new PreviewRealtime(); this.LoadPreviewControl(); } /// /// 加载预览控件 /// private void LoadPreviewControl() { this._preview = new Preview { Dock = DockStyle.Fill, Location = new System.Drawing.Point(0, 0), Name = "Preview", TabIndex = 0, Text = "预览", IsVisibleDocuments = false, IsVisibleDropdownList = true }; this.PreviewPanel.Controls.Add(_preview); _preview.SetDefaultDocument(this._previewRealtime.Document); } /// /// 预览效果 /// /// /// private void PreviewButton_Click(object sender, EventArgs e) { this._preview.Clear(); this._previewRealtime.Build(); this.TipLabel1.Visible = true; this.TipLabel2.Visible = true; this.TipLabel3.Visible = true; this.TipLabel4.Visible = true; this.CreateButton.Visible = true; } /// /// 真正的在Revit中生成想要的图元,效果等于你在预览图中看到的一样 /// /// /// private void CreateButton_Click(object sender, EventArgs e) { var document = RevitRuntime.DataContext.Document; IDraw draw = new Draw(); draw.Demo(document); this.DialogResult = DialogResult.OK; this.Close(); } /// /// 当窗体关闭时发生 /// /// /// private void PreviewForm_FormClosed(object sender, FormClosedEventArgs e) { this._preview.Clear(); } }}
我们使用LoadPreviewControl()方法加载了三维预览控件,初始化了Preview对象,Preview对象是自定义的Winform控件。
预览方法PreviewButton_Click()是一个点击事件,点击后,将出现预览效果。他的核心是调用了this._previewRealtime.Build();
预览效果满意后,可以使用CreateButton_Click()进行确定,并自动关闭窗体,然后在Revit中生成刚刚预览的效果。
由于之前预览时生成的预览效果,将以族实例的方式存储在Revit中,所以,我们在关闭窗体,或者多次预览时,都需要调用一下清除方法:this._preview.Clear();
七、看一下Preview自定义控件的方法定义
IsVisibleDocuments:是否显示文档选择列表
IsVisibleDropdownList:是否显示下拉列表
Clear:清空当前Document文档已经生成的预览对象
SetDefaultDocument:设置默认操作文档
SetDefaultView:设置默认视图,不设的话,我们默认为3d
八、生成预览的接口定义
using Autodesk.Revit.DB;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Previewer.UI{ /// /// 实时预览接口 /// /// marc public interface IPreviewRealtime { /// /// 预览所用的文档对象 /// Document Document { get; } /// /// 创建 /// void Build(); }}
该接口定义了一个属性Document,代表将在哪个Document中生成预览效果。
还定义了一个Build()方法,调用该方法后,将即时在此Document中生成预览效果。
九、绘制图像。也就是建筑了。
using Autodesk.Revit.DB;namespace Previewer.Core{ /// /// 绘制 /// /// marc public interface IDraw { /// /// 制作一个demo /// /// 操作文档 void Demo(Document document); }}
由于我们只是为了Demo,所以绘制方法里,就只写了一个生成Demo的方法。实际生产中,可以自行更换为您自己需要的方法。
最后,你就可以生成这个dll,加载到Revit中进行实际测试了。文章最后附上了完整源码,并带有完整注释。祝您用餐愉快。
源码下载:https://download.csdn.net/download/mazhiyuan1981/12915401