可将其过程描述为,平面a的法向量为na,目标平面的法向量为nb,当将平面a的法向量na被旋转至与nb同向时,停止旋转。
我自己觉得这个问题与StackOverflow这个问题相同https://stackoverflow.com/questions/9423621/3d-rotations-of-a-plane
期望的效果,圆环应该出现在每个线段拐点处,圆环的平面垂直于折线,即折线垂直穿过每个圆环平面的中心(圆环平面应与图中紫色示意线相同)。
我自己采用了以下2种方案:
1. 按照StackOverflow上的答案,构造了答案中提到的矩阵,但是结果不对。结果如下图所示。
具体代码
{
//目标法向量方向
vtkVector3d vec_normal(x - x_before, y - y_before, z - z_before);
vec_normal = vec_normal.Normalized();
//z_direction 为原始法向量方向
vtkVector3d cross_direction = vec_normal.Cross(z_direction).Normalized();
double theta = vtkMath::AngleBetweenVectors(vec_normal.GetData(), z_direction.GetData());
double c = theta;
double s = std::sqrt(1 - theta * theta);
double C = 1 - theta;
vtkSmartPointer<vtkMatrix4x4> m = vtkSmartPointer<vtkMatrix4x4>::New();
double ma[4][4] = { {cross_direction.GetX()*cross_direction.GetX()*C + c,cross_direction.GetX()*cross_direction.GetY()*C - cross_direction.GetZ()*s,cross_direction.GetX()*cross_direction.GetZ()*C + cross_direction.GetY()*s,0}
,{cross_direction.GetY()*cross_direction.GetX()*C + cross_direction.GetZ()*s,cross_direction.GetY()*cross_direction.GetY()*C + c,cross_direction.GetY()*cross_direction.GetZ()*C - cross_direction.GetX()*s,0}
,{cross_direction.GetZ()*cross_direction.GetX()*C - cross_direction.GetY()*s,cross_direction.GetZ()*cross_direction.GetY()*C + cross_direction.GetX()*s,cross_direction.GetZ()*cross_direction.GetZ()*C + c,0}
,{0,0,0,1} };
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
//void SetElement(int i, int j, double value),i行、j列的值为value
m->SetElement(i, j, ma[i][j]);
}
}
vtkNew<vtkTransform> trans;
trans->Translate(x, y, z);
trans->SetMatrix(m);
//trans->RotateWXYZ(vtkMath::DegreesFromRadians(theta), cross_direction[0], cross_direction[1], cross_direction[2]);
//trans->RotateWXYZ(theta, cross_direction[0], cross_direction[1], cross_direction[2]);
vtkNew<vtkTransformPolyDataFilter> pTransformPolyDataFilter;
pTransformPolyDataFilter->SetInputData(circle);
pTransformPolyDataFilter->SetTransform(trans);
pTransformPolyDataFilter->Update();
circle = pTransformPolyDataFilter->GetOutput();
}
方法二,利用vtk中的rotatewxyz方法做旋转。自认为思路与stackoverflow一致,都是利用构造新的旋转轴来进行旋转。因为我也无法确认StackOverflow中给出的矩阵的原理是什么。
vtkNew<vtkTransform> trans;
trans->Translate(x, y, z);
trans->RotateWXYZ(vtkMath::DegreesFromRadians(theta), cross_direction[0], cross_direction[1], cross_direction[2]);
效果如图所示,位置对了,但是圆环的方向与折线方向相同,而不是垂直。