在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出来解决了。
本文来源: