Paraview源码解析7:vtkTransform类

1.类图结构

vtkTransform Class Reference
在这里插入图片描述
在这里插入图片描述

2.代码实现

2.1 Identity

void vtkTransform::Identity()
{
  this->Concatenation->Identity();

  // support for the legacy hack in InternalUpdate
  if (this->Matrix->GetMTime() > this->MatrixUpdateMTime)
  {
    this->Matrix->Identity();
  }

  this->Modified();
}

2.1.1 vtkTransformConcatenation::Identity()

void vtkTransformConcatenation::Identity()
{
  // forget the Pre- and PostMatrix
  this->PreMatrix = nullptr;
  this->PostMatrix = nullptr;
  this->PreMatrixTransform = nullptr;
  this->PostMatrixTransform = nullptr;

  // delete all the transforms
  if (this->NumberOfTransforms > 0)
  {
    for (int i = 0; i < this->NumberOfTransforms; i++)
    {
      vtkTransformPair* tuple = &this->TransformList[i];
      if (tuple->ForwardTransform)
      {
        tuple->ForwardTransform->Delete();
        tuple->ForwardTransform = nullptr;
      }
      if (tuple->InverseTransform)
      {
        tuple->InverseTransform->Delete();
        tuple->InverseTransform = nullptr;
      }
    }
  }
  this->NumberOfTransforms = 0;
  this->NumberOfPreTransforms = 0;
}

2.1.2 this->Matrix->Identity()

vtkMatrix4x4::Identity()

 /**
   * Set equal to Identity matrix
   */
  void Identity()
  {
    vtkMatrix4x4::Identity(*this->Element);
    this->Modified();
  }

2.1.3 this->Modified()

void vtkObject::Modified()
{
  this->MTime.Modified();
  this->InvokeEvent(vtkCommand::ModifiedEvent, nullptr);
}

2.2 Translate

  void Translate(double x, double y, double z) { this->Concatenation->Translate(x, y, z); }

2.2.1 vtkTransformConcatenation::Translate()

void vtkTransformConcatenation::Translate(double x, double y, double z)
{
  if (x == 0.0 && y == 0.0 && z == 0.0)
  {
    return;
  }

  double matrix[4][4];
  vtkMatrix4x4::Identity(*matrix);

  matrix[0][3] = x;
  matrix[1][3] = y;
  matrix[2][3] = z;

  this->Concatenate(*matrix);
}

2.2.2 vtkTransformConcatenation::Concatenate(const double elements[16])

void vtkTransformConcatenation::Concatenate(const double elements[16])
{
  // concatenate the matrix with either the Pre- or PostMatrix
  if (this->PreMultiplyFlag)
  {
    if (this->PreMatrix == nullptr)
    {
      // add the matrix to the concatenation
      vtkSimpleTransform* mtrans = vtkSimpleTransform::New();
      this->Concatenate(mtrans);
      mtrans->Delete();
      this->PreMatrixTransform = mtrans;
      this->PreMatrix = mtrans->GetMatrix();
    }
    vtkMatrix4x4::Multiply4x4(*this->PreMatrix->Element, elements, *this->PreMatrix->Element);
    this->PreMatrix->Modified();
    this->PreMatrixTransform->Modified();
  }
  else
  {
    if (this->PostMatrix == nullptr)
    {
      // add the matrix to the concatenation
      vtkSimpleTransform* mtrans = vtkSimpleTransform::New();
      this->Concatenate(mtrans);
      mtrans->Delete();
      this->PostMatrixTransform = mtrans;
      this->PostMatrix = mtrans->GetMatrix();
    }
    vtkMatrix4x4::Multiply4x4(elements, *this->PostMatrix->Element, *this->PostMatrix->Element);
    this->PostMatrix->Modified();
    this->PostMatrixTransform->Modified();
  }
}

2.2.3 vtkMatrix4x4::Multiply4x4()

inline void vtkMatrix4x4::Multiply4x4(const double a[16], const double b[16], double c[16])
{
  double tmp[16];

  for (int i = 0; i < 16; i += 4)
  {
    for (int j = 0; j < 4; j++)
    {
      tmp[i + j] =
        a[i + 0] * b[j + 0] + a[i + 1] * b[j + 4] + a[i + 2] * b[j + 8] + a[i + 3] * b[j + 12];
    }
  }

  for (int k = 0; k < 16; k++)
  {
    c[k] = tmp[k];
  }
}

2.3 RotateWXYZ

