Paraview源码解析2:vtkArrowGlyphFilter类

paraview热流图(1):添加glyphs
5.8.1 Glyph
VTK学习笔记:vtkXMLPolyDataWriter

Cmake语法:paraview_add_server_manager_xmls怎么理解?

glyph过滤器由vtkArrowGlyphFilter类实现

1. MaskAndExecuter()

int vtkArrowGlyphFilter::MaskAndExecute(vtkIdType numPts, vtkIdType maxNumPts, vtkDataSet* input,
  vtkInformation* vtkNotUsed(request), vtkInformationVector** vtkNotUsed(inputVector),
  vtkInformationVector* outputVector)

代码段2_1:MaskAndExecute()

在这里插入图片描述

图片2_1:

最核心代码

 // transform the arrow point to correct glyph position/orientation
    trans->TransformPoints(arrowpoints, newPoints);

代码段2_2:将箭头点变换为正确的图示符位置/方向

1.1关于参数arrowpoints的完整代码

//
  // We won't modify the arrow source provided (that the users sees in the GUI), we'll use a private copy for our work.
  //我们不会修改提供的箭头源代码(用户在GUI中看到的),我们将使用私有副本进行工作。
  vtkSmartPointer<vtkArrowSource> internalArrow = this->ArrowSourceObject->NewInstance();
  internalArrow->SetTipLength(this->ArrowSourceObject->GetTipLength());
  internalArrow->SetTipRadius(this->ArrowSourceObject->GetTipRadius());
  internalArrow->SetTipResolution(this->ArrowSourceObject->GetTipResolution());
  internalArrow->SetShaftRadius(this->ArrowSourceObject->GetShaftRadius());
  internalArrow->SetShaftResolution(this->ArrowSourceObject->GetShaftResolution());
  internalArrow->SetInvert(this->ArrowSourceObject->GetInvert());
  internalArrow->Update();
  // and get useful information from it
  vtkPolyData* arrow = internalArrow->GetOutput();
  vtkPoints* arrowpoints = arrow->GetPoints();
  vtkIdType numArrowPoints = arrowpoints->GetNumberOfPoints();
    internalArrow->SetShaftRadius(Ashaftradius * sradius * this->ShaftRadiusFactor);
    internalArrow->SetTipRadius(Atipradius * tradius * this->TipRadiusFactor);
    internalArrow->Update();
  // pointers may have changed, so refresh them here before copying
  //指针可能已更改,所以请在复制之前在此处刷新它们
    arrow = internalArrow->GetOutput();
    arrowpoints = arrow->GetPoints();
 // 将箭头点变换为正确的图示符位置/方向
    trans->TransformPoints(arrowpoints, newPoints);

代码段2_3:参数arrowpoints的完整代码

1.1.1 SetShaftRadius

代码:

internalArrow->SetShaftRadius(Ashaftradius * sradius * this->ShaftRadiusFactor);

包含三个参数:Ashaftradius ,sradius , this->ShaftRadiusFactor。
Ashaftradius

double Ashaftradius = this->ArrowSourceObject->GetShaftRadius();

shaftradius:轴半径,默认值为0.03。

sradius

 double sradius = 1.0;
 vtkDataArray* shaftradiusdata =
    this->ShaftRadiusArray ? minput->GetPointData()->GetArray(this->ShaftRadiusArray) : nullptr;
 if (shaftradiusdata && shaftradiusdata->GetNumberOfComponents() == 3)
  {
    shaftradiusMagnitude = true;
  }
   if (shaftradiusdata)
    {
      if (!shaftradiusMagnitude)
        sradius = shaftradiusdata->GetTuple1(i);
      else
        sradius = vtkMath::Norm(shaftradiusdata->GetTuple3(i));
    }

paraview界面并没有看到shaftradiusAarry的设置,因此sradius的值应当为1.0。
vtkMath::Norm代码:

 /**
   * Compute the norm of 3-vector (double version).
   */
  static double Norm(const double v[3])
  {
    return std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
  }

this->ShaftRadiusFactor

this->ShaftRadiusFactor = 1.0;

1.1.2 SetTipRadius

代码:

internalArrow->SetTipRadius(Atipradius * tradius * this->TipRadiusFactor);

中含有三个参数:Atipradius ,tradius , this->TipRadiusFactor。
Atipradius

 double Atipradius = this->ArrowSourceObject->GetTipRadius();

tipradius:箭头半径,默认值为0.1。

