许多时候,开发者希望Revit有这样的功能。当用户对模型进行修改后,二次开发的程序能够相应用户的修改,对模型作出一些相应的修改操作。例如,一些墙上的窗户要求永远居中显示。当用户对这个墙做了长度修改,这个窗户还要自动的在墙的中心处。这就是一个比较容易理解的应用。

这要求Revit具有感知用户所做的操作,并且能随后对模型作出修改。对于感知用户的操作或动作,Revit有两个办法,一个是用反应器,也就是事件。另一个是模型动态更新机制DMU(Dynamic Model Update)。

Revit提供了一些事件,比如捕获文档的打开,保存,关闭,打印,视图切换等等。也提供了构建级别的事件(DocumentChanged)来捕获有新的对象加入,或有些对象发生修改,或一些对象的参数发生变化。但是在DocumentChanged事件处理函数里,无法对模型进行修改。禁止在这里进行模型的修改是为了防止循环调用DocumentChanged事件处理函数,形成死循环。基于这个原因,Revit 提供了DMU机制,模型动态更新。

DMU具有感知用户对模型进行了构建级别的修改,并且可以进行作出相应。而且在这里可以对模型进行修改。它之所以无法触发循环调用,是因为它对模型所做的修改和用户模型所做的修改共享同一个事务。在代码中对模型进行修改后,程序员无法掌控什么时候提交修改事务,Revit系统自动来提交事务的修改。

下面代码是DMU的一个例子,让窗户永居中的代码。

用法:

首先加载和注册DMU:

  [Transaction(TransactionMode.Automatic)]public class UIEventApp : IExternalApplication{// Flag to indicate if we want to show a message at each object modified events. public static bool m_showEvent = false;/// <summary>/// OnShutdown() - called when Revit ends. /// </summary>public Result OnShutdown(UIControlledApplication app){// (1) unregister our document changed event hander app.ControlledApplication.DocumentChanged -= UILabs_DocumentChanged;return Result.Succeeded;}/// <summary>/// OnStartup() - called when Revit starts. /// </summary>public Result OnStartup(UIControlledApplication app){// (2) register our dynamic model updater (WindowDoorUpdater class definition below.) // We are going to keep doors and windows at the center of the wall. // // Construct our updater. WindowDoorUpdater winDoorUpdater = new WindowDoorUpdater(app.ActiveAddInId);// ActiveAddInId is from addin menifest. // Register it UpdaterRegistry.RegisterUpdater(winDoorUpdater);// Tell which elements we are interested in being notified about. // We want to know when wall changes its length. ElementClassFilter wallFilter = new ElementClassFilter(typeof(Wall));UpdaterRegistry.AddTrigger(winDoorUpdater.GetUpdaterId(), wallFilter, Element.GetChangeTypeGeometry());return Result.Succeeded;}
//。。。
}

模型动态更新的实现类。在这里实现了如何更新模型。

 //======================================================== // dynamic model update - derive from IUpdater class //======================================================== public class WindowDoorUpdater : IUpdater{// Unique id for this updater = addin GUID + GUID for this specific updater. UpdaterId m_updaterId = null;// Flag to indicate if we want to perform public static bool m_updateActive = false;/// <summary>/// Constructor /// </summary>public WindowDoorUpdater(AddInId id){m_updaterId = new UpdaterId(id, new Guid("EF43510F-38CB-4980-844C-72174A674D56"));}/// <summary>/// This is the main function to do the actual job. /// For this exercise, we assume that we want to keep the door and window always at the center. /// </summary>public void Execute(UpdaterData data){if (!m_updateActive) return;Document rvtDoc = data.GetDocument();ICollection<ElementId> idsModified = data.GetModifiedElementIds();foreach (ElementId id in idsModified){//  Wall aWall = rvtDoc.get_Element(id) as Wall; // For 2012Wall aWall = rvtDoc.GetElement(id) as Wall; // For 2013CenterWindowDoor(rvtDoc, aWall);//Get the wall solid. Options opt = new Options();opt.ComputeReferences = false;Solid wallSolid = null;GeometryElement geoElem = aWall.get_Geometry(opt);foreach (GeometryObject geoObj in geoElem.Objects){wallSolid = geoObj as Solid;if (wallSolid != null){if (wallSolid.Faces.Size > 0){break;}}}//XYZ ptCenter = wallSolid.ComputeCentroid();        }}

下面这个函数是窗居中操作。

/// <summary>/// Helper function for Execute. /// Checks if there is a door or a window on the given wall. /// If it does, adjust the location to the center of the wall. /// For simplicity, we assume there is only one door or window. /// (TBD: or evenly if there are more than one.) /// </summary>public void CenterWindowDoor(Document rvtDoc, Wall aWall){// Find a winow or a door on the wall. FamilyInstance e = FindWindowDoorOnWall(rvtDoc, aWall);if (e == null) return;// Move the element (door or window) to the center of the wall. // Center of the wall LocationCurve wallLocationCurve = aWall.Location as LocationCurve;XYZ pt1 = wallLocationCurve.Curve.get_EndPoint(0);XYZ pt2 = wallLocationCurve.Curve.get_EndPoint(1);XYZ midPt = (pt1 + pt2) * 0.5;LocationPoint loc = e.Location as LocationPoint;loc.Point = new XYZ(midPt.X, midPt.Y, loc.Point.Z);}/// <summary>/// Helper function /// Find a door or window on the given wall. /// If it does, return it. /// </summary>public FamilyInstance FindWindowDoorOnWall(Document rvtDoc, Wall aWall){// Collect the list of windows and doors // No object relation graph. So going hard way. // List all the door instances var windowDoorCollector = new FilteredElementCollector(rvtDoc);windowDoorCollector.OfClass(typeof(FamilyInstance));ElementCategoryFilter windowFilter = new ElementCategoryFilter(BuiltInCategory.OST_Windows);ElementCategoryFilter doorFilter = new ElementCategoryFilter(BuiltInCategory.OST_Doors);LogicalOrFilter windowDoorFilter = new LogicalOrFilter(windowFilter, doorFilter);windowDoorCollector.WherePasses(windowDoorFilter);IList<Element> windowDoorList = windowDoorCollector.ToElements();// This is really bad in a large model!// You might have ten thousand doors and windows.// It would make sense to add a bounding box containment or intersection filter as well.// Check to see if the door or window is on the wall we got. foreach (FamilyInstance e in windowDoorList){if (e.Host.Id.Equals(aWall.Id)){return e;}}// If you come here, you did not find window or door on the given wall. return null;}

在Revit有三个例子演示了DMU的使用机制。请搜索UpdaterRegistry.RegisterUpdater 找到这几个例子更多了解模型动态更新的用法。

转载请复制以下信息:
原文链接: http://blog.csdn.net/joexiongjin/article/details/84855681
作者:  叶雄进 , Autodesk ADN

