EaBIM一直以来积极响应国家“十二五”推进建筑业信息化的号召,对建筑领域的信息技术开展深入技术交流和探讨!致力于打造“BIM-建筑师-生态技术”三位一体综合资源交流共享平台,希望为BIM与可持续设计理念及技术的普及做出微小的贡献!!!

萧闫子 发表于 2014-1-15 14:05:26

Revit里模型动态更新DMU的用法

许多时候,开发者希望Revit有这样的功能。当用户对模型进行修改后,二次开发的程序能够相应用户的修改,对模型作出一些相应的修改操作。例如,一些墙上的窗户要求永远居中显示。当用户对这个墙做了长度修改,这个窗户还要自动的在墙的中心处。这就是一个比较容易理解的应用。
这要求Revit具有感知用户所做的操作,并且能随后对模型作出修改。对于感知用户的操作或动作,Revit有两个办法,一个是用反应器,也就是事件。另一个是模型动态更新机制DMU(Dynamic Model Update)。


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


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


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


用法:


首先加载和注册DMU:


view plaincopy

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;
}
view plaincopy
//。。。
view plaincopy
}

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

view plaincopy//========================================================    // 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 2012       Wall aWall = rvtDoc.GetElement(id) as Wall; // For 2013       CenterWindowDoor(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();             }   }

下面这个函数是窗居中操作。 view plaincopy
/// <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


JHXT杰西卡 发表于 2014-2-13 10:20:12

本帖最后由 Aaronyee 于 2015-11-2 19:43 编辑 <br /><br />呵呵

www.588102.com 皇_冠现_金网:hg88094.com首存送58元.手机可投だ注任何游戏满1000送1088彩_金だ体育半场结算六_合48倍だ各种彩票游戏

严英华 发表于 2014-2-14 10:14:36

本帖最后由 Aaronyee 于 2015-11-2 19:43 编辑 <br /><br />顶!!!!!!!!!!

www.303811.com 皇_冠现_金网:hg88094.com首存送58元.手机可投℃注任何游戏满1000送1088彩_金℃体育半场结算六_合48倍℃各种彩票游戏

蓝天POLO 发表于 2014-2-20 14:07:39

本帖最后由 Aaronyee 于 2015-11-2 19:43 编辑 <br /><br />路过!!!
不发表意见……

www.138334.com SO娱乐城:真_人.足球.彩票齐全| 开户送10元.首存送58元.手机可投,注任何游戏顶级信用,提现即时到账SO.CC
页: [1]
查看完整版本: Revit里模型动态更新DMU的用法