在vtk中显示标签有好几种方法,前面了解了vtkLabeledDataMapper,现在来了解下vtkLabelPlacementMapper。
在使用vtkLabelPlacementMapper之前,需要先使用vtkPointSetToLabelHierarchy来组织标签数据。首先来看看如何构造标签数据。
首先定义一个vtkStringArray来存放标签名称,同时给这个数组指定名称为labels,在后面需要使用。
vtkStringArray labels = new vtkStringArray();
labels.SetName("labels");
定义点集合,以及cellarray,然后随机生成100个点,以这些点的id值作为标签的值,最后构造一个vtkPolyData,其cell类型为vertex,即显示100个顶点。
vtkPoints points = new vtkPoints();
vtkCellArray verts = new vtkCellArray();
for(int i=0;i<100;i++){
points.InsertNextPoint(math.Random(1,3), math.Random(1,3), math.Random(1,3));
labels.InsertNextValue(String.valueOf(i));
verts.InsertNextCell(1);
verts.InsertCellPoint(i);
}
vtkPolyData polyData = new vtkPolyData();
polyData.SetPoints(points);
polyData.SetVerts(verts);
polyData.GetPointData().AddArray(labels);
然后定义标签文本的属性,即设置字体的大小,字体颜色以及使用何种字体等信息。
vtkTextProperty textProp = new vtkTextProperty();
textProp.SetFontSize(12);
textProp.SetColor(1.0, 1.0, 0.5);
textProp.SetFontFamilyToArial();
// textProp.SetFontFamilyToCourier();
接着定义vtkPointSetToLabelHierarchy,设置输入为前面的polyData,指定作为标签的数组名称为labels,以及标签的个数,最后设置标签文本的属性:
vtkPointSetToLabelHierarchy hie = new vtkPointSetToLabelHierarchy();
hie.SetInput(polyData);
hie.SetMaximumDepth(15);
hie.SetLabelArrayName("labels");
hie.SetTargetLabelCount(100);
hie.SetTextProperty(textProp);
最后使用vtkLabelPlacementMapper来映射vtkPointSetToLabelHierarchy,vtkFreeTypeLabelRenderStrategy
是具体的标签渲染策略。下面的一些方法是用来调整最终标签显示的样式, .SetShapeToNone();设置不显示边框,labelMapper.SetShapeToRect();设置边框为矩形,SetShapeToRoundedRect设置边框为圆角矩形,这些方法在一定程度上会影响标签的渲染速度,因为需要做相应的计算来调整边框的位置等信息。UseUnicodeStringsOff表示不使用Unicode字符串。
vtkLabelPlacementMapper labelMapper = new vtkLabelPlacementMapper();
labelMapper.SetInputConnection(hie.GetOutputPort());
vtkFreeTypeLabelRenderStrategy strategy = new vtkFreeTypeLabelRenderStrategy();
labelMapper.SetRenderStrategy(strategy);
labelMapper.UseDepthBufferOn();
labelMapper.SetShapeToNone();
labelMapper.SetStyleToOutline();
labelMapper.UseUnicodeStringsOff();
labelActor2d = new vtkActor2D();
labelActor2d.SetMapper(labelMapper);
最终效果如图:
相比于vtkLabeledDataMapper,vtkLabelPlacementMapper速度要快一些,但是当数据量上千以后,速度也会变慢,但是还可以接受。另外,vtkLabelPlacementMapper在显示标签时,标签不会相互覆盖,如果后面的标签被挡住了,会自动隐藏,这样屏幕就不会因为标签太多导致拥挤。
这两种标签都是2d 的,即标签始终面向屏幕,而且可以设置字体,缺点就是当显示大量标签时,速度慢,影响用户使用。
在工作的过程中,也尝试了其它的办法,比如使用vtkVectorText结合vtkFollower来显示数字和字母。vtkVectorText是采用三角面的方式来定义一个数字或者字母,一个数字零就包含了很多三角形。vtkFollower实际上就是一个vtkActor,只是它提供了一些方法可使让自身始终朝向相机,因此,可以使用这两者来显示标签,同时保持标签使用朝向屏幕。但是,因为这里的一个标签就是一个actor,当数量达到一定程度时,性能会下降,只是相比前面的两种要快点。
另外一个缺陷是vtkVectorText只定义了常用的ascii字符,即数字以及字母等字符,所以不支持汉字的显示,因此,如何快速的显示大量标签还是没有找到好的解决办法,看来只有等到vtk 6.0出来解决了。