Revit里模型动态更新DMU的用法相关推荐

  1. mysql begin end 用法_超实用的Mysql动态更新数据库脚本的示例讲解(推荐)

    今天小编为大家分享一篇关于Mysql动态更新数据库脚本的示例讲解,具体的upgrade脚本如下: 动态删除索引 DROP PROCEDURE IF EXISTS UPGRADE;DELIMITER $ ...

  2. revit里的BIM模型转fbx真的可以带纹理材质吗?

    网上查到最多的就是,通过间接的形式实现.我想要通过BIM模型转成gltf,进而转成3Dtiles,但是已经可以实现revit转ifc,再由ifc转成gltf或者3Dtiles,但是ifc本身不支持纹理 ...

  3. aaynctask控制多个下载进度_AsyncTask用法解析-下载文件动态更新进度条

    1. 泛型 AysncTask Params:启动任务时传入的参数,通过调用asyncTask.execute(param)方法传入. Progress:后台任务执行的进度,若不用显示进度条,则不需要 ...

  4. 牛客刷题-Java面试题库【动态更新添加题目】(2023.06.19更新)

    讲在前面 ✨ 牛客刷题日记–理解为重中之重 刷题一方面是持续的了解到自己哪方面比较欠缺,另一方面也是从各大厂的面试题可以看出当前所需的技术栈的偏重点,持续的巩固基础和查漏补缺,一如代码深似海–学无止境 ...

  5. Unity项目运行时动态更新光照贴图 | LightMap

    Unity项目运行时动态更新烘培的光照贴图 动态更新烘培的光照贴图 场景的物件没有发生变化(也就是说没有运行时加载在场景上的Prefab) 场景的烘培贴图已经更新,但是有些物件prefab想运行时加载 ...

  6. Spark/Flink广播实现作业配置动态更新

    点击上方"zhisheng",选择"设为星标" 后台回复"ffa"可以查看 Flink 资料 前言 在实时计算作业中,往往需要动态改变一些配 ...

  7. VR App动态更新

    VR App动态更新,对<VR+行业>应用的商业意义 by 高煥堂 所谓"VR App动态更新"禁止开发者在Development-time把R素材绑入App里.只允许 ...

  8. Centos DNS服务(二)-bind主从配置与基于TSIG加密的动态更新

    DNS的主从配置 DNS从服务器也叫辅服DNS服务器,如果网络上某个节点只有一台DNS服务器的话,首先服务器的抗压能力是有限的,当压力达到一定的程度,服务器就可能会宕机罢工, 其次如果这台服务器出现了 ...

  9. Android零基础入门第44节:ListView数据动态更新

    2019独角兽企业重金招聘Python工程师标准>>> 经过前面几期的学习,关于ListView的一些基本用法大概学的差不多了,但是你可能发现了,所有ListView里面要填充的数据 ...

最新文章

  1. 案例丨神策数据赋能物流服务行业数字化转型
  2. 为什么判断 n 是否为质数只需除到开平方根就行了?(直接证明)
  3. 例子简单说说C# ref和out
  4. Kinect for Windows SDK开发初体验(二)操作Camera
  5. 将Markdown嵌入到我们的HTML页面中
  6. mysql可以装到其他端口吗_linux下怎么在另一个端口安装高版本mysql
  7. windows下使用linux terminal
  8. JanusGraph入门实操
  9. 社区团长资金分账该如何高效解决呢?
  10. 一年级计算机上册计划进度表,一年级上册语文教学计划及进度表
  11. 解决Android studio 方法数超过65536的问题
  12. C. Range Increments(差分)
  13. [HDU - 2063] 过山车(二分图)
  14. 区级医院计算机专业职称评审,医院职称晋升程序以及医生各级职称评审要求
  15. ATT格式汇编命令集合
  16. 「 MalabSimulink 」X0 returned by MATLAB S-function ‘NLSEF‘ in ‘ADRC_NN/S-Function1‘ must be a vector
  17. win7文件权限设置
  18. GAMES101作业7及课程总结(重点实现多线程加速,微表面模型材质)
  19. 【远程桌面软件RustDesk】开源远程控制神器!RustDesk为开源虚拟与远程桌面基础架构,也支持网页版,TeamViewer 和向日葵的替代品
  20. 外包公司程序员的水平真的很垃圾吗?

热门文章

  1. html 打印换页(转载)
  2. telegram账号被盗了,无法登录。
  3. 世界级/全国/省份/城市/县区4级联动
  4. Halcon 模板匹配专栏
  5. 曲线(笔迹)简化算法
  6. 周鸿祎:真想不通是张小龙这样的人做出了微信!
  7. 深入浅出百亿请求高可用Redis分布式集群
  8. 今天参加了《第三次全国国土调查》电视电话会议
  9. 声网微信小程序一对一语音通话
  10. 未来楼宇智慧解决方案