在vtk中显示标签有好几种方法,前面了解了vtkLabeledDataMapper,现在来了解下vtkLabelPlacementMapper。

 

在使用vtkLabelPlacementMapper之前,需要先使用vtkPointSetToLabelHierarchy来组织标签数据。首先来看看如何构造标签数据。

 

首先定义一个vtkStringArray来存放标签名称,同时给这个数组指定名称为labels,在后面需要使用。

 

Java代码  
  1. vtkStringArray labels = new vtkStringArray();  
  2. labels.SetName("labels");  

 

定义点集合,以及cellarray,然后随机生成100个点,以这些点的id值作为标签的值,最后构造一个vtkPolyData,其cell类型为vertex,即显示100个顶点。

Java代码  
  1. vtkPoints points = new vtkPoints();  
  2. vtkCellArray verts = new vtkCellArray();  
  3. for(int i=0;i<100;i++){  
  4.       points.InsertNextPoint(math.Random(1,3), math.Random(1,3), math.Random(1,3));  
  5.       labels.InsertNextValue(String.valueOf(i));  
  6.       verts.InsertNextCell(1);  
  7.       verts.InsertCellPoint(i);  
  8. }  
  9.           
  10. vtkPolyData polyData = new vtkPolyData();  
  11. polyData.SetPoints(points);  
  12. polyData.SetVerts(verts);  
  13. polyData.GetPointData().AddArray(labels);  

然后定义标签文本的属性,即设置字体的大小,字体颜色以及使用何种字体等信息。

Java代码  
  1. vtkTextProperty textProp = new vtkTextProperty();  
  2.         textProp.SetFontSize(12);  
  3.         textProp.SetColor(1.01.00.5);  
  4.         textProp.SetFontFamilyToArial();  
  5. //        textProp.SetFontFamilyToCourier();  

 

接着定义vtkPointSetToLabelHierarchy,设置输入为前面的polyData,指定作为标签的数组名称为labels,以及标签的个数,最后设置标签文本的属性: 

Java代码  
  1. vtkPointSetToLabelHierarchy hie = new vtkPointSetToLabelHierarchy();  
  2.         hie.SetInput(polyData);  
  3.         hie.SetMaximumDepth(15);  
  4.         hie.SetLabelArrayName("labels");  
  5.         hie.SetTargetLabelCount(100);  
  6.         hie.SetTextProperty(textProp);  

  最后使用vtkLabelPlacementMapper来映射vtkPointSetToLabelHierarchy,vtkFreeTypeLabelRenderStrategy

是具体的标签渲染策略。下面的一些方法是用来调整最终标签显示的样式, .SetShapeToNone();设置不显示边框,labelMapper.SetShapeToRect();设置边框为矩形,SetShapeToRoundedRect设置边框为圆角矩形,这些方法在一定程度上会影响标签的渲染速度,因为需要做相应的计算来调整边框的位置等信息。UseUnicodeStringsOff表示不使用Unicode字符串。

 

 

Java代码  
  1. vtkLabelPlacementMapper labelMapper = new vtkLabelPlacementMapper();  
  2.         labelMapper.SetInputConnection(hie.GetOutputPort());  
  3.         vtkFreeTypeLabelRenderStrategy  strategy = new vtkFreeTypeLabelRenderStrategy();  
  4.         labelMapper.SetRenderStrategy(strategy);  
  5.         labelMapper.UseDepthBufferOn();  
  6.         labelMapper.SetShapeToNone();  
  7.         labelMapper.SetStyleToOutline();  
  8.         labelMapper.UseUnicodeStringsOff();  
  9.           
  10.         labelActor2d = new vtkActor2D();  
  11.         labelActor2d.SetMapper(labelMapper);  

 

最终效果如图:

相比于vtkLabeledDataMapper,vtkLabelPlacementMapper速度要快一些,但是当数据量上千以后,速度也会变慢,但是还可以接受。另外,vtkLabelPlacementMapper在显示标签时,标签不会相互覆盖,如果后面的标签被挡住了,会自动隐藏,这样屏幕就不会因为标签太多导致拥挤。

 

这两种标签都是2d 的,即标签始终面向屏幕,而且可以设置字体,缺点就是当显示大量标签时,速度慢,影响用户使用。

在工作的过程中,也尝试了其它的办法,比如使用vtkVectorText结合vtkFollower来显示数字和字母。vtkVectorText是采用三角面的方式来定义一个数字或者字母,一个数字零就包含了很多三角形。vtkFollower实际上就是一个vtkActor,只是它提供了一些方法可使让自身始终朝向相机,因此,可以使用这两者来显示标签,同时保持标签使用朝向屏幕。但是,因为这里的一个标签就是一个actor,当数量达到一定程度时,性能会下降,只是相比前面的两种要快点。

另外一个缺陷是vtkVectorText只定义了常用的ascii字符,即数字以及字母等字符,所以不支持汉字的显示,因此,如何快速的显示大量标签还是没有找到好的解决办法,看来只有等到vtk 6.0出来解决了。

 

本文来源: