应用程序: DistanceToSurfaces

Revit平台: 所有

Revit版本: 2011.0

首次发布版本: 2011.0

编程语言: C#

技能水平: 高级

类别: 几何

类型: ExternalApplication

主题:使用动态模型更新在Revit模型中展示分析结果。

摘要:在启动时,外部应用程序会创建一个触发器,该触发器将在项目中的墙体、实体和族实例发生更改时执行。当出现这种情况时,Revit会计算从一个家族实例(sphere.rfa)到每个面的几个点的距离。这些距离用作分析可视化显示的值。

相关类:

Autodesk.Revit.DB.Analysis.FieldDomainPointsByUV

Autodesk.Revit.DB.Analysis.FieldValues

Autodesk.Revit.DB.Analysis.SpatialFieldManager

Autodesk.Revit.DB.BoundingBoxUV

Autodesk.Revit.DB.Events.DocumentOpenedEventArgs

Autodesk.Revit.DB.FaceArray

Autodesk.Revit.DB.FilteredElementCollector

Autodesk.Revit.DB.LocationPoint

Autodesk.Revit.DB.UpdaterRegistry

功能:

1. 在启动时,注册一个DocumentOpened事件。当打开一个文档时,

a.检查球体族是否存在

b.检查是否存在名为“AVF”的3D视图

c.创建一个GetChangeTypeGeometry触发器,当墙体、实体楼板或组件实例更改时触发

2. 当出现此触发器时,

a. 查找球的 XYZ 位置

b. 获取现有的空间字段管理器对象,如果不存在则创建一个

c. 创建一个包含项目中每个墙体或楼板的每个面的面数组,包括就地几何

d. 计算球体原点与每个面上的几个点之间的距离

e. 通过更新空间字段基元,在面上显示这些距离作为分析结果。

使用说明:

打开 DistanceToSurfaces.rvt

移动墙体、块体或球体族的任意实例

完整的源代码请加入QQ群649037449,在群文件中下载RevitSDK.exe,解压后在文件夹中搜索本文中应用程序名称即可获得完整源码

Command.cs

//
// (C) Copyright 2003-2019 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//

using System;
using System.Linq;
using System.Collections.Generic;
using Autodesk.Revit;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.DB.Analysis;
using Autodesk.Revit.UI;


namespace Revit.SDK.Samples.AnalysisVisualizationFramework.CS
{
   [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
   [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
   public class DistanceToSurfaces : IExternalApplication
   {
      public Result OnStartup(UIControlledApplication uiControlledApplication)
      {
         uiControlledApplication.ControlledApplication.DocumentOpened += new EventHandler<DocumentOpenedEventArgs>(docOpen);
         return Result.Succeeded;
      }

      private void docOpen(object sender, DocumentOpenedEventArgs e)
      {
         Autodesk.Revit.ApplicationServices.Application app = sender as Autodesk.Revit.ApplicationServices.Application;
         UIApplication uiApp = new UIApplication(app);
         Document doc = uiApp.ActiveUIDocument.Document;

         FilteredElementCollector collector = new FilteredElementCollector(doc);
         collector.WherePasses(new ElementClassFilter(typeof(FamilyInstance)));
         var sphereElements = from element in collector where element.Name == "sphere" select element;
         if (sphereElements.Count() == 0)
         {
            TaskDialog.Show("Error", "Sphere family must be loaded");
            return;
         }
         FamilyInstance sphere = sphereElements.Cast<FamilyInstance>().First<FamilyInstance>();
         FilteredElementCollector viewCollector = new FilteredElementCollector(doc);
         ICollection<Element> views = viewCollector.OfClass(typeof(View3D)).ToElements();
         var viewElements = from element in viewCollector where element.Name == "AVF" select element;
         if (viewElements.Count() == 0)
         {
            TaskDialog.Show("Error", "A 3D view named 'AVF' must exist to run this application.");
            return;
         }
         View view = viewElements.Cast<View>().First<View>();

         SpatialFieldUpdater updater = new SpatialFieldUpdater(uiApp.ActiveAddInId, sphere.Id, view.Id);
         if (!UpdaterRegistry.IsUpdaterRegistered(updater.GetUpdaterId())) UpdaterRegistry.RegisterUpdater(updater);
         ElementCategoryFilter wallFilter = new ElementCategoryFilter(BuiltInCategory.OST_Walls);
         ElementClassFilter familyFilter = new ElementClassFilter(typeof(FamilyInstance));
         ElementCategoryFilter massFilter = new ElementCategoryFilter(BuiltInCategory.OST_Mass);
         IList<ElementFilter> filterList = new List<ElementFilter>();
         filterList.Add(wallFilter);
         filterList.Add(familyFilter);
         filterList.Add(massFilter);
         LogicalOrFilter filter = new LogicalOrFilter(filterList);

         UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), filter, Element.GetChangeTypeGeometry());
         UpdaterRegistry.AddTrigger(updater.GetUpdaterId(), filter, Element.GetChangeTypeElementDeletion());
      }
      public Result OnShutdown(UIControlledApplication application) {return Result.Succeeded;}
   }