tradius

 double tradius = 1.0;
  vtkDataArray* tipradiusdata =
    this->TipRadiusArray ? minput->GetPointData()->GetArray(this->TipRadiusArray) : nullptr;
  if (tipradiusdata && tipradiusdata->GetNumberOfComponents() == 3)
  {
    tipradiusMagnitude = true;
  }
  if (tipradiusdata)
    {
      if (!tipradiusMagnitude)
        tradius = tipradiusdata->GetTuple1(i);
      else
        tradius = vtkMath::Norm(tipradiusdata->GetTuple3(i));
    }
 

this->TipRadiusFactor

this->TipRadiusFactor = 1.0;

1.1.3 internalArrow->update()

参考vtkArrowSource Class Reference中,vtkArrowSource类继承于vtkPolyDataAlgorithm,vtkPolyDataAlgorithm类继承于vtkAlgorithm类,如下图所示:
在这里插入图片描述
因为类vtkArrowSource和类vtkPolyDataAlgorithm都没有update方法,所以此处调用vtkAlgorithm类的update方法。

void vtkAlgorithm::Update()
{
  int port = -1;
  if (this->GetNumberOfOutputPorts())
  {
    port = 0;
  }
  this->Update(port);
}

1.this->GetNumberOfOutputPorts():

int vtkAlgorithm::GetNumberOfOutputPorts()
{
  return this->OutputPortInformation->GetNumberOfInformationObjects();
}
  ///@{
  /**
   * Get/Set the number of information objects in the vector.  Setting
   * the number to larger than the current number will create empty
   * vtkInformation instances.  Setting the number to smaller than the
   * current number will remove entries from higher indices.
   */
  int GetNumberOfInformationObjects() { return this->NumberOfInformationObjects; }
  1. this->Update(port);
void vtkAlgorithm::Update(int port)
{
  this->GetExecutive()->Update(port);
}
vtkExecutive* vtkAlgorithm::GetExecutive()
{
  // Create the default executive if we do not have one already.
  if (!this->HasExecutive())
  {
    vtkExecutive* e = this->CreateDefaultExecutive();
    this->SetExecutive(e);
    e->Delete();
  }
  return this->Executive;
}

vtkAlgorithm::CreateDefaultExecutive()实现代码:

vtkExecutive* vtkAlgorithm::CreateDefaultExecutive()
{
  if (vtkAlgorithm::DefaultExecutivePrototype)
  {
    return vtkAlgorithm::DefaultExecutivePrototype->NewInstance();
  }
  return vtkCompositeDataPipeline::New();
}

在这里插入图片描述

vtkArrowSource类的协作图
从vtkArrowSource类协作图可以看出,vtkAlgorithm类的DefaultExecutivePrototype变量定义为:

static vtkExecutive* DefaultExecutivePrototype;

因此,vtkAlgorithm::Update(int port)可能调用vtkExecutive::Update(int)或者vtkStreamingDemandDrivenPipeline::Update(int port)。
其中vtkExecutive::Update(int)声明与实现代码如下:

virtual vtkTypeBool Update(int port);
vtkTypeBool vtkExecutive::Update(int)
{
  vtkErrorMacro("This class does not implement Update.");
  return 0;
}

vtkExecutive::Update(int)是一个虚函数,所以更大的可能是调用vtkCompositeDataPipeline类的Update(int)方法。

vtkCompositeDataPipeline类
vtkCompositeDataPipeline是一个支持复合数据集处理的执行程序。它支持知道复合数据集的算法和不知道复合数据集的算法。类型检查在运行时执行。不支持复合数据集的算法必须支持复合数据集中包含的所有数据集类型。管道执行可总结如下:

  • REQUEST_INFORMATION(请求_信息):制作人必须在此过程中提供有关复合数据集内容的信息。可以产生多个块的源(请注意,一个块不同于一个块;每个块由0个或多个块组成)应设置can_HANDLE_piece_REQUEST。

  • REQUEST_UPDATAE_EXTENT(请求_更新_范围):此过程与VTKStreamingDemanAddressPipeline中实现的过程相同

  • REQUEST_DATA(请求_数据):这是算法执行的地方。如果VTKCompositedTapipeline被分配给一个简单的过滤器,它将在循环中调用VTKStreamingDemandAddressInPipeline过程,每次传递不同的块,并将结果收集到一个复合数据集中。

vtkCompositeDataPipeline类继承于vtkStreamingDemandDrivenPipeline类,调用vtkCompositeDataPipeline类实例的update(int port)方法,本质上是调用vtkStreamingDemandDrivenPipeline::Update(int port)。

