Search code examples
pythontextvtk

How to rotate a vtkVectorText to face a direction?


I would like to have a text at a certain position ([1,1,1] in the below example), which face the direction from the origin [0,0,0] to the position the text is [1,1,1]

I've tried to compute two rotation angles between xy and xz axis and applied them with the RotateWXYZ transformation but it doesn't work. The function GetAngleBetweenPoints compute the angle between three coordinates in this case

In addition I would like the text to be centered if possible.

So far I have this code :

from vtk import*
import numpy as np


def GetAngleBetweenPoints( endPt1, connectingPt, endPt2):
    x1 = endPt1[0] - connectingPt[0]
    y1 = endPt1[1] - connectingPt[1]
    x2 = endPt2[0] - connectingPt[0]
    y2 = endPt2[1] - connectingPt[1]
    angle = np.arctan2(y1, x1) - np.arctan2(y2, x2)
    angle = angle * 360 / (2 * np.pi)
    if (angle < 0) :
        angle += 360
    return angle


textSource = vtkVectorText()
textSource.SetText("Hello")
textSource.Update()

transfo = vtk.vtkTransform()
transfo.Identity()
transfo.PostMultiply()

x = 1
xo = 0
y = 1
yo = 0
z =1
zo = 1 
#angle Z
teta = GetAngleBetweenPoints( [x,y], [0,0], [xo,yo])
print(teta)
transfo.RotateWXYZ(+(teta),0, 0, 1)
# angle Y
teta = GetAngleBetweenPoints( [x,z], [0,0], [xo,zo])
print(teta)
transfo.RotateWXYZ(+(teta), 0, 1, 0)
transfo.Translate(x,y,z)

filter = vtk.vtkTransformPolyDataFilter()
filter.SetInputConnection(textSource.GetOutputPort())
filter.SetTransform(transfo)
filter.Update()



#Create a mapper and actor
mapper = vtkPolyDataMapper()
mapper.SetInputConnection(filter.GetOutputPort())

actor =vtkActor()
actor.SetMapper(mapper)
actor.GetProperty().SetColor(1.0, 0.0, 0.0)

#Create a renderer, render window, and interactor
renderer = vtkRenderer()
renderWindow = vtkRenderWindow()
renderWindow.AddRenderer(renderer)
renderWindowInteractor = vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)

renderer.AddActor(actor)
renderer.AddActor(vtk.vtkAxesActor())
renderer.SetBackground(0.4, 0.3, 0.2)

renderWindow.Render()
style = vtk.vtkInteractorStyleMultiTouchCamera()
renderWindowInteractor.SetInteractorStyle(style)
renderWindowInteractor.Start() 

Solution

  • Solution with vtkplotter:

    from vtkplotter import Text
    
    t = Text('hello', pos=(1,1,1), c='white', justify='center') # t is a vtkActor
    t.orientation([1,1,1])
    t.show()
    

    enter image description here