ParaView C++ 插件开发(二)创建插件基本流程

XML插件加载

如果没有通过源码编译安装ParaView,则使用XML进行插件加载是唯一的选择。

首先,服务端管理器XML文件对于滤波器插件是必须的。用来加载滤波器插件到某个类别中的GUI XML文件是可选的。

例如,需要将vtk中的vtkCellDerivatives滤波器作为插件加载到ParaView中。首先需要编写服务器管理配置XML文件(CellDerivatives.xml),该文件和之前为新滤波器编写文件相同:

<ServerManagerConfiguration>
  <ProxyGroup name="filters">
    <SourceProxy name="MyCellDerivatives" class="vtkCellDerivatives" label="My Cell Derivatives">
      <Documentation long_help="Create point attribute array by projecting points onto an elevation vector." short_help="Create a point array representing elevation">
      </Documentation>
      <InputProperty name="Input" command="SetInputConnection">
        <ProxyGroupDomain name="groups">
          <Group name="source"/>
          <Group name="filters"/>
        </ProxyGroupDomain>
        <DataTypeDomain name="input_type">
          <DataType value="vtkDataSet"/>
        </DataTypeDomain>
      </InputProperty>
    </SourceProxy>
  </ProxyGroup>
</ServerManagerConfiguration>

至此,可以使用ParaView中的插件管理器添加该XML文件。

如果该滤波器只有一个输入,需要设置InputProperty的name属性设定为"Input"。否则该滤波器的结果可能不会正确显示在ParaView管线浏览器中。

编译为共享库(Linux)或动态链接库(Windows)

如果从源码进行插件开发,需要将插件编译成共享库或者动态链接库。顶层的CMake文件如下:

# Standard CMake boilerplate. ParaView's 'find_package' requires at least 3.8.
cmake_minimum_required(VERSION 3.8)
project(sharedlibrary)

