【VTK】vtk actor空间变换后的点映射与向量映射

网友投稿 824 2022-08-27

【VTK】vtk actor空间变换后的点映射与向量映射

【VTK】vtk actor空间变换后的点映射与向量映射

在三维空间中,人们通常需要对平面等形体进行旋转,拖拽等操作。比如下面的过程:

将平面绕平面的Y轴旋转一定角度将其绕平面自身的X轴旋转一定角度将平面向向量方向(1, 2, 3)移动一段距离。

这样复杂的操作通常需要我们使用vtkActor提供的操作函数:

void vtkProp3D::RotateY (double angle)void vtkProp3D::RotateX (double angle)void vtkProp3D::AddPosition (double deltaX,double deltaY,double deltaZ)

控制运动的接口我们找到了,但是传入的参数还需要认真思考如何计算。 通常,我们是在事件中计算位置移动向量,或者旋转角度,这里就需要用到vtkRenderWindowInteractor提供的GetEventPosition和GetLastEventPosition函数。他们帮助我们计算Display坐标系的光标坐标值。 平移向量是向量 GetEventPosition => GetLastEventPosition 在平面法向量上的投影。 旋转角度则是 planeOrigin => GetLastEventPosition 与 planeOrigin => GetEventPosition的向量夹角。 如此可知,每一次运动,都需要知道平面中心点或者平面的法向量。同时,在一次运动结束之后,平面中心点或者平面法向量都应该更新。 在文章 ​​​【VTK】平面的平移和旋转​​​ 的末尾片段我有介绍到如何求解actor在线性变化后的平面原点和平面法向量。下面指明一下注意事项: 由actor matrix构造出来的vtkTransform对象不要在求解origin之后又立马求解normal。

#include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;int main(){ setbuf( stdout, NULL ); vtkSmartPointer plane = vtkSmartPointer::New(); vtkSmartPointer mapper = vtkSmartPointer::New(); mapper->SetInputConnection( plane->GetOutputPort() ); vtkSmartPointer actor = vtkSmartPointer::New(); actor->SetMapper( mapper ); double oldNormal[3] = { 0, 0, -1 }; double oldOrigin[3] = { 0, 0, 0 }; actor->RotateY( 45 );// actor->AddPosition( 1, -1, 1 ); vtkSmartPointer transform = vtkSmartPointer::New(); transform->SetMatrix( actor->GetMatrix() ); double *newNormal = transform->TransformDoubleVector( oldNormal ); vtkSmartPointer transform2 = vtkSmartPointer::New(); transform2->SetMatrix( actor->GetMatrix() ); double *newOrigin = transform2->TransformDoublePoint( oldOrigin ); printf( "newNormal: %lf, %lf, %lf\n", newNormal[0], newNormal[1], newNormal[2] ); printf( "newOrigin: %lf, %lf, %lf\n", newOrigin[0], newOrigin[1], newOrigin[2] );/*newOrigin: 0.000000, 0.000000, 0.000000newNormal: -0.707107, 0.000000, -0.707107 (-cos45)*/ vtkSmartPointer renderer = vtkSmartPointer::New(); renderer->AddActor(actor); renderer->SetBackground( 0, 0, 0 ); vtkSmartPointer renderWindow = vtkSmartPointer::New(); renderWindow->AddRenderer( renderer ); vtkSmartPointer renderWindowInteractor = vtkSmartPointer::New(); renderWindowInteractor->SetRenderWindow( renderWindow ); renderWindowInteractor->GetLastEventPosition(); renderer->ResetCamera(); renderWindow->Render(); renderWindowInteractor->Start(); return 0;}

比如上面例子中的​​double *newOrigin = transform2->TransformDoublePoint( oldOrigin );​​​ 如果我是继续使用了transform,那么origin与normal的数值就是一样的了。先计算谁谁就错了。 错误结果:

newNormal: 0.000000, 0.000000, 0.000000newOrigin: 0.000000, 0.000000, 0.000000

这是为什么呢? 看看两个函数的实现:

double *TransformDoublePoint(double x, double y, double z) { this->InternalDoublePoint[0] = x; this->InternalDoublePoint[1] = y; this->InternalDoublePoint[2] = z; this->TransformPoint(this->InternalDoublePoint,this->InternalDoublePoint); return this->InternalDoublePoint; };//------------------------------------------------------------------------double *TransformDoubleVector(double x, double y, double z) { this->InternalDoublePoint[0] = x; this->InternalDoublePoint[1] = y; this->InternalDoublePoint[2] = z; this->TransformVector(this->InternalDoublePoint,this->InternalDoublePoint); return this->InternalDoublePoint; };

vtkLinearTransform将计算结果全都存储在InternalDoublePoint中了,所以例子中的newOrigin和newNormal最终指向同一个double数组,这个数组存储着最后一次计算的结果,即newOrigin。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:语言们都能干什么(语言能为我们做什么)
下一篇:趣文:编程语言伪简史(伪代码是编程语言吗)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~