VTK绘制箭头——支持设置起点、方向和长度
目前网上关于VTK绘制箭头的案例中很多都是用vtkArrowSource来绘制,实际上无法设置箭头的具体坐标起点、方向,中看不中用。如果想创建一个自由设置起点坐标和方向的箭头,在VTK上需要比较麻烦的操作,具体如下:
方法
- 需要自行创建一个仅包含一个顶点的vtkPolyData,要用到vtkVertex,不能用vtkSphereSource。
- 需要给自建的vtkPolyData指定顶点法向量(即向量的朝向),与指定向量长度(利用标量顶点标量实现)。
- 使用vtkArrowSource将vtkPolyData的法向量显现出来。
代码
用两个函数实现:先执行CreateSingleVectorArrowData函数,然后将结果作为的输入执行函数
- CreateSingleVectorArrowData函数:创建箭头的数据
- 输入:origin起点坐标,target终点朝向坐标,length箭头长度
- 输出:vtkPolyData箭头几何数据
//@param origin和target都是三元素的一维数组double[3],length决定可视化向量的长度
vtkPolyData* CreateSingleVectorArrowData(double* origin, double* target, double length)
{
vtkMath* math;
math->Subtract(target, origin, target); //计算向量的朝向 target=target-origin
vtkPoints* points = vtkPoints::New(); //记录起点坐标
points->InsertNextPoint(origin);
vtkVertex *vertex = vtkVertex::New(); //建立起点的拓扑(不建立拓扑的话是不行的)
vertex->GetPointIds()->SetNumberOfIds(points->GetNumberOfPoints());
for (int i = 0; i < points->GetNumberOfPoints(); i++) {
vertex->GetPointIds()->SetId(i, i); //setId(拓扑的id, 顶点的id)
}
vtkDoubleArray* normals = vtkDoubleArray::New(); //创建法向量属性,存入向量的朝向target
normals->SetNumberOfComponents(3);
normals->InsertNextTuple(target);
vtkDoubleArray* scalars = vtkDoubleArray::New(); //创建标量属性,存入向量的长度length
scalars->SetNumberOfComponents(1);
scalars->SetName("scalars");
scalars->InsertNextTuple1(length);
vtkSmartPointer<vtkCellArray> vertices =
vtkSmartPointer<vtkCellArray>::New();
vertices->InsertNextCell(vertex); //将建立的拓扑用vtkCellArray封装,用于赋予vtkPolyData
vtkPolyData *polydata = vtkPolyData::New(); //创建几何实体
polydata->SetPoints(points); //赋予起点
polydata->SetVerts(vertices); //赋予拓扑
polydata->GetPointData()->SetNormals(normals); //赋予向量朝向
polydata->GetPointData()->SetScalars(scalars); //赋予向量长度
return polydata;
}
- GenerateNormalsArrow函数:为箭头几何数据创建具体的箭头几何实体
- 输入:polyData来自CreateSingleVectorArrowData函数输出的箭头数据
- 输出:vtkPolyData能够用于显示的箭头几何实体
vtkPolyData* GenerateNormalsArrow(vtkPolyData* polyData)
{
vtkArrowSource *arrow = vtkArrowSource::New();
arrow->Update();
vtkGlyph3D* glyph = vtkGlyph3D::New();
glyph->SetInputData(polyData);
glyph->SetSourceData(arrow->GetOutput());
glyph->SetScaleFactor(0.1);
glyph->SetVectorModeToUseNormal();
glyph->Update();
return glyph->GetOutput();
}
将GenerateNormalsArrow输出的vtkPolyData结果构建成vtkActor便能显示箭头。
结果
-
起点(0, 0, 0),朝向(1, 1, 1),长度20:
-
加入坐标系: