Revit SDK 介绍:DuplicateGraphics

前言

这个例子介绍如何直接在 Revit 的画布里面绘制任意用户想要的三维图形。或者说,Revit API 暴露了让用户直接参与生成渲染数据的接口。

内容

程序运行的效果如下,它的逻辑:

  1. 选择一个或多个构件,比如墙,点击完成
  2. 通过类 DirectContext3D::DrawContext 在画布绘制选中构件

注意:不是所有构件都能被绘制出来,比如门窗,原因在于这个例子没有考虑这种情况,用户可以自己修改代码来实现。另外,这个只是示例,用户完全可以自己生成完全无关的几何图形。Revit 通过这个接口,把图形的生成权力交给了用户。
Revit SDK 介绍:DuplicateGraphics_第1张图片

实现这个逻辑的关键点

实现这个功能的两个关键点:

  1. 为接口 IDirectContext3DServer 做一个实现,处理绘制相关的内容
  2. 把接口注册到 Revit Application

IDirectContext3DServer

接口的内容:

namespace Autodesk.Revit.DB.DirectContext3D
{
    // DirectContext3D 是一个 external service.
    public interface IDirectContext3DServer : ExternalService.IExternalServer
    {
        // 用于判断在哪些视图下运行。
        bool CanExecute(View dBView);
        string GetApplicationId();
        // 提供包围盒的接口
        Outline GetBoundingBox(View dBView);
        string GetSourceId();
        // 渲染的接口,用于在视图中去显示三维图形
        void RenderScene(View dBView, DisplayStyle displayStyle);
        bool UseInTransparentPass(View dBView);
        // 当前对于第三方插件只能返回false
        bool UsesHandles();
    }
}

这里面渲染的入口是 RenderScene,而这个接口的实现里需要调用DrawContext::FlushBuffer
来向渲染管线里面输入内容,注意这是一个static class

namespace Autodesk.Revit.DB.DirectContext3D
{
    public static class DrawContext
    {
        // 往图形缓冲区传入内容,包括顶点信息和索引信息,以及顶点是什么类型,三角形、边或者点。
        public static void FlushBuffer(VertexBuffer vertexBuffer, int vertexCount, IndexBuffer indexBuffer, int indexCount, VertexFormat vertexFormat, EffectInstance effectInstance, PrimitiveType primitiveType, int start, int primitiveCount);
        public static Camera GetCamera();
        // 获取一系列剪切面。
        public static IList<ClipPlane> GetClipPlanes();
        // 获取裁剪区域。
        public static Rectangle GetClipRectangle();
        //
        // 摘要:
        //     Returns override color that will be applied to geometry during rendering.
        public static bool GetOverrideColor(out Color color);
        //
        // 摘要:
        //     Returns override transparency that will be applied to geometry during rendering.
        public static bool GetOverrideTransparency(out double transparency);
        //
        // 摘要:
        //     Gets the rectangle that represents the extent (in 2D) of the Revit view where
        //     rendering takes place.
        public static Rectangle GetViewRectangle();
        //
        // 摘要:
        //     Checks whether the facilities of this class are available for use in the current
        //     scope.
        public static bool IsAvailable();
        //
        // 摘要:
        //     Checks whether the current rendering pass has been interrupted.
        public static bool IsInterrupted();
        //
        // 摘要:
        //     Determines whether the current rendering pass is for transparent objects.
        public static bool IsTransparentPass();
        //
        // 摘要:
        //     Sets the world transformation that will be applied to geometry during rendering.
        public static void SetWorldTransform(Transform trf);
    }
}

注册用户自己实现的 RevitElementDrawingServer

通过静态方法 ExternalServiceRegistry.GetService 得到对应的 Service,然后将自己的实现加入。

ExternalService directContext3DService = ExternalServiceRegistry.GetService(ExternalServices.BuiltInExternalServices.DirectContext3DService);
RevitElementDrawingServer revitServer = new RevitElementDrawingServer(uidoc, elem, m_offset);
directContext3DService.AddServer(revitServer);

从 ExternalServices.BuiltInExternalServices 这个类可以找到目前 API 可以看到的一些服务,应该都有各自的用途:

namespace Autodesk.Revit.DB.ExternalService
{
    public static class ExternalServices
    {
        public static class BuiltInExternalServices
        {
            public static ExternalServiceId StructuralSectionsService { get; }
            public static ExternalServiceId CloudExternalService { get; }
            public static ExternalServiceId CodeCheckingParameterService { get; }
            public static ExternalServiceId ConnectionTypeChangedService { get; }
            public static ExternalServiceId DirectContext3DService { get; }
            public static ExternalServiceId DuctFittingAndAccessoryPressureDropService { get; }
            public static ExternalServiceId DuctFittingAndAccessoryPressureDropUIService { get; }
            public static ExternalServiceId DuctPressureDropService { get; }
            public static ExternalServiceId EntitlementExternalService { get; }
            public static ExternalServiceId ExternalResourceService { get; }
            public static ExternalServiceId ExternalResourceUIService { get; }
            public static ExternalServiceId FramingProfileService { get; }
            public static ExternalServiceId HoleDefinitionService { get; }
            public static ExternalServiceId IFCExporterService { get; }
            public static ExternalServiceId IFCImporterService { get; }
            public static ExternalServiceId MemberForcesService { get; }
            public static ExternalServiceId ModifyConnectionParametersService { get; }
            public static ExternalServiceId NavisworksExporterService { get; }
            public static ExternalServiceId PathOfTravelCalculationService { get; }
            public static ExternalServiceId PipeFittingAndAccessoryPressureDropService { get; }
            public static ExternalServiceId PipeFittingAndAccessoryPressureDropUIService { get; }
            public static ExternalServiceId PipeFrictionFactorService { get; }
            public static ExternalServiceId PipePlumbingFixtureFlowService { get; }
            public static ExternalServiceId PipePressureDropService { get; }
            public static ExternalServiceId RebarUpdateService { get; }
            public static ExternalServiceId SiteInsertService { get; }
            public static ExternalServiceId SiteLinkerUIService { get; }
            public static ExternalServiceId SnappingService { get; }
            public static ExternalServiceId AlignmentService { get; }
            public static ExternalServiceId ATFTranslationService { get; }
        }
    }
}

实现的具体逻辑

RevitElementDrawingServer 实现接口 IDirectContext3DServer
Revit 2021 SDK\Samples\DuplicateGraphics\CS\RevitElementDrawingServer.cs

对于如何从 Revit 的 Element 里面获取几何图形:

GeometryElement geomElem = m_element.get_Geometry(options);
List<Solid> allSolids = new List<Solid>();
foreach (GeometryObject geomObj in geomElem)
{
   if (geomObj is Solid)
   {
      Solid solid = (Solid)geomObj;
      if (solid.Volume > 1e-06)
         allSolids.Add(solid);
   }
}

foreach (Solid solid in allSolids)
{
   foreach (Face face in solid.Faces)
   {
      if (face.Area > 1e-06)
      {
         Mesh mesh = face.Triangulate();
         // 处理 face 的三角面片,即离散化数据,这个例子是加入到渲染的 buffer 里面,DrawContext.FlushBuffer
      }
   }
}

foreach (Edge edge in solid.Edges)
{
   IList<XYZ> xyzs = edge.Tessellate();
   // 处理 edge 的离散化数据,这个例子是加入到渲染的 buffer 里面,DrawContext.FlushBuffer
}

你可能感兴趣的:(Revit,SDK,介绍,c#)