vtkStreamingDemandDrivenPipeline::Update(int port)代码说明见Paraview源码解析4:vtkStreamingDemandDrivenPipeline类中的1.1节。

1.1.4 vtkPolyData* arrow = internalArrow->GetOutput()

internalArrow为vtkArrowSource类实例
vtkArrowSource类是vtkPolyDataAlgorithm类的子类
所以,internalArrow->GetOutput()调用其父类的GetOutput()方法,即:
vtkPolyDataAlgorithm::GetOutput()。

vtkPolyData* vtkPolyDataAlgorithm::GetOutput()
{
  return this->GetOutput(0);
}
vtkPolyData* vtkPolyDataAlgorithm::GetOutput(int port)
{
  return vtkPolyData::SafeDownCast(this->GetOutputDataObject(port));
}

上面代码段中的this是vtkPolyDataAlgorithm的实例指针,因为vtkPolyDataAlgorithm类继承于vtkAlgorithm类,所以this->GetOutputDataObject()调用其父类的GetOutputDataObject()方法,即vtkAlgorithm::GetOutputDataObject()。

vtkDataObject* vtkAlgorithm::GetOutputDataObject(int port)
{
  return this->GetExecutive()->GetOutputData(port);
}

vtkExecutive::GetOutputData(int port)

vtkDataObject* vtkExecutive::GetOutputData(int port)
{
  if (!this->OutputPortIndexInRange(port, "get data for"))
  {
    return nullptr;
  }

  vtkInformation* info = this->GetOutputInformation(port);
  if (!info)
  {
    return nullptr;
  }

  // for backward compatibility we bring Outputs up to date if they do not
  // already exist
  if (!this->InAlgorithm && !info->Has(vtkDataObject::DATA_OBJECT()))
  {
    // Bring the data object up to date only if it isn't already there
    this->UpdateDataObject();
  }

  // Return the data object.
  return info->Get(vtkDataObject::DATA_OBJECT());
}

this->UpdateDataObject()

int vtkDemandDrivenPipeline::UpdateDataObject()
{
  // The algorithm should not invoke anything on the executive.
  if (!this->CheckAlgorithm("UpdateDataObject", nullptr))
  {
    return 0;
  }

  // Update the pipeline mtime first.
  if (!this->UpdatePipelineMTime())
  {
    return 0;
  }

  // Setup the request for data object creation.
  if (!this->DataObjectRequest)
  {
    this->DataObjectRequest = vtkInformation::New();
    this->DataObjectRequest->Set(REQUEST_DATA_OBJECT());
    // The request is forwarded upstream through the pipeline.
    this->DataObjectRequest->Set(vtkExecutive::FORWARD_DIRECTION(), vtkExecutive::RequestUpstream);
    // Algorithms process this request after it is forwarded.
    this->DataObjectRequest->Set(vtkExecutive::ALGORITHM_AFTER_FORWARD(), 1);
  }

  // Send the request.
  return this->ProcessRequest(
    this->DataObjectRequest, this->GetInputInformation(), this->GetOutputInformation());
}

2.1关于参数newPoints的完整代码:

// we know the output will require NumPoints in Arrow * NumPoints in MaskPoints
  // so we can pre-allocate the output space.
  vtkSmartPointer<vtkPoints> newPoints = vtkSmartPointer<vtkPoints>::New();
  newPoints->Allocate(numArrowPoints * numMaskedPoints);
  // transform the arrow point to correct glyph position/orientation
    trans->TransformPoints(arrowpoints, newPoints);
     output->SetPoints(newPoints);

代码段2_4:参数newPoints的完整代码

2.1.1 numArrowPoints

其中

newPoints->Allocate(numArrowPoints * numMaskedPoints);

中的numArrowPoints就是vtkPolyData中的元素的个数。具体看代码:

// and get useful information from it
  vtkPolyData* arrow = internalArrow->GetOutput();
  vtkPoints* arrowpoints = arrow->GetPoints();
  vtkIdType numArrowPoints = arrowpoints->GetNumberOfPoints();

上面代码段中internalArrow定义见:代码段2_3:参数arrowpoints的完整代码。

2.1.2numMaskedPoints参数

// How many points will we be glyphing (in this process)
  vtkPoints* maskedpoints = this->MaskPoints->GetOutput()->GetPoints();
  vtkIdType numMaskedPoints = maskedpoints->GetNumberOfPoints();

