Revit二次开发小技巧(十七)实时监控模型线的生成
前言:项目中需要一个需求,用户想调用出Revit中自带的绘制模型线方法,然后再绘制结束时,可以拿到绘制的模型线,然后实现后面的算法。这里记录一种方法,通过DocumentChange事件+修改Tag的PropertyChanged事件来实现对应的需求。
以下示例使用的都是Revit2019的环境进行开发,其他版本会涉及到对应的API的不同,可以自行修改
1.背景
用户需要运行命令后,点击选择墙面,然后在墙面上绘制模型线,在推出绘制模式的时候,可以提取线,并且删除绘制的线
2.代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.DB.Events;
using System.ComponentModel;
using Autodesk.Windows;
using System.Windows;namespace RevitTest
{[Transaction(TransactionMode.Manual)]public class DUMDemo : IExternalCommand{/// <summary>/// 创建的构件/// </summary>private List<ElementId> _createIDList = new List<ElementId>();/// <summary>/// 判断是否已经载入/// </summary>private bool _subscribed;/// <summary>/// 外部事件/// </summary>private ExternalEvent _external;public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements){var tReference = commandData.Application.ActiveUIDocument.Selection.PickObject(ObjectType.Face, "选择面");CreateLine(commandData.Application, tReference);return Result.Succeeded;}public void CreateLine(UIApplication uiapp, Reference selRef){Document doc = uiapp.ActiveUIDocument.Document;using (Transaction ts = new Transaction(doc, "CreatModelCurve")){ts.Start();Face face = doc.GetElement(selRef).GetGeometryObjectFromReference(selRef) as Face;Plane tPlan = Plane.CreateByNormalAndOrigin(face.ComputeNormal(new UV()), selRef.GlobalPoint);doc.ActiveView.SketchPlane = SketchPlane.Create(doc, tPlan);ts.Commit();}RevitCommandId revitCommand = RevitCommandId.LookupCommandId("ID_OBJECTS_PROJECT_CURVE");if (revitCommand != null && uiapp.CanPostCommand(revitCommand)){//加入document改变事件uiapp.Application.DocumentChanged += PostElement;//添加标签修改事件foreach (var tab in ComponentManager.Ribbon.Tabs){if (tab.Id == "Modify"){if (_subscribed){tab.PropertyChanged -= TabPropertyChangedEvent;_subscribed = false;}else{tab.PropertyChanged += TabPropertyChangedEvent;_subscribed = true;}break;}}//添加外部事件BaseEvent selectChangeEvent = new BaseEvent();selectChangeEvent.EventAction = app =>{Transaction trans = new Transaction(app.ActiveUIDocument.Document, "删除线");trans.Start();try{app.Application.DocumentChanged -= PostElement;app.ActiveUIDocument.Document.Delete(_createIDList);_createIDList.Clear();}catch (Exception ex){MessageBox.Show(ex.Message);}trans.Commit();};_external = ExternalEvent.Create(selectChangeEvent);uiapp.PostCommand(revitCommand);}}/// <summary>/// 监控构件修改事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void PostElement(object sender, DocumentChangedEventArgs e){List<ElementId> collection = e.GetAddedElementIds().ToList();_createIDList.AddRange(collection);}/// <summary>/// 修改标签事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void TabPropertyChangedEvent(object sender, PropertyChangedEventArgs e){if (!(sender is RibbonTab)){return;}if (!string.Equals(e.PropertyName, "Title", StringComparison.CurrentCultureIgnoreCase)){return;}if (_subscribed == false){(sender as RibbonTab).PropertyChanged -= TabPropertyChangedEvent;MessageBox.Show($"{_createIDList.Count}");_external.Raise();}else{_subscribed = false;}}}/// <summary>/// 外部事件/// </summary>public class BaseEvent : IExternalEventHandler{/// <summary>/// 实现方法的委托函数/// </summary>public Action<UIApplication> EventAction { get; set; }public void Execute(UIApplication app){EventAction?.Invoke(app);}public string GetName(){return "事件";}}
}
3.代码分析
3.1 调用Revit中自带的模型线生成方法
通过直接调用内置方法的CommandId来实现放置模型线的方法
RevitCommandId revitCommand = RevitCommandId.LookupCommandId("ID_OBJECTS_PROJECT_CURVE");
uiapp.PostCommand(revitCommand);
3.2 注册DocumentChange事件
注册DocumentChange事件,通过这个事件去监控构建的添加,然后收集到集合中
uiapp.Application.DocumentChanged += PostElement;
/// <summary>/// 监控构件修改事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void PostElement(object sender, DocumentChangedEventArgs e){List<ElementId> collection = e.GetAddedElementIds().ToList();_createIDList.AddRange(collection);}
3.3 注册修改Tab的PropertyChanged事件
通过tabs去遍历所有的tab,然后ID为"Modify"的Tab对应的是修改按钮。因为进入绘制模型线的时候,Tab会变成“修改 | 放置线”,结束绘制的时候,变回“修改”,因此给tab直接加上属性修改的事件来监控整个流程的开始和结束
foreach (var tab in ComponentManager.Ribbon.Tabs){if (tab.Id == "Modify"){if (_subscribed){tab.PropertyChanged -= TabPropertyChangedEvent;_subscribed = false;}else{tab.PropertyChanged += TabPropertyChangedEvent;_subscribed = true;}break;}}
/// <summary>/// 修改标签事件/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void TabPropertyChangedEvent(object sender, PropertyChangedEventArgs e){if (!(sender is RibbonTab)){return;}if (!string.Equals(e.PropertyName, "Title", StringComparison.CurrentCultureIgnoreCase)){return;}if (_subscribed == false){(sender as RibbonTab).PropertyChanged -= TabPropertyChangedEvent;MessageBox.Show($"{_createIDList.Count}");_external.Raise();}else{_subscribed = false;}}
3.4 注册外部事件
外部事件的作用是在结束整体功能的时候,去除DocumentChange事件,以免照成事件加载多次的现象
//添加外部事件BaseEvent selectChangeEvent = new BaseEvent();selectChangeEvent.EventAction = app =>{Transaction trans = new Transaction(app.ActiveUIDocument.Document, "删除线");trans.Start();try{app.Application.DocumentChanged -= PostElement;app.ActiveUIDocument.Document.Delete(_createIDList);_createIDList.Clear();}catch (Exception ex){MessageBox.Show(ex.Message);}trans.Commit();};_external = ExternalEvent.Create(selectChangeEvent);
BaseEvent是自己定义的外部事件接口,大家可以根据自己的想法来封装
4.写在最后
对得到的构件进行操作的话,逻辑应该写在外部事件里面。
这里提供了一个监控生成构建的解决方案,但是做很复杂的操作时,有可能会出现外部事件丢失的情况。如果是想通过PropertyChanged事件去监控选择了什么构件的话,如果构件选择过多的时候,也是会出现错误的。大家如果遇到类似的问题,可以通过调试的方式去查看对应的问题。
Revit二次开发小技巧(十七)实时监控模型线的生成相关推荐
- Revit二次开发小技巧(十四)封闭墙体最大外轮廓
前言:当前方法使用在既定的情况下,选择闭合的墙体,然后找到对应的外轮廓,并不支持存在开口的情况,仅提供一种思路.Revit版本为2019 代码: using Autodesk.Revit.Attrib ...
- Revit二次开发小技巧(十六)寻找最短路径
最近遇到一个需求,指定两个配电箱,然后找到两个配电箱之间最短的桥架路径.运用了Dijkstra算法去计算最短路径,以配电箱实体.三通.四通为节点,简化中间弯头计算的方式. 背景 选择起点和终点的配电箱 ...
- Revit二次开发小技巧(十二)创建带洞口的墙
这里记录一下项目上遇到的问题,就是创建带洞口的墙的时候,会发现创建接口仅有一个线集合传进去(如下图).当墙体有洞口的时候,线段就只能再一个集合中传进去了. 这时候会遇到一点问题,就是直接把两个轮廓的线 ...
- 用友NC二次开发小技巧:服务端执行SQL语句的方法
大家好,今天给大家分享一下NC二次开发过程中的一个非常有用的小技巧:执行SQL语句. 我们在NC二开的过程中,经常需要直接查询数据库或者直接修改数据库表的字段值.这是一个非常简单并且通用的需求.下面给 ...
- Revit二次开发小火车工具集的复现
这是复现了腿腿教学网麻蛋讲师所做的小火车工具集插件的代码.下面是Github的链接有需要可以下载. https://github.com/yingdajun/BabyTrainCopyDemo
- 【STM32开发小技巧】CUBEMX改变工程模板(FreeMarker一键生成定制文件)
前言 一.使用默认模板 二.使用自定义模板 效果展示 总结 前言 ps:可直接跳到效果展示 众所周知CUBEMX可以生成代码,图形界面可以方便用户进行STM32的配置,有天我就在想能否用户改变生成后的 ...
- Revit二次开发——读取CAD文字实现更新模型的思路
更新模型 与内地BIM项目中 设计院终版图纸一波流翻模的模式不同 香港BIM项目的模式是:设计出图-BIM出碰撞报告-设计再改图-BIM再碰撞报告-反反复复- 模型频繁更新 是BIM项目服务过程中不可 ...
- Revit二次开发实现BIM盈利(以橄榄山快模为例解说) 视频讲座下载
应笔墨闲谈群的邀请, 在10月11号晚8:30分在其群做了一次关于BIM二次开发的讲座. 因为參与者基本上都是从设计院和施工单位来的,所以对Revit二次开发做了纵览性的解说, 以非程序猿能听懂的方式 ...
- 小六六平时的开发小技巧二(Nacos在服务配置中心的妙用)
前言 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206/six-finger 絮叨 小六六打算开一个系列把自己平时的一些开发经验分享出来和 ...
最新文章
- nodejs之connect
- 【计算机网络】网络安全 : 数据加密模型 ( 加密模型 | 密钥 | 密码学 | 密码安全 )
- 生成任意内容任意类型的文件
- c++和python的区别、javascript_python和c++的区别
- 数据库开发——MySQL——基本操作
- linux内核常用函数或宏
- 极简代码:害死人不偿命的(3n+1)猜想 (15分)
- raptor算法流程图例题_RAPTOR流程图+算法程序设计教程
- 离线语音识别软件_从音乐识别软件起家,这家公司如何备战车载AI语音市场GGAI对话...
- 从51能不学编程只学c语言,51单片机C语言学习笔记8:单片机C51编程规范
- 多个线程并发执行完成后再执行主线程-java(有点内容版)
- (转)“宇宙之王”高盛在历史的交叉口,不得不全面走向机器自动化
- 【软件】一个简单好用的取色器TakeColor(百度云免费下载链接)
- Xshell6 plus绿色永久版_SSH连接工具_站长必备工具集
- 注册表(安全 活动桌面)
- P4238 【模板】多项式乘法逆
- 腾亚幕墙Web开发基础教程
- (私人收藏)64个精致的页面loadinggif动画
- 前端学HTTP之web攻击技术
- 计算机软技能,在个人简历中有哪些软技能可以写?
热门文章
- html关闭ios橡皮筋效果,禁止ios浏览器页面上下滚动 (橡皮筋效果)
- linux权限drwx,linux权限基础知识详解
- 《快速掌握PyQt5》专栏整理成书出版啦!
- 【Vue】获取cookie
- 李洵同款爱心加红蓝动态线条爱心
- git 强制更新本地代码与服务器端一致
- ipad vs android,安卓和苹果平板简评 iPad2018和华为平板M610.8英寸版区别对比
- 我的宝宝有了他/她的乳名!
- 计算机科学与探索类别,图像目标类别检测综述-计算机科学与探索.pdf
- 查看端口被占用命令(Windows+Linux)