创建一个旋转矩阵,并根据预乘或后乘语义将其与当前变换连接起来。

  • 角度以度为单位,(x,y,z)指定旋转将围绕的轴。
  /**
   * Create a rotation matrix and concatenate it with the current
   * transformation according to PreMultiply or PostMultiply semantics.
   * The angle is in degrees, and (x,y,z) specifies the axis that the
   * rotation will be performed around.
   */
  void RotateWXYZ(double angle, double x, double y, double z)
  {
    this->Concatenation->Rotate(angle, x, y, z);
  }

2.3.1 vtkTransformConcatenation::Rotate()

void vtkTransformConcatenation::Rotate(double angle, double x, double y, double z)
{
if (angle == 0.0 || (x == 0.0 && y == 0.0 && z == 0.0))
{
  return;
}

// convert to radians
angle = vtkMath::RadiansFromDegrees(angle);

// make a normalized quaternion
double w = cos(0.5 * angle);
double f = sin(0.5 * angle) / sqrt(x * x + y * y + z * z);
x *= f;
y *= f;
z *= f;

// convert the quaternion to a matrix
double matrix[4][4];
vtkMatrix4x4::Identity(*matrix);

double ww = w * w;
double wx = w * x;
double wy = w * y;
double wz = w * z;

double xx = x * x;
double yy = y * y;
double zz = z * z;

double xy = x * y;
double xz = x * z;
double yz = y * z;

double s = ww - xx - yy - zz;

matrix[0][0] = xx * 2 + s;
matrix[1][0] = (xy + wz) * 2;
matrix[2][0] = (xz - wy) * 2;

matrix[0][1] = (xy - wz) * 2;
matrix[1][1] = yy * 2 + s;
matrix[2][1] = (yz + wx) * 2;

matrix[0][2] = (xz + wy) * 2;
matrix[1][2] = (yz - wx) * 2;
matrix[2][2] = zz * 2 + s;

this->Concatenate(*matrix);
}

this->Concatenate(matrix) 代码见2.2.2 vtkTransformConcatenation::Concatenate(const double elements[16])。

2.3.2 vtkMatrix4x4::Identity(double elements[16])

void vtkMatrix4x4::Identity(double elements[16])
{
elements[0] = elements[5] = elements[10] = elements[15] = 1.0;
elements[1] = elements[2] = elements[3] = elements[4] = elements[6] = elements[7] = elements[8] =
  elements[9] = elements[11] = elements[12] = elements[13] = elements[14] = 0.0;
}

2.3.3 vtkMath::RadiansFromDegrees(double x)

inline double vtkMath::RadiansFromDegrees(double x)
{
return x * 0.017453292519943295;
}

2.4 Scale

 /**
   * Create a scale matrix (i.e. set the diagonal elements to x, y, z)
   * and concatenate it with the current transformation according to
   * PreMultiply or PostMultiply semantics.
   */
  void Scale(double x, double y, double z) { this->Concatenation->Scale(x, y, z); }

2.4.1 vtkTransformConcatenation::Scale

void vtkTransformConcatenation::Scale(double x, double y, double z)
{
  if (x == 1.0 && y == 1.0 && z == 1.0)
  {
    return;
  }

  double matrix[4][4];
  vtkMatrix4x4::Identity(*matrix);

  matrix[0][0] = x;
  matrix[1][1] = y;
  matrix[2][2] = z;

  this->Concatenate(*matrix);
}

this->Concatenate(matrix) 代码见2.2.2 vtkTransformConcatenation::Concatenate(const double elements[16])。

2.5 TransformPoints

vtkTransform : public vtkLinearTransform

TransformPoints是父类vtkLinearTransform的方法,所以调用vtkLinearTransform::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);
    }
  }
}
template <class T1, class T2, class T3>
inline void vtkLinearTransformPoints(T1 matrix[4][4], T2* in, T3* out, vtkIdType n)
{
  // Switch based on the number of points to transform: serial processing is
  // faster for a smaller number of transformations.
  if (n >= VTK_SMP_THRESHOLD)
  {
    vtkSMPTools::For(0, n, [&](vtkIdType ptId, vtkIdType endPtId) {
      T2* pin = in + 3 * ptId;
      T3* pout = out + 3 * ptId;
      for (; ptId < endPtId; ++ptId)
      {
        vtkLinearTransformPoint(matrix, pin, pout);
        pin += 3;
        pout += 3;
      }
    });
  }
  else
  {
    for (vtkIdType i = 0; i < n; i++)
    {
      vtkLinearTransformPoint(matrix, in, out);
      in += 3;
      out += 3;
    }
  }
}
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;
}

2.6 vtkTransformConcatenation与vtkTransform中矩阵如何关联起来的?

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

昵称

取消
昵称表情代码图片