   public class SpatialFieldUpdater : IUpdater
   {
      AddInId addinID;
      UpdaterId updaterID;
      ElementId sphereID;
      ElementId viewID;
      public SpatialFieldUpdater(AddInId id, ElementId sphere, ElementId view)
      {
         addinID = id;
         sphereID = sphere;
         viewID = view;
         updaterID = new UpdaterId(addinID, new Guid("FBF2F6B2-4C06-42d4-97C1-D1B4EB593EFF"));
      }
      public void Execute(UpdaterData data)
      {
         Document doc = data.GetDocument();
         Autodesk.Revit.ApplicationServices.Application app = doc.Application;

         View view = doc.GetElement(viewID) as View;
         FamilyInstance sphere = doc.GetElement(sphereID) as FamilyInstance;
         LocationPoint sphereLP = sphere.Location as LocationPoint;
         XYZ sphereXYZ = sphereLP.Point;

         SpatialFieldManager sfm = SpatialFieldManager.GetSpatialFieldManager(view);
         if (sfm == null) sfm = SpatialFieldManager.CreateSpatialFieldManager(view, 3); // Three measurement values for each point
         sfm.Clear();

         FilteredElementCollector collector = new FilteredElementCollector(doc,view.Id);
         ElementCategoryFilter wallFilter = new ElementCategoryFilter(BuiltInCategory.OST_Walls);
         ElementCategoryFilter massFilter = new ElementCategoryFilter(BuiltInCategory.OST_Mass);
         LogicalOrFilter filter = new LogicalOrFilter(wallFilter, massFilter);
         ICollection<Element> elements = collector.WherePasses(filter).WhereElementIsNotElementType().ToElements();

         foreach (Face face in GetFaces(elements))
         {
            int idx = sfm.AddSpatialFieldPrimitive(face.Reference);
            List<double> doubleList = new List<double>();
            IList<UV> uvPts = new List<UV>();
            IList<ValueAtPoint> valList = new List<ValueAtPoint>();
            BoundingBoxUV bb = face.GetBoundingBox();
            for (double u = bb.Min.U; u < bb.Max.U; u = u + (bb.Max.U - bb.Min.U) / 15)
            {
               for (double v = bb.Min.V; v < bb.Max.V; v = v + (bb.Max.V - bb.Min.V) / 15)
               {
                  UV uvPnt = new UV(u, v);
                  uvPts.Add(uvPnt);
                  XYZ faceXYZ = face.Evaluate(uvPnt);
                   // Specify three values for each point
                  doubleList.Add(faceXYZ.DistanceTo(sphereXYZ));
                  doubleList.Add(-faceXYZ.DistanceTo(sphereXYZ));
                  doubleList.Add(faceXYZ.DistanceTo(sphereXYZ) * 10);
                  valList.Add(new ValueAtPoint(doubleList));
                  doubleList.Clear();
               }
            }
            FieldDomainPointsByUV pnts = new FieldDomainPointsByUV(uvPts);
            FieldValues vals = new FieldValues(valList);

            AnalysisResultSchema resultSchema1 = new AnalysisResultSchema("Schema 1", "Schema 1 Description");
            IList<int> registeredResults = new List<int>();
            registeredResults = sfm.GetRegisteredResults();
            int idx1 = 0;
            if (registeredResults.Count == 0)
            {
                idx1 = sfm.RegisterResult(resultSchema1);
            }
            else
            {
                idx1 = registeredResults.First();
            }
            sfm.UpdateSpatialFieldPrimitive(idx, pnts, vals, idx1);
         }
      }
      public string GetAdditionalInformation() { return "Calculate distance from sphere to walls and display results"; }
      public ChangePriority GetChangePriority() { return ChangePriority.FloorsRoofsStructuralWalls; }
      public UpdaterId GetUpdaterId() { return updaterID; }
      public string GetUpdaterName() { return "Distance to Surfaces"; }

      private FaceArray GetFaces(ICollection<Element> elements)
      {
         FaceArray faceArray = new FaceArray();
         Options options = new Options();
         options.ComputeReferences = true;
         foreach (Element element in elements)
         {
            GeometryElement geomElem = element.get_Geometry(options);
            if (geomElem != null)
            {
                foreach (GeometryObject geomObj in geomElem)
               {
                  Solid solid = geomObj as Solid;
                  if (solid != null)
                  {
                     foreach (Face f in solid.Faces)
                     {
                        faceArray.Append(f);
                     }
                  }
                  GeometryInstance inst = geomObj as GeometryInstance;
                  if (inst != null) // in-place family walls
                  {
                     foreach (Object o in inst.SymbolGeometry)
                     {
                        Solid s = o as Solid;
                        if (s != null)
                        {
                           foreach (Face f in s.Faces)
                           {
                              faceArray.Append(f);
                           }
                        }
                     }
                  }
               }
            }
         }
         return faceArray;
      }
   }
}