# There five lines are required in order to set up installation directories
# (which also control build directory locations) and enable shared builds
# (CMake's default is for static build)
include(GNUInstallDirs)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}")
set(CMAKE_LIRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
set(BUILD_SHARED_LIBS ON)

# Find ParaView. This will bring in ParaView's CMake API and imported targets.
find_packate(ParaView REQUIRED)

# Scan the plugin file in order to set up internal data structures for bulding plugins.
paraview_plugin_scan(
  # The 'paraview.plugin' file describing the plugin.
  PLUGIN_FILES "${CMAKE_CURRENT_SOURCE_DIR}/plugin/paraview.plugin"
  # A result variable for the (enabled) plugins found during the scan
  PROVIDES_PLUGINS plugins
  # Enable plugins during this scan by defult
  ENABLE_BY_DEFAULT ON
)

# Build the plugins discovered during the scan
paraview_plugin_build(
  PLUGINS ${plugins}
)

paraview.plugin文件描述了需要进行构建的插件:

NAME
  ElevationFilter
DESCRIPTION
  An example paraview plugin containing server manager XML and the server
  manager classes to build. This plugin can be loaded on the server side.
REQUIRES_MODULES
  VTK::CommonCore
  VTK::FiltersCore

在插件文件夹中(与paraview.plugin文件同一个文件夹中),还有一个CMakeLists.txt文件来说编译信息,内容如下:

paraview_add_plugin(ElevationFiter
  VERSION "1.0"
  MODULE ElevationFilters
  MDOULE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/ElevationFilters/vtk.module"
)

因为我们是在创建自定义滤波器,该滤波器需要是一个VTK Module,以此来支持获取XML中的关于该滤波器的信息。首先,该模块需要在vtk.module中声明。

NAME
  ElevationFilters
DEPENDS
  VTK::FiltersCore
PRIVATE_DEPENDS
  VTK::CommonCore

然后构建模块,将相关的服务器管理器XML文件附加到该模块。注意,由于内部管理库目标的方式,模块名不能与插件名相同。

set(classes vtkMyElevationFilter)

# Find external packages here using 'find_package'.

vtk_module_add_module(ElevationFilters
  CLASSES ${classes})

# Link to external packages here using 'vtk_module_link(ElevationFilters)'

paraview_add_server_manager_xmls(
  XMLS MyElevationFilters.xml
)

使用CMake进行该滤波器插件的构建。只要该插件加载到了ParaView,就会在Alphabetical列表中显示出来。注意,最后会有两个库,加载的是ElevationFilter插件,而不是ElevationFilters模块库文件。

多输入滤波器

如果一个滤波器需要多个输入接口,有两种方式实现:

(1)在VTK滤波器中创建辅助函数,比如SetYourInputName,该函数用于处理VTK管道寻址。

(2)通过XML文件中的编号机型寻址/访问输入连接。port_index属性指明了需要连接的输入接口。SetInputConnection函数是将使用这个port_index实际调用的命令,用于设置管道。

以下是XML文件,该文件中的滤波器拥有多输入。该滤波器将3个vtkPolyData对象作为输入。

<ServerManagerConfiguration>
  <ProxyGroup name="filters">
    <SourceProxy name="LandmarkTransformFilter" class="vtkLandmarkTransformFilters" label="LandmarkTransformFilter">
      <Documentation
         long_help="Align two point sets using vtkLandmarkTransform to compute the best transformation between the two point sets."
         short_help="vtkLandmarkTransformFilter.">
      </Documentation>

      <InputProperty name="SourceLandmarks" port_index="0" command="SetInputConnection">
        <ProxyGroupDomain name="groups">
          <Group name="sources"/>
          <Group name="filters"/>
        </ProxyGroupDomain>
        <DataTypeDomain name="input_type">
          <DataType value="vtkPolyData">
        </DataTypeDomain>
        <Documentation>
          Set the source data set. This data set that will move towards the target data set.
        </Documentation>
      </InputProperty>

      <InputProperty name="TargetLandmars" port_index="1" command="SetInputConnection">
        <ProxyGroupDomain name="groups">
          <Group name="sources"/>
          <Group name="filters"/>
        </ProxyGroupDomain>
        <DataTypeDomain name="input_type">
          <DataType value="vtkPolyData">
        </DataTypeDomain>
        <Documentation>
          Set the target data set. This data set will stay stationary.
        </Documentation>
      </InputProperty>     
 
      <InputProperty
          name="SourceDataSet"
          port_index="2"
          command="SetInputConnection">
        <ProxyGroupDomain name="groups">
          <Group name="sources"/>
          <Group name="filters"/>
        </ProxyGroupDomain>
        <DataTypeDomain name="input_type">
          <DataType value="vtkPolyData"/>
        </DataTypeDomain>
        <Documentation>
          Set the source data set landmark points.
        </Documentation>
      </InputProperty>

      <Hints>
        
      </Hints>

    </SourceProxy>
  </ProxyGroup>
</ServerManagerConfiguration>

要在ParaView中设置输入,只需要在管道浏览器中选择一个输入,并且从Filters菜单中选择一个滤波器。该步骤会打开一个对话框,该对话框中对每个输入接口选择对应的对象。

将类别添加到滤波器菜单

现在假设我们需要将一个新的类别添加到滤波器菜单中,该类别为"Extensions",并且将一个滤波器显示在该菜单中。在这个案例中,我们在XML文件中添加一个提示(hint),该Hints标签会告诉ParaView用哪个类别来显示该滤波器。XML标签如下:

<Hints>
  <ShowInMenu category="Extensions" />
</Hints>

如果该类别已经存在,如"Data Analysis",那么这个滤波器会添加到这个已经存在的类别菜单中。

添加图标

一些Filters中的滤波器拥有自己的图标(如Clip)。添加图标需要编写Qt资源文件(参考MyElevation.qrc):

<RCC>
  <qresource prefix="/MyIcons">
    <file>MyElevationIcon.png</file>
  </qresource>
</RCC>

为了给该滤波器使用图标,需要在服务端管理器XML文件中的Hints标签下添加如下内容:

<Hints>
  <ShowInMenu icon=":/MyIcons/MyElevationIcon.png"/>
</Hints>

最后,在插件的CmakeLists.txt中需要包括MyElevation.qrc文件,代码如下:

paraview_add_plugin(ElevationFilter
  VERSION "1.0"
  MODULES ElevationFilters
  MODULE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/ElevationFilters/vtk.module"
  UI_RESOURCES MyElevation.qrc
)

添加GUI参数控制

只需要简单的在服务端管理器XML文件中添加如下代码,就可以将滤波器的参数展示给ParaView用户。

1、按钮标签

以下标签作为按钮出现,"name"属性对应的字符串作为按钮的文字描述,这里是"My Button"。当用户点击该按钮是,会调用"command"指明的函数,这里"MyButtonClicked"被执行,该函数属于该vtk代理类中的函数。

<Property name="MyButton" command="MyButtonClicked">
</Property>

2、整形值标签

该标签作为文字框(text box)出现

<IntVectorProperty 
  name="bStartByMatchingCentroids"
  command="SetbStartByMatchingCentroids"
  number_of_elements="1"
  default_values="1">
</IntVectorProperty>

3、布尔值标签

该标签作为选择控制框(check box)。该标签使用IntVectorProperty结合一个额外行(BooleanDomain)进行使用,BooleanDomain说明了这是一个选择框而不是文字框。

<IntVectorProperty
  name="bStartByMatchingCentroids"
  command="SetbStartByMatchingCentroids"
  number_of_elements="1"
  default_values="1">
  <BooleanDomain name="bool"/>
</IntVectorProperty>

4、字符串标签

  该标签作为文字框出现在界面上。

<StringVectorProperty
  name="YourStringVariable"
  command="SetYourStringVariable"
  number_of_elements="1"
  default_values="1">
</StringVectorProperty>

5、浮点数标签(double)

该标签作为文字框出现

<DoubleVectorProperty
  name="YourDoubleVariable"
  command="SetYourDoubleVariable"
  number_Of_elements="1"
  default_values="1">
</DoubleVectorProperty>

6、多值浮点数标签(Double)

该标签作为文字框出现。

<DoubleVectorProperty
  name="YourDoubleVectorVariable"
  command="SetYourDoubleVectorVariable"
  number_of_elements="3"
  default_values="1.0 0.0 0.0">
</DoubleVectorProperty>

7、浮点(double)滑动调节按钮

该标签创建一个从0.0到1.0的滑动调节按钮。

<DoubleVectorProperty
  name="PercentToRemove"
  command="SetPercentToRemove"
  number_of_elements="1"
  default_value="0.1">
  <DoubleRangeDomain name="range" min="0.1" max="1.0"/>
</DoubleVectorProperty>

8、下拉列表

该示例创建一个有3个选择的下拉列表,每个选择的值都可以指定。

<IntVectorProperty
  name="TransformMode"
  command="SetTransformMode"
  number_of_elements="1"
  default_values="1">
  <EnumerationDomain name="enum">
    <Entry value="6" text="RigidBody"/>
    <Entry value="7" text="Similarity"/>
    <Entry value="12" text="Affine"/>
  </EnumerationDomain>
  <Documentation>
    This property indicates which transform mode will be used.
  </Documentation>
</IntvectorProperty>

9、从输入数组取值的下拉列表

该示例创建了一个下拉列表,该列表的输入值是从ProgrammableFilter的输入值。

<StringVectorProperty 
  name="SelectInputScalars"
  label="Array"
  command="SetInputArrayToProcess"
  number_of_elements="5"
  element_types="0 0 0 0 2"
  animateable="0">
  <ArrayListDomain
    name="array_list"
    attribute_type="Scalars"
    input_domain_name="inputs_array">
    <RequiredProperties>
      <Property name="Input" function="Input" />
    </RequiredProperties>
  </ArrayListDomain>
</StringVectorProperty>

效果如下图:

10、从文件获取输入的下拉列表

如果您需要使用文件中的值填充列表,并且能够选择/取消选择列表条目(例如,选择从文件中加载哪些变量),请使用类似于以下内容的XML:

<StringVectorProperty information_only="1" name="CellArrayInfo">
  <ArraySelectionInformationHelper attribute_name="Cell" />
</StringVectorProperty>

<StringVectorProperty
  command="SetCellArrayStatus"
  element_types="2 0"
  information_property="CellArrayInfo"
  label="Cell Arrays"
  name="CellArrayStatus"
  number_of_elements="0"
  number_of_elements_per_command="2"
  repeat_command="1">
  <ArraySelectionDmoain name="array_list>
    <RequiredProperties>
      <Property function="ArrayList" name="CellArrayInfo"/>
    </RequiredProperties>
  </ArraySelectionDomain>
  <Documentation>
    ThisP property lists which cell-centered arrays to read.
  </Documentation>
</StringVectorProperty>
也可以使用以下的方式:
<StringVectorProperty
  command="SetCellArrayStatus
  element_type="2 0"
  information_property="CellArrayInfo"
  label="Cell Arrays"
  name="CellArrayStatus"
  number_of_elements="0"
  number_of_elements_per_command="2"
  repeat_command="1">
  <ArrayListDomain name="array_list" attribute_type="Scalars" input_domain_name="input_array">
    <RequiredProperties>
      <Property name="Input" function="Input"/>
    </RequiredProperties>
  </ArrayListDomain>
</StringVectorProperty>

结果如下:

 

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值