MaskPoints定义如下:

  // Method used to pick points
  enum DistributionType
  {
    RANDOMIZED_ID_STRIDES,
    RANDOM_SAMPLING,
    SPATIALLY_STRATIFIED,
    UNIFORM_SPATIAL_BOUNDS,
    UNIFORM_SPATIAL_SURFACE,
    UNIFORM_SPATIAL_VOLUME
  };

2.2 TransformPoints()源代码

//------------------------------------------------------------------------------
void vtkLinearTransform::TransformPoints(vtkPoints* inPts, vtkPoints* outPts)
{
  vtkIdType n = inPts->GetNumberOfPoints();
  vtkIdType m = outPts->GetNumberOfPoints();
  double(*matrix)[4] = this->Matrix->Element;

  this->Update();

  // operate directly on the memory to avoid GetPoint()/SetPoint() calls.
  vtkDataArray* inArray = inPts->GetData();
  vtkDataArray* outArray = outPts->GetData();
  int inType = inArray->GetDataType();
  int outType = outArray->GetDataType();
  void* inPtr = inArray->GetVoidPointer(0);
  void* outPtr = outArray->WriteVoidPointer(3 * m, 3 * n);

  if (inType == VTK_FLOAT && outType == VTK_FLOAT)
  {
    vtkLinearTransformPoints(matrix, static_cast<float*>(inPtr), static_cast<float*>(outPtr), n);
  }
  else if (inType == VTK_FLOAT && outType == VTK_DOUBLE)
  {
    vtkLinearTransformPoints(matrix, static_cast<float*>(inPtr), static_cast<double*>(outPtr), n);
  }
  else if (inType == VTK_DOUBLE && outType == VTK_FLOAT)
  {
    vtkLinearTransformPoints(matrix, static_cast<double*>(inPtr), static_cast<float*>(outPtr), n);
  }
  else if (inType == VTK_DOUBLE && outType == VTK_DOUBLE)
  {
    vtkLinearTransformPoints(matrix, static_cast<double*>(inPtr), static_cast<double*>(outPtr), n);
  }
  else
  {
    double point[3];

    for (vtkIdType i = 0; i < n; i++)
    {
      inPts->GetPoint(i, point);

      vtkLinearTransformPoint(matrix, point, point);

      outPts->SetPoint(m + i, point);
    }
  }
}

2.2.1 vtkLinearTransformPoint()

//------------------------------------------------------------------------------
template <class T1, class T2, class T3>
inline void vtkLinearTransformPoint(T1 matrix[4][4], T2 in[3], T3 out[3])
{
  T3 x = static_cast<T3>(
    matrix[0][0] * in[0] + matrix[0][1] * in[1] + matrix[0][2] * in[2] + matrix[0][3]);
  T3 y = static_cast<T3>(
    matrix[1][0] * in[0] + matrix[1][1] * in[1] + matrix[1][2] * in[2] + matrix[1][3]);
  T3 z = static_cast<T3>(
    matrix[2][0] * in[0] + matrix[2][1] * in[1] + matrix[2][2] * in[2] + matrix[2][3]);

  out[0] = x;
  out[1] = y;
  out[2] = z;
}

vtkSMProxyDefinitionManager是一个远程对象,表示所有进程上的vtkSIProxyDefinitionManager实例。ParaView客户端应该在此类上使用API来添加/更新xml定义,以确保XML在所有进程上都得到了正确的处理/更新。

vtkSIProxyDefinitionManager是一个管理XML代理定义的类。

*它维护vtkpvxmlement的映射(由XML解析器填充),从中可以提取提示、文档、属性和域定义。

*此类触发以下事件:

*\\li\\c vtkSIProxyDefinitionManager::ProxyDefinitionsUpdated-在任何定义更新时触发。如果一组定义正在更新(即新定义已注册、未注册或修改)

*然后,在所有事件都更新后,将触发此事件。

*\\li\\c vtkSIProxyDefinitionManager::CompoundProxyDefinitionsUpdated-在更新自定义代理定义时激发。与ProxyDefinitionsUpdated类似,这是在集体更新后触发的(如果适用)。注意:每当激发CompoundProxyDefinitionsUpdated时,也会激发ProxyDefinitionsUpdated。

*\\li\\c vtkCommand::RegisterEvent-在注册新代理定义或修改旧代理定义(通过扩展)时激发。这适用于常规代理和自定义代理定义。

*\\li\\c vtkCommand::UnRegisterEvent-删除代理定义时激发。由于此类仅支持删除自定义代理,因此只有在删除自定义代理时才会触发此事件。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片